How to perform operations in the BOM of a general assembly that will change properties of the part in the assembly

How to perform operations in the BOM of a general assembly that will change properties of the part in the assembly

roy7BB24
Advocate Advocate
919 Views
9 Replies
Message 1 of 10

How to perform operations in the BOM of a general assembly that will change properties of the part in the assembly

roy7BB24
Advocate
Advocate

Hi All, 

I'm pretty new to iLogic and in the process of starting to create some rules that will simplify how I organize my parts list. 

The first rule I'm looking to create will run like this:

1. The rule is to be run from the general assembly

2. The intent is to create a custom property in all parts that matches the quantity on the BOM. 

(The intent here is if I have used the same part on multiple sub-assemblies, there will be a property that tells you the total qty of the parts in the complete assembly. I've been doing this in the past just exporting a part only level list, but I'd like to do something a little more polished, hence this)

So, the final output is I would have a custom property (say TOTAL QTY) that matches the qty on the BOM in the top level assembly. 

I'm fairly confident I've found the commands to get the BOM Qty and to then copy that to a custom property, what I'm not sure of is how to make read each line of the BOM and apply the operation to it. Likely at some point I'm going to have to work out how to make it ignore frame gen parts as well

 

Any assistance would be much appreciated

 

Kind Regards

 

Roydon Mackay

0 Likes
Accepted solutions (1)
920 Views
9 Replies
Replies (9)
Message 2 of 10

dalton98
Collaborator
Collaborator

Try something like this to get you started. However, it's generally not good practice to have assembly information represented in the parts' properties. This could cause problems if you have the same part in multiple assemblies. Inventor has accounted for this by adding 'Instance properties'. They are like temperary custom iproperties that you can add to your bom/parts lists. 

Dim oADoc As AssemblyDocument = ThisDoc.Document
Dim oBOM As BOM = oADoc.ComponentDefinition.BOM
oBOM.PartsOnlyViewEnabled = True
'oBOM.StructuredViewEnabled = True
Dim oBOMView As BOMView = oBOM.BOMViews.Item("Parts Only")

Dim oRow As BOMRow
For Each oRow In oBOMView.BOMRows

	If oRow.ComponentDefinitions.Count > 1
		MessageBox.Show("duplicate part #'s")
		Continue For
	End If

	'instance property
	'iProperties.InstanceValue(oRow.ComponentDefinitions(1).Occurrences(1).Name, "TOTAL QTYY") = oRow.ItemQuantity

	Dim oDoc As PartDocument
	oDoc = ThisApplication.Documents.Open(oRow.ComponentDefinitions(1).Document.FullFileName, False)

	'custom iproperty
	Try
		oDoc.PropertySets.Item(4).Item("TOTAL QTY").Value = oRow.ItemQuantity
	Catch
		oDoc.PropertySets.Item(4).Add(oRow.ItemQuantity, "TOTAL QTY")
	End Try

	'oDoc.Close(True)
Next

 edit use this for instance property. you only need it for one occurrence

iProperties.InstanceValue(oADoc.ComponentDefinition.Occurrences.AllLeafOccurrences(oRow.ComponentDefinitions(1)).Item(1).Name, "TOTAL QTY1") = oRow.ItemQuantity

 

0 Likes
Message 3 of 10

roy7BB24
Advocate
Advocate

Hi thanks, this works perfectly. 

