Using iLogic to add up an assemblies component weights

Using iLogic to add up an assemblies component weights

ober2558
Enthusiast Enthusiast
1,281 Views
23 Replies
Message 1 of 24

Using iLogic to add up an assemblies component weights

ober2558
Enthusiast
Enthusiast

I am looking to incorporate accurate weights for a large CAD Library without having completely accurate designs/models. I have added a custom iProperty to each part variation within each iPart (located in the iTables) in order to remedy this. My code currently allows for adding up all custom weights from all iPart components and subassembly components within the active assembly. However, there are complex components that I had to turn into iAssemblies containing a large number of iParts and non-iParts in order to function as needed. Therefore I am hoping to add a custom weight column to these iAssemblies themselves to overwrite the custom weights of the subcomponents within them. However, I need a code that will detect if an iAssembly contains the custom weight column and if so use the specified custom weights without also counting the subcomponent custom weights. But if the custom weight column is not detected, to add up the custom weights of the sub-components. I have attached the code I am currently utilizing, Please provide any help you can. Thank you.

Class ThisRule
	Sub Main
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
			MsgBox("An Assembly Document must be active for this rule to work. Exiting.", vbCritical, "")
			Exit Sub
		End If
		Dim oADoc As AssemblyDocument = ThisDoc.Document
		Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
		oWeightList = New List(Of Double)
		RecursivelyProcessComponents(oOccs)
		Dim oTotaliPartsWeight As Double = oWeightList.Sum
		MsgBox("Total iParts Weight = " & oTotaliPartsWeight, vbInformation, "Total iParts Weight")
	End Sub
	
	Dim oWeightList As List(Of Double) 'shared by both routines
	
	Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			If oComp.Suppressed Then Continue For
			If TypeOf oComp.Definition Is VirtualComponentDefinition Then Continue For
			If oComp.IsiPartMember Then
				Dim oMember As iPartMember = oComp.Definition.iPartMember
				oWeightList.Add(CDbl(oMember.Row.Item("Weight [Custom]").Value))
			End If
			If oComp.SubOccurrences.Count > 0 Then
				RecursivelyProcessComponents(oComp.SubOccurrences)
			End If
		Next
	End Sub
End Class

 

0 Likes
1,282 Views
23 Replies
Replies (23)
Message 2 of 24

A.Acheson
Mentor
Mentor

You can just detect an occurrence is an iassembly member then look for the iproperty of the member and add the value. Is there any specific area you need help on? Looping through the factory isn't required for the iassembly member and I think this post here shows how to work the iassembly table.

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

A.Acheson
Mentor
Mentor

Getting the iproperty from the occurrence identified as an iassembly member.

If oOcc.IsiAssemblyMember Then
	Dim iAsmDoc As Document = oOcc.Definition.Document
    Dim CustomWeight as Double = iAsmDoc.PropertySets.Item(4).Item("Weight [Custom]").Value
End If 

 

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 24

ober2558
Enthusiast
Enthusiast

How/where would I input the code from the link code into my current code? and in a way that will override the custom weight values of the subcomponents if and only if the iassembly contains the custom weight column?

0 Likes
Message 5 of 24

A.Acheson
Mentor
Mentor

You can place it in the recursive sub routine before the ipart member detection. If you detect the iproperty is nothing then proceed to process ipart else if has a value then skip ipart processing. You are only reading the value and not setting the value.  

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

ober2558
Enthusiast
Enthusiast

After much trial and error, I am still confused and the code has "unspecified errors". I am not the strongest coder so if you could provide more thorough step-by-step instructions with code, it would be much appreciated. Thank you!

0 Likes
Message 7 of 24

A.Acheson
Mentor
Mentor

This seems to work for me. One fault I was having was not having the member updated. So there is a try catch in there that you can check if the iProperty exist or not. Ensure to test it on you samples. 

Class ThisRule
	Sub Main
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
			MsgBox("An Assembly Document must be active for this rule to work. Exiting.", vbCritical, "")
			Exit Sub
		End If
		Dim oADoc As AssemblyDocument = ThisDoc.Document
		Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
		oWeightList = New List(Of Double)
		RecursivelyProcessComponents(oOccs)
		Dim oTotaliPartsWeight As Double = oWeightList.Sum
		MsgBox("Total iParts Weight = " & oTotaliPartsWeight, vbInformation, "Total iParts Weight")
	End Sub
	
	Dim oWeightList As List(Of Double) 'shared by both routines
	
	Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			If oComp.Suppressed Then Continue For
			If TypeOf oComp.Definition Is VirtualComponentDefinition Then Continue For
				If oComp.IsiAssemblyMember Then
					Logger.Info("Is a iAssembly member: " & oComp.Name )
					Dim iAsmDoc As Document = oComp.Definition.Document
    				Try
						Dim CustomWeight As Double = iAsmDoc.PropertySets.Item(4).Item("Weight [Custom]").Value
						Logger.Info("CustomWeight: " & CustomWeight )
						oWeightList.Add(CustomWeight)
					Catch 
					End Try		
				ElseIf oComp.IsiPartMember Then
					Logger.Info("Is a iPart member: " & oComp.Name )
					Dim oMember As iPartMember = oComp.Definition.iPartMember
					oWeightList.Add(CDbl(oMember.Row.Item("Weight [Custom]").Value))
				End If
			If oComp.SubOccurrences.Count > 0 Then
				RecursivelyProcessComponents(oComp.SubOccurrences)
			End If
		Next
	End Sub
