SolidWorks APIVBASolidWorks 2016+ · built-in VBA editorMIT licenseAdvanced
Round-trip SolidWorks custom properties through a CSV (no PDM)
The shop without a PDM vault still needs to bulk-edit part numbers, materials, and revisions — and clicking through Properties on 200 parts is how an afternoon disappears. This is two macros sharing one schema constant: ExportPropertiesToCsv dumps every part's custom properties in a folder to one CSV; edit it in Excel; ImportPropertiesFromCsv writes the changes back. No vault, no Excel automation, no per-part clicking.
Before you run it
- A folder of
.SLDPRTfiles sharing the same custom-property schema - SolidWorks type-library references ticked in the VBA editor
- Edit the
FOLDERandPROP_NAMESconstants to match your title block before running
The code
Option Explicit
' Two macros, one schema. Export every part's custom properties in a folder
' to CSV, edit in Excel, then write the changes back. Parts only (.SLDPRT) -
' duplicate the loop with swDocASSEMBLY if you also need assemblies.
Const FOLDER As String = "C:\Parts\" ' must end with a backslash
Const CSV_PATH As String = "C:\Parts\properties.csv"
Const PROP_NAMES As String = "Description,PartNumber,Material,Revision" ' edit to your schema
Sub ExportPropertiesToCsv()
Dim swApp As SldWorks.SldWorks
Set swApp = Application.SldWorks
Dim props() As String
props = Split(PROP_NAMES, ",")
Dim f As Integer
f = FreeFile
Open CSV_PATH For Output As #f
Print #f, "File," & PROP_NAMES
Dim fileName As String
fileName = Dir$(FOLDER & "*.sldprt")
Dim opened As Long, failed As Long
Do While fileName <> ""
Dim errs As Long, warns As Long
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.OpenDoc6(FOLDER & fileName, swDocPART, _
swOpenDocOptions_Silent Or swOpenDocOptions_ReadOnly, "", errs, warns)
If Not swModel Is Nothing Then
Dim swCustProp As SldWorks.CustomPropertyManager
Set swCustProp = swModel.Extension.CustomPropertyManager("")
Dim row As String
row = fileName
Dim i As Long
For i = 0 To UBound(props)
Dim val As String, resolved As String
swCustProp.Get4 Trim$(props(i)), False, val, resolved
row = row & "," & Replace(resolved, ",", ";") ' a comma here would break the CSV
Next i
Print #f, row
opened = opened + 1
swApp.CloseDoc swModel.GetTitle
Else
failed = failed + 1
Debug.Print "COULD NOT OPEN: " & fileName
End If
fileName = Dir$()
Loop
Close #f
swApp.SendMsgToUser opened & " file(s) exported to:" & vbNewLine & CSV_PATH & _
vbNewLine & failed & " could not be opened."
End Sub
Sub ImportPropertiesFromCsv()
Dim swApp As SldWorks.SldWorks
Set swApp = Application.SldWorks
Dim props() As String
props = Split(PROP_NAMES, ",")
Dim f As Integer
f = FreeFile
Open CSV_PATH For Input As #f
Dim header As String
Line Input #f, header ' discard the header row
Dim updated As Long, failed As Long
Do While Not EOF(f)
Dim rowText As String
Line Input #f, rowText
Dim cells() As String
cells = Split(rowText, ",")
If UBound(cells) < UBound(props) Then GoTo NextRow
Dim errs As Long, warns As Long
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.OpenDoc6(FOLDER & cells(0), swDocPART, _
swOpenDocOptions_Silent, "", errs, warns)
If Not swModel Is Nothing Then
Dim swCustProp As SldWorks.CustomPropertyManager
Set swCustProp = swModel.Extension.CustomPropertyManager("")
Dim i As Long
For i = 0 To UBound(props)
swCustProp.Add3 Trim$(props(i)), swCustomInfoText, cells(i + 1), _
swCustomPropertyReplaceValue
Next i
swModel.Save3 swSaveAsOptions_Silent, errs, warns
updated = updated + 1
swApp.CloseDoc swModel.GetTitle
Else
failed = failed + 1
Debug.Print "COULD NOT OPEN: " & cells(0)
End If
NextRow:
Loop
Close #f
swApp.SendMsgToUser updated & " file(s) updated, " & failed & " failed." & _
vbNewLine & "Failures (if any) are in the Immediate window (Ctrl+G)."
End SubWhat you get
properties.csv
File,Description,PartNumber,Material,Revision
Bracket_100.SLDPRT,Mounting bracket,BRK-100,6061-T6,C
Standoff_012.SLDPRT,Spacer standoff,STD-012,303 SS,A
CoverPlate.SLDPRT,Access cover,CVR-045,5052-H32,B
3 file(s) exported to:
C:\Parts\properties.csv
0 could not be opened.How it works
- Both subs share one schema constant —
PROP_NAMES— so export and import always agree on which CSV column maps to which property. Change your schema once, in one place. CustomPropertyManager.Get4returns both the raw and the resolved value — resolved is what actually displays (it follows equations and linked properties), which is what belongs in a report.- Export replaces commas in values with semicolons before writing — the classic way a hand-rolled CSV writer corrupts itself is a comma inside a text field.
- Import uses
Add3withswCustomPropertyReplaceValue, so re-running it is safe: properties get overwritten, not duplicated.
Gotchas & honest limits
- Parts only, on purpose — assemblies need
swDocASSEMBLYinOpenDoc6; duplicate the loop with the type swapped if you also batch assemblies. - This reads and writes file-level custom properties, not configuration-specific ones. Pass a configuration name into
CustomPropertyManagerinstead of""for config-specific values. - The import CSV must match the export CSV's column order exactly (
File,then one column per name inPROP_NAMES) — it's positional, not header-matched like the openpyxl report script. - Round-tripping through Excel: format the property columns as text before saving the CSV, or Excel will happily mangle a part number that looks like a number (leading zeros, dashes read as minus signs).
Goes deeper
Want this adapted to your shop — or built into a real tool?
Samples are the free 80%. The last 20% is the part I do for a living.