How to "select" an selection set

How to "select" an selection set

ilovejingle
Enthusiast Enthusiast
11,491 Views
11 Replies
Message 1 of 12

How to "select" an selection set

ilovejingle
Enthusiast
Enthusiast

I have a AutoCAD drawing which consists a lot of block references with attributes. what I want to do is to be able to select some of the blocks by certain rules, then select them, and user can decide what attributes they want to change. I have some code to scan the entire drawing and create a selection set to put all the qualified block references in, the problem is I cannot "Visually" select them so that I can modify the attributes on AutoCAD properties window.

 

The problem:  How to select all entities in a selectionset. I try to use the following method, but it seems that it only select all objects in modelspace.

 

    'ss is the selection set created.
    'msgbox ss.count
    'there are correct number of elements in the selection set.

    ss.Select acSelectionSetAll
    ss.Delete
    ThisDrawing.SendCommand "Select p " & vbCrLf
0 Likes
11,492 Views
11 Replies
Replies (11)
Message 2 of 12

norman.yuan
Mentor
Mentor

There was a very similar topic discussed recently, the code sample provided in that discussion could be what you need with minor modification:

 

https://forums.autodesk.com/t5/visual-basic-customization/vba-return-selection-to-user-for-further-m...

 

HTH

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 12

ilovejingle
Enthusiast
Enthusiast
Thanks for the reply
I do look into your code and the option of using selection filter to
achieve it, the problem is that object can be added to selection set for
different reasons, for my case, I was addeing block ref to my selection set
based on certain attribute values. I dont think it can be achieved using
available filters

iit looks like you need to run a selectall with filtered to make autocad
capture the previous selection
0 Likes
Message 4 of 12

norman.yuan
Mentor
Mentor

Base on my understanding of your original question, what you asked is, ONCE you have an AcadSelectionSet built, then you want all the entities in the SelectionSet highlighted AS IF they are selected by user, so that user can either issue a command against them, or use Property window to modify them. Am I correct on this? If yes, then the focus to my code from the other post for you is the LAST line: 

 

ThisDrawing.SendCommand "SELECT" & vbCr & "P" & vbCr & vbCr

That is, it does not matter how you create a Selection set, using filter or not. SelectAll or not. Just build one in whatever code suitable to you.

 

For example, you can loop through all entities in ModelSpace to find certain entities and add them into a selectionset, something like this way:

 

Public Sub SelectSomethin()

  Dim ss As AcadSelectionSet

  Set ss=BuildSelectionSet()

  If ss.Count>0 Then

    ThisDrawing.SendCommand "SELECT" & vbCr & & "P" & vbCr & vbCr

  Else

    Msgbox "No entity selected!"

  End If

End Sub

 

Private Function BuildSelectionSet() As AcadSelectionSet

  Dim ent As AcadEntity

  Dim ents() As AcadEntity

  Dim i As Integer

  Dim ss As AcadSelectionSet

  On Error Resume Next

  Set ss=ThisDrawing.SelectionSets("MySet")

  If ss Is Nothing Then

    Set ss=ThisDrawing.SelectionSet.Add("MySet")

  Else

    ss.Cear

  End If

  For Each ent In ThisDrawing.ModelSpace

    If IsMyTarget(ent) Then

      ReDim Preserve ents(i)

      Set ents(i)=ent

      i=i+1

    End If

  Next

  If i>0 Then

    ss.AddItem ents

  End If

  Set BuildSelectionSet = ss

End Sub 

 

Private Function IsMyTarget(ent As AcadEntity) As Boolean

   '' Use whatever logic to determine whether this entity show be 

   '' added into the SelectionSet or not

   ...

   Is MyTarget=True/False

End Function

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 12

ilovejingle
Enthusiast
Enthusiast

Thank for the reply, but I am afraid it does not work as you described.

You do understand my intention 100% correctly, I am using exactly the code you write here.

 

 

    If testCase Then
        ThisDrawing.Utility.Prompt vbLf + "Find :" + objBlk.EffectiveName
        ReDim Preserve objlist(i)
        Set objlist(i) = objBlk
        i = i + 1
    End If
    If UBound(objlist) > 0 Then ss.AddItems (objlist)
    ThisDrawing.Utility.Prompt vbLf + "Total Find :" + CStr(ss.count)
    ThisDrawing.SendCommand "SELECT" & vbCr & "P" & vbCr & vbCr

The code runs correctly, and 

ss.Count

is able to capture the correct amount of block refs I am inserted ,but it won't be recognized as a previous selection by AutoCAD. here is the command line results.

Total Find :50
Command: SELECT

Select objects: P
No previous selection set.

 

0 Likes
Message 6 of 12

norman.yuan
Mentor
Mentor

Ah, I now see where the problem is: it looks like, AutoCAD only register "Previous" selection set when AcadSelectionSet.Select()/SelectXXXX() method is called and only remember the entities selected by the method call. entities added/removed via code does not reflect in the "Previous" selection set.

 

So, it looks like you need to come up with very fine-tuned selection filters to call on Select() method. Unfortunately for your case, if the blocks you are trying to select are dynamic ones, you probably cannot apply block name filter, thus very difficult to select with Select(acSelectionSetAll, filters, filterValues...) method.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 7 of 12

ilovejingle
Enthusiast
Enthusiast

Thanks for the reply anyway.  looks like there is no easy way of doing this.

I think of a work around, which manipulate the visibility status of the block, since I am not working with dynamic blocks and not using the visibility properties at all for Xref files. 