End Class

 

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

ober2558
Enthusiast
Enthusiast

After trying this new code, I am still having issues. It does not seem to overwrite the subcomponents of the iAssembly, nor does it count the iAssemblies custom weight column. The logic of the code makes sense to me but it is still not working as expected. Any guidance or help on this issue?

0 Likes
Message 9 of 24

A.Acheson
Mentor
Mentor

I wasn't able to test the original rule you had with ipart member inside an iassembly so likely it is still entering the sub occurrences of the iassembly because it hasn't been told otherwise. In the catch portion of the iassemblymember detection insert the recursive call. Remove it from outside the iassembly/ipart member if statement. When located there it is telling the loop to enter the sub occurrences. You may need to add a filter for regular assemblies depending in how your structure is set up. 

 

I would suggest setting up logger statements for each occurrence by name  so you can see which occurrences are being targeted. If necessary turn of the recursive loop call and just focus on the main occurrence for now then sub occurrences etc. 

 

Also ensure this workflow is possible with the manual workflow as ipart/iassembly are read only so you will be doing just that reading and not writing.

 

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

ober2558
Enthusiast
Enthusiast

I've attempted your suggestion but I am still having issues. As I have mentioned, I am not exactly a seasoned coder and am very new to iLogic. If you could provide a more in-depth explanation along with the suggested code it would be much appreciated. Thank you!

0 Likes
Message 11 of 24

A.Acheson
Mentor
Mentor

Here is the image of the changes. Sorry for long description but I was just using a phone and the formatting of the code went all overt he place and I said the description was easier to follow. This may or not work but a lot of this is trial and error and unfortunately without a sample data set set up it can be difficult to test the out come. 

 

Try also including a logger line so you can see what is happening. 

Logger.info("OccurrenceName: " & oComp.Name)

 

AAcheson_0-1674231547442.png

 

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

ober2558
Enthusiast
Enthusiast

Thank you again for your continued help. The code still is not counting the iAssembly custom weights but rather the subcomponent iParts custom weights within the iAssembly. I have attached a code below that I tinkered with a bit. That code counts the assemblies' iPart custom weights the iAssembly custom weights but also the iAssemblies subcomponent iPart custom weights. Is there a way I can alter that code to subtract the subcomponent iPart weights from the total? Or another suggestion for the most recent iteration of the code posted on this forum? Any help pr suggestions are greatly appreciated.

Class ThisRule
	Sub Main
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
			MsgBox("An Assembly Document must be active for this rule to work. Exiting.", vbCritical, "")
			Exit Sub
		End If
		Dim oADoc As AssemblyDocument = ThisDoc.Document
		Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
		oWeightList = New List(Of Double)
		RecursivelyProcessComponents(oOccs)
		Dim oTotaliPartsWeight As Double = oWeightList.Sum
		MsgBox("Total iParts Weight = " & oTotaliPartsWeight, vbInformation, "Total iParts Weight")
	End Sub
	
	Dim oWeightList As List(Of Double) 'shared by both routines
	
	Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			If oComp.Suppressed Then Continue For
			If TypeOf oComp.Definition Is VirtualComponentDefinition Then Continue For
			If oComp.IsiAssemblyMember Then
				Dim oMember As iAssemblyMember = oComp.Definition.iAssemblyMember
				oWeightList.Add(CDbl(oMember.Row.Item("Weight [Custom]").Value))
			Else If oComp.IsiPartMember Then
				Dim oMember As iPartMember = oComp.Definition.iPartMember
				oWeightList.Add(CDbl(oMember.Row.Item("Weight [Custom]").Value))
			End If
			If oComp.SubOccurrences.Count > 0 Then
				RecursivelyProcessComponents(oComp.SubOccurrences)
			End If
		Next
	End Sub
0 Likes
Message 13 of 24

A.Acheson
Mentor
Mentor

Making the changes as noted above in the previous post this rule works to check the iAssembly for iProperty and if not found then goes through the sub occurrences to find the iPart iProperty. If you need additional functionality please advise. I am not sure if this is your end result but this is the functionality at the moment.

 

iAssembly not found.

AAcheson_0-1674238217828.png

