iLogic - Looping through multiple assemblies within a larger assembly file

iLogic - Looping through multiple assemblies within a larger assembly file

ABoaro
Enthusiast Enthusiast
3,797 Views
8 Replies
Message 1 of 9

iLogic - Looping through multiple assemblies within a larger assembly file

ABoaro
Enthusiast
Enthusiast

I have code working that loops through an individual assembly. I understand how to iterate within parts of an assembly but I am having trouble taking it a step higher.

 

I have a larger assembly file that has 'sub' assemblies within the file. I want my rule to be able to loop through ALL sub assemblies within the larger assembly file. I am thinking of using the enumerator add on for the assembly class but I am having issues with the code only working for the first assembly in the document.

 

In psuedo code, 

 

For Each oAssembly in This Assembly document 

        Execute

	Dim AssyDoc As AssemblyDocument = ThisDoc.Document
		Dim oAsmCompDef As AssemblyComponentDefinition = AssyDoc.ComponentDefinition

		Dim oDocFile As Document, oDocFileName As String

		For Each oOcc As ComponentOccurrence In oAsmCompDef.Occurrences
		If Not TypeOf oOcc.Definition Is VirtualComponentDefinition Then
			
			oDocFile = oOcc.Definition.Document

			oDocFileName = oDocFile.displayname
					MessageBox.Show(oDocFileName)
			'Set your delimiter
			Delimiter = InStr(oDocFileName, "-")
			Description = Left(oDocFileName, Delimiter - 1)
				
				Select iProperties.Value(oDocFileName, "Custom", "Routing")
					Case "SA"
						iProperties.Value(oDocFileName, "Custom", "Priority") = 1
					Case "FR"
						iProperties.Value(oDocFileName, "Custom", "Priority") = 2
					Case "I"
						iProperties.Value(oDocFileName, "Custom", "Priority") = 3
					Case "FN"
						iProperties.Value(oDocFileName, "Custom", "Priority") = 4
					Case "FU"
						iProperties.Value(oDocFileName, "Custom", "Priority") = 5
				End Select

		End If
		Next

Next

 

I don't know what is the best way possible to loop through assemblies. Any help is appreciated.

 

0 Likes
Accepted solutions (1)
3,798 Views
8 Replies
Replies (8)
Message 2 of 9

J-Camper
Advisor
Advisor
Accepted solution

This is a basic outline for looping through an assembly with sub assemblies using sub routines,  You will have to add your actual code where ever it belongs, and add extra logic filters [if then statements] to limit which documents to process:

Sub Main
	
	If ThisApplication.ActiveDocumentType <> kAssemblyDocumentObject Then MessageBox.Show("This rule is designed to only work in assembly documents.", "Wrong Document Type") : Exit Sub
	
	Dim parentDoc As AssemblyDocument = ThisApplication.ActiveDocument
	
	'Do anything unique to main assembly
	
	Call AssemblyRunner(parentDoc)
	
End Sub

Sub AssemblyRunner(aDoc As AssemblyDocument)
	
	'Do things to the assembly file if any
	MessageBox.Show(aDoc.DisplayName, "Assembly:")
	
        'Start Looping
	For Each oOcc As ComponentOccurrence In aDoc.ComponentDefinition.Occurrences
		If oOcc.DefinitionDocumentType = kAssemblyDocumentObject
			Call AssemblyRunner(oOcc.Definition.Document)
		Else If oOcc.DefinitionDocumentType = kPartDocumentObject
			Call PartRunner(oOcc.Definition.Document, aDoc)
		End If
	Next
	
End Sub

Sub PartRunner(pDoc As PartDocument, parent As AssemblyDocument)
	
	'Do Part things
	MessageBox.Show(pDoc.DisplayName & vbCrLf & vbCrLf & _
					"Found in Assembly: " & parent.DisplayName, "Part:")

End Sub

 

Message 3 of 9

kevinv
Enthusiast
Enthusiast

I have been using a loop like this for years and it works fine with smaller assemblies with child assemblies (less than 150 parts).  However, we also build complex assemblies with north of 1000 parts. For some reason the time this takes to loop seems exponential as part count increases. It might have something to do with a rule calling itself (always felt sketchy). Four hours and forty seven minutes to run on a recent job (ouch).

 

Anyway, I have learned a better way and have just completed a re-write of our base code that updates our assemblies. Other than having to deal with some metric parameter conversions (long story) this new method is fantastic!! 

 

