Traverse Assembly and create total cost while filtering some properties

Traverse Assembly and create total cost while filtering some properties

tracey
Enthusiast Enthusiast
1,375 Views
18 Replies
Message 1 of 19

Traverse Assembly and create total cost while filtering some properties

tracey
Enthusiast
Enthusiast

I found this code by E_Jeph and altered it to traverse through an assembly, ignore parts that are reference, phantom or material 'copper' and add up the cost of all to create a total.  It only does this for the top assembly despite the recursive to traverse through all sub assemblies.  I have tackled this every which way.  I have a leaf occurrence rule that I could adapt but I need to get values from some assemblies as well as parts, so it needs to look at all.  Can anyone see why this won't look at sub assemblies and parts? The blue text may need altering.  Really stuck here so any help would be appreciated.  Thank you.

 

Sub Main TraverseAssemblySample()
    ' Get the active assembly.
    Dim oAsmDoc As AssemblyDocument
    oAsmDoc = ThisApplication.ActiveDocument

    Dim oCost As Decimal
    oCost = 0

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

    MsgBox(oCost)
End Sub

Private Sub TraverseAssembly(ByVal Occurrences As ComponentOccurrences, _
ByVal Level As Integer, _
ByRef oCost As Double)
    ' Iterate through all of the occurrence in this collection.  This
    ' represents the occurrences at the top level of an assembly.
    For Each oOcc As ComponentOccurrence In Occurrences

' Skip Phantom and reference parts.
If oOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure _
Or oOcc.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Then

                        ' Do Nothing

                Else
        ' The occurrence is valid count the cost.
        ' Get the document file for this occurrence
        Dim oDoc As Document
        oDoc = oOcc.Definition.Document

        ' Get the iPropertySet that constains the estimated cost property
        Dim oPropSet As PropertySet
        oPropSet = oDoc.PropertySets.Item("Design Tracking Properties")

        ' Get the cost of this occurrence
        oCost += oPropSet.Item("Cost").Value

         End If

        ' 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, oCount)
        End If
    Next
End Sub

0 Likes
Accepted solutions (3)
1,376 Views
18 Replies
Replies (18)
Message 2 of 19

JhoelForshav
Mentor
Mentor
Accepted solution

Made some changes to the code

 

Sub Main TraverseAssemblySample()
    ' Get the active assembly.
    Dim oAsmDoc As AssemblyDocument
    oAsmDoc = ThisApplication.ActiveDocument

    Dim oCost As Decimal

    ' Call the function that does the recursion.
    oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)

    MsgBox(oCost)
End Sub

Private Function TraverseAssembly(ByVal Occurrences As ComponentOccurrences) As Decimal
    ' Iterate through all of the occurrence in this collection.  This
    ' represents the occurrences at the top level of an assembly.
	Dim oCost As Decimal = 0
    For Each oOcc As ComponentOccurrence In Occurrences

' Skip Phantom and reference parts.
If oOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure _ 
Or oOcc.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Then

                  

                Else
        ' The occurrence is valid count the cost.
        ' Get the document file for this occurrence
        Dim oDoc As Document
        oDoc = oOcc.Definition.Document

        ' Get the iPropertySet that constains the estimated cost property
        Dim oPropSet As PropertySet
        oPropSet = oDoc.PropertySets.Item("Design Tracking Properties")

        ' Get the cost of this occurrence
        oCost += oPropSet.Item("Cost").Value

         End If

        ' Check to see if this occurrence represents a subassembly
        ' and recursively call this function to traverse through it.
        If oOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
           oCost += TraverseAssembly(oOcc.Definition.Occurrences)
        End If
    Next
	Return oCost
End Function

 

Seems to me that the ByRef argument oCost didnt work as expected for multiple levels like that.

 

This should work 🙂

Message 3 of 19

JhoelForshav
Mentor
Mentor

I posted something here that i left some junk in the code. Saw that i could edit replys later. So ignore this...

0 Likes
Message 4 of 19

tracey
Enthusiast
Enthusiast

Thank you for being willing to help though!

Message 5 of 19

JhoelForshav
Mentor
Mentor

Maybe my posts was a little confusing. The code in my first reply should work... Just meant that i left some messageboxes etc. in there at first but it's edited now.

Please accept as solution if it works for you 🙂

0 Likes
Message 6 of 19

tracey
Enthusiast
Enthusiast

Thank you.. it works a treat!

Message 7 of 19

tracey
Enthusiast
Enthusiast

One more question.  If I suppress a file or subassy the rule throws an exception until I reverse the suppression!  Why would it find this problematic?  Do I have to add script to tell it to ignore suppressed files?

0 Likes
Message 8 of 19

