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: 

Model States and Inability to Change Parameter Values in Component Occurrences

7 REPLIES 7
Reply
Message 1 of 8
ForrestJudd
998 Views, 7 Replies

Model States and Inability to Change Parameter Values in Component Occurrences

I'm having trouble changing parameters in child occurrences from the assembly level when those child occurrences include Model States. This applies to both assembly components and part components.

 

The attached sample is as simple as it gets. There is a top level assembly (TestAssy211.iam) and a single referenced sub assembly (TestSubAssy211.iam). TestSubAssy211.iam has a single parameter named "TestParam".  The top level assembly has a rule (Rule0) with a single line: 

 

Parameter("TestSubAssy211:1", "TestParam") = 2

This works fine if the sub assembly has no Model states. It also works fine if the sub assembly has model states. It even works fine if the main assembly is referencing one of those model states. 

 

However, if I open the sub assembly in its own window then update/save/close that sub assembly the rule no longer works, and throws the following error:

 

ForrestJudd_0-1665101617259.png

ForrestJudd_1-1665101632108.png

This is with Inventor 2023.1.1.

 

I'm seeing issues with both parameter updates and component suppress/unsuppress that I never saw prior to the transition to Model States from LoDs.  Is there something that needs to be done now that Model States are in play to make these updates more reliable? This is a fundamental behavior that 'just worked' prior to Inventor 2022 and now appears to be very easily broken.

 

For what it's worth, I can duplicate the parameter update error using direct API calls as well, both from an iLogic rule and from VBA, so it's not iLogic-specific.

 

 

 

7 REPLIES 7
Message 2 of 8
WCrihfield
in reply to: ForrestJudd

Hi @ForrestJudd.  I do not believe they have updated or created a new version of that Parameter() iLogic shortcut snippet, which allows you to specify a ModelState name yet.  They do have a couple other new iLogic shortcut snippets for other purposes which will work with a specific ModelState though.  So, if a situation calls for it, we basically need to create our own similar functioning methods (a custom Sub routine).  That simple iLogic snippet can work in some situations, but when the ModelState that the assembly component object is set to doesn't match the ModelState that is currently 'active' in the model file being referenced by that component, it may not work right.  An example case may be where your assembly has several component instances, which all reference the same source model document, but each of those components may be set to different ModelState versions of it.  Basically each ModelState represents a different version of the document, and you need to be working with what is called the 'factory' document, which is essentially just the version of the document that is currently under the influence of the 'active' ModelState.  That is the only version you can make edits/changes to.  You can sometimes access/read data from other versions, but can't make changes to them.

 

Here is one such custom function I made a while back that may be able to help you with this seemingly simple task.  It is fairly long though, in an attempt to get it free of potential errors/problems.  It is not set up exactly like the iLogic snippet, but it worked OK in my scenario testing.  Plus, other versions can be made, that work slightly different, if needed.  You can review its contents to follow what is going on.  I left some comments in there to help understand the train of thought, and why I am doing some of the things I am doing.

 

Sub Main
	If ThisApplication.ActiveDocumentType <> 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 = ThisApplication.ActiveDocument
	
	'get the source parameter / value to copy down
	Dim oTopAsmParam As Inventor.Parameter = Nothing
	Try
		oTopAsmParam = oADoc.ComponentDefinition.Parameters.Item("Param2Copy")
	Catch
		MsgBox("Failed to find/get 'source' parameter/value.", vbCritical, "")
		Exit Sub
	End Try
	
	'find/get component representing part within the sub-assembly
	Dim oTargetPartOcc As ComponentOccurrence = Nothing
	Try
		oTargetPartOcc = oADoc.ComponentDefinition.Occurrences.ItemByName("Part3:2")
	Catch
		MsgBox("Failed to find/get component representing the Part within the Sub-Assembly.", vbCritical, "")
		Exit Sub
	End Try
	CopyParamToComponentWithModelState(oTargetPartOcc, oTopAsmParam)
	
End Sub