For reference this intention of this property is that when I do a single part drawing (something to get profiled or machined I have a property that shows the entire qty required in the general assembly, and I'll also set this property to be part of the view label. It's a little atypical but it's intentional at least. 

My only problem here is that I don't entirely understand the code you gave me. For reference I've got around 8 years' experience in inventor, but this is my first foray into i-logic and the like. I brought a book from Autodesk and have gone through a number of tutorials but haven't been finding much past setting and controlling parameters, where my end goal is to set up some rules that will help me organize my assemblies and parts lists much better. Any idea where I'd look for information to better understand this part of iLogic

 

Kind Regards

 

Roydon Mackay

0 Likes
Message 4 of 10

A.Acheson
Mentor
Mentor

I would second Dalton's recommendation of not putting assembly specific info into a part file especially if they may be reused on another project and this qty information is not updated. Information like this should be put directly on the drawing. You could do this in a few ways depending on how your drawing package is set up.

In the Drawing:

as long as you have a reference to the main assembly on your drawing such as a partslist or a view  you will be able to extract the parts qty information from this and place it in the view label.

From the Model:

The longer indirect route is to run down through the Main assembly via the BOM or Documents, recorded the qty and open the drawing associated with the part assuming it is named the same and find the view and place it in the view label.  

 

So this code is working out of the BOM contents. Much the same as you adding in a custom iProperty here and looking across at item qty and copying the value into the custom iproperty "TOTAL QTY". 

AAcheson_0-1672601969989.png

As for help on the subject the API Manual has some help in the form of a VBA Sample which may look a little daunting also because it is in a slightly different language than Dalton's sample . If you look under Objects in the API help you can start figuring out what each line of code is doing. 

AAcheson_1-1672602321340.png

And for the propertysets referenced at the bottom of the code  here is a helpful article. PropertySets object Index of 4 or by string  "Inventor User Defined Properties" is access to the Custom tab of the iproperties dialogue box. Not the two methods you can get to the same information. Method 1 is longer but more controllable. 

AAcheson_2-1672603453484.png

API PropertySets: Method1

'custom iproperty
	Try
		oDoc.PropertySets.Item(4).Item("TOTAL QTY").Value = oRow.ItemQuantity
	Catch
		oDoc.PropertySets.Item(4).Add(oRow.ItemQuantity, "TOTAL QTY")
	End Try

ilogic iproperty: Method2

'custom iproperty
	Try
		iProperties.Value(oDoc.DisplayName,"Custom", "TOTAL QTY") = oRow.ItemQuantity
	Catch
	End Try

 

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

roy7BB24
Advocate
Advocate

Hi thanks for the help, 

The comments are noted, I think once I'm sorted, I'll go to pulling the information from the drawing as recommended

For reference my setup here is always - one General assembly per project, I have my own content center set up, but I don't have any libraries as such. All parts only exist in this project for this build, If I want to use a part or assembly for another project, I just copy the part into that project file. This is something I do very rarely. I work on my own as a contractor so right now there's no need to worry about other people. But all the same working from the drawing seems safer/smarter and P1 of the drawing is always the general assembly, so I'd likely pull my information from there. 

Right now, though I would also like to be able to tell the qty of assemblies. I've modified the code that Dalton wrote to pick up on assemblies as well as parts and changed the BOM to structured, however it's having the obvious effect of setting the quantities to what's shown in the structured view. The goal here would be that the rule will hunt through the whole assembly to give me the total qty of a part assembly required. E.g if I use an assembly on the third layer and again on the second layer, I would like it to tell me I need to make two of these assemblies. 

This is how I've modified the code. 

The intention is that

1) I have changed the Bom to be structured and not First level only

2) The first run sets the "TOTAL QTY" = 0

3) The intention of the second run is that when I go through each row it would add anything already in that property to the what's showing in the item qty at that level. i.e. I threw 5 random parts into the top-level assembly, and then 3 random parts into a sub assembly in placed this in the main assembly. When it hits the row of parts the second time it would add the new qty to the existing qty to give the total qty. This currently isn't working but I'm unsure if this is because of the structured parts list not being correct or my logic to add the values. 

Any assistance would be appreciated

 

Kind Regards

 

Roydon Mackay

Dim oAdoc As AssemblyDocument = ThisDoc.Document
Dim oBOM As BOM = oAdoc.ComponentDefinition.BOM
'oBOM.PartsOnlyViewEnabled = True
oBOM.StructuredViewEnabled = True
oBOM.StructuredViewFirstLevelOnly = False
'oBOM.StructuredViewEnabled = True
Dim oBOMView As BOMView = oBOM.BOMViews.Item("Structured")

Dim oRow As BOMRow
For Each oRow In oBOMView.BOMRows
	Dim oDoc As Document
	oDoc = ThisApplication.Documents.Open(oRow.ComponentDefinitions(1).Document.FullFileName, False)
	oDoc.PropertySets.Item(4).Item("TOTAL QTY").Value = 0
	Next
	
