US$0.00
0

Traverse Assembly Tree Recursively – SOLIDWORKS API

This topic is most definitely a recurring one. I often find myself revisiting old pieces of code I wrote a while ago and having to copy-paste. So I thought it would be a good idea to congregate all that in one useful post for future reference. In this article, we are going to explain traverse assembly tree recursively.

Unfortunately, the code samples we have from the SOLIDWORKS Corp fall behind in terms of proper recursion, which is essential for navigating complex assembly structures. Below in this documentation, you will find an example that uses VBA recursion to drill down into an assembly tree effectively.

The code examples provided here go beyond the basics often found in the standard SOLIDWORKS API SDK documentation, offering a more robust and reusable solution. I’ve prepared the code in C#, VB.NET, and VBA, demonstrating the easy yet effective technique to traverse assembly completely.

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: The highlighted green line in the C# and VB.NET samples needs to be updated by the user with a proper assembly path. The VBA code sample assumes that an assembly document is open and active in SOLIDWORKS.


VBA


  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
    Wend
    
    
    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()
             Wend
        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()
    Wend
     
    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
    Next
    Replicate = s
 
End Function

C#


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;
            Console.ReadLine();
            
            swApp.QuitDoc(swModel.GetTitle());
            swApp.ExitApp();
        }
        static void TraverseFeatureForComponents(Feature swFeature, Action<Component2> performAction)
        {
            var swSubFeature = default(Feature);
           
                var swComponent = swFeature.GetSpecificFeature2() as Component2;
                if (swComponent != null)
                {
                    performAction(swComponent);
                    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)
            {
                parentCount++;
                swParentComponent = swParentComponent.GetParent();
            }
            string indentation = string.Join(string.Empty, Enumerable.Repeat(" ", parentCount));
            Console.WriteLine($"{indentation}{swComponent.Name}");
        }
         
    }
}

VB.NET


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
            Console.ReadLine()
            swApp.QuitDoc(swModel.GetTitle())
            swApp.ExitApp()
        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
                performAction(swComponent)
                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))
            Console.WriteLine($"{indentation}{swComponent.Name}")
        End Sub
    End Class
End Namespace

Using these recursive functions, you have at your fingertips a powerful and effective tool for working with your SOLIDWORKS assembly data. If all you wish to do is examine the structure or SOLIDWORKS sort assembly tree alphabetically, the code presented here is a good place to begin. If you are still finding that you’re stuck or have specific questions about tailoring this code, don’t hesitate to reach out!

Author

Amen Jlili

Amen Jlili is the founder and technical director of Blue Byte Systems Inc., a software company in Vancouver, Canada, specializing in automating SOLIDWORKS and PDM. With over a decade of experience, he has authored several courses and open-source frameworks related to the SOLIDWORKS API. His leadership ensures that Blue Byte Systems prioritizes customer satisfaction and delivers high-quality software and CAD design solutions.
0
    0
    Your Cart
    Your cart is emptyReturn to Shop
    ×