VBA - Find Occurrence in Assembly Given Part Name as a String

VBA - Find Occurrence in Assembly Given Part Name as a String

eric.frissell26WKQ
Advocate Advocate
723 Views
6 Replies
Message 1 of 7

VBA - Find Occurrence in Assembly Given Part Name as a String

eric.frissell26WKQ
Advocate
Advocate

Hi guys, I'm writing a script and currently stuck trying to figure out how to access an occurrence from within a top level assembly given that I have the part name as a string.  The occurrence could be a part within the top level assembly, a sub-assembly, or a part within a sub-assembly.  Currently the way I'm accessing a part looks like;

 

Public Sub FindMyPart()

//Bunch of erroneous stuff

    Dim oAsmDoc As AssemblyDocument
    Set oAsmDoc = ThisApplication.ActiveDocument
    Dim oAsmDef As AssemblyComponentDefinition
    Set oAsmDef = oAsmDoc.ComponentDefinition
    Dim oGetDocName As ComponentOccurrence
    Dim oOccs As ComponentOccurrencesEnumerator
    Dim SearchName As String 'SearchName is a variable pulled from elsewhere but we'll define it below
    
    'Begin a loop
    SearchName = "SomeRandomPartNumberPulledFromElsewhere"

    Dim oDoc as Document
    Set oDoc = ThisApplication.Documents.ItemByName(SearchName)

   'NOTE: this is where I get lost, any calls to activate, open, or really do anything end up resulting in compile errors
    'Do some stuff to the part
    ' iterate over more part numbers
End Sub 

 

I've seen a few suggestions that people have used to turn visibility on or off but because visibility is controlled at the assembly level the part is never accessed.  Any suggestions?

0 Likes
Accepted solutions (1)
724 Views
6 Replies
  • VBA
Replies (6)
Message 2 of 7

JhoelForshav
Mentor
Mentor

Hi @eric.frissell26WKQ 

Try this 🙂 It'll find the first occurrence with the specified part number and select it in the assembly.

 

Sub FindOccurrence()
Dim oAsmDoc As AssemblyDocument
    Set oAsmDoc = ThisApplication.ActiveDocument
    Dim oAsmDef As AssemblyComponentDefinition
    Set oAsmDef = oAsmDoc.ComponentDefinition
    Dim oOccs As ComponentOccurrencesEnumerator
    Dim SearchName As String 'SearchName is a variable pulled from elsewhere but we'll define it below
    Dim oFoundOcc As ComponentOccurrence
    SearchName = "SomeRandomPartNumberPulledFromElsewhere"
    Dim refDoc As Document
    For Each refDoc In oAsmDoc.AllReferencedDocuments
        If refDoc.PropertySets("Design Tracking Properties")("Part Number").Value = SearchName Then
           Set oOccs = oAsmDef.Occurrences.AllReferencedOccurrences(refDoc)
            Exit For
        End If
   Next
If oOccs Is Nothing = False Then
    Set oFoundOcc = oOccs(1)
Else
MsgBox "No occs found"
Exit Sub
End If
Call oAsmDoc.SelectSet.Select(oFoundOcc)
End Sub

oOccs becomes a collection of all the occurrences of that part. In this case I select the first one but if there are more you could do something with each of them or whatever you want 🙂

 

Message 3 of 7

A.Acheson
Mentor
Mentor

Here is a link to working with parts in assemblies. I assume you want to work with the occurrence in some way? 

https://modthemachine.typepad.com/my_weblog/2009/03/accessing-assembly-components.html


Below is the looping through occurrences recursion loop. The debug.print will give an idea of what the rule is doing. At the moment this set up to find the occurrences name. Place in the parameter you want to find there and the operation. 

Public Sub TraverseAssemblySample() 
    ' Get the active assembly.
    Dim oAsmDoc As AssemblyDocument
    Set oAsmDoc = ThisApplication.ActiveDocument
    Debug.Print oAsmDoc.DisplayName

    ' Call the function that does the recursion.
    Call TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences, 1)
End Sub