Class ThisRule
	Sub Main
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
			MsgBox("An Assembly Document must be active for this rule to work. Exiting.", vbCritical, "")
			Exit Sub
		End If
		Dim oADoc As AssemblyDocument = ThisDoc.Document
		Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
		oWeightList = New List(Of Double)
		RecursivelyProcessComponents(oOccs)
		Dim oTotaliPartsWeight As Double = oWeightList.Sum
		MsgBox("Total iParts Weight = " & oTotaliPartsWeight, vbInformation, "Total iParts Weight")
	End Sub
	
	Dim oWeightList As List(Of Double) 'shared by both routines
	
	Sub RecursivelyProcessComponents(oComps As ComponentOccurrences)
		If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
		For Each oComp As ComponentOccurrence In oComps
			If oComp.Suppressed Then Continue For
			If TypeOf oComp.Definition Is VirtualComponentDefinition Then Continue For
				If oComp.IsiAssemblyMember Then
					Logger.Info("Is a iAssembly member: " & oComp.Name )
					Dim iAsmDoc As Document = oComp.Definition.Document
    				Try
						Dim CustomWeight As Double = iAsmDoc.PropertySets.Item(4).Item("Weight [Custom]").Value
						Logger.Info("CustomWeight: " & CustomWeight )
						oWeightList.Add(CustomWeight)
					Catch 
							If oComp.SubOccurrences.Count > 0 Then
								RecursivelyProcessComponents(oComp.SubOccurrences)
							End If
					End Try		
				ElseIf oComp.IsiPartMember Then
					Logger.Info("Is a iPart member: " & oComp.Name )
					Dim oMember As iPartMember = oComp.Definition.iPartMember
					oWeightList.Add(CDbl(oMember.Row.Item("Weight [Custom]").Value))
				End If
		
		Next
	End Sub
End Class

 

 

 

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

ober2558
Enthusiast
Enthusiast

As I briefly went over in my original post, my ultimate goal is to find the total weight of an assembly without using the default mass properties of Inventor, but rather through the utilization of a custom weight column in the iTables. My current CAD library of components is a mix of iParts and iAssemblies, with some of the iAssemblies containing iPart subcomponents. I would like my code to add up the weights of all iParts and iAssemblies within the active assembly. However, because some of the iAssemblies have iParts that contain the custom weight column in their iTables, I need the code to override the subcomponent's custom weight values (rather than counting them) and only take the custom weight value of the active iAssembly member as a whole. So ultimately I would like the code to add up the custom weights of the iAssemblies (not its subcomponents) and iParts present in the active assembly and deliver a total weight. I hope this clears up any confusion. Thank you again.

0 Likes
Message 15 of 24

A.Acheson
Mentor
Mentor

Hi @ober2558  thanks for going over the end goal again it makes it a little clearer. I've gone through a similar task and abandoned  it because there are challenges to this workflow. 

In this line of your explanation here 

"However, because some of the iAssemblies have iParts that contain the custom weight column in their iTables, I need the code to override the subcomponent's custom weight values (rather than counting them) "

I am thinking this overiding of custom weight value is not possible.

Have you tested to see if this is possible in a manual workflow? Can you explain override the subcomponent's custom weight? Overiding of any weight in an ipart/iassembly isn't possible which is why a custom iproperty is required to store the weight. Can you provided images of how this is being achieved. With these images it can then be clearer how to replicate the manual workflow in code. What can be done is to stick the iassembly into another assembly and overide the assemblies mass with counted custom iproperty values. 

 

 

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

ober2558
Enthusiast
Enthusiast

By "overriding" I simply mean to ignore the iAssemblies subcomponent's custom weights in favor of the custom weights listed in the iAssembly member table.

 

For example: I have an assembly composed of 2 iParts and 1 iAssembly both of which contain a custom weight column in their iTables. The iAssembly is composed of 3 iParts and 1 non-iPart. Each of these 3 iParts have multiple members in their iTables with an associated custom weight column. the non-iPart does not have a "custom weight". 

 

I would like my code to calculate the total weight of an assembly using the custom weights located in the iTables. So in full, the custom weight of both iParts added to the custom weight listed in the iAssembly iTable. I do not want the custom weights of the 3 iParts located within the iAssembly to be included in the overall weight. 

 

Let me know if I can help explain any further. Thank you.

0 Likes
Message 17 of 24

A.Acheson
Mentor
Mentor

The code posted in post 13 is doing what your requesting. Can you test and show the logger results and values returned. Either your data set is different than mine or there is something not working correctly. 

 

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

ober2558
Enthusiast
Enthusiast

In my current assembly, I have an iAssembly and 2 iParts, the code is not counting the iAssembly weight but rather the iAssemblies subcomponent weights. I have attached the logger info below. the last 2 iParts listed in the logger are subcomponents of the iAssembly.

 

Logger.jpg

0 Likes
Message 19 of 24

A.Acheson
Mentor
Mentor

From memory the rule as set up will only skip to sub occurrences when the iprop is not present in the table. Does the custom mass iprop exist in the I assembly but value is zero? If so you need to input that condition to control the recursion of sub occurrences. 

 

 

You can of course approach this in a different way and simply have a different for loop of occurrences, add relevant iAssembly members to a list then work through this list and count the custom mass iprops.  More code but maybe easier to understand. 

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

ober2558
Enthusiast
Enthusiast

The iAssembly has a column with non-zero values for custom weight in the iTable, so I am not really sure where the issue is. 

0 Likes