- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I have the following code to update the names in my assembly browser tree in Inventor 2021. It works fine but the model tree does not show the updates until the rule is done so the message box is shown before the model tree is visually updated.
in the code debug.print() just wraps messagebox.show() in a custom library I have for debugging my code. This is a remnant of days before Logger.
For Each oCompOcc In oCompDef.Occurrences
occNum = GetDigitsAfterColon(oCompOcc.Name)
If occNum Is Nothing Then badOcc = True
debug.Print(2, "occNum " & occNum, ruleName)
sPartNum = iProperties.Value(oCompOcc.Name, "Project", "Part Number").Trim()
sPartDesc = iProperties.Value(oCompOcc.Name, "Project", "Description").Trim()
If Len(sPartDesc) = 0 Then badOcc = True
newBrowserName = sPartNum & " ~ " & If(len(sPartDesc) > 0, sPartDesc, "▲▲▲ Missing Description ▲▲▲") & ":" & If(occNum IsNot Nothing, occNum,"▲▲▲ Missing Instance ID ▲▲▲")
oCompOcc.Name = newBrowserName
Next
If badOcc Then
debug.Print(0,"You have 1 or more parts with a missing Description or a missing instance ID." & vbCrLf & vbCrLf & "Please edit the part and update the Description iProperty using the Model Properties Form and save the part." & vbCrLf & vbCrLf & "For a missing Instance ID, please edit the description in the assembly model tree and add one. "":1""", ruleName)
End If
This is how it behaves.
This is how it should look
I want that view before the messagebox pops up so the user can identify the nonconforming parts while the error is on screen.
This is problematic. How can I ensure that the browser tree is visually updated prior to showing the messagebox using my debug.print()?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
If when you call debug.print, that shows a MessageBox, and you have that code within the loop for every component, then there is not much way to avoid it showing before the task is complete. You could try a line of code to update the assembly just before calling that debug.print line, but I do not see a variable with a reference to the main assembly shown in your example code. Something like AssemblyDocument.Update, AssemblyDocument.Update2, or ThisApplication.ActiveView.Update. It looks like your code renames all components starting with their Part Number iProperty value, followed by their Description iProperty value, if available. Have you thought about creating a collection before the loop starts, then within the loop, if a problem component is found, you could add that component to the collection, that way you still have a reference to the problem components when the process is done, and can do something with them at that point? We could also help you re-write the code in some way, if needed. Do you just maintain the portion after the colon (:) then?
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
@WCrihfield Thank you for your time. Here is the entire rule. We have a template for rules that this is built using. Should be easy enough to follow. I added all three update lines in and still have the same behavior. If I am approaching this wrong, I am open to any suggestion on how to restructure this. We are attempting to maintain the instance number that was provided by Inventor. Occasionally someone will rename a browser node and remove the :# so our existing script (not written by me) crashes. This is my attempted rewrite into our template with some added functionality to help identify the problem components and avoid the generic exception message.
'Define Imports below
Imports System.Text.RegularExpressions
AddVbFile "LSIiLogicLibrary.VB"
AddVbFile "LSIiLogicDebugger.VB"
Class BrowserNames
' Instantiate the LSI iLogic Function Library
Shared Dim lsiLib As LSIiLogicLibrary = New LSIiLogicLibrary
' Instantiate the LSI Debugging Library and set the debugging level for this rule
' - 0 = None; 1 = Minimal; 2 = Verbose
Shared Dim debug As LSIiLogicDebugger = New LSIiLogicDebugger(0)
' Set the rule name for use later in the rule
Shared Dim ruleName As String = "Browser Names"
Sub Main()
'Rule: BrowserNames
'Purpose: This rule updates the model browser to show PN ~ DESCRIPTION : OCCURRENCE
' If the description is blank, an error will be shown with instructions on how to correct it
'Set initial script references to the Inventor Application and the Document
Dim oApp As Inventor.Application = ThisApplication
Dim doc, oDoc As Document
doc = ThisDoc.Document
oDoc = oApp.ActiveDocument
' Set the type of document this rule is targeted to
' - valid entries are "Drawing", "Part", "Assembly"
Dim ruleTargetType() As String = {"Assembly"}
' Test If we are actually in the document before running rule
' - prevents running rule if triggered from another doc
If Not doc Is oDoc Then
Exit Sub
End If
' Test If we are in the correct document type for the rule
' - prevents running the rule on an incorrect document type
If Not lsiLib.checkDocType(ruleTargetType, oDoc.DocumentType) Then
Dim msgStr = "This is not the correct document type for rule """ & ruleName & """." + vbCrLf + "The correct document types are: "
For i As Integer = 0 To UBound(ruleTargetType)
msgStr = msgStr + vbCrLf + vbTab + ruleTargetType(i)
Next
debug.Print(0, msgStr, ruleName, MessageBoxButtons.OK, MessageBoxicon.Information)
Exit Sub
End If
'Setup TransactionManager so we can undo our changes later
Dim oTransMgr As TransactionManager = oApp.TransactionManager
Dim oTrans As Transaction
Try
debug.Print(1,"Running the rule", ruleName)
'Begin the transaction
oTrans = oTransMgr.StartTransaction(oDoc, ruleName)
' Rule code should be placed in Sub Rule() below
Rule(oApp, oDoc)
'End and commit the transaction for later Undo
If Not oTrans Is Nothing Then
oTrans.End()
End If
Catch ex As Exception
' Abort the transaction so we dont leave it orphaned (avoid possible memory leak)
If Not oTrans Is Nothing Then
oTrans.Abort()
End If
debug.Print(0,"There is an error in the script. Please see the notes below or notIfy the script author." & vbCrLf & "Please provide the drawing/part number, rev and the following error text." & vbCrLf & vbCrLf & ruleName & ": " & ex.Message, ruleName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
End Try
'Update the document
InventorVb.DocumentUpdate()
End Sub
'
' Rule(oApp As Inventor.Application, oDoc as Document)
' - This is where the actual rule code lives.
' - We Get a reference To the Application And the Active Document by default
'
Sub Rule(oApp As Inventor.Application, oDoc As Document)
' Comment the following line if using Try...Catch in the rule
' On Error Resume Next
' Cast the current document to the correct type based on what we expect it to be
' as different document types have similar methods that do different things, we
' need to specify the document type and use the correct types in our script
Dim oPartDoc As PartDocument
Dim oAsmDoc As AssemblyDocument
Dim oDrawDoc As DrawingDocument
Select Case oDoc.DocumentType
Case Inventor.DocumentTypeEnum.kDrawingDocumentObject
'Document is a Drawing. Use oDrawDoc as your docuemnt reference in your code
oDrawDoc = DirectCast(oDoc, DrawingDocument)
Case Inventor.DocumentTypeEnum.kAssemblyDocumentObject
'Document is an Assembly. Use oAsmDoc as your docuemnt reference in your code
oAsmDoc = DirectCast(oDoc, AssemblyDocument)
Case Inventor.DocumentTypeEnum.kPartDocumentObject
'Document is a Part. Use oPartDoc as your docuemnt reference in your code
oPartDoc = DirectCast(oDoc, PartDocument)
End Select
debug.Print(2,"Document cast successful!", ruleName) 'This was just a placeholder that was never removed from the template
'Begin code here
Dim badOcc As Boolean = False
Dim oCompDef As Inventor.ComponentDefinition = oAsmDoc.ComponentDefinition
Dim oCompOcc As Inventor.ComponentOccurrence
Dim oPartCompDef As Inventor.PartComponentDefinition
Dim oPane As BrowserPane = oAsmDoc.BrowserPanes.Item("Model")
Dim occNum, sPartNum, sPartDesc As String
For Each oCompOcc In oCompDef.Occurrences
occNum = GetDigitsAfterColon(oCompOcc.Name)
If occNum Is Nothing Then badOcc = True
debug.Print(2, "occNum " & occNum, ruleName)
sPartNum = iProperties.Value(oCompOcc.Name, "Project", "Part Number").Trim()
sPartDesc = iProperties.Value(oCompOcc.Name, "Project", "Description").Trim()
If Len(sPartDesc) = 0 Then badOcc = True
oCompOcc.Name = sPartNum & " ~ " & If(len(sPartDesc) > 0, sPartDesc, "▲▲▲ Missing Description ▲▲▲") & ":" & If(occNum IsNot Nothing, occNum,"▲▲▲ Missing Instance ID ▲▲▲")
Next
oAsmDoc.Update2()
InventorVb.DocumentUpdate()
ThisApplication.ActiveView.Update()
If badOcc Then
debug.Print(0,"You have 1 or more parts with a missing Description or a missing instance ID." & vbCrLf & vbCrLf & "Please edit the part and update the Description iProperty using the Model Properties Form and save the part." & vbCrLf & vbCrLf & "For a missing Instance ID, please edit the description in the assembly model tree and add one. "":1""", ruleName)
End If
End Sub
Function GetDigitsAfterColon(input As String) As String
Dim regexPattern As String = ":(\d+)$" ' colon character followed by one or more digits
Dim match As Match = Regex.Match(input, regexPattern)
If match.Success Then
' Extract and return the digits
Return match.Groups(1).Value
Else
' No match found
Return Nothing
End If
End Function
End Class
Again, I am super grateful for your eyes on this. Please feel free to tear this down. I am just a hobbyist programmer and some of this might be inefficient or just wrong. Thank you.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
As a reference, here is the original rule that was given to us by a vendor before my time here.
Dim oDoc As Document = ThisDoc.Document
Dim oCompDef As Inventor.ComponentDefinition = oDoc.ComponentDefinition
Dim oCompOcc As Inventor.ComponentOccurrence
For Each oCompOcc in oCompDef.Occurrences
searchfor = ":"
firstchr = oCompOcc.Name.IndexOf(searchfor)
firstchr = firstchr+1
totalchr = Len(oCompOcc.Name) - firstchr
post1 = Right(oCompOcc.Name, totalchr)
newBrowserName1 = iProperties.Value(oCompOcc.Name, "Project", "Part Number") & post1
oCompOcc.Name = newBrowserName1
newBrowserName2 = iProperties.Value(oCompOcc.Name, "Project", "Part Number") & " ~ " & iProperties.Value(oCompOcc.Name, "Project", "Description") & ":" & post1
oCompOcc.Name = newBrowserName2
firstchr= ""
totalchr= ""
post1 = ""
newBrowserName1 = ""
newBrowserName2= ""
Next
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi @tfrohe_LSI. That is certainly a long and involved rule template you have there, and it even seems to be referencing two other external iLogic rules for extra functionality. It does seem like a bit of overkill to me, but if that system is working OK for you guys, then who am I to judge. I also occasionally use references to external rules with extra resources in them from time to time. There are several ways that this situation could be handled differently, but I guess it all comes down to personal preference and what you ideally want to see happen (how you want it to work). Just attempting to maintain the existing integers at the end of the component name may not be enough in a situation like this, but there is only one way to find out...testing. The code you are using to extract the digits after the colon is a fairly advanced technique that I do not see that often, so I have not used it for that exact purpose before. I generally just first make sure that the component name 'Contains' the ":" (colon) character, then use the 'Split' function to split the name into the portion before that character, and the portion after that character. Of course, if for some reason three is more than one colon character in its name, that would normally cause problems.
I created an alternate iLogic rule of my own, just as something to try out or compare with the functionality of your current solution. It does utilize the Logger functionality to log some useful information to the iLogic Log window, but you can comment those lines out, if you do not want to pay attention to that as a resource. This code also keeps track of all components that encountered issues with a 'Dictionary' type collection. Each entry would potentially contain the component object as its 'Key', and a note/message about what was wrong with that component as the value of the dictionary entry. Then, if any problem components were found, it loops back through those problem components, informing you about the current name of each one, and what the problem was. As I said, there are many directions and different actions that could be done here, so this is just one possibility among many. I could have also added the problem components to a HighlightSet, as an additional way to point them out, but that is often just a fleeting moment that they remain highlighted, so often not super helpful.
Sub Main
If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("An Assembly Document must be active for this rule to work. Exiting.", vbCritical, "")
Return
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oOccs As ComponentOccurrences = oADoc.ComponentDefinition.Occurrences
If oOccs.Count = 0 Then Return
Dim oOccsWithProblems As New Dictionary(Of Inventor.ComponentOccurrence, String)
For Each oOcc As ComponentOccurrence In oOccs
If oOcc.Name.Contains(":") Then
'assumes that there is just one instance of the ":" string present
'if more than that, that would mess this process up
Dim oSections() As String = oOcc.Name.Split(":") 'split the name into multiple Strings devided by the ":" character
If oSections.Length <> 2 Then
'the split resulted in more or less than 2 Strings
'code here for what to do about that situation
oOccsWithProblems.Add(oOcc, "More Or Less Than 2 Sections In Name When Split By Colon")
Continue For 'skip to next component
End If
Dim sName As String = oSections.First 'the portion of the name before the ":" character
Dim sInstance As String = oSections.Last 'the portion of the name after the ":" character
Dim sPN As String = iProperties.Value(oOcc.Name, "Project", "Part Number")
If sPN = "" Then
'what to do when the Part Number iProperty value is empty
Logger.Debug("Component named: " & oOcc.Name & vbCrLf & _
"...had empty Part Number value.")
sPN = "▲▲▲ Missing Part Number ▲▲▲"
oOccsWithProblems.Add(oOcc, "Empty Part Number")
'Continue For 'skip to next component
End If
Dim sDesc As String = iProperties.Value(oOcc.Name, "Project", "Description")
If sDesc = "" Then
'what to do when the Description iProperty value is empty
Logger.Debug("Component named: " & oOcc.Name & vbCrLf & _
"...had empty Description value.")
sDesc = "▲▲▲ Missing Description ▲▲▲"
oOccsWithProblems.Add(oOcc, "Empty Description")
'Continue For 'skip to next component
End If
Dim sNewOccName As String = sPN & " ~ " & sDesc & ":" & sInstance
Try
oOcc.Name = sNewOccName
Catch oEx As Exception
Logger.Error("Error renaming component..." & vbCrLf & _
"From: " & oOcc.Name & vbCrLf & _
"To: " & sNewOccName)
End Try
Else 'component's name did not contain ":"
Logger.Debug("Component named: " & oOcc.Name & vbCrLf & _
"...does not have ':' character in its name.")
oOccsWithProblems.Add(oOcc, "No Colon")
End If
Next
If oADoc.RequiresUpdate Then oADoc.Update2(True)
'If oADoc.Dirty Then oADoc.Save2(True)
If oOccsWithProblems.Count > 0 Then
For Each oEntry As KeyValuePair(Of Inventor.ComponentOccurrence, String) In oOccsWithProblems
Dim oComp As ComponentOccurrence = oEntry.Key
Dim sNote As String = oEntry.Value
'some code here for what to do with each problem component, such as a report or message to the user
MessageBox.Show("Component named: " & oComp.Name & vbCrLf & sNote, "Component With Problem", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Next
End If
End Sub
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I also have experienced some finicky behavior of SelectionSet in the past. Thank you for your interpretation. You have given me some ideas on how to change things up a little. It still does not seem to update the browser tree visually until the message boxes have been displayed. At the very least it is inconsistent. On one run, it visually updates 2 items then displays the message boxes (12) before visually updating the rest of the browser. On another run, it does not visually update any of them before the message boxes start appearing. If i have some time tomorrow i will try to record a video of the behavior.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
You have the entire "Rule" sub inside a transaction. I think you need the transaction to close before Inventor will update to show changes. Try it without the Transaction
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Glad it is working. I will say a transaction is a good thing to have when doing something like this as you will easily hit the undo limit in any large assembly. I would move the transaction somewhere where you can end it before calling the message box for the user.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Another thing you could explore where transactions are concerned is the TransactionManager.SetCheckPoint method. I do not know if using that would force the internal updates you are looking for, but it sounds interesting enough to check it out, just in case. It appears like a way to sub divide a long transaction into sections. Transactions can also apparently have parent or child transactions, but I have never attempted to create child transactions within another transaction before, so I do not know how that would work. Perhaps if one main transaction was created before doing anything, then another transaction is started while that other one is still in effect, the newer one will be a child of the older one...not sure. Either way, that would be a lot of transactions to manage in a code for what should be a fairly simple task. ![]()
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
@WCrihfieldThanks for pointing that out. I ready the full article on transactions yesterday, after @J-Camper mentioned transactions being a potential issue, and made the same discovery you did. I'm not sure I need that much functionality here so will likely save that for some future task.