JhoelForshav
Mentor
Mentor
Sub Main TraverseAssemblySample()
    ' Get the active assembly.
    Dim oAsmDoc As AssemblyDocument
    oAsmDoc = ThisApplication.ActiveDocument

    Dim oCost As Decimal

    ' Call the function that does the recursion.
    oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)

    MsgBox(oCost)
End Sub

Private Function TraverseAssembly(ByVal Occurrences As ComponentOccurrences) As Decimal
    ' Iterate through all of the occurrence in this collection.  This
    ' represents the occurrences at the top level of an assembly.
	Dim oCost As Decimal = 0
    For Each oOcc As ComponentOccurrence In Occurrences

'Skip suppressed
If oOcc.Suppressed = False Then
' Skip Phantom and reference parts.
If oOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure _ 
Or oOcc.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Then

                  

                Else
        ' The occurrence is valid count the cost.
        ' Get the document file for this occurrence
        Dim oDoc As Document
        oDoc = oOcc.Definition.Document

        ' Get the iPropertySet that constains the estimated cost property
        Dim oPropSet As PropertySet
        oPropSet = oDoc.PropertySets.Item("Design Tracking Properties")

        ' Get the cost of this occurrence
        oCost += oPropSet.Item("Cost").Value

         End If

        ' Check to see if this occurrence represents a subassembly
        ' and recursively call this function to traverse through it.
        If oOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
           oCost += TraverseAssembly(oOcc.Definition.Occurrences)
        End If
		End If
    Next

	Return oCost
End Function

Does it work for you to simply skip supressed occurrences like this? or do you want to include cost of suppressed components too?

0 Likes
Message 9 of 19

tracey
Enthusiast
Enthusiast

Hi,  I don't need to add in the cost of suppressed files.  When I suppress a file, this rule still throws an exception even with your addition Smiley Indifferent  very odd.

 

0 Likes
Message 10 of 19

JhoelForshav
Mentor
Mentor

hmm... I'll take a look at it. Check that you got the latest version of my reply though. I edited it because first i acidentally put if oOcc.Suppressed = True. It should be if oOcc.Suppressed = False obviouslySmiley Very Happy

0 Likes
Message 11 of 19

JhoelForshav
Mentor
Mentor
Accepted solution

I can't seem to replicate your problem. But if you've checked that you got the latest cody as described in previous post you could try a simple try-catch instead... If that doesnt work i think i'll need an assembly-file from you to test the code in in order to replicate the problem.

But first, try this 🙂

Sub Main TraverseAssemblySample()
	' Get the active assembly.
	Dim oAsmDoc As AssemblyDocument
	oAsmDoc = ThisApplication.ActiveDocument

	Dim oCost As Decimal

	' Call the function that does the recursion.
	oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)

	MsgBox(oCost)
End Sub

Private Function TraverseAssembly(ByVal Occurrences As ComponentOccurrences) As Decimal
	' Iterate through all of the occurrence in this collection.  This
	' represents the occurrences at the top level of an assembly.
	Dim oCost As Decimal = 0
	For Each oOcc As ComponentOccurrence In Occurrences

		Try
			' Skip Phantom and reference parts.
			If oOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure _
				Or oOcc.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Then



			Else
				' The occurrence is valid count the cost.
				' Get the document file for this occurrence
				Dim oDoc As Document
				oDoc = oOcc.Definition.Document

				' Get the iPropertySet that constains the estimated cost property
				Dim oPropSet As PropertySet
				oPropSet = oDoc.PropertySets.Item("Design Tracking Properties")

				' Get the cost of this occurrence
				oCost += oPropSet.Item("Cost").Value

			End If

			' Check to see if this occurrence represents a subassembly
			' and recursively call this function to traverse through it.
			If oOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
				oCost += TraverseAssembly(oOcc.Definition.Occurrences)
			End If
		Catch

		End Try
	Next

	Return oCost
End Function
Message 12 of 19

tracey
Enthusiast
Enthusiast

This works fine now. 🙂

Thank you

Message 13 of 19

tracey
Enthusiast
Enthusiast

Hi, I have a final question.  How to I capture the returned value.  I have tried a line after it such as:  iProperties.Value("Custom", "BOM_Price") = oCost

oCost being the Value returned by oCost.  I am trying to save the returned value somewhere so I can use it later.  Any ideas?

 

 

0 Likes
Message 14 of 19

JhoelForshav
Mentor
Mentor

Do i understand correctly that you want to store the calculated value in a custom iProperty named BOM_Price?

0 Likes
Message 15 of 19

tracey
Enthusiast
Enthusiast

Hi, yes that’s what I would like to do so I can access the value later In a drawing.

 

thank you for your help!

 

kind regards

 

Tracey

