Filtering the Selection Set

Filtering the Selection Set

tim11_manhhieu
Advocate Advocate
1,638 Views
8 Replies
Message 1 of 9

Filtering the Selection Set

tim11_manhhieu
Advocate
Advocate

I'm learning about Filtering the Selection Set, and tried running the code in the example but nothing happened, is there something wrong?

 

Sub xxx()

    Dim filterType(2) As Integer
    Dim filterData(2) As Variant
    Dim filter1, filter2 As Variant
    Dim circleSelectionSet As acadSelectionSet

    filterType(0) = 0: filterData(0) = "CIRCLE"
    filterType(1) = 4: filterData(1) = "<"
    filterType(2) = 40: filterData(2) = 5#
 
    On Error Resume Next
    Set circleSelectionSet = ThisDrawing.SelectionSets.Add("CircleSelection")
    If Err.Number <> 0 Then
        Set circleSelectionSet = ThisDrawing.SelectionSets.Item("CircleSelection")
        circleSelectionSet.Clear
    End If
    On Error GoTo 0

    filter1 = filterType
    filter2 = filterData

    circleSelectionSet.Select acSelectionSetAll, , , filter1, filter2

End Sub
0 Likes
1,639 Views
8 Replies
Replies (8)
Message 2 of 9

saboh12617
Contributor
Contributor

Hello,

 

As explained there About Adding Complexity to Your Filter List Conditions (VBA/ActiveX), you did one error :

Your FilterType(1) is of value 4 instead of -4 required for operators.

Then, I am not sure about the second one, but I had some issues with the Array types of the parameters of the .Select function :

I often had errors when the filterType was of type Variant : it needed to be Integer(). So I would recommand directly using your first arrays like so :

circleSelectionSet.Select acSelectionSetAll, , , filterType, filterData

And if it does not work, then put them in Variant variables (filter1, filter2) as you did.

0 Likes
Message 3 of 9

tim11_manhhieu
Advocate
Advocate

thanks for your respond.
I have referred to the code below and tried all the cases but nothing happens, it is very frustrating.

1) change sstext.SelectOnScreen FilterType, FilterData -> sstext.Select acSelectionSetAll, , , FilterType, FilterData

2) use directly FilterType, FilterData

3) use filter1, filter2 as Variant

 

tim11_manhhieu_0-1737678511521.png

 

tim11_manhhieu_1-1737678575739.png

 

 

Option Explicit

Sub Ch4_FilterBlueCircleOnLayer0()
    
On Error Resume Next
ThisDrawing.SelectionSets("SS5").Delete
On Error GoTo 0
    
Dim sstext As acadSelectionSet
Dim FilterType(2) As Integer
Dim FilterData(2) As Variant
Dim filter1, filter2 As Variant

Set sstext = ThisDrawing.SelectionSets.Add("SS5")

FilterType(0) = 0
FilterData(0) = "Circle"
FilterType(1) = -4
FilterData(1) = ">="
FilterType(2) = 40
FilterData(2) = 5#

filter1 = FilterType
filter2 = FilterData

'sstext.SelectOnScreen FilterType, FilterData
'sstext.Select acSelectionSetAll, , , FilterType, FilterData
sstext.Select acSelectionSetAll, , , filter1, filter2

End Sub

 

 

0 Likes
Message 4 of 9

grobnik
Collaborator
Collaborator
    filterType(0) = 0: filterData(0) = "CIRCLE"
    filterType(1) = -4: filterData(1) = "<OR"
    filterType(2) = -4: filterData(2) = ">="
    filterType(3) = 40: filterData(3) = 5#
    filterType(4) = -4: filterData(4) = "OR>"

I make two circles with diameters 5 and 35 here below the result with or logic operator

grobnik_0-1737748985086.png

 

Message 5 of 9

Ed__Jobe
Mentor
Mentor

In addition to the suggestion by @grobnik , you can use my BuildFilter and AddSelectionSet functions. I highly reccomend that you don't include On Error Resume Next in your main method. By using AddSelectionSet function, you restrict it's use to a utility function. Otherwise, it can mask unwanted errors and make it hard to debug. Try not to do too many things in one method but break it down to using one task per method.

BuildFilter filterType, filterData, 0, "Circle", -4, "<OR", -4, ">=", 40, 5,-4, "OR>"

Ed


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.
How to post your code.

EESignature

0 Likes
Message 6 of 9

tim11_manhhieu
Advocate
Advocate

thank for both reply. 

 

1) I tried your way and grobnik's way, it found the circle that satisfies the condition but it doesn't show the select mark.

 

2) Can you explain to me the meaning of

filterType(1) = -4: filterData(1) = "<OR" and filterType(4) = -4: filterData(4) = "OR>"?

It seems complicated compared to the example code.

 

tim11_manhhieu_0-1738716557472.png

 

tim11_manhhieu_0-1738716913480.png

 

 

 

Option Explicit

Sub test4()
    Dim varType As Variant
    Dim varData As Variant
'    BuildFilter varType, varData, 0, "TEXT", 8, "0"
    BuildFilter varType, varData, 0, "Circle", -4, "<OR", -4, ">=", 40, 5, -4, "OR>"

    
    Dim ss1 As acadSelectionSet
    Dim arEnts() As AcadText
    Set ss1 = AddSelectionSet("ss1")
    ss1.Select acSelectionSetAll, , , varType, varData
