Fabrication shops that receive DWG files from SolidWorks drawings often expect specific AutoCAD layers — BRASS, STAINLESS_STEEL, ALUMINUM — matching the actual part materials. The native Save As layer mapping table in Document Properties → DXF/DWG Export → Map SolidWorks to DXF/DWG maps entity types to layers, not component materials. There is no UI checkbox that says “use material name as layer.”

This post shows the API approach: read each component’s material from the drawing views, create named layers in the drawing document, assign components to those layers, then export to DWG. It covers the key API calls, a complete working VBA macro, and the three edge cases that will silently fail on a naive implementation.

Why the Native Layer Mapping Table Falls Short

SOLIDWORKS’s built-in DXF/DWG layer mapping lets you map SolidWorks entity categories to DWG layers:

  • Annotations → layer “Annotations”
  • Dimensions → layer “Dimensions”
  • Sketch entities → layer “Sketch”
  • Part/assembly geometry → layer “0” (AutoCAD default)

What it cannot do is distinguish between a brass component and a stainless steel component in the same drawing view. Both are “part geometry” as far as the export engine is concerned. The mapping table is keyed on entity type and SolidWorks layer name — neither of which carries material information.

The only path to material-based layer assignment is to manipulate the drawing document programmatically before exporting.

The API Approach

The workflow has three stages:

  1. Read: iterate each drawing view using ISheet::GetViews(), call IView::GetVisibleComponents() to get the visible components, then read each component’s material via IPartDoc::GetMaterialPropertyName2()
  2. Prepare: for each unique material name, create a named layer in the drawing’s layer manager via ILayerMgr::AddLayer()
  3. Assign: set each component’s layer via IComponent2::Layer, then call SaveAs to produce the DWG

The export itself is a standard SaveAs call — once the components are assigned to named layers, the DWG output reflects those layer assignments directly. SolidWorks layer names become AutoCAD layer names.

The VBA Macro

Paste this into the SolidWorks VBA editor (Tools → Macros → New) and run it against an open drawing:

Option Explicit

Dim swApp As SldWorks.SldWorks

Sub ExportDWGByMaterial()
    Set swApp = Application.SldWorks

    Dim swModel As SldWorks.ModelDoc2
    Set swModel = swApp.ActiveDoc

    If swModel Is Nothing Then
        MsgBox "No active document."
        Exit Sub
    End If

    If swModel.GetType() <> swDocDrawing Then
        MsgBox "Active document must be a drawing (.slddrw)."
        Exit Sub
    End If

    Dim swDraw As SldWorks.DrawingDoc
    Set swDraw = swModel

    Dim swLayerMgr As SldWorks.LayerMgr
    Set swLayerMgr = swModel.GetLayerManager()

    ' Dictionary to track which material layers have been created this run
    Dim layerMap As Object
    Set layerMap = CreateObject("Scripting.Dictionary")

    Dim vSheetNames As Variant
    vSheetNames = swDraw.GetSheetNames()

    Dim i As Integer
    For i = 0 To UBound(vSheetNames)
        swDraw.ActivateSheet vSheetNames(i)

        Dim swSheet As SldWorks.Sheet
        Set swSheet = swDraw.GetCurrentSheet()

        Dim vViews As Variant
        vViews = swSheet.GetViews()

        If Not IsEmpty(vViews) Then
            Dim j As Integer
            For j = 0 To UBound(vViews)
                Dim swView As SldWorks.View
                Set swView = vViews(j)

                ' Index 0 is always the sheet format view — skip it
                If j = 0 Then GoTo NextView

                ProcessView swView, swLayerMgr, layerMap
NextView:
            Next j
        End If
    Next i

    ' Build output path: replace .slddrw extension with .dwg
    Dim savePath As String
    savePath = Left(swModel.GetPathName(), Len(swModel.GetPathName()) - 7) & ".dwg"

    Dim errors As Long
    Dim warnings As Long
    Dim bRet As Boolean
    bRet = swModel.Extension.SaveAs(savePath, 0, swSaveAsOptions_Silent, _
                                    Nothing, errors, warnings)

    If bRet Then
        MsgBox "Exported: " & savePath & vbNewLine & _
               "Material layers created: " & layerMap.Count
    Else
        MsgBox "Export failed. errors=" & errors & ", warnings=" & warnings
    End If
End Sub