Still reading? I am happy to report that I ran the new loop on that same job that took almost five hours. New code finished exact same functionality in under five minutes!! That is not a typo, 5 minutes instead of 5 hours. Small assemblies take seconds to update.

 

I am happy to share what I have learned but I feel completely alone in even trying this kind of thing. Anyone else need to update data in large assemblies with iLogic?

 

In short, my new loop can update iProperties, Parameters, and even suppress/unsuppressed part features in ALL assembly children (sub parts and sub assemblies to all depths) in a single pass, amazing! Can you tell I am happy about this? Hit me up if you want specifics.

0 Likes
Message 4 of 9

engilic
Advocate
Advocate

Can you specify what your code does?
It looks interesting.

0 Likes
Message 5 of 9

kevinv
Enthusiast
Enthusiast

Hello engilic,

 

We build custom equipment and have been getting further and further into automating same-but-different designs. When a new job is sold we are utilizing existing designs that we call "cores" to get us way ahead from the start. 

 

We are using vault basic to "copy design" the cores into a new job folder. From there the engineer will check out the new design and start customizing it for the customer. We have an iLogic form on our assembly template for the engineer to fill out. They can specify a new global size (height, width, and depth) as well as their initials and the new job number. 

 

(ok, so the form can do way more than that too - create DXFs for entire assemblies, open all models, create PDFs for all drawings, change sheet metal gauge, and export the BOM for purchasing and production, but that is for other threads).

 

The two buttons related to this thread are "Update All" and "Update iProperties". Update iProperties could probably go away now as it was a band-aid to deal with the fact that "update all" was soooo stinking slow. 

 

Why was it so slow? Not sure actually, but I suspect that it has to do with an iLogic rule that would call itself. This never felt right to me but it was the only way I could find that allowed me to interact with sub part and sub assembly Parameters. I did not come up with this code, I am sure I found it here on the forum or elsewhere online years ago, but the rule starts like this:

 

Private Sub Iterate(Occurrences As ComponentOccurrences, Level As Integer)
 
There is a main sub above that where I update the top level assembly stuff and then call that rule, where it would then call itself over and over again. It all worked, but as I stated above it would take HOURS to run on larger assemblies. The breakthrough was when I figured out how to interact with Parameters using this loop:
 
For Each OpenDoc In oAsmDoc.AllReferencedDocuments

 

Using this loop in the past it was easy to interact with iProperties (see reference to update iproperties button above) but I could not interact with Parameters using the object OpenDoc. From the way things worked with the iterate rule I expected to be able to do something like this:

 

Parameter(OpenDoc, A_Width)=Parameter(A_Width)
 
But that was not a thing and forced me to use the iterate loop for Parameters. How do you interact with Parameters while using the OpenDoc object? Like this:
 
OpenDoc.Componentdefinition.Parameters.UserParameters("A_Width").value = Parameter("A_Width")
 
This loop only interacts with each child only one time (even if there are patterns or multiple instances) and reduced runtime from 5 hours to 5 minutes for one specific assembly. One important thing to know about the line above. All my Inventor units are imperial but the .value above is metric. Easy enough to convert, if needed, but it caught me off guard.
 
I hope that helps.
 
 
0 Likes
Message 6 of 9

engilic
Advocate
Advocate

Thank you @kevinv .

Would be nice to see the code if it is not too long.

0 Likes
Message 7 of 9

rob.van-der-veek
Participant
Participant

Hi Kevinv, 
I'm also interested in the code you are using. Is it possible to share the iLogic code? maybe you can remove specific parts that you won't want to share by changing this to 'your code here'. 
It can help a lot of people to spead up there iLogic rules. Thank you.

 

Rob

0 Likes
Message 8 of 9

kevinv
Enthusiast
Enthusiast

Hello Rob and Engilic,

 

I am happy to share my code but there is so much. I have continued to develop what this rule can do, and it has grown to almost 700 lines of code. 

 

The biggest advancement is that I figured out a way to make the rule Alacarte. I now use this code for almost all of my automation. I send the rule a list of tasks from other external rules, and it does only what is asked to the assembly (or part) and then all children in the case that it is running from an assembly.

 

The first rule I will post below is a rule that we call "Update All". The rule builds a task list, then calls the main rule that does all of the tasks. We have many rules now that have this task list and we just comment out the tasks we don't want. For example, the rule that only changes sheet metal gauge of all parts in an assembly will have everything commented out except "GUAGE". It will call the same rule as "Update All" but will only do one task as it loops through everything. Here is the calling rule:

 

