catch the instance property and add that to the instance name

catch the instance property and add that to the instance name

carlos.manteigas
Participant Participant
1,093 Views
10 Replies
Message 1 of 11

catch the instance property and add that to the instance name

carlos.manteigas
Participant
Participant
Accepted solutions (1)
1,094 Views
10 Replies
Replies (10)
Message 2 of 11

WCrihfield
Mentor
Mentor

What is the name of the 'instance' iProperty which is holding this serial number?  Once that serial number is found, how do you want it to effect the name of the component within the active assembly?  Do you want it to become the new full name of the component, or just part of its name?  If just part of its name, then which part, and how do you want the new name to be formatted?

 

Edit:  I think I found the name "Serial Number". (If that is correct.)

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 11

WCrihfield
Mentor
Mentor
Accepted solution

Hi @carlos.manteigas.  I just wrote an iLogic rule for you that may do what you are asking, but since I still don't have the answers to the questions from my last post, I'm not sure if it is doing it the way you want it done yet.  Basically, when you have that main assembly open/active, then run this rule, it should start recursively iterating through all of the components looking for an 'instance' iProperty named "Serial Number", then use its value to rename the component it was within.  I put the main task into its own Sub routine, so that it would be easily transferable, if needed.  I also encapsulated the whole process within a single transaction, so that it could simply click 'UNDO' once to undo it all, if needed.

Here is the iLogic rule's code:

Sub Main
	oADoc = ThisAssembly.Document
	oADef = oADoc.ComponentDefinition
	oOccs = oADef.Occurrences
	oTrans = ThisApplication.TransactionManager.StartTransaction(oADoc, "Rename Components W/ SN")
	RecusivelyIterateComponents(oOccs)
	oTrans.End
End Sub

Sub RecusivelyIterateComponents(oComps As ComponentOccurrences)
	If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub
	For Each oComp As ComponentOccurrence In oComps
		Try
			If oComp.OccurrencePropertySetsEnabled Then
				Dim oInstPSet As PropertySet = oComp.OccurrencePropertySets.Item(1)
				Dim oInstP As Inventor.Property = oInstPSet.Item("Serial Number")
				Dim oSN As String = oInstP.Value.ToString
				If oSN <> "" Then oComp.Name = oSN
			End If
		Catch
		End Try
		If oComp.SubOccurrences.Count > 0 Then
			RecusivelyIterateComponents(oComp.SubOccurrences)
		End If
	Next
End Sub

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.

If you want and have time, I would appreciate your Vote(s) for My IDEAS :bulb: or you can Explore My CONTRIBUTIONS

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 11

carlos.manteigas
Participant
Participant
WOW!!!!

Thank you @WCrihfield!!!
Worked like charm! 🙂
0 Likes
Message 5 of 11

martin.djignagard
Explorer
Explorer

Hi!

 

I know it has been a few years since this was resolved but I am trying to reuse the code and it works fine in the main assembly but it does not change the name of the components/Occurences in the sub assemblies.

I've tried to debug it a bit and it seems that it still iterates over every item but it does not update it.

Has something changed with iLogic/Inventor over the years where it blocks the updates in sub assemblies or maybe I am just bad 😄

 

See before and after picture from a dummy assembly

 

martindjignagard_0-1744024367382.png martindjignagard_1-1744024382613.png

 

 

0 Likes
Message 6 of 11

WCrihfield
Mentor
Mentor

Hi @martin.djignagard.  Were all of the instance properties assigned to all of the occurrences while the 'main/top' assembly was the 'active' document, or were some of them assigned to sub components while other sub assemblies were the active document.  Knowing this detail is important, because 'instance' properties depend on whichever Document was currently the 'active' (visibly showing on your screen at the time, for editing), and I believe they may also depend on which ModelState was 'active' at the moment the instance property was created.

Also, there are two different ways to recursively iterate over multiple levels of component occurrences in an assembly, and each way can change how things work.  When using the ComponentOccurrence.SubOccurrences property to access lower level occurrences, the lineage or association with the top/main assembly is preserved, meaning some types of changes made will be made from the perspective of the top/main assembly, instead of the individual occurrence definitions being iterated through.  However, when using ComponentOccurrence.Definition.Occurrences to iterate through them, it is actually stepping down into the 'definition' of the sub assembly, instead of just another layer of sub components of the top/main assembly, and because of this, most/all changes made will effect the individual component definitions (and files where those definitions are saved) for all those occurrences.  Which way is best for a specific situation depends on your goals, what you are planning on doing to/with each occurrence, and where you want the changes to be saved.

So, if all instance properties were assigned to all sub occurrences while the main/top assembly was active, and the same ModelState of that main/top assembly was also active during all instance property assignments, then the original way of iterating the sub occurrences (using SubOccurrrences property) would be best, but if instance properties were assigned while other sub assemblies were active, then they will only be found again when that sub assembly's definition is being worked within again, so stepping down through the occurrences by way of their definitions would be necessary.  And if my theory is correct about the same ModelState that was active when the instance assignments were made needing to be active again to find those instance properties, then there may need to be some ModelState activations included in the process also, but I am not sure.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 11

