Occurrences from Document

Occurrences from Document

NachoShaw
Advisor Advisor
2,067 Views
8 Replies
Message 1 of 9

Occurrences from Document

NachoShaw
Advisor
Advisor

Hey

 

Hoping someone can help me out here, i cant seem to get this right.... Im using DocumentsEnumerator to get all assembly references. These consist of parts & sub assemblies. There are some instances where we get an assembly with 1 single part inside so in those instances, I need to promote that part out of the found assembly into the top level assembly and then delete the found assembly. ALL of the sub assemblies are only 1 level down so this should be straight forward but im not getting it right tonight... The DocumentsEnumerator has an assembly DocumentType condition as shown below

Dim CurrDoc As AssemblyDocument = _invApp.ActiveDocument
Dim oRefDocs As DocumentsEnumerator = CurrDoc.AllReferencedDocuments
        ' Iterate through the list of documents.
        For Each oRefDoc As Inventor.Document In oRefDocs
         Select Case oRefDoc.DocumentType
                Case DocumentTypeEnum.kAssemblyDocumentObject
                   'Call Promote HERE
                    Dim CurrAssy As AssemblyDocument = oRefDoc 'see below
                    Promote(CurrAssy)
            End Select
        Next

The big problem i am finding is oRefDoc. I am trying to assign it as something but i cannot seem to access Document, ComponentDefinition or ComponentOccurrence. I was hoping for oRefDoc.Document.ComponentDefinition

 

Im using this code from api to promote

Public Sub Promote(ByVal FoundAssembly As AssemblyDocument)
    'need to use FoundAssy in the sub
    ' Get the active assembly document
    Dim oDoc As AssemblyDocument = _invApp.ActiveDocument
    Dim oDef As AssemblyComponentDefinition = oDoc.ComponentDefinition

    ' Get the top level occurrence of an assembly
    Dim oSubAssyOcc As ComponentOccurrence = oDef.Occurrences.Item(1)

    ' Get the 2nd level occurrence under the assembly occurrence
    Dim oSubOcc As ComponentOccurrenceProxy = oDef.Occurrences.Item(1).SubOccurrences.Item(1)
    Set oSubOcc = oSubAssyOcc.SubOccurrences.Item(1)

    Dim oPane As BrowserPane = oDoc.BrowserPanes.Item("Model")

    ' Get the browser nodes corresponding to the two occurrences
    Dim oTargetNode As BrowserNode
    Set oTargetNode = oPane.GetBrowserNodeFromObject(oSubAssyOcc)

    Dim oSourceNode As BrowserNode
    Set oSourceNode = oPane.GetBrowserNodeFromObject(oSubOcc)

    ' Reorder the nodes to promote the sub-occurrence to the top level
    Call oPane.Reorder(oTargetNode, True, oSourceNode)
    
    oSubAssyOcc.Delete
End Sub

 

i know that oSubASssyOcc needs to be the the found Assembly oRefDoc in the Enumerator but as an occurrence. Seeing as its been found in the enumerator, not a top level loop, its not an occurrence per se because its been found as an object in the enumerator instead. So, i cant get this to work properly. It looks like the Browsernode is expecting an occurrence hence why this isnt working. What am i not seeing?

 

Thanks

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.


0 Likes
2,068 Views
8 Replies
Replies (8)
Message 2 of 9

CattabianiI
Collaborator
Collaborator


Try out this snippet to get oSubAssyOcc in Promote method:

 

' Get first occurrence of found assembly
Dim
oSubAssyOcc As ComponentOccurrence = Nothing For Each occ As ComponentOccurrence In oDef.Occurrences If occ.Definition.Document.FullFileName = FoundAssembly.FullFileName Then oSubAssyOcc = occ Exit For End If Next

 

0 Likes
Message 3 of 9

WCrihfield
Mentor
Mentor

Try this version of the code.  It's just one external iLogic rule.

 

 

Sub Main
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
'Iterate through the list of documents.
Dim oOcc As ComponentOccurrence
Dim oAssyOcc As ComponentOccurrence

For Each oOcc In oADef.Occurrences
	If oOcc.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
		oAssyOcc = oOcc
		If oAssyOcc.Definition.Occurrences.Count = 1 Then
			Promote(oADoc,oAssyOcc)
		End If
	End If
Next
End Sub

