Hi there, I have a section of code (see below) which runs a program which highlights a part/subassembly red, then gives the user a list dialgue box in order to easily replace the compent. At present, I have this code repeated for each part/subassembly in my main assemby (i.e. FRAME, POWER_RISER, BUSBAR_CHAMBER, BUSBAR_ASSEMBLY...).
Having the code repeated multiple times, means it is very time consuming to modify. I want to be able to generate a list then have the code below, run for each of the entries in the list. So I need something along the lines of
dim mylist as something
mylist = FRAME, POWER_RISER, BUSBAR_CHAMBER, BUSBAR_ASSEMBLY...
FOR each entry in mylist
run all the code below (with the words 'BUSBAR_ASSEMBLY' replaced with 'mylist'
END
Could someone give me some help with the code writting please?
Thanks,
Wayne
Component.Color("BUSBAR_ASSEMBLY")="Red(FLAT)"Parameter("busbar_assembly_partno")=InputListBox("Please select the part number of the busbar assembly you wish to use", MultiValue.List("busbar_assembly_partno"), MultiValue.List("busbar_assembly_partno"), Title :="Assembly Editor", ListName :="Busbar Assembly")Component.Color("BUSBAR_ASSEMBLY")="As Material"iPart.ChangeRow("BUSBAR_ASSEMBLY", Parameter("busbar_assembly_partno"))'Component.Replace("BUSBAR_ASSEMBLY","C:\ARTICULATE\09\090\09090GT0000023\" & Parameter("busbar_assembly_partno") & ".iam", True)iLogicVb.UpdateWhenDone=True
'Check to see if the part has changed. If it hasn't, check to see if it exists.IfParameter("busbar_assembly_partno")<>iProperties.Value("BUSBAR_ASSEMBLY", "Project", "Part Number")IfDir("C:\ARTICULATE\09\090\09090GT0000023\"&Parameter("busbar_assembly_partno")&".iam")=""ThenMessageBox.Show("The busbar assembly, "&Parameter("busbar_assembly_partno")&", does not exist locally. Please GET the part from Vault (you don't need to check it out) then click 'OK'", "Assembly Editor", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)iPart.ChangeRow("BUSBAR_ASSEMBLY", Parameter("busbar_assembly_partno"))MessageBox.Show("Now please Check , "&Parameter("busbar_assembly_partno")&", back in", "Assembly Editor", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)EndIfEndIf
'Check to see of the part has changed. If it hasn't, prompt to check it out of vault.IfParameter("busbar_assembly_partno")<>iProperties.Value("BUSBAR_ASSEMBLY", "Project", "Part Number")MessageBox.Show("The busbar assembly could not be changed to "&Parameter("busbar_assembly_partno")&". Make sure you have the latest version of the file and all it's children from Vault then click 'OK'", "Assembly Editor", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)iPart.ChangeRow("BUSBAR_ASSEMBLY", Parameter("busbar_assembly_partno"))EndIf
'Check to see of the part has changed. IfParameter("busbar_assembly_partno")<>iProperties.Value("BUSBAR_ASSEMBLY", "Project", "Part Number")MessageBox.Show("The busbar assembly could still not be changed to "&Parameter("busbar_assembly_partno")&". iAssemblies are jerks", "Assembly Editor", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)EndIf
Solved! Go to Solution.
Solved by Curtis_Waguespack. Go to Solution.
Hi waynehelley,
I didn't follow your exact goal here (your code did not paste too well), but here are a couple of examples that might help.
Here's a quick example checking a list against a string:
testString = "Hello World I am a text string." 'create list Dim myArrayList As New ArrayList myArrayList.add("Hello") myArrayList.add("World") myArrayList.add("Roadrunner") Dim oString as Object i = 0 For Each oString in myArrayList If testString.Contains(myArrayList.Item(i)) Then MessageBox.Show(myArrayList.Item(i) & ": was found!", "iLogic") Else MessageBox.Show(myArrayList.Item(i) & ": was NOT found.", "iLogic") End if i= i+1 Next
Here's a quick example that creates a list from the assembly components and then presents them in a listbox:
' set a reference to the assembly component definintion. ' This assumes an assembly document is open. Dim oAsmCompDef As AssemblyComponentDefinition oAsmCompDef = ThisApplication.ActiveDocument.ComponentDefinition 'create a list Dim myArrayList As New ArrayList 'Iterate through all of the assembly occurrences Dim oOccurrence As ComponentOccurrence For Each oOccurrence In oAsmCompDef.Occurrences 'add the occurrence name to the list myArrayList.add(oOccurrence.Name) Next 'present the user with the list to choose from myComponent = InputListBox("Select one.", myArrayList, myArrayList.item(0), "iLogic", "List") 'report the selection MessageBox.Show("You selected: " & myComponent & vblf & " from the list.", "iLogic")
I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com
Hi Curtis, thanks for the reply. I will explain a bit better.
I started with your blog post about using ilogic to highlight and Update Features During Changes (http://inventortrenches.blogspot.co.uk/2011/02/autodesk-ilogic-highlight-and-update.html)
I modified the code so that instead of highlighting features in a part and being given the option to alter the dimension, the code highlights subassemblies within an assembly then gives the user a list of subassemblies to replace the current subassembly. I have this code working fine (it is attached if you want to take a look, although i have shortened it so it only concentrates on one subassembly replace in my main assembly, whereas I want it to go through each of the sub-assemblies one by one).
If you look at your code below, you have just copied it 3 times replacing the feature name. My code is longer (as i want error messages to appear if the replace has not worked) and i want it to be repeated many times as there is going to be many sub assemblies going into my main assembly. This makes it very difficult to modify the code as every time I want to make a change, I have to change the code for each subassembly.
To overcome this i want to make a list then have a FOR function run a few lines of code for each of the entries in the list. Below is the code from your blog post...
------------------------------------------------------------------------------------------------------------------------------------------
I think I have worked it out for myself using your second example.
Thanks for your help.
Wayne
hi Curtis
Using your second example (arraylist from assembly components) how would one go about highlighting on screen the component currently selected in the inputlist box?
So as the user scrolls through the list the corresponding model file highlights on screen?
I'm not sure this is possible using the listbox method (which is my preference) but know it can be done using the pick on screen method.
Thanks in advance.
Bryan
What you would need for that would be a Do or While loop to keep the list box activating continuosly allowing the user pass the occurrence name to another loop of the assembly occurrences all references occurrences. Next identify the occurrence name selected in the list box then add to HighlightSet(sample here) then repeat.
Here is a code that should fit your brief. It is untested so save your work before testing.
' set a reference to the assembly document. ' This assumes an assembly document is open. Dim oAssyDoc as AssemblyDocument = ThisDoc.Document
' set a reference to the assembly component definintion.
Dim oAsmCompDef As AssemblyComponentDefinition = oAssyDoc.ComponentDefinition 'create a list Dim myList As New List (Of String)
'Iterate through all of the assembly occurrences Dim oOccurrence As ComponentOccurrence For Each oOccurrence In oAsmCompDef.ComponentOccurrences.AllReferencedOccurrences(oAsmCompDef) 'add the occurrence name to the list myList.add(oOccurrence.Name) Next
'Start a loop
While True 'present the user with the list to choose from myComponent = InputListBox("Select one.", myList, myList.item(0), "iLogic", "List")
'Condition to exit the loop If IsNothing(myComponent) Then Exit While 'report the selection MessageBox.Show("You selected: " & myComponent & vblf & " from the list.", "iLogic")
' Create a highlight set. Dim oSet1 As HighlightSet = oAssyDoc.CreateHighlightSet ' Change the color of the highlight set to green. oSet1.Color = ThisApplication.TransientObjects.CreateColor(0, 255, 0)
For Each oOccurrence In oAsmCompDef.ComponentOccurrences.AllReferencedOccurrences(oAsmCompDef)
' Filter collection for the one selected
If oOccurrence.Name = myComponent Then
' Clear any previous select object
oSet1.Clear
' Add the first object to the highlight set.
oSet1.AddItem(oOccurrence)
End If
Next
End While
hi Alan
Thanks for your reply.
I get an error on this line saying "public member "ComponentOccurrences on type AssemblyComponentdefinition not found"
For Each oOccurrence In oAsmCompDef.ComponentOccurrences.AllReferencedOccurrences(oAsmCompDef)
Do you have any ideas on this?
Yes there is an error here.
Try this for the for loop
For Each oOccurrence In oAsmCompDef.Occurrences.AllReferencedOccurrences(oAsmCompDef)
hi Alan
So that worked and I now get a selectable list. the currently selected item however does not highlight until the OK button is selected and then the input listbox remains open.
Ideally I want the highlighted item to highlight on list selection and not remain highlighted if the user selects a new list item. Also is it possible to rather list items (assemblies or parts) only once in the list? finally pressing the OK button should close the list and allow for further processing of the last selected item in the list.
Many thanks for your efforts thus far
All of those requests can be a bit of an ask with these simple tools and the way it's currently setup but you can put in a few work arounds.
If you don't want to have the list box pop after selecting but still browse the model to see the part you can use a pick function in a while loop. Once you press Esc the list comes up again.
'Start a loop
While True
Dim oObject As Object = ThisApplication.CommandManager.Pick(kPartFeatureFilter, "Just Browsing! Press Esc to exit")
If IsNothing(oObject) Then Exit While
Loop
'
Can you give an idea of what the end goal for the tool is? Instead of the list of documents can you just select them by mouse using Pick function or is your preference a list of names?
You could also pass a selected name into another list and do something at the end of your rule.
If you want only one occurrence you might be better to look at the documents than the occurrences. Here is a helpful article and the document loop. Highlight will work on document objects too.
Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
' Get all of the referenced documents.
Dim oRefDocs As DocumentsEnumerator = oAsmDoc.AllReferencedDocuments
' Iterate through the list of documents.
Dim oRefDoc As Document
For Each oRefDoc In oRefDocs
Logger.Info(oRefDoc.DisplayName)
Next
hi Alan
yes I see that it is becoming a bit of a beast.
I have used the AllReferencedDociments option, and that gets me closer to what i want.
So the end goal is to allow the user to run a bunch of code on either the active open model, processing all parts (sub-assemblies included) or drill down to any particular sub-assembly and process without having to specifically open that sub-assembly. So its just an ease of use thing i suppose, grab the top level model and off you go. Our numbering system gives limited clues as to what the assembly is so i thought the list and selection highlight would be an easy way forwards.
Your suggestions are brilliant and help heaps so i'll press on and see what I can come up with that's workable.
Replying to a super old post here, but:
I was able to use Curtis' post here to make an iLogic rule. The idea is when you run it the program will search for features containing the names in the array (currently just feature1 and feature2) then toggle their suppression state. I've gotten it to work not using an array and just 1 string (i.e. Dim Featurename as "Feature1") so I know the suppression part works. The below code, however gets hung up on line 15, citing "Object reference not set to an instance of an object."
I feel like I'm 1 line away from cracking it, but maybe just not fully understanding this object based reference stuff. Any help is appreciated.
Sub Main() Dim oDoc As PartDocument = ThisDoc.Document Dim oFeatures As PartFeatures = oDoc.ComponentDefinition.Features Dim oFeature As PartFeature Dim IsVisible As Boolean = False Dim AidFeatures As New ArrayList AidFeatures.Add("Feature1") AidFeatures.Add("Feature2") Dim oString As Object i = 0 For Each oString In AidFeatures If oFeature.Name.Contains(AidFeatures.Item(i)) Then IsVisible = Feature.IsActive(oFeature.Name) If IsVisible = True Feature.IsActive(ofeature.name) = False 'MsgBox("Active") End If If IsVisible = False Feature.IsActive(oFeature.Name) = True 'MsgBox("Inactive") End If End If i = i+1 Next End Sub
Here is another perhaps cleaner way to approach looping through the lost of strings. It will avoid indexes.
Sub Main()
Dim oDoc As PartDocument = ThisDoc.Document
Dim oFeatures As PartFeatures = oDoc.ComponentDefinition.Features
Dim oFeature As PartFeature
Dim IsVisible As Boolean = False
Dim AidFeatures As New List (Of String)
AidFeatures.Add("Feature1")
AidFeatures.Add("Feature2")
For Each str As String In AidFeatures
If oFeature.Name.Contains(str) Then
IsVisible = Feature.IsActive(oFeature.Name)
If IsVisible = True
Feature.IsActive(ofeature.name) = False
'MsgBox("Active")
End If
If IsVisible = False
Feature.IsActive(oFeature.Name) = True
'MsgBox("Inactive")
End If
End If
Next
End Sub
Indeed you were just missing one line. The message you were getting was saying that oFeature was not being set before it was being used. Here is your example updated to set oFeature to be the feature in the features collection that matches the name from the list. Note that if there is no feature in the part by that name, this could return an error.
I included A.Acheson's suggestion to remove the index and just use the variable from the loop as well.
Also, the logic an be simplified to just set the IsActive status of the feature to always be equal the opposite of it's current state by using the Not operator, see 2nd example.
Dim oDoc As PartDocument = ThisDoc.Document Dim oFeatures As PartFeatures = oDoc.ComponentDefinition.Features Dim oFeature As PartFeature Dim IsVisible As Boolean = False Dim AidFeatures As New ArrayList AidFeatures.Add("Feature1") AidFeatures.Add("Feature2") Dim oString As Object For Each oString In AidFeatures oFeature = oFeatures.Item(oString) If oFeature.Name.Contains(oString) Then IsVisible = Feature.IsActive(oFeature.Name) If IsVisible = True Feature.IsActive(oFeature.Name) = False 'MsgBox("Active") End If If IsVisible = False Feature.IsActive(oFeature.Name) = True 'MsgBox("Inactive") End If End If Next
A simplified version of the code above to toggle the status of each feature named in the list
Dim oDoc As PartDocument = ThisDoc.Document Dim oFeatures As PartFeatures = oDoc.ComponentDefinition.Features Dim oFeature As PartFeature Dim AidFeatures As New List(Of String) AidFeatures.Add("Feature1") AidFeatures.Add("Feature2") For Each oString As String In AidFeatures oFeature = oFeatures.Item(oString) If oFeature.Name.Contains(oString ) Then Feature.IsActive(oFeature.Name) = Not Feature.IsActive(oFeature.Name) End If Next
Thank you Curtis, I was able to get it to work. At first I was confused as I was getting INVALIDARG errors. It was because the original code looked for a string that contained the text string. So I could suppress Feature1a, Feature1b, Feature1c, etc. all but inputting just "Feature1" into the array.
If oFeature.Name.Contains(oString) Then
With the new snippet of code you sent over looks like I just have to be exact with adding things to the array. So using the above example it would only suppress a feature called "Feature1."
Again, thank you for the help Curtis! Hope this helps someone else one day 😄
Can't find what you're looking for? Ask the community or share your knowledge.