Inventor Macro: Recursive Function and Enumerator

When automating Inventor, it often happens that we need to cross several levels of objects, especially when we want to iterate through all the components and subcomponents of an assembly.
To do this, it is common to use a Recursive, a function that recalls itself a number of times indefinitely.
As in the following example, where we collect a collection of names of all the components of an assembly:
Private Sub ComponentsNames_Recursive() Dim cNames As Collection Dim oAssyDoc As AssemblyDocument Set oAssyDoc = ThisApplication.ActiveDocument Set cNames = GetAllComponentsNames(oAssyDoc) End Sub Private Function GetAllComponentsNames(ByVal oAssyDoc As AssemblyDocument) As Collection Dim cNames As New Collection Dim oCompOcc As ComponentOccurrence For Each oCompOcc In oAssyDoc.ComponentDefinition.Occurrences cNames.Add oCompOcc.Name If oCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then Dim cSubCompOccNames As Collection Set cSubCompOccNames = GetAllComponentsNames(oCompOcc.Definition.Document) Dim sSubCompOccName As Variant For Each sSubCompOccName In cSubCompOccNames cNames.Add sSubCompOccName Next End If Next Set GetAllComponentsNames = cNames End Function
Public Sub ComponentsNames_Recursive() Dim assemblyDocument As AssemblyDocument = InventorApplication.ActiveDocument Dim names As Collection = GetAllComponentsNames(assemblyDocument) End Sub Private Function GetAllComponentsNames(ByVal assemblyDocument As AssemblyDocument) As Collection Dim names As New Collection Dim occurrence As ComponentOccurrence For Each occurrence In assemblyDocument.ComponentDefinition.Occurrences names.Add(occurrence.Name) If occurrence.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then Dim subOccNames As Collection = GetAllComponentsNames(occurrence.Definition.Document) For Each subOccName as Object In subOccNames names.Add(subOccName) Next End If Next Return names End Function
public void ComponentsNames_Recursive() { AssemblyDocument assemblyDocument = InventorApplication.ActiveDocument; Collection names = GetAllComponentsNames(assemblyDocument); } private Collection GetAllComponentsNames(AssemblyDocument assemblyDocument) { Collection names = new Collection(); ComponentOccurrence occurrence; foreach (var occurrence in assemblyDocument.ComponentDefinition.Occurrences) { names.Add(occurrence.Name); if (occurrence.DefinitionDocumentType == DocumentTypeEnum.kAssemblyDocumentObject) { Collection subOccNames = GetAllComponentsNames(occurrence.Definition.Document); foreach (object subOccName in subOccNames) names.Add(subOccName); } } return names; }
But you can also achieve the same result in less lines of code through the Enumerators, as in the following example:
Private Sub ComponentsNames_Enumerator() Dim cNames As New Collection Dim oAssyDoc As AssemblyDocument Dim oCompOccEnum As ComponentOccurrencesEnumerator Dim oCompOcc As ComponentOccurrence Set oAssyDoc = ThisApplication.ActiveDocument Set oCompOccEnum = oAssyDoc.ComponentDefinition.Occurrences.AllReferencedOccurrences(oAssyDoc.ComponentDefinition) For Each oCompOcc In oCompOccEnum cNames.Add oCompOcc.Name Next End Sub
Public Sub ComponentsNames_Enumerator() Dim names As New Collection Dim assemblyDocument As AssemblyDocument = InventorApplication.ActiveDocument Dim compOccEnum As ComponentOccurrencesEnumerator = assemblyDocument.ComponentDefinition.Occurrences.AllReferencedOccurrences(assemblyDocument.ComponentDefinition) For Each compOcc As ComponentOccurrence In compOccEnum names.Add(compOcc.Name) Next End Sub
public void ComponentsNames_Enumerator() { Collection names = new Collection(); AssemblyDocument assemblyDocument = InventorApplication.ActiveDocument; ComponentOccurrencesEnumerator compOccEnum = assemblyDocument.ComponentDefinition.Occurrences.AllReferencedOccurrences(assemblyDocument.ComponentDefinition); foreach (ComponentOccurrence compOcc in compOccEnum) names.Add(compOcc.Name); }
The advantage is especially at the performance level because the Enumerators are normally optimized for iteration.
Now it’s up to you to choose the way you prefer.