martin.djignagard
Explorer
Explorer

Hi @WCrihfield and thank you for a very thorough and quick response, much appreciated!

I tried switching what was used in the recursion call from SubOccureences to Definition.Occurrences and it worked great!

To be honest I am no sure what is meant that the 'main/top' assembly is active when creating the instance property. From my knowledge you can only assign IP to children of the current assembly/sub assembly that is active, see snippet where inventor does not allow me to edit the IP of Box2, only when I am in Assem2/Assem2 is active I am allowed to edit. 

martindjignagard_0-1744028281350.png

 

0 Likes
Message 8 of 11

WCrihfield
Mentor
Mentor

It is true that there does not appear to be a way to 'manually' create or work with instance properties of lower level sub occurrences, but I was not sure if you may have created them using a code based process, such as something similar to the one you are attempting to use here.  I probably could have worded it better.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 9 of 11

Stakin
Collaborator
Collaborator

@martin.djignagard wrote:

Hi @WCrihfield and thank you for a very thorough and quick response, much appreciated!

I tried switching what was used in the recursion call from SubOccureences to Definition.Occurrences and it worked great!

To be honest I am no sure what is meant that the 'main/top' assembly is active when creating the instance property. From my knowledge you can only assign IP to children of the current assembly/sub assembly that is active, see snippet where inventor does not allow me to edit the IP of Box2, only when I am in Assem2/Assem2 is active I am allowed to edit. 

martindjignagard_0-1744028281350.png

 


I modified @WCrihfield 's Snippet, by now ,it can change sub assembly occurrences name, try

Sub RecusivelyIterateComponents(oAdocs As Document)
	Dim oAdoc As AssemblyDocument = TryCast(oAdocs, AssemblyDocument)
	If oAdoc Is Nothing Then Exit Sub
	Dim oComps As ComponentOccurrences
	oComps=oAdoc.ComponentDefinition.Occurrences
	If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub	
	Dim oSuboccList As New List(Of String)
	Dim  oComp As ComponentOccurrence
	For Each oComp In oComps
		If oComp.Suppressed = True Then Continue For
		If oComp.Definition.Type=Inventor.ObjectTypeEnum.kWeldsComponentDefinitionObject Then Continue For
		If oComp.OccurrencePropertySetsEnabled Then
			Dim oInstPSet As PropertySet = oComp.OccurrencePropertySets.Item(1)
			Try
			Dim oInstP As Inventor.Property = oInstPSet.Item("Serial Number")
			Dim oSN As String = oInstP.Value.ToString
			If oSN <> "" Then oComp.Name = oSN
			Catch
			End Try	
		End If
		If oComp.DefinitionDocumentType = Inventor.DocumentTypeEnum.kAssemblyDocumentObject  Then
			Dim oDoc As AssemblyDocument
			Dim oFileName As String 
			oDoc = oComp.Definition.Document			
			oFileName=oDoc.FullDocumentName
			If Not oSuboccList.Contains(oFileName ) Then 
				oSuboccList.Add(oFileName )
				oDoc = ThisApplication.Documents.Open(oFileName, False)				
				RecusivelyIterateComponents(oDoc)
'				oDoc.Close(True)
			End If
		End If
	Next
	oADoc.Save	
End Sub

 

Message 10 of 11

WCrihfield
Mentor
Mentor

Hi @Stakin.  Interesting approach switching the 'input' parameter to a single Document, instead of the collection of occurrences.  I am not sure how well that would work out if the process jumps to another Document each time an occurrence within that Document represents a sub assembly, but I have not tested any of this, because I very rarely use instance properties.  Below is an updated version of my code example from nearly 3 years ago.  It is still split into just 2 routines.

Sub Main
	Dim oADoc As AssemblyDocument = TryCast(ThisDoc.Document, Inventor.AssemblyDocument)
	If oADoc Is Nothing Then Return
	RecusivelyIterateComponents(oADoc.ComponentDefinition.Occurrences)
	oADoc.Update2(True)
	'oADoc.Save2(True)
End Sub

Sub RecusivelyIterateComponents(oComps As Inventor.ComponentOccurrences)
	If oComps Is Nothing OrElse oComps.Count = 0 Then Return
	For Each oComp As Inventor.ComponentOccurrence In oComps
		'<<< do something with each occurrence here >>>
		If oComp.Suppressed Then Continue For
		Try
			If oComp.OccurrencePropertySetsEnabled = True Then
				Dim sSN As String = oComp.OccurrencePropertySets.Item(1).Item("Serial Number").Value.ToString()
				If sSN IsNot Nothing AndAlso sSN <> "" Then oComp.Name = sSN
			End If
		Catch ex As Exception
			Logger.Error(ex.ToString)
		End Try
		'<<< now recurse down into deeper occurrences, if there are any >>>
		If oComp.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			'<<< use next line to edit each component's definition & referenced file >>>
			RecusivelyIterateComponents(oComp.Definition.Occurrences)
			'<<< use next line if changes should only effect main/top assembly >>>
			'RecusivelyIterateComponents(oComp.SubOccurrences)
		End If
	Next