Private Sub TraverseAssembly(Occurrences As ComponentOccurrences, _
                             Level As Integer)
    ' Iterate through all of the occurrence in this collection.  This
    ' represents the occurrences at the top level of an assembly.
    Dim oOcc As ComponentOccurrence
    For Each oOcc In Occurrences ' Check to see if this is a part.
        If oDoc.DocumentType = kPartDocumentObject Then
‘get occurrence by name
If oOcc.Name = search name………….Then
’Do something
End If
End IF 
' Print the name of the current occurrence.
Debug.Print Space(Level * 3) & oOcc.Name

      ' Check to see if this occurrence represents a subassembly 
    ' and recursively call this function to traverse through it.     If oOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
    Call TraverseAssembly(oOcc.SubOccurrences, Level + 1)         End If
Next End Sub          

 

 

If this solved a problem, please click (accept) as solution.‌‌‌‌
Or if this helped you, please, click (like)‌‌
Regards
Alan
0 Likes
Message 4 of 7

eric.frissell26WKQ
Advocate
Advocate

Oh I like this.  Using the part number from the design tracking properties is a pretty good approach.  Tried to push this into the code and not getting any errors, but the behavior seems to be a little off.  Ultimately I'm trying to access the user defined properties of that occurrence

 

Just to clarify this is how it works... The refDoc portion is pretty simple -

 

Loop through all the referenced documents and return the occurrence of refDoc once the PartNumber from the tracking portion matches SearchName and exit the loop.

 

Next check the occurrences - if it's 'not' nothing then oFoundOcc is set to the first occurrence 

 

After that, the call to oAsmDoc.SelectSet.Select(oFoundOcc)...  In this portion is the 'call' just telling Inventor go to oAsmDoc and select oFoundOcc?  I've really only used Call to run a subroutine, but it seems like that's what this line is from other SelecSet examples?

 

Public Sub 

// Excel Stuff


    Dim oAsmDoc As AssemblyDocument
    Set oAsmDoc = ThisApplication.ActiveDocument
    Dim oAsmDef As AssemblyComponentDefinition
    Set oAsmDef = oAsmDoc.ComponentDefinition
    Dim oOccs As ComponentOccurrencesEnumerator
    Dim oFoundOcc As ComponentOccurrence
    Dim refDoc As Document
    Dim PropDoc As Document
    Dim oPropSet As PropertySet
    Dim invModPClass As PropertySet
    Dim prop As Property
    Dim SearchName As String
    Dim SNameCell As Integer
    Dim FinishCell As Integer
    Dim PClassCell As Integer
    Dim LTimeCell As Integer
    Dim DTypeCell As Integer
    Dim RM_QTYCell As Integer
    SNameCell = 2
    FinishCell = 15
    PClassCell = 11
    LTimeCell = 12
    DTypeCell = 13
    RM_QTYCell = 14
    
    ' Variables pre-loop
    Dim i As Integer
    Dim NumRows As Integer
    NumRows = excelApp.Range("A1", Range("A1").End(xlDown)).Rows.Count
    Debug.Print ("Number of rows: " + NumRows)
    
    ' begin loop
    For i = 1 To (NumRows - 1)
    i = i + 1
    ' In Excel get part name
    SearchName = excelApp.Cells(i, SNameCell)
    
    ' In Excel get properties
    Finish = excelApp.Cells(i, FinishCell)
    PClass = excelApp.Cells(i, PClassCell)
    LeadTime = excelApp.Cells(i, LTimeCell)
    DType = excelApp.Cells(i, DTypeCell)
    RM_QTY = excelApp.Cells(i, RM_QTYCell)
    
    ' In Inventor find part
    For Each refDoc In oAsmDoc.AllReferencedDocuments
        If refDoc.PropertySets("Design Tracking Properties")("PartNumber").Value = SearchName Then
            Set oOccs = oAsmDef.Occurrences.AllReferencedOccurrences(refDoc)
            Exit For
        End If
    Next
    If oOccs Is Nothing = False Then
        Set oFoundOcc = oOccs(1)
        Call oAsmDoc.SelectSet.Select(oFoundOcc)
    Else
    MsgBox (SearchName & " was not found")
    End If
    
    
    
    Set PropDoc = oFoundOcc.Definition.Document
    
    ' In Inventor assign property to part
    'Debug.Print (SearchName)
    'Debug.Print ("  Finish: " & Finish)
    'Debug.Print ("  PClass: " & PClass)
    'Debug.Print ("  LeadTime: " & LeadTime)
    'Debug.Print ("  DType: " & DType)
    
    Set oPropSet = PropDoc.PropertySets.Item("Inventor User Defined Properties")
    On Error Resume Next
    Set prop = oPropSet.Item("M1_PClass")
    prop.Value = PClass
    If Err Then
        Set invModPClass = oPropSet.Add(PClass, "M1_PClass")
        Call oPropSet.Add(PClass, "M1_PClass")
    End If
    
    ' repeat
    Next
    
