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.
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