Traverse Assembly Tree Recursively -SOLIDWORKS API

Amen Jlili

This topic is most definitely a recurring one. I find myself having to go back to old pieces of code I wrote a while ago and copy-paste. I thought it would be a good idea to congregate all that in one useful post for future references.

Unfortunately, the code samples provided by SOLIDWORKS Corp lacks proper recursion. Below, you will find the same example that recursively drills down on an assembly tree in C#, VB.NET and VBA.

Note: While the logic respects the assembly order, it will not traverse the FeatureManager display tree as it appears in SOLIDWORKS (i.e. it ignores components organized into folders). To traverse the FeatureManager design tree exactly as it appears, use this object.

Note: Highlighted green line in the C# and VB.NET sample need to be updated by user with a proper assembly path. The VBA code sample assumes that an assembly document is open and active in SOLIDWORKS.


  Dim swApp As SldWorks.SldWorks
Dim swRootAssemblyModelDoc As ModelDoc2

Sub main()

    Set swApp = Application.SldWorks
    swApp.CommandInProgress = True
    Set swRootAssemblyModelDoc = swApp.ActiveDoc
    Dim swFeature As Feature
    Set swFeature = swRootAssemblyModelDoc.FirstFeature
    While Not swFeature Is Nothing
     TraverseFeatureForComponents swFeature
     Set swFeature = swFeature.GetNextFeature
    swApp.CommandInProgress = False
End Sub

Private Sub TraverseFeatureForComponents(ByVal swFeature As Feature)
    Dim swSubFeature As Feature
    Dim swComponent As Component2
    Dim typeName As String
    typeName = swFeature.GetTypeName2
    If typeName = "Reference" Then
        Set swComponent = swFeature.GetSpecificFeature2
        If Not swComponent Is Nothing Then
         LogComponentName swComponent
           Set swSubFeature = swComponent.FirstFeature()
             While Not swSubFeature Is Nothing
                TraverseFeatureForComponents swSubFeature
                Set swSubFeature = swSubFeature.GetNextFeature()
        End If
    End If
End Sub

Private Sub LogComponentName(ByVal swComponent As Component2)
    Dim parentCount As Long
    Dim swParentComponent As Component2
    Set swParentComponent = swComponent.GetParent()
    While Not swParentComponent Is Nothing
     parentCount = parentCount + 1
     Set swParentComponent = swParentComponent.GetParent()
    Dim indentation As String
    indentation = Replicate(" ", parentCount)
    Debug.Print indentation & swComponent.Name2
End Sub
Public Function Replicate(RepeatString As String, ByVal NumOfTimes As Long)
    Dim s As String
    Dim c As Long
    Dim l As Long
    Dim i As Long

    l = Len(RepeatString)
    c = l * NumOfTimes
    s = Space$(c)

    For i = 1 To c Step l
        Mid(s, i, l) = RepeatString

    Replicate = s
End Function


using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.Linq;

namespace AssemblyTreeTraversal
    class Program
        static void Main(string[] args)
            SldWorks swApp = default(SldWorks);
            ModelDoc2 swModel = default(ModelDoc2);
            string assemblyFileName = @"C:\PDM2020\example\Full_Grill_Assembly.SLDASM";

            swApp = System.Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")) as SldWorks;

            if (swApp == null)
                throw new Exception("Failed to open SOLIDWORKS");
            swApp.Visible = true;

            // increase performance 
            swApp.CommandInProgress = true;

            swModel = swApp.OpenDoc(assemblyFileName, (int)swDocumentTypes_e.swDocASSEMBLY) as ModelDoc2;

            Console.WriteLine("Document opened. Tree:");

             var swRootAssemblyModelDoc = swApp.ActiveDoc as ModelDoc2;
             Action<Component2> action = LogComponentName;
            var swFeature = swRootAssemblyModelDoc.FirstFeature() as Feature;
            while (swFeature != null)
                TraverseFeatureForComponents(swFeature, action);
                swFeature = swFeature.GetNextFeature() as Feature;


            swApp.CommandInProgress = false;


        static void TraverseFeatureForComponents(Feature swFeature, Action<Component2> performAction)
            var swSubFeature = default(Feature);
                var swComponent = swFeature.GetSpecificFeature2() as Component2;
                if (swComponent != null)

                    swSubFeature = swComponent.FirstFeature();
                    while (swSubFeature != null)
                        TraverseFeatureForComponents(swSubFeature, performAction);
                        swSubFeature = swSubFeature.GetNextFeature() as Feature;
        static void LogComponentName(Component2 swComponent)
            // this code is not performant  
            int parentCount = 0;
            Component2 swParentComponent;
            swParentComponent = swComponent.GetParent();
            while (swParentComponent != null)
                swParentComponent = swParentComponent.GetParent();
            string indentation = string.Join(string.Empty, Enumerable.Repeat(" ", parentCount));



Imports SolidWorks.Interop.sldworks
Imports SolidWorks.Interop.swconst

Namespace AssemblyTreeTraversal
    Class Program
        Private Shared Sub Main(ByVal args As String())
            Dim swApp As SldWorks = Nothing
            Dim swModel As ModelDoc2 = Nothing
            Dim assemblyFileName As String = "C:\PDM2020\example\Full_Grill_Assembly.SLDASM"

            swApp = System.Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application"))

            If swApp Is Nothing Then Throw New Exception("Failed to open SOLIDWORKS")
            swApp.Visible = True
            swApp.CommandInProgress = True
            swModel = swApp.OpenDoc(assemblyFileName, swDocumentTypes_e.swDocASSEMBLY)
            Console.WriteLine("Document opened. Tree:")
            Dim swRootAssemblyModelDoc As ModelDoc2 = swApp.ActiveDoc
            Dim action As Action(Of Component2) = AddressOf LogComponentName
            Dim swFeature As Feature = swRootAssemblyModelDoc.FirstFeature()

            While swFeature IsNot Nothing
                TraverseFeatureForComponents(swFeature, action)
                swFeature = swFeature.GetNextFeature()
            End While

            swApp.CommandInProgress = False
        End Sub

        Private Shared Sub TraverseFeatureForComponents(ByVal swFeature As Feature, ByVal performAction As Action(Of Component2))
            Dim swSubFeature = Nothing
            Dim swComponent = TryCast(swFeature.GetSpecificFeature2(), Component2)

            If swComponent IsNot Nothing Then
                swSubFeature = swComponent.FirstFeature()

                While swSubFeature IsNot Nothing
                    TraverseFeatureForComponents(swSubFeature, performAction)
                    swSubFeature = swSubFeature.GetNextFeature()
                End While
            End If
        End Sub

        Private Shared Sub LogComponentName(ByVal swComponent As Component2)
            Dim parentCount As Integer = 0
            Dim swParentComponent As Component2
            swParentComponent = swComponent.GetParent()

            While swParentComponent IsNot Nothing
                parentCount += 1
                swParentComponent = swParentComponent.GetParent()
            End While

            Dim indentation As String = String.Join(String.Empty, Enumerable.Repeat(" ", parentCount))
        End Sub
    End Class
End Namespace

More great articles

Delete all properties for the active configuration – SOLIDWORKS MACRO

The following macro deletes all the properties from the active configuration. The macro is written used late-binding so it is…

Read Story

Add watermark to your drawings – Macro

Add watermark macro in action. This macro adds a watermark to the active sheet of the active drawing document: 'www.bluebyte.biz…

Read Story

Early binding vs Late Binding: How to write macros that will always run with no errors

TLDR: Here's what you need to know about Early Binding Vs Late Binding Use early binding for writing macros. It…

Read Story