For Each oRow In oBOMView.BOMRows
	If oRow.ComponentDefinitions.Count > 1
		MessageBox.Show("Duplicate Part #'s") 
	End If

	Dim oDoc As Document
	oDoc = ThisApplication.Documents.Open(oRow.ComponentDefinitions(1).Document.FullFileName, False)
	'Catch
	'Dim oDoc As AssemblyDocument
	'oDoc = ThisApplication.Documents.Open(oRow.ComponentDefinitions(1).Document.FullFileName, False)
	'End Try
	'custom iProperty
	Try 
		oDoc.PropertySets.Item(4).Item("TOTAL QTY").Value = oRow.ItemQuantity + oDoc.PropertySets.Item(4).Item("TOTAL QTY").Value
	Catch
		'oDoc.PropertySets.Item(4).Add(oRow.ItemQuantity, "TOTAL QTY")
	End Try
	
	'oDoc.Close (True)
	
	Next

 

0 Likes
Message 6 of 10

A.Acheson
Mentor
Mentor
Accepted solution

So working with the structured BOM is a little trickier as you have nested parts within sub assemblies. For this you need a recursion loop to enter the sub assembly and navigate the child rows. The below seems to work for this. 

Sub Main

    'Reference to the assembly document.
    Dim Doc As AssemblyDocument = ThisApplication.ActiveDocument

    'Reference to the BOM.
    Dim BOM As BOM = Doc.ComponentDefinition.BOM

    'Make sure that the structured view is enabled.
    BOM.StructuredViewEnabled = True
    
    'Reference to the "Structured" BOMView.
    Dim BOMView As BOMView = BOM.BOMViews.Item("Structured")
    
	'Reset Total Qty iProp.
	ResetBOMRowQty(BOMView.BOMRows)
    
	'Set Total Qty iProp.
	SetBOMRowQty(BOMView.BOMRows)
	
End Sub

Private Sub SetBOMRowQty(BOMRows As BOMRowsEnumerator)
  
    'Iterate through the contents of the BOM Rows.
    For i As Integer = 1 To BOMRows.Count
        ' Get the current row.
        Dim Row As BOMRow = BOMRows.Item(i)

        'Reference to the primary ComponentDefinition of the row
        Dim CompDef As ComponentDefinition = Row.ComponentDefinitions.Item(1)
		Dim TotalQty As [Property] = CompDef.Document.PropertySets.Item(4).Item("TOTAL QTY")
		Try 
			If TotalQty.Value <= 0 Then
			   TotalQty.Value = Row.ItemQuantity
			ElseIf TotalQty.Value > 0 Then
			   TotalQty.Value = TotalQty.Value + Row.ItemQuantity
			End If
		Catch
			CompDef.Document.PropertySets.Item(4).Add(Row.ItemQuantity, "TOTAL QTY")
		End Try
		
		'Recursively iterate child rows if present.
	    If Not Row.ChildRows Is Nothing Then
	     	SetBOMRowQty(Row.ChildRows)
	    End If
	Next
	
End Sub

Private Sub ResetBOMRowQty(BOMRows As BOMRowsEnumerator)
  
    'Iterate through the contents of the BOM Rows.
    For i As Integer = 1 To BOMRows.Count
        'Get the current row.
        Dim Row As BOMRow = BOMRows.Item(i)

        'Reference to the primary ComponentDefinition of the row
        Dim CompDef As ComponentDefinition = Row.ComponentDefinitions.Item(1)
		
		Try 
			CompDef.Document.PropertySets.Item(4).Item("TOTAL QTY").Value = 0 
		Catch
		End Try
		
        'Recursively iterate child rows if present.
        If Not Row.ChildRows Is Nothing Then
         	ResetBOMRowQty(Row.ChildRows)
        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 7 of 10

roy7BB24
Advocate
Advocate

Hi All, Sorry went AWOL for a minute their but I'm back on this again. 

Hey I've run that script, Im getting an error as shown in the snip below.

The script ran successfully the first time I ran it. To test it further I added a third layer to the assembly and this error appeared. I also noticed that when I deleted the third level out, the error remained. 

I've attached the test assembly I've been using via a dropbox download 

https://www.dropbox.com/t/b65OVOxc2bgPmZw7

If anyone's got any idea about the error, it would be much appreciated.

 

Kind Regards

 

