Hello,
I'm working on creating an iLogic rule designed to change the model states of parts within an assembly depending on a binary choice at the beginning. I think I have most of it down, but I am running into the following error, and google has not been able to help me out as the error is a vague one.
Error on line 29 in rule: Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))
What's also strange, is is I say false/off for the prompt at the start, Line 36 will sometimes give the same error, but sometimes say "Class not specified." Can't replicate exactly when it says it. Just sometimes.
Below is my code, edited slightly to remove most comments:
iLogicVb.UpdateWhenDone = True Dim IsVisible As Boolean = InputRadioBox("Turn all Model States On/Off", "On", "Off", False, "Model State Toggle") Dim oAssyDoc As AssemblyDocument oAssyDoc = ThisApplication.ActiveDocument Dim oRefDocs As DocumentsEnumerator oRefDocs = oAssyDoc.AllReferencedDocuments Dim oRefDoc As Document For Each oRefDoc In oRefDocs If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then oModelStates = oRefDoc.ComponentDefinition.ModelStates If IsVisible = True Dim oModelState As ModelState oModelState = oModelStates.Item("ModelState2").Activate '<-- Line 29 End If If IsVisible = False Dim oModelState As ModelState oModelState = oModelStates.Item("[Primary]").Activate '<--Line 36 End If End If Next
Any help would be much appreciated!
Solved! Go to Solution.
Solved by Curtis_Waguespack. Go to Solution.
Add: Logger.Info(oRefDoc.FullFileName) after For to see which file is the problem.
You can see it in iLogic Log window.
Need to set log level to Info.
Maybe it cannot activate ModelState that is activated.
Check ActiveModel State first:
https://help.autodesk.com/view/INVNTOR/2024/ENU/?guid=ModelStates_ActiveModelState
Hi @Jack_DuttonTM2JK , there were a few things I noticed.
oModelState = oModelStates.Item("ModelState2").Activate '<-- Line 29
So we could do this with 2 lines, here we get the model state (noun) on the first line and then activate it (verb) on the second line, to get this to work:
oModelState = oModelStates.Item("ModelState2") oModelState.Activate
But having said that, since we're not really doing anything with the variable( the noun) , we don't really need it. We can just go straight to the verb and issue the action directly;
oModelStates.Item("ModelState2").Activate
3. With all of that in mind, the larger issue is that we need to access the factory document and get the model states collection from it, but the assembly is referencing a member document.
Frederick_Law's suggestion to peek at the logger was close, but if you were to look at the fullfilename of the part that is oRefDoc it would be something like this:
C:\Temp\Part1.ipt
but the fulldocumentname of oRefDoc would be something like this:
C:\Temp\Part1.ipt<Model State2>
So basically if we're working with a referenced document with model states we need to track up from it and get its factory document.
You can think of Model States like iParts in this sense that each member is it's own document and belongs to a parent/factory document. It's just that for model states, the member documents are "virtual" and don't live on disk, so we as users don't really know they exist, until we start doing this sort of task.
In any case, give this a try and I think it will work for you.
iLogicVb.UpdateWhenDone = True Dim IsVisible As Boolean = InputRadioBox("Turn all Model States On/Off", "On", "Off", False, "Model State Toggle") Dim oAssyDoc As AssemblyDocument oAssyDoc = ThisDoc.Document Dim oRefDocs As DocumentsEnumerator oRefDocs = oAssyDoc.AllReferencedDocuments Dim oRefDoc As Document For Each oRefDoc In oRefDocs If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then Logger.Info(oRefDoc.FullFileName)
Logger.Info(oRefDoc.FullDocumentName) Dim oDoc As PartDocument = oRefDoc.ComponentDefinition.FactoryDocument Dim oModelStates As ModelStates = oDoc.ComponentDefinition.ModelStates If IsVisible = True oModelStates.Item("ModelState2").Activate ElseIf IsVisible = False oModelStates.Item("[Primary]").Activate End If End If Next
Hi @Curtis_Waguespack and @Frederick_Law,
Thank you both for your help!
I implemented the changes Curtis proposed and no Error! However the code isn't doings what it's supposed to. Checking the log it's able to find the parts in the assembly, but it's not changing the models states.
I ran some tests on just a part file to make sure it would work, and it does. Just using a smaller version of the code above:
Dim IsVisible As Boolean = InputRadioBox("Turn all Model States On/Off", "On", "Off", False, "iLogic") Dim oDoc As PartDocument = ThisDoc.Document Dim oModelStates As ModelStates = oDoc.ComponentDefinition.ModelStates If IsVisible = True oModelStates.Item("ModelState2").Activate
ElseIf IsVisible = False oModelStates.Item("[Primary]").Activate End If
I put some MsgBox("test") commands after the If statements on IsVisible, and it reaches them. So Maybe the Activate command just doesn't work from the assembly level? Is this something you'd have to "traverse" the assembly for? I've seen that in some other commands but haven't used it before.
Again, thanks for the help!
@Jack_DuttonTM2JK, have a look at these examples.
The challenge to set a MS in all levels comes from the following:
So the 3rd example attempts to chain all this together, but I've not tested it well to see where it might run into issues. I left a lot of logger lines in it for you to try and help debug should you run into issues testing this, but in production it would be better to comment those out since writing lots of log lines can slow things down.
Hope this helps,
Curtis
1) Activate MS at document level
Dim IsVisible As Boolean = InputRadioBox("Turn all Model States On/Off", "On", "Off", False, "iLogic") Dim oDoc As Document = ThisDoc.Document.ComponentDefinition.FactoryDocument Dim oModelStates As ModelStates = oDoc.ComponentDefinition.ModelStates If IsVisible = True oModelStates.Item("ModelState2").Activate ElseIf IsVisible = False oModelStates.Item("[Primary]").Activate End If
2) Activate MS at first assembly level
( probably no reason to use this version, but it does provide a cleaner example of what is needed to work with MSs from the assembly)
iLogicVb.UpdateWhenDone = True Dim IsVisible As Boolean = InputRadioBox("Turn all Model States On/Off", "On", "Off", False, "Model State Toggle") Dim oAssyDoc As AssemblyDocument oAssyDoc = ThisDoc.Document Dim oDoc As PartDocument For Each oOcc As ComponentOccurrence In oAssyDoc.ComponentDefinition.Occurrences.AllLeafOccurrences If oOcc.Definition.Document.DocumentType = DocumentTypeEnum.kPartDocumentObject Then oDoc = oOcc.Definition.Document oDoc.Update2(False) If IsVisible = True oOcc.ActiveModelState = "ModelState2" ElseIf IsVisible = False oOcc.ActiveModelState = "[Primary]" End If End If Next
3) Activate MS at all levels
(Since we can't push MS changes down more then one level in an assembly, we need open the document and set the MS, and then set the MS in the assembly it is used in)
Sub Main Dim IsVisible As Boolean = InputRadioBox("Select", "MS2", "Primary", False, "Model State Toggle") Dim oDoc As AssemblyDocument = ThisDoc.Document 'activate ModelState in the top level If IsVisible = True ThisDoc.ActiveModelState = "ModelState2" ElseIf IsVisible = False ThisDoc.ActiveModelState = "[Primary]" End If oMSName = ThisDoc.ActiveModelState Call TraverseAssembly(oDoc.ComponentDefinition.Occurrences, oMSName) InventorVb.DocumentUpdate() End Sub Dim ProcesssedDocumentsList As New ArrayList Sub TraverseAssembly(Occurrences As ComponentOccurrences, oMSName As String) Dim oDoc As AssemblyDocument Dim oOcc As ComponentOccurrence For Each oOcc In Occurrences If oOcc.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then Call TraverseAssembly(oOcc.SubOccurrences, oMSName) End If 'get the parent, if it exists, open it and activate the model states in it If oOcc.ParentOccurrence IsNot Nothing Then Logger.Info("oOcc: " & oOcc.Name) Logger.Info("parent: " & oOcc.ParentOccurrence.Name) Call OpenParent(oOcc.ParentOccurrence, oMSName) ProcesssedDocumentsList.remove(oParentName = oOcc.ParentOccurrence.Definition.Document.fullfilename) End If InventorVb.DocumentUpdate() 'this update is important to keep the assembly synced Logger.Info(" oOcc: " & oOcc.Name) Logger.Info("Current MS: " & oOcc.ActiveModelState.ToString) Try oOcc.ActiveModelState = oMSName Catch Logger.Info("!!!!! Could not activate : " & oMSName & " in " & oOcc.Name) End Try Next End Sub Sub OpenParent(oParent As ComponentOccurrence, oMSName As String) oParentDoc = oParent.Definition.Document oParentDoc.Update2(False) oParentName = oParentDoc.fullfilename Logger.Info("oParentName: " & oParentName) 'if this doc has been proccessed already, skip it If ProcesssedDocumentsList.contains(oParentName) Then Exit Sub oDoc = ThisApplication.Documents.Open(oParentName, False) Logger.Info(" Opened: " & oDoc.fullfilename) ProcesssedDocumentsList.add(oDoc.fullfilename) oFactoryDoc = ThisDoc.Document.ComponentDefinition.FactoryDocument Try oFactoryDoc.ComponentDefinition.ModelStates(oMSName).activate Catch Logger.Info("!!!!!!!!!!!!!!!!!!!! Could not activate : " & oMSName & " in " & oParentName) End Try For Each iOcc In oDoc.ComponentDefinition.Occurrences Logger.Info("iOcc: " & iOcc.Name) iOcc.ActiveModelState = oMSName Next oDoc.Close Logger.Info(" Closed: " & oDoc.fullfilename) End Sub
WOOOW! Curtis you are a GENIUS! It took me some time to go line by line and understand everything, but it works perfectly! I made a few personal adjustments right at the top to not change the parent document model states. So I just commented out the:
If IsVisible = True ThisDoc.ActiveModelState = "Cad_Aids" ElseIf IsVisible = False ThisDoc.ActiveModelState = "[Primary]" End If
oMSName = ThisDoc.ActiveModelState
And replaced it with:
If IsVisible = True oMSName = "ModelStates2" ElseIf IsVisible = False oMSName = "[Primary]" End If
Mine is less future proof with the hard callouts, but it works out, haha.
But honestly I first tested it but just copy pasting you exact code and it worked, so again thank you very much sir!
Can't find what you're looking for? Ask the community or share your knowledge.