Code Library
SolidWorks APIVBASolidWorks 2016+ · built-in VBA editorMIT license

Export a flat BOM (part counts) from a SolidWorks assembly to CSV

Purchasing wants "how many of each part is in this machine?" and the drawing BOM answers per-subassembly, not for the whole tree. This macro flattens the entire assembly: every component at every level, suppressed ones skipped, counted by file + configuration (so a short and long version of the same part number stay separate rows), written to a CSV that opens straight in Excel.

Before you run it

  • An assembly open and saved (the CSV lands next to it)
  • SolidWorks type-library references ticked in the VBA editor

The code

GitHub
Option Explicit

' Flat parts count for the active assembly -> CSV next to the assembly file.
' Counts every component at every level; suppressed components are skipped.
' Rows are keyed by file + configuration, so config variants count separately.

Sub main()
    Dim swApp As SldWorks.SldWorks
    Set swApp = Application.SldWorks

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

    If swModel Is Nothing Then
        swApp.SendMsgToUser "Open an assembly first."
        Exit Sub
    End If
    If swModel.GetType <> swDocASSEMBLY Then
        swApp.SendMsgToUser "This macro runs on assemblies only."
        Exit Sub
    End If
    If swModel.GetPathName = "" Then
        swApp.SendMsgToUser "Save the assembly first (the CSV goes next to it)."
        Exit Sub
    End If

    Dim swAssy As SldWorks.AssemblyDoc
    Set swAssy = swModel
    swAssy.ResolveAllLightWeightComponents False   ' lightweight comps report nothing

    Dim counts As Object
    Set counts = CreateObject("Scripting.Dictionary")

    Dim vComps As Variant
    vComps = swAssy.GetComponents(False)           ' False = all levels, flattened

    Dim i As Long
    For i = 0 To UBound(vComps)
        Dim swComp As SldWorks.Component2
        Set swComp = vComps(i)
        If swComp.GetSuppression <> swComponentSuppressed Then
            Dim key As String
            key = swComp.GetPathName & "|" & swComp.ReferencedConfiguration
            counts(key) = counts(key) + 1
        End If
    Next i

    Dim csvPath As String
    csvPath = Left$(swModel.GetPathName, _
                    InStrRev(swModel.GetPathName, ".") - 1) & "_BOM.csv"

    Dim f As Integer
    f = FreeFile
    Open csvPath For Output As #f
    Print #f, "File,Configuration,Quantity"

    Dim k As Variant
    For Each k In counts.Keys
        Dim pieces() As String
        pieces = Split(k, "|")
        Dim baseName As String
        baseName = Mid$(pieces(0), InStrRev(pieces(0), "\") + 1)
        Print #f, baseName & "," & pieces(1) & "," & counts(k)
    Next k
    Close #f

    swApp.SendMsgToUser counts.Count & " unique part/config rows written to:" & _
        vbNewLine & csvPath
End Sub

How it works

  • GetComponents(False) is the whole trick: with False it returns every component instance at every level as one flat array — no recursion needed.
  • A Scripting.Dictionary keyed on path|configuration counts instances; reading a missing key returns Empty, and Empty + 1 = 1, so the count line works without an existence check.
  • GetSuppression <> swComponentSuppressed skips suppressed components — they're modeled, but they're not in the machine.
  • ResolveAllLightWeightComponents runs first because lightweight components can report empty data to the API.
  • Output goes through plain Open/Print — no Excel automation, so it runs in seconds on thousand-part assemblies.

Gotchas & honest limits

  • This is a flat count, not an indented BOM — subassembly structure is deliberately erased. For indented BOMs use the drawing BOM table.
  • Filenames containing commas will break the CSV columns; wrap fields in quotes if your naming allows commas (better: don't allow commas).
  • Counts are model truth, not engineering truth: envelope components and "exclude from BOM" flags are not consulted in this minimal version — that's the first upgrade to make.
  • Huge assemblies opened lightweight take a pause on the resolve step. That's the price of correct data.

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.

Get in touch
Home
Blog
Tools
Code
Email
LinkedIn
Résumé