Public Sub Promote(ByRef oADoc As AssemblyDocument, ByRef oAssyOcc As ComponentOccurrence)
	Dim oRefDef As AssemblyComponentDefinition = oAssyOcc.ComponentDefinition
	Dim oOcc1 As ComponentOccurrence = oRefDef.Occurrences.Item(1)
	Dim oPane As BrowserPane = oADoc.BrowserPanes.Item("Model")
	Dim oMainNode As BrowserNode = oPane.GetBrowserNodeFromObject(oAssyOcc)
	Dim oSubNode As BrowserNode = oPane.GetBrowserNodeFromObject(oOcc1)
	oPane.Reorder(oMainNode, True, oSubNode)
	oAssyOcc.Delete
End Sub

 

 

I hope this helps.
If this solves your problem, or answers your questions, please click 'Accept As Solution".
Or, if this helps you reach your goal, please click 'LIKES" 👍.

 

Also, if you're interested, here are a few of the 'Ideas' I'd like to get implemented.
If you agree with any of them, please vote for them.

  • MessageBox, InputBox, and InputListBox Size & Format Options Click Here
  • Constrain & Dimension Images In Assembly Sketches & Drawing Sketches (TitleBlocks & SketchedSymbols) Click Here
  • Save Section View Status In DesignViewRepresentation (So It Can Be Used In The Drawing) Click Here
  • Add SolidBodies Folder In iLogic Rule Editor Model Tab Click Here
  • Convert All Views To Raster Before Autosave Stores To 'OldVersions' Folder Click Here

Inventor 2020 Help | Inventor Forum | Inventor Customization Forum | Inventor Ideas Forum

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 9

NachoShaw
Advisor
Advisor

Hi

 

Thanks for the reply. I was trying to avoid looping the assembly occurrences themselves as can be time consuming. In many instances, there are mass multiple occurrences of the same part and an assembly loop will look at each one of them. The ReferencedDocuments only looks at the actual document references and ignores the occurrence count.

 

Thanks

 

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.


0 Likes
Message 5 of 9

JamieVJohnson2
Collaborator
Collaborator

Time consuming no more...