0 Likes
Message 16 of 19

JhoelForshav
Mentor
Mentor
Accepted solution

Try this as your main sub:

 

Sub Main TraverseAssemblySample()
    ' Get the active assembly.
    Dim oAsmDoc As AssemblyDocument
    oAsmDoc = ThisApplication.ActiveDocument
	
	Dim oCost As Decimal
	
	Dim oCustomProps As PropertySet = oAsmDoc.PropertySets.Item("User Defined Properties")
	Dim oProperty As Inventor.Property
	
	
	Try
	'Try to access the property BOM_Price
	oProperty = oCustomProps.Item("BOM_Price")
	Catch
	'If failure, assume property doesn't exist and create it
	oProperty = oCustomProps.Add(0,"BOM_Price")
	End Try
	
    ' Call the function that does the recursion.
    oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)
	
	'Custom properties doesn't seem to like datatype decimal, so i put in the value as a double.
	oProperty.Value = CDbl(oCost)
End Sub
Message 17 of 19

JhoelForshav
Mentor
Mentor

Or like this if you want to include a dollar sign for example:

 

Sub Main TraverseAssemblySample()
' Get the active assembly.
Dim oAsmDoc As AssemblyDocument
oAsmDoc = ThisApplication.ActiveDocument

Dim oCost As Decimal

Dim oCustomProps As PropertySet = oAsmDoc.PropertySets.Item("User Defined Properties")
Dim oProperty As Inventor.Property


Try
'Try to access the property BOM_Price
oProperty = oCustomProps.Item("BOM_Price")
Catch
'If failure, assume property doesn't exist and create it
oProperty = oCustomProps.Add("","BOM_Price")
End Try

' Call the function that does the recursion.
'oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)

oProperty.Value = oCost.ToString & " $"
End Sub

Message 18 of 19

tracey
Enthusiast
Enthusiast

Thank you for helping Smiley Happy Seems to work well.  This code creates a custom property called "BOM_Price, traverses the assembly, skips reference and phantom parts and all "Copper" parts.  Adds up the cost and puts the value in the custom iProperty so I can use it elsewhere.  Here is the final code:

 

Sub Main()

 

    ' Get the active assembly.

    Dim oAsmDoc As AssemblyDocument

    oAsmDoc = ThisApplication.ActiveDocument

    Dim oCost As Decimal

    Dim oCustomProps As PropertySet = oAsmDoc.PropertySets.Item("User Defined Properties")

    Dim oProperty As Inventor.Property

    '   

'Call the function that does the recursion.

        Try

'    'try to access the property BOM_Price

            oProperty = oCustomProps.Item("BOM_Price")

        Catch

'    'If failure, assume prop doesnt exist and create it

            oProperty = oCustomProps.Add("", "BOM_Price")

        End Try

'    'Call the function that does the recursion.

    oCost = TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)

'   

    oProperty.Value = CDbl(oCost)

MsgBox(oCost)

    End Sub

 

 

Private Function TraverseAssembly(ByVal Occurrences As ComponentOccurrences) As Decimal

    ' Iterate through all of the occurrence in this collection.  This

    ' represents the occurrences at the top level of an assembly.

    Dim TotalCost As Decimal = 0

    Dim oCost As Decimal = 0

 

    For Each oOcc As ComponentOccurrence In Occurrences

            Dim oBrowserNode As String

            oBrowserNode = oOcc.Name

            Try

                ' Skip Phantom and reference parts.

                If oOcc.BOMStructure = BOMStructureEnum.kPhantomBOMStructure Or

                oOcc.BOMStructure = BOMStructureEnum.kReferenceBOMStructure Or

                iProperties.MaterialOfComponent(oBrowserNode) = "Copper" Then

            Else

        ' The occurrence is valid count the cost.

        ' Get the document file for this occurrence

        Dim oDoc As Document

        oDoc = oOcc.Definition.Document

 

        ' Get the iPropertySet that constains the estimated cost property

        Dim oPropSet As PropertySet

        oPropSet = oDoc.PropertySets.Item("Design Tracking Properties")

 

        ' Get the cost of this occurrence

        oCost += oPropSet.Item("Cost").Value

 

         End If

 

        ' Check to see if this occurrence represents a subassembly

        ' and recursively call this function to traverse through it.

        If oOcc.DefinitionDocumentType = kAssemblyDocumentObject Then

           oCost += TraverseAssembly(oOcc.Definition.Occurrences)

        End If   

    Catch

    End Try

    Next

    'iProperties.Value(Name, "Custom", "BOM_Price") = oCost

    Return oCost

 

End Function

 

 

 

Message 19 of 19

rcoi
Contributor
Contributor

2023. This code works excelent. Thank you