Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iLogic to update/change Model State for each part in the assembly

14 REPLIES 14
SOLVED
Reply
Message 1 of 15
frahaman7SKBG
2717 Views, 14 Replies

iLogic to update/change Model State for each part in the assembly

Can someone look at me code and pinpoint why its not working? It says error on the Line 6. 

 

Thank you

Dim oDoc As Document = ThisApplication.ActiveDocument
Dim aDoc As DocumentsEnumerator = oDoc.AllReferencedDocuments
Dim iDoc As Document
For Each iDoc In aDoc
    'Here we set Model State in each of the parts in assembly
	Dim comp As DerivedPartComponent = iDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents.Item(1)
	comp.Definition.ActiveModelState = "Master"
	

Next
14 REPLIES 14
Message 2 of 15
Ralf_Krieg
in reply to: frahaman7SKBG

Hello

 

Your code fails cause not every referenced document in an assembly contains a derived component. Do you really want to enable the model state of the derived component? The commet in your code suggests to enable the model state for each component occurrence in your assembly which is something different.


R. Krieg
RKW Solutions GmbH
www.rkw-solutions.com
Message 3 of 15
frahaman7SKBG
in reply to: Ralf_Krieg

Thank you for your reply @Ralf_Krieg ,  You are correct, all my parts in the assembly is derived from a single IPT with multiple Solid Body and Model States. Im trying to put together an iLogic code that can be used to change Model state for each part in the assembly. In the future if I do have an assembly with a mixture of derived and traditional parts, I can use an IF Statement to explode those. 

 

If I understood correctly, you are suggesting I use 'Occurance' instead of 'Reference' for my code? 

Message 4 of 15

I rewrote the script using the API help, but its not doing anything and its not even giving me any error so I m not sure what I'm doing wrong now. 

 

    Dim oDoc As AssemblyDocument
    oDoc = ThisApplication.ActiveDocument

    Dim oAssemblyCompDef As AssemblyComponentDefinition
    oAssemblyCompDef = oDoc.ComponentDefinition

    ' Specify an occurrence to change its active model state.
    Dim oOccu As ComponentOccurrence
    oOccu = oAssemblyCompDef.Occurrences(1)

    ' Get native document ComponentDefinition of occurrence.
    Dim oOccuDef As ComponentDefinition
    oOccuDef = oOccu.Definition
    
    ' Before switch the active model state of an occurrence you should check if the document is up to date.
'    If oOccuDef.Document.RequiresUpdate Then
'        MsgBox ("Can not switch active model state because the native document is not up to date!")
'    Else
        Dim oModelStates As ModelStates
        oModelStates = oOccuDef.ModelStates
        
        Dim oModelState As ModelState
        For Each oModelState In oModelStates
            If oModelState.Name <> oOccu.ActiveModelState Then
    
                oOccu.ActiveModelState = "Master"
                Exit Sub
            End If
        Next
Message 5 of 15
Ralf_Krieg
in reply to: frahaman7SKBG

Hello

 

You don't want to change the model state of the part document. You want to change the model state of the occurrence of this part document. That's different. A part can have multiple occurrences within an assembly. Eac hof this occurences can have it's own model state active. Non of the active model states in thghe occurrences have to be the active model state in the part document.

 

Try this example:

Option Explicit On
Private Sub Main()
	Dim oDoc As AssemblyDocument = ThisDoc.Document
	Dim oOccs As ComponentOccurrences = oDoc.ComponentDefinition.Occurrences
	Call ProcessOccs(oOccs)
End Sub

Private Sub ProcessOccs(ByVal oOccs As ComponentOccurrences)
    Dim oOcc As ComponentOccurrence
    For Each oOcc In oOccs
        If oOcc.SubOccurrences.Count > 0 Then
            Call ProcessOccs(oOccs) 'recursive call in case of subassemblies
        End If
        
		If IsDerived(oOcc) Then
        	oOcc.ActiveModelState = "Master"
		Else
			'Code for non derived parts
		End If
    Next
End Sub

Private Function IsDerived(ByVal oOcc As ComponentOccurrence) As Boolean
	
	Dim oDoc As Document = oOcc.Definition.Document
	Dim oPartDoc As PartDocument
	If oDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		oPartDoc = DirectCast(oDoc, PartDocument)
		If oPartDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents.Count >0 Then
			Return True
		End If
	End If
	
	Return False
End Function

 


R. Krieg
RKW Solutions GmbH
www.rkw-solutions.com
Message 6 of 15
frahaman7SKBG
in reply to: Ralf_Krieg

Hello @Ralf_Krieg , Thank you for the code, it gave me a broader understanding of how iLogic and Model State works. The code works flawlessly for the task you have explained. But I must apologies as my earlier explanation wasn't fully clear. I am trying to do something slightly different. Each of my parts in the assembly was made using the 'Make Component" or "Derive" command from a single multi-body with the Model States IPT file. I am trying to write a code that would allow me to change the reference Model State for that 'Derived' part. Below is a screenshot of what needs to change for the individual parts.  I have also attached a Screencast of my assembly showing the manual process. 

 

