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
Solved! Go to Solution.
Solved by Ralf_Krieg. Go to Solution.
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.
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?
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
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
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.
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
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.
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
(Not an Autodesk Employee)
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
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
(Not an Autodesk Employee)
@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."
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.