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:
- Read: iterate each drawing view using
ISheet::GetViews(), callIView::GetVisibleComponents()to get the visible components, then read each component’s material viaIPartDoc::GetMaterialPropertyName2() - Prepare: for each unique material name, create a named layer in the drawing’s layer manager via
ILayerMgr::AddLayer() - 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.