End Sub

 

At the moment it's printing every value from my excel window into the window so I know it's getting the values from Excel.  The values (i.e. PClass, M1_Pclass) are not being updated in the parts themselves.  Sorry if I didn't give you enough information about this ahead of time, it seemed like it was going to be a little easier.  Find occurrence -> get occurrence definition as document -> access property sets -> add values but it's misbehaving

0 Likes
Message 5 of 7

eric.frissell26WKQ
Advocate
Advocate

Thanks @A.Acheson, I use this to traverse assemblies in some of my other scripts but didn't want to write it for this because I thought there might be an easier way to simply "search" the referenced components, and then activate/open that component, do some stuff, close the component, and loop through for all the components.

0 Likes
Message 6 of 7

JhoelForshav
Mentor
Mentor
Accepted solution

@eric.frissell26WKQ 

I don't really see the point in getting the occurrence from the document if you're only using that occurrence to get the document again. If you want to find the document and change some custom property I'd suggest something like this:

 

 

Sub EditCustomProps()
Dim oAsmDoc As AssemblyDocument
    Set oAsmDoc = ThisApplication.ActiveDocument
    Dim oAsmDef As AssemblyComponentDefinition
    Set oAsmDef = oAsmDoc.ComponentDefinition
    Dim SearchName As String 'SearchName is a variable pulled from elsewhere but we'll define it below
    SearchName = "SomeRandomPartNumberPulledFromElsewhere"
    Dim refDoc As Document
    Dim DocFound As Boolean
    DocFound = False
    For Each refDoc In oAsmDoc.AllReferencedDocuments
        If refDoc.PropertySets("Design Tracking Properties")("Part Number").Value = SearchName And oAsmDef.Occurrences.AllReferencedOccurrences(refDoc).Count > 0 Then
            DocFound = True
            Exit For
        End If
   Next
If DocFound Then
    Dim oCustomProps As PropertySet
    Set oCustomProps = refDoc.PropertySets("Inventor User Defined Properties")
    On Error Resume Next
    'To create the property if it doesn't exist, otherwise it'll fail
    Call oCustomProps.Add("SomeValue", "SomeName")
    'If property already exists, code will skip to this line
    oCustomProps("SomeName").Value = "SomeValue"
Else
    MsgBox "No occs found in assembly"
    Exit Sub
End If
End Sub

 

 

And yes, the line:

Call oAsmDoc.SelectSet.Select(oFoundOcc)

was just to select the occurrence in the assembly so you'd see that it was found 😉

 

0 Likes
Message 7 of 7

eric.frissell26WKQ
Advocate
Advocate

Thanks @JhoelForshav !  This was really helpful!  I should have given you a little more information in the first post but I thought I had the right approach by getting the occurrence, figuring that would be enough to get to the properties, since I wasn't aware I could call the document directly.  The code you supplied seems to be working well.  Still a few bugs but probably on my end.

 

the line   oCustomProps("SomeName").Value = "SomeValue"   is intended to overwrite any value in the SomeName custom iProperty field, right?

0 Likes