Sub ProcessView(swView As SldWorks.View, _
                swLayerMgr As SldWorks.LayerMgr, _
                layerMap As Object)

    Dim vComps As Variant
    vComps = swView.GetVisibleComponents()

    If IsEmpty(vComps) Or IsNull(vComps) Then Exit Sub

    Dim i As Integer
    For i = 0 To UBound(vComps)
        Dim swComp As SldWorks.Component2
        Set swComp = vComps(i)

        ' Drawing-context components: GetModelDoc2 returns Nothing when
        ' the assembly was opened lightweight. See Gotcha #1 below.
        Dim swRefModel As SldWorks.ModelDoc2
        Set swRefModel = swComp.GetModelDoc2()

        If swRefModel Is Nothing Then
            Debug.Print "Lightweight — skipped: " & swComp.Name2
            GoTo NextComp
        End If

        ' GetVisibleComponents recurses to leaf parts, but guard anyway
        If swRefModel.GetType() <> swDocPart Then GoTo NextComp

        Dim swPart As SldWorks.PartDoc
        Set swPart = swRefModel

        Dim matDb As String
        Dim matName As String
        matName = swPart.GetMaterialPropertyName2( _
                      swComp.ReferencedConfiguration, matDb)

        ' Normalize missing or placeholder material strings
        If matName = "" Or matName = "Material <not specified>" Then
            matName = "UNASSIGNED"
        End If

        ' Sanitize for DWG: uppercase, spaces to underscores, max 31 chars
        ' (DWG R2000 format cap; modern DWG supports 255 but this is safe everywhere)
        Dim layerName As String
        layerName = UCase(Left(Replace(matName, " ", "_"), 31))

        ' Create the layer once per unique material encountered
        If Not layerMap.Exists(layerName) Then
            If swLayerMgr.GetLayer(layerName) Is Nothing Then
                swLayerMgr.AddLayer layerName, matName, _
                    MaterialColor(layerName), swLineSolid, swLW_NORMAL
            End If
            layerMap.Add layerName, True
        End If

        ' Assign this component's drawing entities to the material layer
        swComp.Layer = layerName

NextComp:
    Next i
End Sub

Function MaterialColor(layerName As String) As Long
    ' COLORREF values — these colors appear in AutoCAD when the DWG is opened
    Select Case layerName
        Case "BRASS", "BRASS_ALLOY"
            MaterialColor = RGB(218, 165, 32)   ' gold
        Case "STAINLESS_STEEL", "STAINLESS_STEEL_AISI_304", _
             "STAINLESS_STEEL_AISI_316"
            MaterialColor = RGB(150, 150, 150)  ' medium gray
        Case "ALUMINUM_1060_ALLOY", "ALUMINUM_6061-T6", "ALUMINUM"
            MaterialColor = RGB(200, 200, 200)  ' light gray
        Case "PLAIN_CARBON_STEEL", "AISI_1020", "STEEL"
            MaterialColor = RGB(50, 50, 50)     ' near-black
        Case "COPPER", "COPPER_ALLOY"
            MaterialColor = RGB(184, 115, 51)   ' copper brown
        Case "TITANIUM", "TITANIUM_ALLOY"
            MaterialColor = RGB(135, 169, 107)  ' olive
        Case Else
            MaterialColor = RGB(0, 0, 0)        ' black fallback
    End Select
End Function

Gotcha #1: Lightweight Assemblies Break GetModelDoc2

IView::GetVisibleComponents() returns drawing-context component references. When the drawing’s referenced assembly was opened in lightweight mode, swComp.GetModelDoc2() returns Nothing. The assembly’s part documents are not loaded into memory, so the COM pointer has nowhere to resolve.

The symptom is that the macro completes without error, but no material layers appear in the output DWG — every component silently hit the GoTo NextComp branch.

Fix: before running the macro, force a full load of the drawing’s referenced models. Right-click any drawing view → “Open Assembly” → close and reload the drawing. Or set Tools → Options → System Options → Performance → “Resolve Lightweight Components” to “Always” for the session.

If you’re building this into a batch pipeline, programmatically reload lightweight components before processing the drawing:

' Force-resolve any lightweight components in the assembly
Dim swAss As SldWorks.AssemblyDoc
Set swAss = swApp.OpenDoc6(assemblyPath, swDocAssembly, _
                            swOpenDocOptions_Silent, "", errors, warnings)
swAss.ResolveAllLightweightComponents True
swAss.ForceRebuild3 False

Gotcha #2: Multi-Body Parts with Mixed Materials

The macro above calls GetMaterialPropertyName2() on the IPartDoc and gets one material name per component. This is correct for single-body parts. For multi-body parts where different bodies carry different materials (common in weldments and machined blocks with inserts), GetMaterialPropertyName2() returns the material of the first body or the configuration’s part-level material override — whichever takes precedence.