Thank you again for your help. 

 

 

 

frahaman7SKBG_0-1640633427425.png

 

Message 7 of 15

<iframe width="240" height="400" src="https://screencast.autodesk.com/Embed/Timeline/a3598980-acfc-4516-b40c-4d912044dedc" frameborder="0" allowfullscreen webkitallowfullscreen></iframe>
Message 8 of 15
Ralf_Krieg
in reply to: frahaman7SKBG

Hello

 

No, I missunderstood. I marked the new lines of code and commented the one line replaced by it.

 

Option Explicit on

Private Sub Main()
	Dim oDoc As AssemblyDocument = ThisDoc.Document
	Dim oOccs As ComponentOccurrences = oDoc.ComponentDefinition.Occurrences
	Call ProcessOccs(oOccs)
End Sub

Private Sub ProcessOccs(ByVal oOccs As ComponentOccurrences)
    Dim oOcc As ComponentOccurrence
    For Each oOcc In oOccs
        If oOcc.SubOccurrences.Count > 0 Then
            Call ProcessOccs(oOccs) 'recursive call in case of subassemblies
        End If
        
		If IsDerived(oOcc) Then
        	'oOcc.ActiveModelState = "Master"
			' NEW #############################################################################
			If oOcc.DefinitionDocumentType = kPartDocumentObject Then
	            Dim oOccCompDef As PartComponentDefinition= oOcc.Definition
	            Dim oOccDerivedPartComponents As DerivedPartComponents= oOccCompDef.ReferenceComponents.DerivedPartComponents
	            
	            Dim oOccDerivedPartComponent As DerivedPartComponent
	            For Each oOccDerivedPartComponent In oOccDerivedPartComponents
	                Dim oOccDerivedPartCompDef As DerivedPartDefinition = oOccDerivedPartComponent.Definition
	                oOccDerivedPartCompDef.ActiveModelState = "Master"
	                oOccDerivedPartComponent.Definition = oOccDerivedPartCompDef
	            Next
	        End If
			' #############################################################################
		Else
			'Code for non derived parts
		End If
    Next
End Sub

Private Function IsDerived(ByVal oOcc As ComponentOccurrence) As Boolean
	
	Dim oDoc As Document = oOcc.Definition.Document
	Dim oPartDoc As PartDocument
	If oDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		oPartDoc = DirectCast(oDoc, PartDocument)
		If oPartDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents.Count >0 Then
			Return True
		End If
	End If
	
	Return False
End Function

R. Krieg
RKW Solutions GmbH
www.rkw-solutions.com
Message 9 of 15
frahaman7SKBG
in reply to: Ralf_Krieg

Thank you so much for your help on this @Ralf_Krieg , your code worked flawlessly. 

 

I have made minor addition to include user input for the Model State. If anyone is

Sub Main
	oDoc = ThisDoc.Document
	'Saves this document
	oDoc.Save
	'Checks if the active document is an assembly
	If oDoc.DocumentType = kAssemblyDocumentObject
		'Gets the assembly occurrences
		Dim oOccs As ComponentOccurrences = oDoc.ComponentDefinition.Occurrences
		'Call the subprocedure to traverse the assembly
		
		myModelState = InputBox("Enter your Model State Name", "iLogic - Model State""")
		TraverseAssembly(oOccs, myModelState)
		ChangeModelState(myModelState)
		
		
	End If
	
iLogicVb.UpdateWhenDone = True

End Sub

'***************


Public Sub TraverseAssembly(oOccs As ComponentOccurrences,myModelState As String)

	
	Dim oOcc As ComponentOccurrence
	For Each oOcc In oOccs
		If oOcc.Suppressed = False Then
			'Occurrence Name (Display Name)
			oOccName = oOcc.Name
				Try	
					iProperties.Value(oOccName, "Custom", "Model_State:") = myModelState
	
				Catch
					'It won't be able to change Read-Only parts (File  not checked out from the Vault)
					MessageBox.Show("This is a Read Only: " & oOcc.Name, "Title")
				End Try
			
			If oOcc.DefinitionDocumentType = kAssemblyDocumentObject
				TraverseAssembly(oOcc.Definition.Occurrences, myModelState)
			End If
		End If
	Next


'Update Assembly Properties	
iProperties.Value("Custom", "Model_State:") = myModelState

	
End Sub


Private Sub ChangeModelState(myModelState As String)
	Dim oDoc As AssemblyDocument = ThisDoc.Document
	Dim oOccs As ComponentOccurrences = oDoc.ComponentDefinition.Occurrences
	Call ProcessOccs(oOccs, myModelState)