These two babies (I've shared in the past) take Inventor coding to the next level.  Parallel computing.  They work in VB.Net with Visual Studio and the iLogic IDE.

    ''' <summary>
    ''' Finds sub occurrence based on partial name. This routine is multi-threaded with bailout.  
    ''' If the component occurrence is found in an assembly, it grabs it and bails out of that assembly.  
    ''' If it is found as a sub component in 3 assemblies, it will add then bail out of each one.  
    ''' It is not the intention of the program to find more than one component at the same level.
    ''' </summary>
    ''' <param name="cdOccurrences">Parent Assembly ComponentOccurrences reference</param>
    ''' <param name="subOccName">Name of Component to find</param>
    ''' <returns>Returns the ComponentOccurance if first level and ComponentOccuranceProxy if lower level.</returns>
    Public Function GetSubOccurrenceProxyByName(ByVal cdOccurrences As ComponentOccurrences, ByVal subOccName As String, Optional PartialName As Boolean = False, Optional FindAtSameLevel As Boolean = False) As Object
        Dim cop As Object = Nothing 'return a ComponentOccurrence at this level, or ComponentOccurrenceProxy from lower level
        System.Threading.Tasks.Parallel.For(1, cdOccurrences.Count + 1,
             Sub(index, status)
                 Dim co As ComponentOccurrence = cdOccurrences(index)
                 If PartialName = True Then
                     If co.Name.Contains(subOccName) Then
                         cop = co
                         If FindAtSameLevel = False Then status.Stop() 'this line stops the entire for loop
                         Return 'this line stops the rest of this sub from running, and code continues to run other index items
                     End If
                 Else
                     If co.Name = subOccName Then
                         cop = co
                         If FindAtSameLevel = False Then status.Stop()
                         Return
                     End If
                 End If
                 If co.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
                     If TypeOf co.Definition Is AssemblyComponentDefinition OrElse TypeOf co.Definition Is WeldmentComponentDefinition Then
                         Dim sco As ComponentOccurrence = GetSubOccurrenceProxyByName(co.Definition.Occurrences, subOccName, PartialName, FindAtSameLevel)
                         If sco IsNot Nothing Then
                             co.CreateGeometryProxy(sco, cop)
                             If FindAtSameLevel = False Then status.Stop()
                         End If
                     End If
                 End If
             End Sub)
        Return cop
    End Function

    ''' <summary>
    ''' Finds sub occurrence based on partial name. This routine is multi-threaded with bailout.  
    ''' If the component occurrence is found in an assembly, it grabs it and bails out of that assembly.  
    ''' If it is found as a sub component in 3 assemblies, it will add then bail out of each one.  
    ''' It is not the intention of the program to find more than one component at the same level.
    ''' </summary>
    ''' <param name="cdOccurrences"></param>
    ''' <param name="subOccName"></param>
    ''' <param name="PartialName">Find value as part of a name</param>
    ''' <param name="FindAtSameLevel">look for multiple items in the same assembly without bailing out</param>
    ''' <returns></returns>
    Public Function GetSubOccurrenceProxiesByName(ByVal cdOccurrences As ComponentOccurrences, ByVal subOccName As String, Optional PartialName As Boolean = False, Optional FindAtSameLevel As Boolean = False) As List(Of ComponentOccurrence)
        Dim cops As New List(Of ComponentOccurrence)
        Dim cop As ComponentOccurrenceProxy = Nothing
        System.Threading.Tasks.Parallel.For(1, cdOccurrences.Count + 1,
             Sub(index, status)
                 Dim co As ComponentOccurrence = cdOccurrences(index)
                 'Debug.Print(co.Name)
                 If co.Suppressed = False Then
                     If PartialName = True Then
                         If co.Name.Contains(subOccName) Then
                             SyncLock cops
                                 cops.Add(co)
                             End SyncLock
                             If FindAtSameLevel = False Then status.Stop() 'this line stops the entire for loop
                             Return 'this line stops the rest of this sub from running, and code continues to run other index items
                         End If
                     Else
                         If co.Name = subOccName Then
                             SyncLock cops
                                 cops.Add(co)
                             End SyncLock
                             If FindAtSameLevel = False Then status.Stop()
                             Return
                         End If
                     End If
                     If co.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
                         If TypeOf co.Definition Is AssemblyComponentDefinition OrElse TypeOf co.Definition Is WeldmentComponentDefinition Then
                             Dim scos As List(Of ComponentOccurrence) = GetSubOccurrenceProxiesByName(co.Definition.Occurrences, subOccName, PartialName, FindAtSameLevel)
                             If scos.Count > 0 Then
                                 For Each sco As ComponentOccurrence In scos
                                     co.CreateGeometryProxy(sco, cop)
                                     SyncLock cops
                                         cops.Add(cop)
                                     End SyncLock
                                 Next
                                 If FindAtSameLevel = False Then status.Stop()
                             End If
                         End If
                     End If
                 End If
             End Sub)
        Return cops
    End Function
Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
Message 6 of 9

WCrihfield
Mentor
Mentor

OK. How about this version.

Sub Main
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oRefAsm As AssemblyDocument
Dim oRefAsmDef As AssemblyComponentDefinition
For Each oRefAsm In oADoc.AllReferencedDocuments
	oRefAsmDef = oRefAsm.ComponentDefinition
	If oRefAsmDef.Occurrences.Count = 1 Then
		Promote(oADoc,oRefAsm)
	End If
Next
End Sub

Public Sub Promote(ByRef oADoc As AssemblyDocument, ByRef oRefAsm As AssemblyDocument)
	Dim oRefDef As AssemblyComponentDefinition = oRefAsm.ComponentDefinition
	Dim oOcc1 As ComponentOccurrence = oRefDef.Occurrences.Item(1)
	Dim oPane As BrowserPane = oADoc.BrowserPanes.Item("Model")
	Dim oMainNode As BrowserNode = oPane.GetBrowserNodeFromObject(oRefAsm)
	Dim oSubNode As BrowserNode = oPane.GetBrowserNodeFromObject(oOcc1)
	oPane.Reorder(oMainNode, True, oSubNode)
	oRefAsm.Delete
End Sub

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 7 of 9

NachoShaw
Advisor
Advisor

Hey

 

I did manage to make some progress but like everything, you only get to 90% 😂

 Sub Test()
Dim oRefDocs As DocumentsEnumerator = CurrDoc.AllReferencedDocuments
 For Each oRefDoc As Inventor.Document In oRefDocs
     Select Case oRefDoc.DocumentType
            Case DocumentTypeEnum.kAssemblyDocumentObject
                 PromoteToTopLevel(CurrDoc, oRefDoc)
     End Select
Next
End Sub

    Public Sub PromoteToTopLevel(ByRef oADoc As AssemblyDocument, ByRef oRefDoc As AssemblyDocument)

        Dim oRefDef As AssemblyComponentDefinition = oRefDoc.ComponentDefinition
        Dim oOcc1 As ComponentOccurrence = oRefDef.Occurrences.Item(1)

        Dim oPane As BrowserPane = oADoc.BrowserPanes.Item("Model")
        Dim oMainNode As BrowserNode = oPane.GetBrowserNodeFromObject(oRefDef)
        Dim oSubNode As BrowserNode = oPane.GetBrowserNodeFromObject(oOcc1)
        Call oPane.Reorder(oMainNode, True, oSubNode)

        'i need to delete here
    End Sub

So i can promote all of the sub occurrences from the assembly but what i cant do is delete the assembly that the sub occurrences were promoted from. Seems i only have the delete function with an occurrence and i cant seem to convert the assembly to an occurrence itself, i can only access its sub occurrences....

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.


0 Likes
Message 8 of 9

NachoShaw
Advisor
Advisor

i managed to do it this way, probably not the most efficient but it work ok 🙂

 

Public Sub PromoteToTopLevel(ByRef oADoc As AssemblyDocument, ByRef oRefDoc As AssemblyDocument)

        Dim oRefDef As AssemblyComponentDefinition = oRefDoc.ComponentDefinition
        Dim oOcc1 As ComponentOccurrence = oRefDef.Occurrences.Item(1)

        Dim oPane As BrowserPane = oADoc.BrowserPanes.Item("Model")
        Dim oMainNode As BrowserNode = oPane.GetBrowserNodeFromObject(oRefDef)
        Dim oSubNode As BrowserNode = oPane.GetBrowserNodeFromObject(oOcc1)
        Call oPane.Reorder(oMainNode, True, oSubNode)

        Dim oAsmDef As AssemblyComponentDefinition = oADoc.ComponentDefinition
        For Each oOcc As ComponentOccurrence In oAsmDef.Occurrences
            If oOcc.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
                Dim AssyName As String = Replace(oRefDoc.DisplayName, ".iam", "")
                Dim oAssyOcc As ComponentOccurrence = oOcc
                If oOcc.Name.Contains(AssyName) Then
                    oOcc.Delete()
                    Exit For
                End If

            End If
        Next
    End Sub

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.


0 Likes
Message 9 of 9

NachoShaw
Advisor
Advisor

Weirdly enough, i found a solution in some of my own code i had posted on here a couple of years ago...

Public Sub LoopAllComponents(ByVal CurrDoc As AssemblyDocument)
Dim oRefDocs As DocumentsEnumerator = CurrDoc.AllReferencedDocuments
For Each oRefDoc As Inventor.Document In oRefDocs
  Select Case oRefDoc.DocumentType
         Case DocumentTypeEnum.kAssemblyDocumentObject
              Dim oAsmDef As AssemblyComponentDefinition = CurrDoc.ComponentDefinition
              Dim oName As String = oRefDoc.FullFileName
              Dim oDoc As Document = _invApp.Documents.ItemByName(oName)
              Dim oOccs As ComponentOccurrencesEnumerator = _           
                       oAsmDef.Occurrences.AllReferencedOccurrences(oDoc)
              Dim getCount As DocumentsEnumerator = oRefDoc.AllReferencedDocuments

              If getCount.Count > 0 Then
                 PromoteToTopLevel(CurrDoc, oRefDoc, oOccs.Item(1))
              End If
   End Select
End Sub

Public Sub PromoteToTopLevel(ByRef oADoc As AssemblyDocument, ByRef oRefDoc As AssemblyDocument, ByVal CurrOcc As ComponentOccurrence)

        Dim oRefDef As AssemblyComponentDefinition = oRefDoc.ComponentDefinition
        Dim oOcc1 As ComponentOccurrence = oRefDef.Occurrences.Item(1)

        Dim oPane As BrowserPane = oADoc.BrowserPanes.Item("Model")
        Dim oMainNode As BrowserNode = oPane.GetBrowserNodeFromObject(CurrOcc)
        Dim oSubNode As BrowserNode = oPane.GetBrowserNodeFromObject(oOcc1)
        Call oPane.Reorder(oMainNode, True, oSubNode)

        CurrOcc.Delete()
    End Sub

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.