End Sub

...but these days, I usually use 3 routines when recursively iterating through potentially multi-level collections.  Below is an example that is set-up like that.  I think I originally picked up that little trick/strategy from Jelte De Jong (another respected forum user who is also an Expert Elite member) a couple years ago.  I'm not sure if either way gives more advantage than the other, but I just like the idea of a clean, standalone routine that just manages the recursion process, with a 'pointer' to a different routine for processing each item involved.  Recursing the model browser tree can be done with a similar set-up.

Sub Main
	Dim oADoc As AssemblyDocument = TryCast(ThisDoc.Document, Inventor.AssemblyDocument)
	If oADoc Is Nothing Then Return
	RecurseComponents(oADoc.ComponentDefinition.Occurrences, AddressOf ProcessComponent)
	oADoc.Update2(True)
	'oADoc.Save2(True)
End Sub

Sub RecurseComponents(oComps As ComponentOccurrences, ComponentProcess As Action(Of ComponentOccurrence))
	If oComps Is Nothing OrElse oComps.Count = 0 Then Return
	For Each oComp As ComponentOccurrence In oComps
		ComponentProcess(oComp)
		If Not oComp.Suppressed AndAlso _
			oComp.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			'<<< use next line to edit each component's definition & referenced file >>>
			RecurseComponents(oComp.Definition.Occurrences, ComponentProcess)
			'<<< use next line if changes should only effect main/top assembly >>>
			'RecurseComponents(oComp.SubOccurrences, ComponentProcess)
		End If
	Next
End Sub

Sub ProcessComponent(oComp As ComponentOccurrence)
	If (oComp Is Nothing) OrElse oComp.Suppressed Then Return
	Try
		If oComp.OccurrencePropertySetsEnabled = True Then
			Dim sSN As String = oComp.OccurrencePropertySets.Item(1).Item("Serial Number").Value.ToString()
			If sSN IsNot Nothing AndAlso sSN <> "" Then oComp.Name = sSN
		End If
	Catch ex As Exception
		Logger.Error(ex.ToString)
	End Try
End Sub

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 11 of 11

Stakin
Collaborator
Collaborator

@WCrihfield ,I accept your advice,referencing a subassembly document directly because that has already been opened, removing the open subassembly document statement.I add “oSuboccList” to avoid modify the same subassembly multiple times.Byref the “oSuboccList”,the snippets are a little more responsive.

Sub Main
	oADoc = ThisAssembly.Document
	Dim oSuboccList As New List(Of String)
	oTrans = ThisApplication.TransactionManager.StartTransaction(oADoc, "Rename Components W/ SN")
	RecusivelyIterateComponents(oADoc,oSuboccList)
	oTrans.End
End Sub

Sub RecusivelyIterateComponents(oAdocs As Document,ByRef oSuboccList As List(Of String))
	Dim oAdoc As AssemblyDocument = TryCast(oAdocs, AssemblyDocument)
	If oAdoc Is Nothing Then Exit Sub
	Dim oComps As ComponentOccurrences
	oComps=oAdoc.ComponentDefinition.Occurrences
	If IsNothing(oComps) OrElse oComps.Count = 0 Then Exit Sub	
	Dim  oComp As ComponentOccurrence
	For Each oComp In oComps
		If oComp.Suppressed = True Then Continue For
		ProcessComponent(oComp)
		If oComp.DefinitionDocumentType = Inventor.DocumentTypeEnum.kAssemblyDocumentObject  Then
			Dim oDoc As AssemblyDocument
			Dim oFileName As String 
			oDoc = oComp.Definition.Document			
			oFileName=oDoc.FullDocumentName
			If Not oSuboccList.Contains(oFileName ) Then 
				oSuboccList.Add(oFileName )	
				RecusivelyIterateComponents(oDoc,oSuboccList)
			End If
		End If
	Next
	oADoc.Save	
End Sub
Sub ProcessComponent(oComp As ComponentOccurrence)
	If (oComp Is Nothing) OrElse oComp.Suppressed Then Return
	Try
		If oComp.OccurrencePropertySetsEnabled = True Then
			Dim sSN As String = oComp.OccurrencePropertySets.Item(1).Item("Serial Number").Value.ToString()
			If sSN IsNot Nothing AndAlso sSN <> "" Then oComp.Name = sSN
		End If
	Catch ex As Exception
		Logger.Error(ex.ToString)
	End Try
End Sub