Roydon Mackay

0 Likes
Message 8 of 10

A.Acheson
Mentor
Mentor

Line 32 is declaring the iproperty. If it doesn't exist it will error. This should be brought inside the try catch like below. 

	
		Try 
	        Dim TotalQty As [Property] = CompDef.Document.PropertySets.Item(4).Item("TOTAL QTY")
			If TotalQty.Value <= 0 Then
			   TotalQty.Value = Row.ItemQuantity
			ElseIf TotalQty.Value > 0 Then
			   TotalQty.Value = TotalQty.Value + Row.ItemQuantity
			End If
		Catch
			CompDef.Document.PropertySets.Item(4).Add(Row.ItemQuantity, "TOTAL QTY")
		End Try

 

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

roy7BB24
Advocate
Advocate

Hi Guys, Thanks for all the help. I made the tweak as per Achesons recommendation and the script has started working. I noticed final issue where due to the structured BOM, on the second level of the assembly it wasn't accounting for the quantity of the parent sub-assembly, and this was going through the entire BOM. Using the skills, I've developed by copying the work you've been kind enough to do for me I've made some changes to the script to allow for this quantity and the script runs without error. Thanks, a heap to everyone who helped me with this, I was able to learn a heap from your help. 

 

Sub Main
		'Reference to the assembly document
		Dim Doc As AssemblyDocument = ThisApplication.ActiveDocument
		
		'Reference to the BOM
		Dim BOM As BOM = Doc.ComponentDefinition.BOM
		
		'Enable Structured View
		BOM.StructuredViewEnabled = True
		
		'Reference to the structured BomView
		Dim BomView As BOMView = BOM.BOMViews.Item("Structured")
		
		'Reset Total Qty Iprop
		ResetBOMRowQty(BomView.BOMRows)
		
		'Set Total Qty iProp
		SetBOMRowQty(BomView.BOMRows, 1)
		
	End Sub
	
	Private Sub SetBOMRowQty(BOMRows As BOMRowsEnumerator, amount As Integer)
		
		'iterate through the contents of the BOM Rows
		For i As Integer = 1 To BOMRows.Count
			'Get the Current Row
			Dim Row As BOMRow = BOMRows.Item(i)
			
			'Reference to the primary ComponentDefinition of the Row
			Dim CompDef As ComponentDefinition = Row.ComponentDefinitions.Item(1)
			
			Try
				Dim TotalQty As [Property] = CompDef.Document.PropertySets.Item(4).Item("TOTAL QTY")
				If TotalQty.Value <= 0 Then
					TotalQty.Value = Row.ItemQuantity * amount
				ElseIf TotalQty.Value > 0 Then
					TotalQty.Value = TotalQty.Value + Row.ItemQuantity * amount
				End If
			Catch
				Compdef.Document.PropertySets.Item(4).Add(Row.ItemQuantity, "TOTAL QTY")
			End Try
			
			'Recursively Iterate the Child Rows if Present
			If Not Row.ChildRows Is Nothing Then
			Dim j As Integer = Row.ItemQuantity * amount
				SetBOMRowQty(Row.ChildRows, j)
			End If
		Next
	End Sub
	
	Private Sub ResetBOMRowQty(BOMRows As BOMRowsEnumerator)
		'iterat throught the contents of the BOM Rows
		For i As Integer = 1 To BOMRows.Count
			'Get the Current Row
			Dim Row As BOMRow = BOMRows.Item(i)
			
			'Reference to the primary ComponentDefinition of the row
			Dim Compdef As ComponentDefinition = Row.ComponentDefinitions.Item(1)
			
			Try
				Compdef.Document.PropertySets.Item(4).Item("TOTAL QTY").Value = 0
			Catch
				Compdef.Document.PropertySets.Item(4).Add(Row.ItemQuantity, "TOTAL QTY")
			End Try
			
			'Recursively Iterate child rows if present
			If Not Row.ChildRows Is Nothing Then
				ResetBOMRowQty(Row.ChildRows)
			End If
		Next
	End Sub

 

Message 10 of 10

A.Acheson
Mentor
Mentor

Glad you got it working, nice work!!. I had omitted the sub assembly components multiplying. These kind of workflow requires extensive testing given the nested components.

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