Sub CopyParamToComponentWithModelState(oOcc As ComponentOccurrence, oSourceParam As Inventor.Parameter, _
Optional oTargetModelStateName As String = vbNullString, Optional oTargetParamName As String = vbNullString)
	If IsNothing(oOcc) OrElse IsNothing(oSourceParam) Then Exit Sub
	If oOcc.Suppressed Then Exit Sub 'or try to open its referened document to be able to access its param
	If oTargetModelStateName = "" Then oTargetModelStateName = oOcc.ActiveModelState
	If oTargetParamName = "" Then oTargetParamName = oSourceParam.Name
	If TypeOf oOcc.Definition Is VirtualComponentDefinition Then Exit Sub
	'get the 'factory' document, if one exists (the version we can edit)
	Dim oFacDoc As Document
	If oOcc.Definition.IsModelStateMember Then
		oFacDoc = oOcc.Definition.FactoryDocument
	Else
		oFacDoc = oOcc.Definition.Document
	End If
	Dim oMSs As ModelStates = oFacDoc.ComponentDefinition.ModelStates
	'make sure the specified ModelState exists.  If so, get it.
	Dim oTargetMS As ModelState = Nothing
	Try
		oTargetMS = oMSs.Item(oTargetModelStateName)
	Catch
		'could offer to create the ModelState if it is not found too
		Logger.Error("Failed to find ModelState named '" & oTargetModelStateName & _
		"' within component named '" & oOcc.Name & "'.")
		Exit Sub
	End Try
	'record whether we opened the factory document, so we know if we need to close it again when done
	Dim oFacDocOpened As Boolean = False
	'that ModelState must either be 'active' or get 'activated' before you can edit a param within it
	If oMSs.ActiveModelState IsNot oTargetMS Then
		'if the target ModelState is not 'active', or the MemberEditScope is not set to 'edit active member',
		'then the factory document will need to be 'visibly' opened before you can 'activate' that ModelState,
		'and before you can change the MemberEditScope status, both of which will need to happen
		oFacDoc = ThisApplication.Documents.Open(oFacDoc.FullDocumentName, True)
		oFacDocOpened = True
		oTargetMS.Activate
	End If
	If oMSs.MemberEditScope <> MemberEditScopeEnum.kEditActiveMember Then
		oMSs.MemberEditScope = MemberEditScopeEnum.kEditActiveMember
	End If
	Dim oParams As Inventor.Parameters = oFacDoc.ComponentDefinition.Parameters
	'make sure target parameter exists.  If not, try to create it.
	Dim oTargetParam As Inventor.Parameter = Nothing
	Try
		oTargetParam = oParams.Item(oTargetParamName)
	Catch
		oTargetParam = oParams.UserParameters.AddByValue(oTargetParamName, oSourceParam.Value, oSourceParam.Units)
	Catch
		Logger.Error("Failed to find or create target parameter named '" & oTargetParamName & _
		"' within component named '" & oOcc.Name & "'.")
		Exit Sub
	End Try
	If Not IsNothing(oTargetParam) Then
		If oTargetParam.Value <> oSourceParam.Value Then
			oTargetParam.Value = oSourceParam.Value
		End If
	End If
	If oFacDoc.RequiresUpdate Then oFacDoc.Update2(True)
	If oFacDoc.Dirty Then oFacDoc.Save2(False)
	If oFacDocOpened Then oFacDoc.Close(True)
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) 👍.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 8
ForrestJudd
in reply to: WCrihfield

Thanks so much for the fast and thorough reply!

 

I would assume this same approach needs to be taken when suppressing or unsuppressing components as well, but I can't get it to work. For example, I have in a sub assembly a rule that suppresses and unsuppresses using Component.IsActive. That rule works just fine when the sub assembly is the active document. However, when calling the rule in the child from the top level assembly, any call to Component.IsActive that would result in a component changing suppression state fails with the same COM error as would changing a parameter value.

 

I tried to modify the parameter copy sub you provided to instead run a rule in the occurrence, but I'm still getting the same error. Here's my rule in the parent with my new sub "RunRuleInComponentWithModelState":

 

 

 

Sub Main()
	Dim TargetOcc As Inventor.ComponentOccurrence = ThisDoc.Document.ComponentDefinition.Occurrences.ItemByName("TestSubAssy211:1")
	RunRuleInComponentWithModelState(TargetOcc, "SC", "iLogic")
End Sub

