Ilogic to select parts with specific criteria

Ilogic to select parts with specific criteria

jack.morrish
Explorer Explorer
1,259 Views
5 Replies
Message 1 of 6

Ilogic to select parts with specific criteria

jack.morrish
Explorer
Explorer

Hello all,

 

Hoping for a bit advice here!

I'm building a product configurator, which makes parts visible/ hidden depending on options picked in a user form.

I'm trying to give the option to colour certain components withing the assembly - for example all of the upholstery panels.  The upholstery panels could be identified either by a custom iproperty field (containing the text "UPH", or a custom appearance applied to them (eg "Uph_appearance").  Once they are all selected by Ilogic, the user can then open the appearance browser and apply a finish to all selected components.  Even better if the Ilogic can select the relevant components and then open the appearance browser itself : )

I don't want to use component.color, as the user may need to make a custom appearance, and the list of options is too long for the form.

 

I have found the following code by @g.georgiades  which selects components that have the same appearance as one you have selected - which works great - I just can't seem to edit it to correctly select components that meet a certain criteria.

 

If easier, I could name all of the specific components that need selecting (rather than choosing them based on iproperties or appearance) - I just haven't had much luck with the selectset function to date.

 

Glad of any thoughts - thanks!

 

Jack

 

Public Class Select_By_Appearance
	Sub main()
		'Only operate in assemblies.
		If ThisDoc.Document.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then Exit Sub
		Dim doc As AssemblyDocument = ThisAssembly.Document

		'Collect the occurrences the user has selected currently
		Dim sel As List(Of ComponentOccurrence) = doc.SelectSet.Cast(Of Object).Where(Function(f) TypeOf f Is ComponentOccurrence).Cast(Of ComponentOccurrence).ToList()
		If sel.Count = 0 Then Exit Sub

		'Collect unique appearances for selected occurrences to match against. Use Appearance name for simplicity.
		Dim assets As List(Of String) = sel.Select(Function(s) s.Appearance.DisplayName).Distinct().ToList()

		Dim cpt As ComponentDefinition = doc.ComponentDefinition

		'Collect all occurrences from the assembly, both assemblies and sub components. Filter any potential duplicate occurrences.
		Dim occs As IEnumerable(Of ComponentOccurrence) = cpt.Occurrences.Cast(Of ComponentOccurrence).Concat(cpt.Occurrences.AllLeafOccurrences.Cast(Of ComponentOccurrence)).Distinct()

		'List to hold the matches
		Dim toselect As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection

		'Loop over all occurrences and add to selection list if any of the match appearances match.
		For Each occ As ComponentOccurrence In occs
			If assets.Any(Function(r) String.Equals(r, occ.Appearance.DisplayName, StringComparison.InvariantCultureIgnoreCase)) Then
				toselect.Add(occ)
			End If
		Next

		'Select all matches for viewing or further processing.
		doc.SelectSet.SelectMultiple(toselect)
	End Sub
End Class

 

 

0 Likes
Accepted solutions (1)
1,260 Views
5 Replies
Replies (5)
Message 2 of 6

JelteDeJong
Mentor
Mentor
Accepted solution

Some time ago I wrote a blog post "Universal occurrence search function". You might find it interesting. This example rule is created with the same principle in mind.

Sub Main()

    Dim doc As AssemblyDocument = ThisDoc.Document

    Dim list As IEnumerable(Of ComponentOccurrence)

    Dim result = MsgBox("Do you want to get all Angle Supports? If 'No' I will vind all 2x2 tubes.", MsgBoxStyle.YesNo)
    If (result = MsgBoxResult.Yes) Then
        list = findAllWhere(doc, AddressOf IsAngleSupport)
    Else
        list = findAllWhere(doc, AddressOf IsTube2x2)
    End If

    MsgBox(list.Count & " items found.")

    Dim collection = CastToObjectCollection(list)
	doc.SelectSet.Clear()
    doc.SelectSet.SelectMultiple(collection)

End Sub

Public Function CastToObjectCollection(list As IEnumerable(Of ComponentOccurrence)) As ObjectCollection
    Dim collection As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection

    For Each occ As ComponentOccurrence In list
        collection.Add(occ)
    Next
    Return collection
End Function


Public Function IsAngleSupport(occ As ComponentOccurrence) As Boolean
    Dim def As ComponentDefinition = occ.Definition
    Dim doc As Document = def.Document
    Dim propSet As PropertySet = doc.PropertySets.Item("Design Tracking Properties")
    Dim prop As [Property] = propSet.Item("Part Number")
    Dim val As String = prop.Value
    Return (val.Contains("Angle Support"))
End Function

