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.