It is not a perfect and flawless solution but works for me.

  For Each objEnt In ThisDrawing.ModelSpace
        If TypeOf objEnt Is AcadBlockReference Then
            Set objblk = objEnt
            AltEntVisibility objblk, True
            If isTheBlock(objblk, strOpt, strIdentKey, isExact) Then
                ThisDrawing.Utility.Prompt vbLf + "Find :" + objblk.EffectiveName
                ReDim Preserve objlist(i)
                Set objlist(i) = objblk
                AltEntVisibility objblk, False
                i = i + 1
            End If
        End If
    Next
    
    If i > 0 Then
        ss.AddItems objlist
    End If

'   Create Temp SS to be able to select things so that AutoCAD can cache the selection set

    Dim newSS As AcadSelectionSet
    Set newSS = A_FuncLib.CreateSS("TempSS")
    
'   Create an filter type and value
'   Filter on the element's visibility sates
'   Previous qualified blocks has been put to invisible.
    Dim fCode(0 To 1) As Integer
    Dim fData(0 To 1) As Variant
    fCode(0) = 0: fData(0) = "INSERT"
    fCode(1) = 60: fData(1) = 1
    newSS.Select acSelectionSetAll, , , fCode, fData
'   Make the everything in ss visiable again
    For Each objEnt In ss
        AltEntVisibility objEnt, True
    Next
    Dim isSSEmpty As Boolean: isSSEmpty = (newSS.count <= 0)
'   Delete the newSS, so that AutoCad can cache the selection set as "Previous Selection Set"
    newSS.Clear: newSS.Delete
    
    If Not isSSEmpty Then
        ThisDrawing.SendCommand "Select p " & vbCrLf
        ThisDrawing.Utility.Prompt vbLf + "Total Find :" + CStr(ss.count)
    Else
        ThisDrawing.Utility.Prompt vbLf + "Nothing Found!"
    End If
ExitNormal:
ss.Clear
ss.Delete
LockWindowUpdate 0
Exit Sub
Err:
ThisDrawing.Utility.Prompt vbLf + "Action Aborted !" + vbLf
GoTo ExitNormal
End Sub

 

0 Likes
Message 8 of 12

norman.yuan
Mentor
Mentor

Another way to do it might be a bit simpler. Here is the psuedo logic:

 

1. Loop through all entities to identify the target ones.

2. For each target entity, attach XData with given XData application name

3. Define selection set filter to select entities with XData application name

4. Create SelectionSet and call Select() to select all entities with the XData application name filter. At this point, AutoCAD register the SelectionSet as "Previous"

5. Remove the XData attached to those entities

6. Delete the selectionset, if desired

7. Now it is ready to call SendCommand "Select" & vbCr & "P" & ....

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 9 of 12

brian_adams
Collaborator
Collaborator

could you public all the code/ it's a part of it only

I also want do make selection of precise object but i whant to do it useing ID of object

and i stucked

0 Likes
Message 10 of 12

serag.hassouna
Advocate
Advocate

Selecting a selection set visually for the user to interact with them is fairly easy in AutoLISP using a function called sssetfirst.
It has 2 arguments, the first one you need to set it to nil, and the second one is the variable that has the selection set identification bound to it.
However, you have an ActiveX selection set (called ss), so, the trick is to assign the members of ss to an AutoLISP selection set, this can be done by an AutoLISP function called vlaSel->Sel written by @Doaiena.
What remains finally is to invoke vlaSel->Sel, this can be done in 2 steps as follows:-

  1. Define vlaSel->Sel into your drawing.
    ThisDrawing.SendCommand "(defun vlaSel->Sel ( vlaSel / sel )" & vbLf & _
    "(setq sel (ssadd))" & vbLf & _
    "(vlax-for obj vlaSel" & vbLf & _
    "(ssadd (vlax-vla-object->ename obj) sel)" & vbLf & _
    ")" & vbLf & _
    "sel" & vbLf & _
    ")" & vbCr
  2. Invoke the function
    'Given that the selection set's name is MySSName
    ThisDrawing.SendCommand "(setq ss (vlaSel->Sel (vla-item (vla-get-selectionsets (vla-get-activedocument (vlax-get-acad-object))) ""MySSName"")))" & vbCr
    ThisDrawing.SendCommand "(sssetfirst nil ss)" & vbCr
    Or, if the selection set's name is stored in a variable, e.g. called SSName,
    'its name could be fetched with
    Dim SSName As String
    SSName = ss.Name
    the invocation statement is
    ThisDrawing.SendCommand "(setq ss (vlaSel->Sel (vla-item (vla-get-selectionsets (vla-get-activedocument (vlax-get-acad-object))) & Chr(34) & MySSName & Chr(34) & )))" & vbCr
    ThisDrawing.SendCommand "(sssetfirst nil ss)" & vbCr
0 Likes
Message 11 of 12

norman.yuan
Mentor
Mentor

If anyone wonders how the steps I suggested here would work or not, see this latest discussion on the same topic and my code solution.

 

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 12 of 12

ivan_protsenko
Community Visitor
Community Visitor

I may be a bit late, but I think I've found a mistake in the invocation with variable name. Looks like you forgot quotation marks. It should be:

ThisDrawing.SendCommand "(setq ss (vlaSel->Sel (vla-item (vla-get-selectionsets (vla-get-activedocument (vlax-get-acad-object)))" & Chr(34) & MySSName & Chr(34) & ")))" & vbCr
ThisDrawing.SendCommand "(sssetfirst nil ss)" & vbCr
0 Likes