Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
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: 

Create Model States using iLogic

20 REPLIES 20
SOLVED
Reply
Message 1 of 21
zoe.baker-bushby
4288 Views, 20 Replies

Create Model States using iLogic

I have an assembly that has a duplication of the same part. 

The part has only the master model state, but I want to be able to add model states to this part via ilogic.

 

This line creates model states at the assembly level (which I don't need).

oModelState = oDoc.ComponentDefinition.ModelStates.Add(oName)
		oDoc.ActiveModelState = oName

 

This is what I am trying to do... vaguely...

Dim oDoc As AssemblyDocument
	
Dim oOcc As ComponentOccurrence 	
For Each oOcc In Occurrences
'The below line does not work, what is the correct syntax????
oOcc.ComponentDefinition.ModelStates.Add(oName)
next

 

Any help/advice would be great?

 

Labels (3)
20 REPLIES 20
Message 2 of 21

This might get you closer to your goal.

Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
'define the variable "oName"
oName = "ModelState1"
For Each oOcc As ComponentOccurrence  In oADoc.ComponentDefinition.Occurrences
    If TypeOf oOcc.Definition Is PartComponentDefinition Then
		Dim oPDef As PartComponentDefinition = oOcc.Definition
		Dim oFound As Boolean  = False
		For Each oMS As ModelState In oPDef.ModelStates
			If oMS.Name = oName Then
				oFound = True
				Exit For 'found it, so don't create it
			End If
		Next
		If oFound = False Then
			'did not find it, so create it
			oPDef.ModelStates.Add(oName)
		End If
		oOcc.ActiveModelState = oName
	End If
Next

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 :light_bulb: or you can Explore My CONTRIBUTIONS

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 21
JelteDeJong
in reply to: WCrihfield

I see @WCrihfield was just a bit faster than me but here is my approach.

Dim doc As AssemblyDocument = ThisDoc.Document
Dim occ As ComponentOccurrence = doc.ComponentDefinition.Occurrences.Item(1)

Dim facDoc As PartDocument = occ.Definition.Document
If (facDoc.ComponentDefinition.IsModelStateMember) Then
    facDoc = facDoc.ComponentDefinition.FactoryDocument
End If
Dim modelStates As ModelStates = facDoc.ComponentDefinition.ModelStates
Dim newModelStateName = "YourNameHere"
Dim modelState As ModelState = modelStates.Add()
modelState.Name = newModelStateName
modelState.Activate()

occ.ActiveModelState = newModelStateName

if you want to know why I find the factory document first then you can read my blog post on that topic.

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

Message 4 of 21

Both solutions work quite well! Thank you both 😀

Message 5 of 21

Having some issues running rules/setting parameters on the new active model state

I have used the solution code with minor alterations:

Dim doc As AssemblyDocument = ThisDoc.Document
Dim occ As ComponentOccurrence '= doc.ComponentDefinition.Occurrences.Item(1)

Dim oName = "COURSE 1 STEEL TANK SHEET:8"

For Each occ In doc.ComponentDefinition.Occurrences
	If occ.Name = oName Then
		Dim facDoc As PartDocument = occ.Definition.Document
		If (facDoc.ComponentDefinition.IsModelStateMember) Then
		    facDoc = facDoc.ComponentDefinition.FactoryDocument
		End If
		Dim modelStates As ModelStates = facDoc.ComponentDefinition.ModelStates
		Dim newModelStateName = "N1"
		Dim modelState As ModelState = modelStates.Add()
		modelState.Name = newModelStateName
		modelState.Activate()
		occ.ActiveModelState = newModelStateName
	End If
Next

ilogicVb.RunRule("COURSE 1 STEEL TANK SHEET:8", "ManwayCutOut")

Here it goes through each occurrence and looks for 'COURSE 1 STEEL TANK SHEET:8' which is the occurrence of the part that I want on the different model state. (So part such as COURSE 1 STEEL TANK SHEET:1 will still be set to Master model state.)  

The issue is that it will not then run the last line. We get a lovely unspecified error. The rule 'ManwayCutOut' does exist in this part. If I go and delete the new ModelState and have every thing back on Master I can run this one line fine...

Had issues with the following line too

Parameter("COURSE 1 STEEL TANK SHEET:" & BespokeSheet, "ManwayType") = MWAY_TYPE

Which again if I delete the new ModelState and have everything back on Master I can run both the parameter line and the ilogicvb.runrule line.

 

Tried a different approach with setting everything to the new Model State and then running the issue lines but still get the unspecified error...

 

Any advise/help??

 

Message 6 of 21

Can you post an images of what the other tab of that error message says?  Most often the "More Info" tab of those error messages contains more useful information, so I usually advise folks to post an image of the contents of both tabs of any error messages they get, when trying to diagnose the error.

 

Also, just a tip, but if you just want to work with one specifically named component, you can get it directly by its name (using ItemByName()), without needing to loop through all components, unless that component is at a lower level (below some sub-assemblies).  Here is an alternative to the last code you posted that shows how to use this technique.

Dim doc As AssemblyDocument = ThisDoc.Document
oName = "COURSE 1 STEEL TANK SHEET:8"
occ = doc.ComponentDefinition.Occurrences.ItemByName(oName)
Dim facDoc As PartDocument = occ.Definition.Document
oPCD = facDoc.ComponentDefinition
If oPCD.IsModelStateMember Then
	facDoc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = "N1"
oMState = oMStates.Add(newModelStateName)
oMState.Activate()
occ.ActiveModelState = newModelStateName
iLogicVb.RunRule(oName, "ManwayCutOut")

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 21

You may also want to post the contents of that other rule you are trying to run, because the error message suggests that the error is in that rule.  It may have to do with document references and/or using iLogic snippets that target the 'active' document by default, when you may need to be more specifically targeting the 'local' document instead.  When running code from a main assembly, usually that main assembly will remain the 'active' document, until you do something that 'activates' another document to become the 'active' document.  This little issue trips tons of folks up, and it can be difficult to diagnose without lots of experience/knowledge about the references/methods being used.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 8 of 21

Here is the ManwayCutOut rule:

 

If ManwayType = 600 Then
Feature.IsActive("MWAY600 Centre") = True
Feature.IsActive("MWAY600 Holes") = True
Feature.IsActive("MWAY600 PCD") = True
Feature.IsActive("MWAY800 Centre") = False
Feature.IsActive("MWAY800 Holes") = False
Feature.IsActive("MWAY800 PCD") = False
Feature.IsActive("MWAY900 Centre") = False
Feature.IsActive("MWAY900 Holes") = False
Feature.IsActive("MWAY800 PCD") = False

Else If ManwayType = 800 Then
Feature.IsActive("MWAY800 Centre") = True
Feature.IsActive("MWAY800 Holes") = True
Feature.IsActive("MWAY800 PCD") = True
Feature.IsActive("MWAY600 Centre") = False
Feature.IsActive("MWAY600 Holes") = False
Feature.IsActive("MWAY600 PCD") = False
Feature.IsActive("MWAY900 Centre") = False
Feature.IsActive("MWAY900 Holes") = False
Feature.IsActive("MWAY900 PCD") = False

Else If ManwayType = 900 Then
Feature.IsActive("MWAY900 Centre") = True
Feature.IsActive("MWAY900 Holes") = True
Feature.IsActive("MWAY900 PCD") = True
Feature.IsActive("MWAY800 Centre") = False
Feature.IsActive("MWAY800 Holes") = False
Feature.IsActive("MWAY800 PCD") = False
Feature.IsActive("MWAY600 Centre") = False
Feature.IsActive("MWAY600 Holes") = False
Feature.IsActive("MWAY600 PCD") = False

End If


iLogicVb.UpdateWhenDone = True

With the additional error message tab attached.

 

Your new code works, just again will not run the:

iLogicVb.RunRule(oName, "ManwayCutOut")

 

Message 9 of 21

OK.  So in this case, the info in that other tab wasn't that helpful after all.  But after seeing your other rule, I can instantly see why it is having problems.  You are using the unquoted names of local parameters and the Feature.IsActive() iLogic snippet without specifying a target component name or document name.  That set-up is usually great for local rules, but when you run that rule remotely, while another document is the 'active' document, it may cause problems.  I'm not 100% sure whether the Feature.IsActive() iLogic snippet targets the 'active' document or the 'local' document by default, when you don't specify a component name or document name as the first input variable.  I assume it is targeting the 'active' document though.  And in this case, the main assembly is still the 'active' document when this rule is getting ran remotely, which may be causing the problem.

 

There are some alternative ways this rule could be laid out, but it starts to get more complicated when we do.

What I would suggest first, before attempting to rewrite your local rule differently, would be to activate this document just before we use that line of code to run it.  That may eliminate the problem.  If not, then we may look into rewriting that rule a bit to make it work in this situation.

So...I just slightly tweaked the earlier main code to activate that part document just before the line to run the rule.

Dim doc As AssemblyDocument = ThisDoc.Document
oName = "COURSE 1 STEEL TANK SHEET:8"
occ = doc.ComponentDefinition.Occurrences.ItemByName(oName)
Dim facDoc As PartDocument = occ.Definition.Document
oPCD = facDoc.ComponentDefinition
If oPCD.IsModelStateMember Then
	facDoc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = "N1"
oMState = oMStates.Add(newModelStateName)
oMState.Activate()
occ.ActiveModelState = newModelStateName
facDoc.Activate
iLogicVb.RunRule(oName, "ManwayCutOut")
're-activate the main assembly afterwards, if needed
'but test both ways, in case more time is needed for the rule to do its thing
'doc.Activate

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 10 of 21

Hi thank you for your help so far!

 

Having issues with this code:

It requires me to have the part open along side the assembly so that it can run:

facDoc.Activate

I can not work with having the part open along side the assembly, so is there anyway around this?

 

Testing WITH the part open so that the facDoc.Activate line runs still does not solve the run issue of:

iLogicVb.RunRule(oName, "ManwayCutOut")

 

You mentioned being able to approach this by setting up the "ManwayCutOut" rule so that it can be run remotely, it may be better to try that approach if you have any advice on that?

 

Any more help/advice would be great

 

Message 11 of 21

OK. That's fine. Generally, unless the assembly is in 'Express Mode' all components within the assembly are at least 'initiated', if not fully open (in the background, not visibly). So you usually don't have to open or close any of those documents that are being represented by the components. But I can understand not wanting the other document visibly activated, especially when the code leaves them that way when its done. It can be annoying and might possibly interfere with other operations.

 

Sure, we can look into changing that other rule as needed for this situation.  I created something for you to try.  I left several lines of comments in this code for you, just as additional information that may be useful to you.  When dealing with parameters, there is a tricky & extremely annoying situation to be aware of, involving the 'units' of any numerical values (other than unit-less).  There are several ways of accessing and dealing with parameters, and some return different results than others.  When using either the unquoted name of a 'local' parameter in a 'local' rule, and when using the iLogic snippet 'Parameters("parameter_name")', these will both return the true 'document units' value of the parameter directly.  But when using either the iLogic snippet 'Parameter.Param("parameter_name").Value', or the normal API way 'Document.ComponentDefinition.Parameters.Item("parameter_name").Value' to get the parameter's value, it will return the 'database units' version of its Value, instead of the 'document units' version of it.  I generally prefer to use the API route, then convert the units back as needed, instead of using the iLogic snippets for this task, because it's more reliable, clearer, & better documented.  But I would need to know what type of units were being used ahead of time, to convert the units properly within the code.

 

Here is the new version of that local rule that you can try:

 

'just using a dummy variable here,
'to preserve automation/triggering behavior of unquoted local parameter
oDV = ManwayType

'get the 'local' part document object (the document this rule is saved within)
Dim oPDoc As PartDocument = ThisDoc.Document
oPDef = oPDoc.ComponentDefinition

'if the parameter is numerical, and not unit-less,
'this will return 'database units' version of the parameter's Value,
'not the 'document units' version of it
'oManwayType = oPDef.Parameters.Item("ManwayType").Value

oDocName = ThisDoc.FileName(True)

'these two will get the 'document units' version of the parameter's Value
'oManwayType = ManwayType 'unquoted parameter name
oManwayType = Parameter(oDocName, "ManwayType")

oFeats = oPDef.Features

If oManwayType = 600 Then
	oFeats.Item("MWAY600 Centre").Suppressed = False
	oFeats.Item("MWAY600 Holes").Suppressed = False
	oFeats.Item("MWAY600 PCD").Suppressed = False
	oFeats.Item("MWAY800 Centre").Suppressed = True
	oFeats.Item("MWAY800 Holes").Suppressed = True
	oFeats.Item("MWAY800 PCD").Suppressed = True
	oFeats.Item("MWAY900 Centre").Suppressed = True
	oFeats.Item("MWAY900 Holes").Suppressed = True
	oFeats.Item("MWAY800 PCD").Suppressed = True
ElseIf oManwayType = 800 Then
	oFeats.Item("MWAY800 Centre").Suppressed = False
	oFeats.Item("MWAY800 Holes").Suppressed = False
	oFeats.Item("MWAY800 PCD").Suppressed = False
	oFeats.Item("MWAY600 Centre").Suppressed = True
	oFeats.Item("MWAY600 Holes").Suppressed = True
	oFeats.Item("MWAY600 PCD").Suppressed = True
	oFeats.Item("MWAY900 Centre").Suppressed = True
	oFeats.Item("MWAY900 Holes").Suppressed = True
	oFeats.Item("MWAY900 PCD").Suppressed = True
ElseIf oManwayType = 900 Then
	oFeats.Item("MWAY900 Centre").Suppressed = False
	oFeats.Item("MWAY900 Holes").Suppressed = False
	oFeats.Item("MWAY900 PCD").Suppressed = False
	oFeats.Item("MWAY800 Centre").Suppressed = True
	oFeats.Item("MWAY800 Holes").Suppressed = True
	oFeats.Item("MWAY800 PCD").Suppressed = True
	oFeats.Item("MWAY600 Centre").Suppressed = True
	oFeats.Item("MWAY600 Holes").Suppressed = True
	oFeats.Item("MWAY600 PCD").Suppressed = True
End If

oPDoc.Update

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 12 of 21

Hi,

 

Having issues with this line:

Parameter.Param().Value

See error message images attached

(Is line 47 due to commenting out the previous code for safe keeping)

 

Little out of my depth here but you are explaining everything clearly so thank you for that.

 

 

Message 13 of 21

Oops... I didn't mean to leave that line in there.  I was just playing around with the different methods of getting that parameter.  Just delete that whole line.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 14 of 21

Thought it was out of place 🙂

 

Still having issues with getting the rule to run, definitely need to go back to approaching it from assembly level?

 

So just to refresh:

We have an assembly with duplications of the same part. 

We are selecting part variation 'COURSE 1 STEEL TANK SHEET:8'.

We are creating a new model state within this part called N1.

We are activating this model state on just this variation, the other parts are still set to Master. (All this is successful!)

Then we are wanting to run a rule within COURSE 1 STEEL TANK SHEET:8 while it is on model state N1...

This rule is to unsuppress features so that N1 model state differs from the Master model state.

 

This can all be done manually but we want to have it all automatic...

 

This works to create the N1 model state within COURSE 1 STEEL TANK SHEET:8

Dim doc As AssemblyDocument = ThisDoc.Document
oName = "COURSE 1 STEEL TANK SHEET:8"
occ = doc.ComponentDefinition.Occurrences.ItemByName(oName)
Dim facDoc As PartDocument = occ.Definition.Document
oPCD = facDoc.ComponentDefinition
If oPCD.IsModelStateMember Then
	facDoc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = "N1"
oMState = oMStates.Add(newModelStateName)
oMState.Activate()
occ.ActiveModelState = newModelStateName

 

However this line will not run (when added at the end):

iLogicVb.RunRule(oName, "ManwayCutOut")

 

So attempted:

Dim doc As AssemblyDocument = ThisDoc.Document
oName = "COURSE 1 STEEL TANK SHEET:8"
occ = doc.ComponentDefinition.Occurrences.ItemByName(oName)
Dim facDoc As PartDocument = occ.Definition.Document
oPCD = facDoc.ComponentDefinition
If oPCD.IsModelStateMember Then
	facDoc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = "N1"
oMState = oMStates.Add(newModelStateName)
oMState.Activate()
occ.ActiveModelState = newModelStateName
facDoc.Activate
iLogicVb.RunRule(oName, "ManwayCutOut")
're-activate the main assembly afterwards, if needed
'but test both ways, in case more time is needed for the rule to do its thing
'doc.Activate

But the iLogicVb.RunRule(oName, "ManwayCutOut") still will not run.

And I can not work with having the COURSE 1 STEEL TANK SHEET:8 part visibly active along side the main assembly.

 

Then we tried changing the ManwayCutOut rule but this doesn't fix it as the call from the higher level rule just does not work.

 

I tried a test:

iLogicVb.RunRule(oName, "TEST")

Run a rule in COURSE 1 STEEL TANK SHEET:8 while N1 Model State is active where TEST had the following code:

MessageBox.Show("WORKING")

But this will not even run...

 

So I believe the runrule triggger is not working due to the activity state, so can we make the COURSE 1 STEEL TANK SHEET:8 active without it being visibly active??

 

I hope this is clear.

 

Thanks

Message 15 of 21

Based on that recap and what you said at the end of 'Message 5', my best guess is that there is a bug preventing us from running local rules (or all rules effecting that document) while a ModelState other than "Master" is active.  It kind of sounds familiar...like I've heard about this before somewhere, but I can't remember where.  May have been a webinar or something about the current limitations of ModelStates.  And it also seems to be blocking your simple call to set the value of the parameter while a ModelState other than "Master" is active.  I know that non-Master ModelStates have a table in them that can be edited, similar to an iPart, iAssembly, or iFeature table, that can be edited like a spreadsheet (with Excel or whatever native editor you have).  And I know that the ModelStates object has a MemberEditScope property that needs to be set to specify whether changes effect all ModelStates or just the 'active' ModelState.  But I honestly have not tried this specific task before yet.

 

Here's a thought as we explore this idea.  I bet we have to first set the MemberEditScope setting to "kEditActiveMember" (without quotes).  Then either edit the table, or dig down into the ModelState.FactoryDocument, then into its ComponentDefinition.Parameters.Item("parameter_name").Value to get/set its value only for that one ModelState, when dealing with a Parameter.  Similar process for suppressing or un-suppressing a feature only in that one ModelState.  Using the API route would look like oModelState.FactoryDocument.ComponentDefinition.Features.Item("feature name").Suppressed = True.  We may have to do all of this from that main rule in the assembly, instead of using that local rule within the part document.  I'm not 100% sure, though.  The process I just stated makes better/clearer sense to me right now though.  If we were to edit the table, it might get more complicated, because we won't know how its all laid out to find stuff within, so we would likely have to use a series of loops through rows & columns to find the right cell values to change.

 

PS.  I tested that route on a test assembly and it works.  (Digging down into the FactoryDocument to get the Parameters & Featrues, that is.)

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 16 of 21

Got the following to work:

Dim doc As AssemblyDocument = ThisDoc.Document
oName = "COURSE 1 STEEL TANK SHEET:8"
occ = doc.ComponentDefinition.Occurrences.ItemByName(oName)
Dim facDoc As PartDocument = occ.Definition.Document
oPCD = facDoc.ComponentDefinition
If oPCD.IsModelStateMember Then
	facDoc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = "N1"
oMState = oMStates.Add(newModelStateName)
oMState.Activate()
occ.ActiveModelState = newModelStateName

oMState.FactoryDocument.ComponentDefinition.Features.Item("MWAY900 Centre").Suppressed = False
oMState.FactoryDocument.ComponentDefinition.Features.Item("MWAY900 Holes").Suppressed = False
oMState.FactoryDocument.ComponentDefinition.Features.Item("MWAY900 PCD").Suppressed = False

 

This does require shifting the ManwayCutOut code into this top level rule, which I can do. It is a workable solution.

However it certainly seems to be the long way to do it, the ilogicvb.runrule trigger should work. I will report this as a possible bug.

 

Thank you for all of your help, finally have a workable solution! 😀

 

 

 

 

Message 17 of 21
junGQMXK
in reply to: zoe.baker-bushby

Hi, zoe.baker-bushby,

 

recently we were trying to transfer to inventor 2022. I am trying to imitate the suppress and unsuppress operations under LOD by using model state. I really met a lot of difficulties and puzzles.

 

1. you said you would report some potential bugs to autodesk. Did you report them? did you get any feedback from autodesk? The difficulties you met are bugs or not?

 

2. have you found any good methods to do suppress and unsuppress locally inside a part or assembly?

 

thank you in advance.

Message 18 of 21
zoe.baker-bushby
in reply to: junGQMXK

Hi,

We did report some bugs to autodesk. It has been confirmed that there are issues with moving LOD parts with suppressed parts into 2022. We have rules that suppress/unsuppress parts but due to moving to 2022 these would not run. 

We got given a rule to run to delete all iLogic LOD in an assembly, info can be found here:

https://knowledge.autodesk.com/support/inventor/troubleshooting/caas/sfdcarticles/sfdcarticles/The-C...

 

This then allowed us to resume normally running of our code. 

 

Hope this helps with what you are after.

Message 19 of 21
tecnico
in reply to: zoe.baker-bushby

it is possible to create a similar rule but which allows, within the PART, to create a model state with the same name as the modified parameter (For example, parameter name HEIGHT = 30 MODEL STATUS = 30)
and if it does not exist, create it otherwise activate the already existing one? I think you can also use the way of a list that is updated with each new value.

 

* I asked the same question also in another discussion but I realized only now that they were discussing in a group environment

Message 20 of 21
zoe.baker-bushby
in reply to: tecnico

Not completely certain what you are asking but I have put this together:

Dim Doc As PartDocument = ThisDoc.Document
oPCD = Doc.ComponentDefinition
If oPCD.IsModelStateMember Then
	Doc = oPCD.FactoryDocument
End If
oMStates = oPCD.ModelStates
newModelStateName = HEIGHT
oMState = oMStates.Add(newModelStateName)

 Hope that helps 😊

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

Post to forums  

Autodesk Design & Make Report