Sub RunRuleInComponentWithModelState(oOcc As ComponentOccurrence, RuleName As String, Optional oTargetModelStateName As String = vbNullString)
If IsNothing(oOcc) Then Exit Sub
	If oOcc.Suppressed Then Exit Sub 'or try to open its referened document to be able to access its param
	If oTargetModelStateName = "" Then oTargetModelStateName = oOcc.ActiveModelState
	If TypeOf oOcc.Definition Is VirtualComponentDefinition Then Exit Sub
	'get the 'factory' document, if one exists (the version we can edit)
	Dim oFacDoc As Document
	If oOcc.Definition.IsModelStateMember Then
		oFacDoc = oOcc.Definition.FactoryDocument
	Else
		oFacDoc = oOcc.Definition.Document
	End If
	Dim oMSs As ModelStates = oFacDoc.ComponentDefinition.ModelStates
	'make sure the specified ModelState exists.  If so, get it.
	Dim oTargetMS As ModelState = Nothing
	Try
		oTargetMS = oMSs.Item(oTargetModelStateName)
	Catch
		'could offer to create the ModelState if it is not found too
		Logger.Error("Failed to find ModelState named '" & oTargetModelStateName & _
		"' within component named '" & oOcc.Name & "'.")
		Exit Sub
	End Try
	'record whether we opened the factory document, so we know if we need to close it again when done
	Dim oFacDocOpened As Boolean = False
	'that ModelState must either be 'active' or get 'activated' before you can edit a param within it
	If oMSs.ActiveModelState IsNot oTargetMS Then
		'if the target ModelState is not 'active', or the MemberEditScope is not set to 'edit active member',
		'then the factory document will need to be 'visibly' opened before you can 'activate' that ModelState,
		'and before you can change the MemberEditScope status, both of which will need to happen
		oFacDoc = ThisApplication.Documents.Open(oFacDoc.FullDocumentName, True)
		oFacDocOpened = True
		oTargetMS.Activate
	End If
	If oMSs.MemberEditScope <> MemberEditScopeEnum.kEditActiveMember Then
		oMSs.MemberEditScope = MemberEditScopeEnum.kEditActiveMember
	End If
	
	'Try to run the rule
	Try
		Logger.Debug("Running rule " & RuleName & " in occurrence " & oOcc.Name)
		iLogicVb.RunRule(oOcc.Name, RuleName)
	Catch ex As Exception
		Logger.Debug("Failed to run rule " & RuleName & " in occurrence " & oOcc.Name & System.Environment.NewLine() & "Exception: " & ex.Message)
	End Try
	If oFacDoc.RequiresUpdate Then oFacDoc.Update2(True)
	If oFacDoc.Dirty Then oFacDoc.Save2(False)
	If oFacDocOpened Then oFacDoc.Close(True)
End Sub

 

 

 

The rule in the child component throws the exception in this case:

 

ForrestJudd_0-1665425939270.png

ForrestJudd_1-1665425959870.png

And the rule in the sub assembly is just a very simple one for testing:

 

 

If Component.IsActive("SubComp2:1") = False Then
	Component.IsActive("SubComp1:1") = False
	Component.IsActive("SubComp2:1") = True
	Component.IsActive("SubComp3:1") = False
Else
	Component.IsActive("SubComp1:1") = True
	Component.IsActive("SubComp2:1") = False
	Component.IsActive("SubComp3:1") = True
End If

 

 

 

Any thoughts?

 

 

Message 4 of 8
WCrihfield
in reply to: ForrestJudd

Hi @ForrestJudd.  Sorry for long delay.  Had lots of stuff going on.  The second error screen indicates that the error is happening on Line 2 of a rule named "SC", where it trying to set a component's BOMStructure.  But the simple rule code you posted at the end does not appear to be doing anything with BOMStructure, just component suppression (IsActive = not suppressed).  One thing that comes to mind is the document reference of that simple rule...or rather the lack of a document reference.  It is totally relying on that one iLogic shortcut snippet, which is unclear about which document it is targeting.  I suspect it may be trying to target the main assembly, because the main assembly would remain the 'active' document in this situation.  I have a slight edit you can make to that rule that should clear up the document reference thing, if that is the problem.

Try this edited version of your rule code in the sub assembly.

Dim oDoc As Document = ThisDoc.Document
SOP = iLogicVb.CreateObjectProvider(oDoc)
If SOP.Component.IsActive("SubComp2:1") = False Then
	SOP.Component.IsActive("SubComp1:1") = False
	SOP.Component.IsActive("SubComp2:1") = True
	SOP.Component.IsActive("SubComp3:1") = False
