Inventor Macro: Recursive Function and Enumerator

autodesk-inventor-automation-recursive-and-enumerator-post

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.

You may also like...