Sub Main()
Dim TaskList As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
TaskList.Clear

TaskList.Add("task1", "SCREENSHOT")
TaskList.Add("task3", "USERFORM")
TaskList.Add("task4", "MASS")
TaskList.Add("task5", "PARAMETERS")
TaskList.Add("task6", "SUBFORM")
TaskList.Add("task7", "TITLE")
TaskList.Add("task8", "TEMPLATES")
TaskList.Add("task9", "GAUGE")
'TaskList.Add("task10", "RENAMEPARAMETERS")

iLogicVb.RunExternalRule("Update", TaskList)

End Sub

 

Below is the "Update" rule that is called at the end of the rule above (heavily trimmed for length).

Here are a few key lines with explanation.

First:

oDesTrackProps("Designer").Value = iProperties.Value("Project", "Designer")
The left side of the equal sign is the iProperty "Designer" of each child and the right is the iPropery "Designer" of the parent assembly.
second:
OpenDoc.componentdefinition.parameters.UserParameters("T_2").value = Parameter("T_2")
The left side of the equal sign is the child parameter named "T_2" and the right is the parent parameter of the same name. (Note: child parameters accessed this way will always be metric. You may need to convert even if all your settings are imperial)

 

Sub main()
Dim oDoc As Document 	
Dim oAsmDoc As AssemblyDocument 
Dim oPartDoc As PartDocument
oDoc = ThisDoc.Document
Dim OpenDoc As Document 

'Make sure code is running on an assembly or Part
	If oDoc.DocumentType = kPartDocumentObject Then
		GoTo Part_Code
	ElseIf oDoc.DocumentType = kAssemblyDocumentObject Then
		oAsmDoc = ThisApplication.ActiveDocument  
	ElseIf oDoc.DocumentType = kDrawingDocumentObject Then	
		MsgBox("This is a Drawing",,"Ending Run")
		Exit Sub	
	End If
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'Tasks for Assembly File
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'[YOUR CODE FOR PARENT ASSEMBLY HERE] - I WILL LEAVE ONE EXAMPLE BELOW

'Calling an external rule to capture a screenshot of the model and save it to our server but only if the calling rule asks for "SCREENSHOT"
If IsInArrayIndex("SCREENSHOT", DoTasks) > 0 Then 
'1. Take a screen shot ■■ ╫╫╫╫╫╫╫╫╫╫"SCREENSHOT"╫╫╫╫╫╫╫╫╫╫
	uu = Len(oAsmDoc.DisplayName)
	If uu = 8 Then   'Only take capture of top level models (all top level models have 8 digit display names)
		iLogicVb.RunExternalRule("Image Capture")
	End If