To handle per-body materials, replace the GetMaterialPropertyName2 call with a body iteration:

' Per-body material assignment (replaces the single GetMaterialPropertyName2 call)
Dim vBodies As Variant
vBodies = swPart.GetBodies2(swAllBodies, True)

If Not IsEmpty(vBodies) Then
    Dim k As Integer
    For k = 0 To UBound(vBodies)
        Dim swBody As SldWorks.Body2
        Set swBody = vBodies(k)

        Dim bodyMatDb As String
        Dim bodyMatName As String
        bodyMatName = swBody.GetMaterialPropertyName( _
                          swComp.ReferencedConfiguration, bodyMatDb)

        If bodyMatName = "" Then bodyMatName = "UNASSIGNED"

        Dim bodyLayerName As String
        bodyLayerName = UCase(Left(Replace(bodyMatName, " ", "_"), 31))

        ' Create layer if needed, same as above
        If Not layerMap.Exists(bodyLayerName) Then
            If swLayerMgr.GetLayer(bodyLayerName) Is Nothing Then
                swLayerMgr.AddLayer bodyLayerName, bodyMatName, _
                    MaterialColor(bodyLayerName), swLineSolid, swLW_NORMAL
            End If
            layerMap.Add bodyLayerName, True
        End If

        ' For per-body assignment you need IView::GetVisibleEntities2
        ' filtered by each body's faces, then move those entities to the layer.
        ' swComp.Layer assigns all entities of the component at once —
        ' per-body granularity requires entity-level selection.
    Next k
End If

The swComp.Layer property assigns all of the component’s drawing entities to one layer simultaneously. Per-body granularity requires iterating IView::GetVisibleEntities2(swComp, swViewEntityType_Face), filtering faces by body, selecting them via IModelDocExtension::SelectByID2, and then setting the layer for the selection. That’s a larger macro; the single-component approach covers the majority of real drawings.

Gotcha #3: Flat-Pattern Views Return Nothing for IView::Bodies

If your drawing contains sheet-metal flat-pattern views, IView::Bodies returns Nothing for those views — a documented SolidWorks API limitation noted in the help for IView::Bodies. The macro above uses GetVisibleComponents() throughout, which works correctly for flat-pattern views. This only becomes an issue if you’re trying to read materials from IView::Bodies instead of from the component’s part document.

The SolidWorks API gotchas reference covers IView::Bodies returning Nothing as a silent failure — the call succeeds with no error, you just get no data.

Layer Assignments Persist in the Drawing

swComp.Layer = layerName modifies the drawing document. After export, the drawing has all its components assigned to material-named layers. Depending on your team’s drawing template setup, this may or may not be desirable as a permanent change.

To export and then undo the layer assignments:

' After SaveAs succeeds, undo all layer assignment changes
Dim nUndoCount As Integer
nUndoCount = layerMap.Count + 1  ' rough upper bound
Dim m As Integer
For m = 1 To nUndoCount
    swModel.Extension.RunCommand swCommands_e.swCommands_Undo, ""
Next m

Or, more cleanly, record the original layer for each component before modifying it and restore afterward.

Connecting to the DXF/DWG Layer Mapping Table

Once components are assigned to material-named layers, the DXF/DWG Export layer mapping table (Document Properties → DXF/DWG Export) gives you a second level of control: you can remap SolidWorks layer names to DWG layer names, change their colors in the output, or merge multiple material layers into one. The macro sets the raw layer structure; the mapping table lets you normalize it for downstream consumers.

For shops that already use SolidWorks DXF layer mapping for laser cutting shops, this macro is the upgrade path — instead of mapping entity types to processing layers, you map material-specific layers to the CAM process layers your operators expect.

Extending to Batch Export

The macro processes one drawing at a time. To extend to batch mode — iterating all drawings in a folder and exporting each to DWG with material layers — see the batch STEP and DXF export system options vs macro post for the outer loop structure. The ProcessView / ExportDWGByMaterial logic above slots directly into that loop.

For production use as an add-in rather than a standalone macro, the in-process vs standalone SOLIDWORKS API execution comparison is worth reading before committing to an architecture — the drawing export code runs cleanly in both contexts, but in-process execution avoids the COM connection overhead on each file.

CadShift’s batch DXF export handles flat patterns with material metadata embedded in DXF layers and layer descriptions, so if your workflow is specifically sheet metal → flat pattern DXF → laser cutting, that path handles the material-per-body tracking automatically.