Else
	SOP.Component.IsActive("SubComp1:1") = True
	SOP.Component.IsActive("SubComp2:1") = False
	SOP.Component.IsActive("SubComp3:1") = True
End If

If that fixes the problem, but you have this same local rule within a lot of documents, there are ways of replacing the rule's code contents remotely in several documents with an external rule, or with an Autodesk AddIn called 'iLogic Rule Batch Tool'.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 8
ForrestJudd
in reply to: WCrihfield

No worries on any delay - I really appreciate your effort on this. I've never used iLogic Object Providers, so I may be using it wrong, but trying SOP.Component.IsActive() led to the following error when running the rule in the child component itself:

 

ForrestJudd_0-1665507867840.png

ForrestJudd_2-1665507907020.png

Which is weird, because the iLogic Code Editor implies that SOP.Component should be an ICadComponent:

ForrestJudd_3-1665508852856.png

However, in the screen capture above you can see I'm calling SOP.Component.Set_IsActive(), which does work in the child component rule. Unfortunately that doesn't solve the problem when calling from the main assembly. So I don't think this is an issue with context. 

 

Even trying to explicitly set the suppression state of a component in a child from the assembly when that child has Model States defined leads to an error. For example:

 

 

 

Dim TargetOcc As Inventor.ComponentOccurrence = ThisDoc.Document.ComponentDefinition.Occurrences.ItemByName("TestSubAssy211:1")

Dim TargetOccCompDef As AssemblyComponentDefinition = TargetOcc.Definition
Dim Part1Occ As Inventor.ComponentOccurrence = TargetOccCompDef.Occurrences.ItemByName("SubComp1:1")
Part1Occ.Suppress

 

 

 

ForrestJudd_5-1665509617125.png

 

Finally, I tried manipulating the Model State and member edit scope prior to changing the suppression state of the child component (when changing the state from the top level assembly) using the same logic as the original "Copy Parameter" sub you provided, and that still leads to the same error:

 

ForrestJudd_6-1665510678865.png

 

I was hoping there was a simple resolution to this problem, but at this point I'm wondering if there's any way at all to manage suppression state of components within child components -  whether from the top-level document or from within the child. Without further investigation, the two solutions I see right now are:

  • Update parameters in children, close the parent document, open all children individually and run their rules, then re-open the parent document
  • Remove model states entirely from the child components, at which point component suppression works without issue, regardless of the method used.

 

I've attached my test assembly in case you're interested. There's a lot of messy code now for the various things I've tried.

Message 6 of 8
J_Dumont
in reply to: ForrestJudd

Hello,

 

Are there any updates to this post? I'm running into the same issue when trying to change a parameter of a part that has model states from an assembly.

 

I found this in the iLogic help, but it's not working.

 

https://help.autodesk.com/view/INVNTOR/2022/ENU/?guid=GUID-418B956A-AC3F-48D8-BEBC-FC28C4B51DA2

 

 

Message 7 of 8
WCrihfield
in reply to: J_Dumont

Hi @J_Dumont.  The general subject of how to change parameter values in components from an assembly, when multiple ModelStates are involved has become a pretty popular topic here on this forum the last few years, since ModelStates were introduced in the 2022 version of Inventor.  There are several discussions, and multiple techniques being used in many different examples.  It is definitely more complicated than it used to be, but still doable.

 

Are you getting any useful error messages, or are they all just Unspecified Error (E-Fail) type messages pointing to lines of code where you are trying to change parameter values?  Are you only working with top level components, or are you also trying to change parameter values within parts that are within sub assemblies (or deeper)?  Are you using iLogic snippets (such as Parameter(), like in that link), or are you using Inventor API code paths for this task?  Got an example code you are having problems with, that you could share here, so that we could take a look at it?  Please be as specific and detailed as possible.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 8 of 8
J_Dumont
in reply to: ForrestJudd

Hey @WCrihfield 

Thanks for the quick reply.

 

Here is the code that changes the active model state and the parameter.

 

'Set Grille style using Model States
Dim LinearBarLength = GrillLength - GrillToFeameClearance
Component.ActiveModelState("Linear Bar")=BarGrilleStyle
InventorVb.DocumentUpdate() 
Parameter("Linear Bar", "Length") = LinearBarLength

Here is the message I received.

J_Dumont_0-1715347162652.png

 

 

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

Post to forums  

Technology Administrators


Autodesk Design & Make Report