End Sub

Private Sub ProcessOccs(ByVal oOccs As ComponentOccurrences, myModelState As String)
    Dim oOcc As ComponentOccurrence
    For Each oOcc In oOccs
        If oOcc.SubOccurrences.Count > 0 Then
            Call ProcessOccs(oOccs, myModelState) 'recursive call in case of subassemblies
        End If
        
		If IsDerived(oOcc) Then

			If oOcc.DefinitionDocumentType = kPartDocumentObject Then
	            Dim oOccCompDef As PartComponentDefinition= oOcc.Definition
	            Dim oOccDerivedPartComponents As DerivedPartComponents= oOccCompDef.ReferenceComponents.DerivedPartComponents
	            
	            Dim oOccDerivedPartComponent As DerivedPartComponent
				
				'Change Model State of each occurence
	            For Each oOccDerivedPartComponent In oOccDerivedPartComponents
	                Dim oOccDerivedPartCompDef As DerivedPartDefinition = oOccDerivedPartComponent.Definition
	                oOccDerivedPartCompDef.ActiveModelState = myModelState
	                oOccDerivedPartComponent.Definition = oOccDerivedPartCompDef
	            Next
	        End If

		Else
			'Code for non derived parts
		End If
    Next
End Sub

Private Function IsDerived(ByVal oOcc As ComponentOccurrence) As Boolean
	
	Dim oDoc As Document = oOcc.Definition.Document
	Dim oPartDoc As PartDocument
	If oDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		oPartDoc = DirectCast(oDoc, PartDocument)
		If oPartDoc.ComponentDefinition.ReferenceComponents.DerivedPartComponents.Count >0 Then
			Return True
		End If
	End If
	
	Return False
End Function



interested, here is the final code. 

 

 

Message 10 of 15
drietzler1
in reply to: frahaman7SKBG

I have been trying to do exactly what your doing here. For some reason in Inventor 2024 when I use this code, It works halfway then seems to just freeze up my inventor program. Have you updated it at all?
Message 11 of 15
WCrihfield
in reply to: drietzler1

After a quick review of the last code posted here, I saw a little section of the rule that seems like it could be problematic in the right conditions.  The following block of code copied from above seems to me like it could cause an endless loop if the first component in the component collection had more than one SubOccurrences.

Private Sub ProcessOccs(ByVal oOccs As ComponentOccurrences, myModelState As String)
    Dim oOcc As ComponentOccurrence
    For Each oOcc In oOccs
        If oOcc.SubOccurrences.Count > 0 Then
            Call ProcessOccs(oOccs, myModelState) 'recursive call in case of subassemblies
        End If

...because it is feeding the same exact collection it started with back to the start of the loop again, instead the SubOccurrences of the single oOcc that it just encountered.  I'm guessing that maybe that one line should be:

Call ProcessOccs(oOcc.SubOccurrences, myModelState)

, but maybe I'm wrong.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 12 of 15
k.grigoriou
in reply to: frahaman7SKBG

Hi i need your help if you can

 

I'm trying to do something similar

i want to have the i logic inside the derived part. and when i want to change the model state to change one custom i property and after to run the ilogic and according to this i property to change the model state

Message 13 of 15
WCrihfield
in reply to: k.grigoriou

Hi @k.grigoriou.  This sort of thing can become very confusing to wrap our minds around remotely, so it would be best if you fully explained the situation you currently have in as much detail as possible.  Then explain what you want to do from there, in as much detail as possible.  It seems like we could be talking about a lot of references to other references here, and coding needs to be extremely specific for it to work.  If posting some screen captured images might help explain it, then please include those too.  Can you do the steps you want the code to do manually?  If so, explaining (or showing) those steps may be very important to us being able to replicate those actions by code.  Also, often if something can not be done manually, it also can not be done by code either.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 14 of 15
k.grigoriou
in reply to: WCrihfield

@WCrihfield, sorry, you are correct.

 

Let's say I have a part with the name "Test 1_Substitute_1.ipt."

I created this part using the "Derive Assembly" function from the assembly with the name "Test 1.iam."

The original assembly "Test 1" has 3 model states: the primary, Model1, and Model2.

Now, what I want is, when I'm running a rule (test_rule1) inside the part "Test 1_Substitute_1.ipt," to be able to change the model state. The way to change the model state is by using a custom iProperty within the part "Test 1_Substitute_1.ipt" with the name "Model_state."

 

Message 15 of 15
t_fransman
in reply to: Ralf_Krieg

I am trying to do a similar function, my assembly has a table and the skeleton has the same table matching values width and length.  I just want the non- hardware ( not dervied  parts) parts to change to the selected version of the like the mulit body skeleton one does  when it is changed so i can use any size of the assembly. Doesn't seem to play well with mutil body solid skeleton . This code just crashes my session. 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report