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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
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#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
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 |