Public Function IsTube2x2(occ As ComponentOccurrence) As Boolean
    Dim def As ComponentDefinition = occ.Definition
    Dim doc As Document = def.Document
    Dim propSet As PropertySet = doc.PropertySets.Item("Design Tracking Properties")
    Dim prop As [Property] = propSet.Item("Part Number")
    Dim val As String = prop.Value
    Return (val.Contains("2x2 Tube"))
End Function

Public Function findAllWhere(doc As AssemblyDocument,
    predicate As Func(Of ComponentOccurrence, Boolean)) As IEnumerable(Of ComponentOccurrence)

    Return doc.ComponentDefinition.
        Occurrences.AllLeafOccurrences.Cast(Of ComponentOccurrence).
        Where(predicate)

End Function

 

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 3 of 6

jack.morrish
Explorer
Explorer

Incredible - thanks Jelte!

Your code had more functionality than I was needing, so have simplified to the below, and it now looks at the subject iproperty rather than the part number.

 

Sub Main()

    Dim doc As AssemblyDocument = ThisDoc.Document

    Dim list As IEnumerable(Of ComponentOccurrence)
	
        list = findAllWhere(doc, AddressOf IsUph)

    Dim collection = CastToObjectCollection(list)
	doc.SelectSet.Clear()
    doc.SelectSet.SelectMultiple(collection)

End Sub

Public Function CastToObjectCollection(list As IEnumerable(Of ComponentOccurrence)) As ObjectCollection
    Dim collection As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection

    For Each occ As ComponentOccurrence In list
        collection.Add(occ)
    Next
    Return collection
End Function


Public Function IsUph(occ As ComponentOccurrence) As Boolean
    Dim def As ComponentDefinition = occ.Definition
    Dim doc As Document = def.Document
    Dim propSet As PropertySet = doc.PropertySets.Item("Inventor Summary Information")
    Dim prop As [Property] = propSet.Item("Subject")
    Dim val As String = prop.Value
    Return (val.Contains("UPH"))
End Function

Public Function findAllWhere(doc As AssemblyDocument,
    predicate As Func(Of ComponentOccurrence, Boolean)) As IEnumerable(Of ComponentOccurrence)

    Return doc.ComponentDefinition.
        Occurrences.AllLeafOccurrences.Cast(Of ComponentOccurrence).
        Where(predicate)

End Function

 

If you have a chance, would you mind walking me through how to alter this so that it just adds say Part 1:1 and Part 2:1 to the collection, and selects those? (rather than searching for properties)  No hurry, the above has solved my immediate need - I'd just be interested to know for the future.

 

Thanks again - appreciate your help!

 

Jack

0 Likes
Message 4 of 6

jack.morrish
Explorer
Explorer

@JelteDeJong  - I realise I had accepted the solution, so you may not have seen my additional question.

 

Would you mind walking me through how to alter this so that it just adds say Part 1:1 and Part 2:1 to the collection, and selects those? (rather than searching for properties).

In some circumstances (when using with IF statements) it will be easier to specify specific parts to be selected, rather than via the properties of the part.

 

Would be very glad on your thoughts when you get a chance - thanks very much!

 

Jack

0 Likes
Message 5 of 6

JelteDeJong
Mentor
Mentor

The only thing you need to make it work is a function that takes an occurrence and returns a boolean Then plug it into the method findAllWhere. In this case, it's easy.  I just needed to add the method "IsPart1or2" and it works. have a look at this:

Sub Main()
    Dim doc As AssemblyDocument = ThisDoc.Document

    Dim list As IEnumerable(Of ComponentOccurrence)

	list = findAllWhere(doc, AddressOf IsPart1or2)


    MsgBox(list.Count & " items found.")

    Dim collection = CastToObjectCollection(list)
	doc.SelectSet.Clear()
    doc.SelectSet.SelectMultiple(collection)
End Sub

Public Function IsPart1or2(occ As ComponentOccurrence) As Boolean
    Return (occ.Name = "Part 1:1" Or occ.Name = "Part 2:1")
End Function




Public Function CastToObjectCollection(list As IEnumerable(Of ComponentOccurrence)) As ObjectCollection
    Dim collection As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection

    For Each occ As ComponentOccurrence In list
        collection.Add(occ)
    Next
    Return collection
End Function

Public Function findAllWhere(doc As AssemblyDocument,
    predicate As Func(Of ComponentOccurrence, Boolean)) As IEnumerable(Of ComponentOccurrence)

    Return doc.ComponentDefinition.
        Occurrences.AllLeafOccurrences.Cast(Of ComponentOccurrence).
        Where(predicate)

End Function

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

0 Likes
Message 6 of 6

jack.morrish
Explorer
Explorer

Genius! Thanks @JelteDeJong  - had been trying to get this to work for days.

Really appreciate your expertise -thanks again.

 

Jack

0 Likes