'
'    ReDim arEnts(0 To ss1.Count - 1)
'    Dim ent As AcadText
'    Dim i As Integer
'    i = 0
'    Dim cnt As Integer
'    cnt = 0
'    For Each ent In ss1
'        If ent.TextString Like "*@200" Or ent.TextString Like "*x200" Then
'            Set arEnts(i) = ent
'            i = i + 1
'        End If
'    Next ent
'    ReDim arEnts(0 To i - 1)
'    Debug.Print i & " text entities found."
End Sub

Public Sub BuildFilter(typeArray As Variant, dataArray As Variant, ParamArray gCodes())

'Purpose
'Fills a pair of variants with arrays for use as a selection set filter
'
'Arguments
'Two variants (not variant arrays) and an unlimited number of group code / value pairs
'
'Example
'BuildFilter fType, fData, 0, "LINE", 7, "WALLS"

    Dim fType() As Integer, fData()
    Dim index As Long, i As Long
    
    index = LBound(gCodes) - 1
        
    For i = LBound(gCodes) To UBound(gCodes) Step 2
        index = index + 1
        ReDim Preserve fType(0 To index)
        ReDim Preserve fData(0 To index)
        fType(index) = CInt(gCodes(i))
        fData(index) = gCodes(i + 1)
    Next
    typeArray = fType: dataArray = fData

End Sub


Public Function AddSelectionSet(SetName As String) As acadSelectionSet
' This routine does the error trapping neccessary for when you want to create a
' selectin set. It takes the proposed name and either adds it to the selectionsets
' collection or sets it.
    On Error Resume Next
    Set AddSelectionSet = ThisDrawing.SelectionSets.Add(SetName)
    If Err.Number <> 0 Then
        Set AddSelectionSet = ThisDrawing.SelectionSets.Item(SetName)
        AddSelectionSet.Clear
    End If
End Function

 

 

0 Likes
Message 7 of 9

grobnik
Collaborator
Collaborator

@tim11_manhhieu Hi, the code "-4" identify a logic operator, as "OR" is.

in the specific issue I ask to filter all object type required (circle with diameter) Higher than XXX or Lower than ("<OR" or "OR>").

In any case I guess it will be more easy select all "CIRCLE" object and later select object only with diameter required.

Could you try as follow (your code little bit modified):

Sub test4()
    Dim varType As Variant
    Dim varData As Variant
'    BuildFilter varType, varData, 0, "TEXT", 8, "0"
    BuildFilter varType, varData, 0, "Circle" '-4, "<OR", -4, ">=", 40, 5, -4, "OR>"

    
    Dim ss1 As AcadSelectionSet
   ' Dim arEnts() As AcadText
    Set ss1 = AddSelectionSet("ss1")
    ss1.Select acSelectionSetAll, , , varType, varData
'
  '  ReDim arEnts(0 To ss1.Count - 1)
  ' Dim ent As Object ' AcadText
   Dim i As Integer
   i = 0
  ' Dim cnt As Object
   cnt = 0
    For Each Nent In ss1
    If TypeOf Nent Is AcadCircle Then
        Set MyEnts = Nent
        If MyEnts.Diameter >= 35 And MyEnts.Diameter <= 35 Then
            
            Debug.Print ss1.Count & " entities found. Diameter: " & MyEnts.Diameter
            i = i + 1
        End If
    End If
    Next Nent
   ' ReDim arEnts(0 To i - 1)
    
End Sub

Public Sub BuildFilter(typeArray As Variant, dataArray As Variant, ParamArray gCodes())

'Purpose
'Fills a pair of variants with arrays for use as a selection set filter
'
'Arguments
'Two variants (not variant arrays) and an unlimited number of group code / value pairs
'
'Example
'BuildFilter fType, fData, 0, "LINE", 7, "WALLS"

    Dim fType() As Integer, fData()
    Dim index As Long, i As Long
    
    index = LBound(gCodes) - 1
        
    For i = LBound(gCodes) To UBound(gCodes) Step 2
        index = index + 1
        ReDim Preserve fType(0 To index)
        ReDim Preserve fData(0 To index)
        fType(index) = CInt(gCodes(i))
        fData(index) = gCodes(i + 1)
    Next
    typeArray = fType: dataArray = fData

End Sub


Public Function AddSelectionSet(SetName As String) As AcadSelectionSet
' This routine does the error trapping neccessary for when you want to create a
' selectin set. It takes the proposed name and either adds it to the selectionsets
' collection or sets it.
    On Error Resume Next
    Set AddSelectionSet = ThisDrawing.SelectionSets.Add(SetName)
    If Err.Number <> 0 Then
        Set AddSelectionSet = ThisDrawing.SelectionSets.Item(SetName)
        AddSelectionSet.Clear
    End If
End Function

Where you will found all "CIRCLE"s with Selection Set and later check the diameter.

If you have more than one diameter you can add to your code a Select Case function 

 

Select Case XXX (item in selection set) 

 

Case  XXX (item in selection set) is XXX

...do something

 

Case YYYY  (item in selection set) 

....do something of other

 

End Select

Message 8 of 9

tim11_manhhieu
Advocate
Advocate

thank you, i will try it.

0 Likes
Message 9 of 9

Ed__Jobe
Mentor
Mentor

In the help topic that @saboh12617 linked to in the first post, it says "Use a -4 DXF code to indicate a relational operator in your filter specification. Specify the operator as a string.". So filterType is -4 and filterData is the operator, such as "<OR".

Ed


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.
How to post your code.

EESignature