Hello together,
i found this code and i changed it a bit - works ok but only for parts in an assembly. If i have a sub-assembly with parts, i dont get the sum of this one.
I Need your help to modify the code that it will sum parts and sub-assemblies.
Thanks in advance...
Regards
Martin
'- - - - - - - - - - - find or create custom iProperty - - - - - - - - - - 'Define the open document Dim openDoc As Document openDoc = ThisDoc.Document 'Look at all of the files referenced in the open document Dim docFile As Document For Each docFile In openDoc.AllReferencedDocuments 'Dim propertyName1 As String = "HK_Stand" 'define custom property collection 'oCustomPropertySet = docFile.PropertySets.Item("Inventor User Defined Properties") 'Try 'look for property 'oProp = oCustomPropertySet.Item(propertyName1) 'Catch ' Assume error means not found so create it 'oCustomPropertySet.Add(0, propertyName1) 'End Try Next '- - - - - - - - - - - sum the custom iProperty - - - - - - - - - - 'clear the custom property in the assembly iProperties.Value("Project", "estimated cost") = 0 'set a reference to the assembly component definintion. 'This assumes an assembly document is open. Dim oAsmCompDef As AssemblyComponentDefinition oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition 'Iterate through all of the occurrences Dim oOccurrence As ComponentOccurrence For Each oOccurrence In oAsmCompDef.Occurrences 'check for and skip virtual components '(in case a virtual component trips things up) 'If Not TypeOf oOccurrence.Definition Is VirtualComponentDefinition Then 'Property In the Assembly xNumber = iProperties.Value("Project", "estimated cost") 'property in the parts yNumber = iProperties.Value(oOccurrence.Name, "Project", "estimated cost") sumNumber = xNumber + yNumber 'set property values iProperties.Value("Project", "estimated cost") = Round (sumNumber,2) HK_Stand = sumNumber 'Else 'End If Next
Solved! Go to Solution.
Solved by wayne.brill. Go to Solution.
I think this code which I recently wrote would serve 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, oCost) End If Next End Sub
Here is the link to the original topic
https://forums.autodesk.com/t5/inventor-customization/calculate-total-assembly-cost/td-p/6412356
The 'ComponentOccurrences' will only contain the direct children of the Assembly, not the childrens' children.
In order to traverse the whole assembly using the approach you have, you will have to traverse it recursively.
There is a sample in the API Help "Traverse an Assembly" that lays out quite well how to traverse sub assemblies recursively.
HOWEVER, instead of getting the documents component occurrences, you could get ALL referenced files. You even have this code already in your snippet, only it has been commented out.
For Each docFile In openDoc.AllReferencedDocuments
Using AllReferencedDocuments (ARD) instead of ComponentOccurrences will automatically include all of the files recursively. At which point you will have a hold of each document which makes up your assembly.
Since I'm not sure what you are doing with the components once you have them, I can't say for sure which solution you will need to implement.
It might be helpful for you to explain exactly what the goal of your program is, so that we can advise on how to accomplish that, and not just how to access files recursively.
HOWEVER, instead of getting the documents component occurrences, you could get ALL referenced files. You even have this code already in your snippet, only it has been commented out.
For Each docFile In openDoc.AllReferencedDocuments
Using AllReferencedDocuments (ARD) instead of ComponentOccurrences will automatically include all of the files recursively. At which point you will have a hold of each document which makes up your assembly.
Does AllReferencedDocuments consider parts that are placed multiple times? ea bolt is placed 20x but is only 1 document?
Jef_E,
You're correct, the documents would not duplicate. Given that they are doing something which appears to be assessing the cost of the parts, I'd assume that won't work for them, but since there was really no explanation of what they are doing, I can't really say.
Thanks both for answering and thanks for your help.
What we like to do is the following. We need to fill automaticly (run the code) the estimated cost of the ZB_test_01 that includes 4 times test_01 and one time ZB_test_02. But at the time i run the code there is no cost calculated for ZB_test_02! Only the parts include the estimated cost!
BTW ... if i run your code with ilogic i get a mistake message. What did i wrong?
Thanks in advance
Regards
Martin
Hi Martin,
I could research this. Please upload an assembly I could use to recreate the problem. If you want to keep it private let me know.
Thanks,
Wayne
Hi Wayne,
thank you very much for your support. You will find 2 assemblies and 3 parts and 1 Picture. Our Problem is very easy, we have a code that modifies the main assemblie (real good), this code tooks costs from an Excel sheet into the parts.
The Problem that we have, the code that summs the estimated cost, works only in the main assemblie, not in the subs!
So if the main assembly AAA is open and someone changes the estimated cost, for example test_03 from 1€ to 11€, the estimated cost of the AAA is still 301€ instead of 311€.
Maybe there is a way, that the code runs to all assemblies and sums the estimated cost of each.
Thanks again for your help Wayne.
Regards Martin
'- - - - - - - - - - - find or create custom iProperty - - - - - - - - - - 'Define the open document Dim openDoc As Document openDoc = ThisDoc.Document 'Look at all of the files referenced in the open document Dim docFile As Document For Each docFile In openDoc.AllReferencedDocuments 'Dim propertyName1 As String = "HK_Stand" 'define custom property collection 'oCustomPropertySet = docFile.PropertySets.Item("Inventor User Defined Properties") 'Try 'look for property 'oProp = oCustomPropertySet.Item(propertyName1) 'Catch ' Assume error means not found so create it 'oCustomPropertySet.Add(0, propertyName1) 'End Try Next '- - - - - - - - - - - sum the custom iProperty - - - - - - - - - - 'clear the custom property in the assembly iProperties.Value("Project", "estimated cost") = 0 'set a reference to the assembly component definintion. 'This assumes an assembly document is open. Dim oAsmCompDef As AssemblyComponentDefinition oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition 'Iterate through all of the occurrences Dim oOccurrence As ComponentOccurrence For Each oOccurrence In oAsmCompDef.Occurrences 'check for and skip virtual components '(in case a virtual component trips things up) 'If Not TypeOf oOccurrence.Definition Is VirtualComponentDefinition Then 'Property In the Assembly xNumber = iProperties.Value("Project", "estimated cost") 'property in the parts yNumber = iProperties.Value(oOccurrence.Name, "Project", "estimated cost") sumNumber = xNumber + yNumber 'set property values iProperties.Value("Project", "estimated cost") = Round (sumNumber,2) HK_Stand = sumNumber 'Else 'End If Next
Hi Martin,
Here is an update to your rule that iterates through the assembly and gets the iProperty values. Comment or uncomment the MessageBox lines as needed to see what is happening when the rule runs. I believe it does what you are asking for.
Sub Main '- - - - - - - - - - - sum the custom iProperty - - - - - - - - - - 'clear the custom property in the assembly iProperties.Value("Project", "estimated cost") = 0 'set a reference to the assembly component definintion. 'This assumes an assembly document is open. Dim oAsmCompDef As AssemblyComponentDefinition oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition 'Iterate through all of the occurrences Dim oOccurrence As ComponentOccurrence For Each oOccurrence In oAsmCompDef.Occurrences Call ProcessAllChildren(oOccurrence) Next MessageBox.Show("Setting Estimated cost for top level assbly to: " & sumNumber, "Estimated cost") iProperties.Value("Project", "estimated cost") = Round (sumNumber,2) End Sub 'Global Private sumNumber As Double = 0 Public Sub ProcessAllChildren(ByRef oOccurrence As ComponentOccurrence) If Not TypeOf oOccurrence.Definition Is VirtualComponentDefinition Then 'property in the parts yNumber = iProperties.Value(oOccurrence.Name, "Project", "estimated cost") MessageBox.Show("yNumber = " & yNumber, oOccurrence.Name) sumNumber = sumNumber + yNumber MessageBox.Show("sumNumber = " & sumNumber,"Running Total") Else MessageBox.Show("This is a VirtualComponentDefinition", oOccurrence.Name) End If Dim oCompOcc As ComponentOccurrence Dim oComponentSubOccurrences As ComponentOccurrences ' For Each oCompOcc In oOccurrence.SubOccurrences ' MessageBox.Show("In SubOccurrences", oCompOcc.Name) If oCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then 'MessageBox.Show("DefinitionDocumentType = Assembly", oCompOcc.Name) oComponentSubOccurrences = oCompOcc.SubOccurrences If Not oComponentSubOccurrences Is Nothing Then 'MessageBox.Show("oComponentSubOccurrences Is Not Nothing", oCompOcc.Name) If oComponentSubOccurrences.count > 0 Then 'MessageBox.Show("oComponentSubOccurrences.count > 0", oCompOcc.Name) ProcessAllChildren(oCompOcc) End If End If Else 'MessageBox.Show("DefinitionDocumentType = Part", oCompOcc.Name) ProcessAllChildren(oCompOcc) End If Next End Sub
I am not sure why sub assembly bbb has it's own value for the iProperty. It seems like the sub assembly would just have a value of zero. (its cost would equal the cost of the parts that it has). The code could be updated so that it sets estimated cost for each Sub Assembly and then the top assembly would be set to only the components it has. (parts and Sub Assemblies)
Thanks,
Wayne
Thank you very much Wayne,
we are on the right way! There are just two problems:
1. The code did not sum the amount of the virtual part (50€)
2. You are right with the cost of BBB! There is a mistake, the total cost of BBB shouldt be the sum of all parts. That means, all sub-assemblies shouldt have their estimated cost that is the sum of all parts. All sub-assemblies must stored the sum of the parts in the custom "estimated cost" (so i can Show this in a partlist)
Is it posible to change the code for that?
In the example the sum of all parts shouldt be: 301€
Thank you very much Wayne....
Regards
Martin
Hi Martin,
Here is the approach I came up with. Instead of doing this all in one top level rule, have a rule in every Sub Assembly that gets its cost and puts it in the "Estimated Cost" for that sub assembly. Each sub assembly runs the rule in the sub assemblies it has. To try this, put this rule in every assembly and then run it from the top assembly. You should see message boxes setting the values for each assembly. You will probably want to change the name of the rule. (currently it is "Sum_Cost_WB_3). If you use a different name of course you will need to change the string in this call to the name you use.
auto.RunRule(oOccurrence.Definition.Document, "Sum_Cost_WB_3")
I believe this approach is ok even though you will need to add the rule to each assembly.
Sub Main '- - - - - - - - - - - sum the custom iProperty - - - - - - - - - - 'clear the custom property in the assembly iProperties.Value("Project", "estimated cost") = 0 'set a reference to the assembly component definintion. 'This assumes an assembly document is open. Dim oAsmCompDef As AssemblyComponentDefinition 'oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition oAsmCompDef = ThisDoc.Document.ComponentDefinition Dim oOccurrence As ComponentOccurrence 'Process the sub assemblies For Each oOccurrence In oAsmCompDef.Occurrences 'MessageBox.Show("For Each oOccurrence " , "Comp Def") If oOccurrence.DefinitionDocumentType = kAssemblyDocumentObject Then If Not TypeOf oOccurrence.Definition Is VirtualComponentDefinition Then auto = iLogicVb.Automation auto.RunRule(oOccurrence.Definition.Document, "Sum_Cost_WB_3") End If End If Next 'Iterate through all of the top level occurrences for this assembly get the sum For Each oOccurrence In oAsmCompDef.Occurrences TotalAllParts(oOccurrence) Next MessageBox.Show("Setting Estimated cost for " & ThisDoc.Document.DisplayName & " to: " & sumNumber, ThisDoc.Document.DisplayName) iProperties.Value("Project", "estimated cost") = Round (sumNumber,2) End Sub 'Global Private sumNumber As Double = 0 Sub TotalAllParts(ByRef oOccurrence As ComponentOccurrence) yNumber = iProperties.Value(oOccurrence.Name, "Project", "estimated cost") MessageBox.Show("yNumber = " & yNumber, oOccurrence.Name) sumNumber = sumNumber + yNumber End Sub
Thanks,
Wayne
Thank you very much Wayne,
thats the solution i needed. (sorry for the late reply, vacation 😉
Regards
Martin
I've been entering Estimated Cost for assembly components and Googled how to make Inventor calculate the cost of the assembly. I ran across this thread. Kind of discouraging that Inventor doesn't calculate the cost on its own. What's the point of having the cost field in the iProperties in the first place?
Anyway, how do you use the code? I tried to create a rule from it, but got an error:
RunRule: Cannot find a rule with the name: "Sum_Cost_WB_3"
Thanks,
Bill
Hi Bill,
i never go with this - there are too many possible misstakes to get the estimated cost. We go this way:
We create an Excel file of our parts (out of the erp-system) with the estimate-cost of each.
The code goes with the partlist out of the idw file and creates an excelfile.
The code ask for the processing time of the assembly and write it to an ipropertie to use it with the excelfile.
So we get an new excelfile, that shows the partlist with the cost of each part and the cost of the assembly (sum of each)
maybe this gives you an idea ...
Regards Martin
Hi Peter,
Long story short - we do not go with the estimate cost out of Inventor. We are creating an Excel file with all of our items (item no and estimate costs). Also we exports the boom list out of the idw as excel file. So we have two excel files. These both we are checking with the Excel tool VLOOKUP (sverweis) and so we are getting the esimate cost of each item of the boom calculate with the number of the item.
Hope this gives you an idea.
Regards Martin
So, This may be a more streamlined option that appears to run in an external rule and doesn't require insertion into each assembly. All that to say, I only played with this a little, but it does seem to get the job done.
Can't find what you're looking for? Ask the community or share your knowledge.