End If
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
'Now loop through all assembly children
'■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
For Each OpenDoc In oAsmDoc.AllReferencedDocuments 
	'''Tasks for ALL sub assemblies and parts

	'putting the full file name of each item in the assembly into a shared STRING variable that can be used in external rules
	SharedVariable("WorkDoc") = OpenDoc.FullFileName

	' setting up propery sets so that we can interact with iProperties of each item
	'	'See list at bottom (below sub) of what iProperties are in what set
		Dim oPropSets As PropertySets = OpenDoc.PropertySets
		Dim oSumInfo As PropertySet = oPropSets.Item("Inventor Summary Information")
		Dim oDocSumInfo As PropertySet = oPropSets.Item("Inventor Document Summary Information")
		Dim oDesTrackProps As PropertySet = oPropSets.Item("Design Tracking Properties")
		Dim oUserDefProps As PropertySet = oPropSets.Item("Inventor User Defined Properties")

	'[YOUR CODE FOR EACH ITEM HERE - LEAVING IN ONE EXAMPLE BELOW]

	If IsInArrayIndex("SUBFORM", DoTasks) > 0 Then 
	'5. Update Form iProperties (Job#, Engineer)■■ ╫╫╫╫╫╫╫╫╫╫"SUBFORM"╫╫╫╫╫╫╫╫╫╫
		If Parameter("T_1") = "" Or Parameter("T_1") = Nothing Then
			'do nothing
		Else
			oDesTrackProps("Project").Value = Parameter("T_1")
			Try
			OpenDoc.componentdefinition.parameters.UserParameters("T_1").value = Parameter("T_1")	'update sub assembly userform
			Catch
			End Try
		End If
		If Parameter("T_2") = "" Or Parameter("T_2") = Nothing Then
			'Do nothing	
		Else
			oDesTrackProps("Designer").Value = iProperties.Value("Project", "Designer")
			Try
			OpenDoc.componentdefinition.parameters.UserParameters("T_2").value = Parameter("T_2")	'update sub assembly userform
			Catch
			End Try
		End If
	End If
'END OF LOOP
Next 
'update all 
iLogicVb.UpdateWhenDone = True
iLogicVb.DocumentUpdate
'zoom all (GIVES USER VISUAL THAT RULE IS FINISHED RUNNING
ThisApplication.ActiveView.Fit
'STOP THE RULE HERE 
Exit Sub
'«««««««««««««««««■«■«■««««««■«««««««■«■«■««««■■■■■■■««««■«■«■««««««««««««««««««««««««««««««««««««««««««««««««««««««
'«««««««««««««««««■««««■««««■««■«««««■««««■««««««■««««««■«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
'«««««««««««««««««■«■«■««««■«■■«■««««■«■«■«««««««■«««««««■«■«■««««««««««««««««««««««««««««««««««««««««««««««««««««««
'«««««««««««««««««■«««««««■««««««■«««■«««■«««««««■««««««««««««■«««««««««««««««««««««««««««««««««««««««««««««««««««««
'«««««««««««««««««■«««««««■««««««■«««■««««■««««««■«««««««■«■«■««««««««««««««««««««««««««««««««««««««««««««««««««««««
Part_Code:	'Code below only runs when this rule is called from a part file.
'==================================================

End Sub

'USE THIS AS REFERENCE LIST TO PROPERLY CALL IPROPERTIES - DOES NOT MATCH CURRENT IPROPERTY TABS IN SOFTWARE '''1) Inventor Summary Information ''' 1) Title ''' 2) Subject ''' 3) Author ''' 4) Keywords ''' 5) Comments ''' 6) Last Saved By ''' 7) Revision Number ''' 8) Thumbnail '''2) Inventor Document Summary Information ''' 1) Category ''' 2) Manager ''' 3) Company '''3) Design Tracking Properties ''' 1) Creation Time ''' 2) Part Number ''' 3) Project ''' 4) Cost Center ''' 5) Checked By ''' 6) Date Checked ''' 7) Engr Approved By ''' 8) Engr Date Approved ''' 9) User Status ''' 10) Material ''' 11) Part Property Revision Id ''' 12) Catalog Web Link ''' 13) Part Icon ''' 14) Description ''' 15) Vendor ''' 16) Document SubType ''' 17) Document SubType Name ''' 18) Proxy Refresh Date ''' 19) Mfg Approved By ''' 20) Mfg Date Approved ''' 21) Cost ''' 22) Standard ''' 23) Design Status ''' 24) Designer ''' 25) Engineer ''' 26) Authority ''' 27) Parameterized Template ''' 28) Template Row ''' 29) External Property Revision Id ''' 30) Standard Revision ''' 31) Manufacturer ''' 32) Standards Organization ''' 33) Language ''' 34) Defer Updates ''' 35) Size Designation ''' 36) Categories ''' 37) Stock Number ''' 38) Weld Material ''' 39) Mass ''' 40) SurfaceArea ''' 41) Volume ''' 42) Density ''' 43) Valid MassProps ''' 44) Flat Pattern Width ''' 45) Flat Pattern Length ''' 46) Flat Pattern Area ''' 47) Sheet Metal Rule ''' 48) Last Updated With ''' 49) Sheet Metal Width ''' 50) Sheet Metal Length ''' 51) Sheet Metal Area ''' 52) Material Identifier ''' 53) Appearance ''' 54) Flat Pattern Defer Update '''4) Inventor User Defined Properties Public Function IsInArrayIndex(stringToFind As String, arr As Object) As Long IsInArrayIndex = -1 Dim i As Long For i = LBound(arr, 1) To UBound(arr, 1) If arr(i) = stringToFind Then IsInArrayIndex = i Exit Function End If Next i End Function

If you are having trouble with child iProperties it is likely an issue of using the correct "Property Sets". See the lines near the top that dim all of the ProperySets and then see the index at the bottom of what propertyset to use. These do NOT align with the current iProperties tab groups.

 

Much of the code above I have farmed from the forums and other online sources. I only claim a small amount of it as my own.

 

I hope this helps. Feel free to ask questions.

0 Likes
Message 9 of 9

kevinv
Enthusiast
Enthusiast

Sorry I missed this question; I have updated the thread with the code.

0 Likes