Jump to content

Select blocks with specific values for specific attribute tags


PrimeTimeAction

Recommended Posts

Try the following:

;; Select Blocks by Attribute Tag and/or Value  -  Lee Mac
;; Selects all attributed blocks in the current layout which contain a specified attribute value.

(defun c:selblkbyatt ( / att atx ent idx sel str tag )
    (setq str (strcase (getstring t "\nSpecify attribute value <any>: "))
          tag (strcase (getstring (strcat "\nSpecify attribute tag" (if (= "" str) ": " " <any>: "))))
    )
    (if (not (= "" str tag))
        (if
            (and
                (setq sel
                    (ssget "_X"
                        (list
                           '(000 . "INSERT")
                           '(066 . 1)
                            (if (= 1 (getvar 'cvport))
                                (cons 410 (getvar 'ctab))
                               '(410 . "Model")
                            )
                        )
                    )
                )
                (progn
                    (repeat (setq idx (sslength sel))
                        (setq ent (ssname sel (setq idx (1- idx)))
                              att (entnext ent)
                              atx (entget  att)
                              flg nil
                        )
                        (while
                            (and (= "ATTRIB" (cdr (assoc 0 atx)))
                                (not
                                    (and
                                        (or (= "" str) (wcmatch (strcase (cdr (assoc 1 atx))) str))
                                        (or (= "" tag) (wcmatch (strcase (cdr (assoc 2 atx))) tag))
                                    )
                                )
                            )
                            (setq att (entnext att)
                                  atx (entget  att)
                            )
                        )
                        (if (= "SEQEND" (cdr (assoc 0 atx)))
                            (ssdel ent sel)
                        )
                    )
                    (< 0 (sslength sel))
                )
            )
            (sssetfirst nil sel)
            (princ "\nNo blocks found.")
        )
    )
    (princ)
)

 

Edited by Lee Mac
  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

Thanks alot @Lee Mac ,works great!

Would it be possible to add an option to choose a specific block name?

I have the same attributes in many blocks in my drawing, so this lisp would be much more useful and quick this way.

Link to comment
Share on other sites

The following program will allow you to specify either a block name, attribute tag, or attribute value (or all three), and will return a selection of all blocks matching the given criteria, residing in the current layout:

;; Block Selection  -  Lee Mac
;; Selects all blocks in the current layout with a given block name or which contain a specified attribute tag and/or value.

(defun c:bsel ( / att atx blk cnt ent enx flg idx sel str tag )
    (setq blk (strcase (getstring t  "\nSpecify block name <any>: "))
          tag (strcase (getstring "\nSpecify attribute tag <any>: "))
          str (strcase (getstring t (strcat "\nSpecify attribute value" (if (= "" tag blk) ": " " <any>: "))))
    )
    (if (not (= "" str tag blk))
        (if
            (and
                (setq sel
                    (ssget "_X"
                        (append
                           '((000 . "INSERT"))
                            (if (not (= "" tag str)) '((066 . 1)))
                            (if (/= "" blk) (list (cons 2 (strcat "`*U*," blk))))
                            (if (= 1 (getvar 'cvport))
                                (list (cons 410 (getvar 'ctab)))
                               '((410 . "Model"))
                            )
                        )
                    )
                )
                (progn
                    (repeat (setq idx (sslength sel))
                        (setq ent (ssname sel (setq idx (1- idx)))
                              enx (entget ent)
                        )
                        (cond
                            (   (not (or (= "" blk) (wcmatch (strcase (LM:name->effectivename (cdr (assoc 2 enx)))) blk)))
                                (ssdel ent sel)
                            )
                            (   (member (cdr (assoc 66 enx)) '(nil 0)))
                            (   (progn
                                    (setq att (entnext ent)
                                          atx (entget  att)
                                          flg nil
                                    )
                                    (while
                                        (and (= "ATTRIB" (cdr (assoc 0 atx)))
                                            (not
                                                (and
                                                    (or (= "" str) (wcmatch (strcase (cdr (assoc 1 atx))) str))
                                                    (or (= "" tag) (wcmatch (strcase (cdr (assoc 2 atx))) tag))
                                                )
                                            )
                                        )
                                        (setq att (entnext att)
                                              atx (entget  att)
                                        )
                                    )
                                    (= "SEQEND" (cdr (assoc 0 atx)))
                                )
                                (ssdel ent sel)
                            )
                        )
                    )
                    (< 0 (setq cnt (sslength sel)))
                )
            )
            (progn
                (princ (strcat "\n" (itoa cnt) " block" (if (= 1 cnt) "" "s") " found."))
                (sssetfirst nil sel)
            )
            (princ "\nNo blocks found.")
        )
    )
    (princ)
)

;; Block Name -> Effective Block Name  -  Lee Mac
;; blk - [str] Block name

(defun LM:name->effectivename ( blk / rep )
    (if
        (and (wcmatch blk "`**")
            (setq rep
                (cdadr
                    (assoc -3
                        (entget
                            (cdr (assoc 330 (entget (tblobjname "block" blk))))
                           '("acdbblockrepbtag")
                        )
                    )
                )
            )
            (setq rep (handent (cdr (assoc 1005 rep))))
        )
        (cdr (assoc 2 (entget rep)))
        blk
    )
)

(princ)

 

  • Like 1
Link to comment
Share on other sites

  • 5 weeks later...

Wow, great lisp @Lee Mac. Thanks.

Would it be possible to export this data to excel?

Something like search value "0.5" in "speed" attribute tag, but all result go to excel (with value of remaining attributes). 

Link to comment
Share on other sites

1 hour ago, aqes2 said:

Wow, great lisp @Lee Mac. Thanks.

Would it be possible to export this data to excel?

Something like search value "0.5" in "speed" attribute tag, but all result go to excel (with value of remaining attributes). 

 

Thank you, I'm pleased that you like the program.

 

Whilst your request is certainly possible to achieve, I'm afraid this would not be a quick modification to the current code.

Edited by Lee Mac
Link to comment
Share on other sites

1 hour ago, aqes2 said:

Wow, great lisp @Lee Mac. Thanks.

Would it be possible to export this data to excel?

Something like search value "0.5" in "speed" attribute tag, but all result go to excel (with value of remaining attributes). 

Here is a workaround :

Lee Mac lisp gets you the selection set you need.

You can then cut the objects and paste them to a new DWG file >express tools>export attributes> save txt file as excel> edit in excel> import attributes> copy blocks back to original DWG.

Link to comment
Share on other sites

7 hours ago, BIGAL said:

Lee what about nentsel pick an attribute, you get block name, tag name and default attribute value, did something using this method. Now where is it.

 

Recently we're doing this:

(while (setq result (LeeDoesAGreatJob))
  (apply 'ConstructiveCriticism result)
)

 

Link to comment
Share on other sites

On 1/14/2019 at 2:12 PM, NoamBrand said:

Here is a workaround :

Lee Mac lisp gets you the selection set you need.

You can then cut the objects and paste them to a new DWG file >express tools>export attributes> save txt file as excel> edit in excel> import attributes> copy blocks back to original DWG.

A more simple workaround would be like this:

Lee Mac lisp gets you the selection set you need.

express tools>export attributes>select objects: p  (this will select the last selection set)> save txt file as excel> edit in excel> import attrattributes.

Link to comment
Share on other sites

@Lee Mac, thank for respond. At least I know it's possible.

 

@NoamBrand, yeah, I know it. I was wondering how do it all by lisp. First my idea was to do few lisp with the same attribute but other value go to .txt and after that to excel. But I failed. And now here. Anyway, thanks for tips, I gratful for your respond.

Link to comment
Share on other sites

  • 10 months later...
On 12/13/2018 at 10:34 PM, Lee Mac said:

The following program will allow you to specify either a block name, attribute tag, or attribute value (or all three), and will return a selection of all blocks matching the given criteria, residing in the current layout:


;; Block Selection  -  Lee Mac
;; Selects all blocks in the current layout with a given block name or which contain a specified attribute tag and/or value.

(defun c:bsel ( / att atx blk cnt ent enx flg idx sel str tag )
    (setq blk (strcase (getstring t  "\nSpecify block name <any>: "))
          tag (strcase (getstring "\nSpecify attribute tag <any>: "))
          str (strcase (getstring t (strcat "\nSpecify attribute value" (if (= "" tag blk) ": " " <any>: "))))
    )
    (if (not (= "" str tag blk))
        (if
            (and
                (setq sel
                    (ssget "_X"
                        (append
                           '((000 . "INSERT"))
                            (if (not (= "" tag str)) '((066 . 1)))
                            (if (/= "" blk) (list (cons 2 (strcat "`*U*," blk))))
                            (if (= 1 (getvar 'cvport))
                                (list (cons 410 (getvar 'ctab)))
                               '((410 . "Model"))
                            )
                        )
                    )
                )
                (progn
                    (repeat (setq idx (sslength sel))
                        (setq ent (ssname sel (setq idx (1- idx)))
                              enx (entget ent)
                        )
                        (cond
                            (   (not (or (= "" blk) (wcmatch (strcase (LM:name->effectivename (cdr (assoc 2 enx)))) blk)))
                                (ssdel ent sel)
                            )
                            (   (member (cdr (assoc 66 enx)) '(nil 0)))
                            (   (progn
                                    (setq att (entnext ent)
                                          atx (entget  att)
                                          flg nil
                                    )
                                    (while
                                        (and (= "ATTRIB" (cdr (assoc 0 atx)))
                                            (not
                                                (and
                                                    (or (= "" str) (wcmatch (strcase (cdr (assoc 1 atx))) str))
                                                    (or (= "" tag) (wcmatch (strcase (cdr (assoc 2 atx))) tag))
                                                )
                                            )
                                        )
                                        (setq att (entnext att)
                                              atx (entget  att)
                                        )
                                    )
                                    (= "SEQEND" (cdr (assoc 0 atx)))
                                )
                                (ssdel ent sel)
                            )
                        )
                    )
                    (< 0 (setq cnt (sslength sel)))
                )
            )
            (progn
                (princ (strcat "\n" (itoa cnt) " block" (if (= 1 cnt) "" "s") " found."))
                (sssetfirst nil sel)
            )
            (princ "\nNo blocks found.")
        )
    )
    (princ)
)

;; Block Name -> Effective Block Name  -  Lee Mac
;; blk - [str] Block name

(defun LM:name->effectivename ( blk / rep )
    (if
        (and (wcmatch blk "`**")
            (setq rep
                (cdadr
                    (assoc -3
                        (entget
                            (cdr (assoc 330 (entget (tblobjname "block" blk))))
                           '("acdbblockrepbtag")
                        )
                    )
                )
            )
            (setq rep (handent (cdr (assoc 1005 rep))))
        )
        (cdr (assoc 2 (entget rep)))
        blk
    )
)

(princ)

 

Is it possible to modify the Lisp that it also select blocks with no value/emty attributen?

Thanks

Pmxcad

Link to comment
Share on other sites

  • 1 year later...
On 12/13/2018 at 4:34 PM, Lee Mac said:

The following program will allow you to specify either a block name, attribute tag, or attribute value (or all three), and will return a selection of all blocks matching the given criteria, residing in the current layout:



;; Block Selection  -  Lee Mac
;; Selects all blocks in the current layout with a given block name or which contain a specified attribute tag and/or value.

(defun c:bsel ( / att atx blk cnt ent enx flg idx sel str tag )
    (setq blk (strcase (getstring t  "\nSpecify block name <any>: "))
          tag (strcase (getstring "\nSpecify attribute tag <any>: "))
          str (strcase (getstring t (strcat "\nSpecify attribute value" (if (= "" tag blk) ": " " <any>: "))))
    )
    (if (not (= "" str tag blk))
        (if
            (and
                (setq sel
                    (ssget "_X"
                        (append
                           '((000 . "INSERT"))
                            (if (not (= "" tag str)) '((066 . 1)))
                            (if (/= "" blk) (list (cons 2 (strcat "`*U*," blk))))
                            (if (= 1 (getvar 'cvport))
                                (list (cons 410 (getvar 'ctab)))
                               '((410 . "Model"))
                            )
                        )
                    )
                )
                (progn
                    (repeat (setq idx (sslength sel))
                        (setq ent (ssname sel (setq idx (1- idx)))
                              enx (entget ent)
                        )
                        (cond
                            (   (not (or (= "" blk) (wcmatch (strcase (LM:name->effectivename (cdr (assoc 2 enx)))) blk)))
                                (ssdel ent sel)
                            )
                            (   (member (cdr (assoc 66 enx)) '(nil 0)))
                            (   (progn
                                    (setq att (entnext ent)
                                          atx (entget  att)
                                          flg nil
                                    )
                                    (while
                                        (and (= "ATTRIB" (cdr (assoc 0 atx)))
                                            (not
                                                (and
                                                    (or (= "" str) (wcmatch (strcase (cdr (assoc 1 atx))) str))
                                                    (or (= "" tag) (wcmatch (strcase (cdr (assoc 2 atx))) tag))
                                                )
                                            )
                                        )
                                        (setq att (entnext att)
                                              atx (entget  att)
                                        )
                                    )
                                    (= "SEQEND" (cdr (assoc 0 atx)))
                                )
                                (ssdel ent sel)
                            )
                        )
                    )
                    (< 0 (setq cnt (sslength sel)))
                )
            )
            (progn
                (princ (strcat "\n" (itoa cnt) " block" (if (= 1 cnt) "" "s") " found."))
                (sssetfirst nil sel)
            )
            (princ "\nNo blocks found.")
        )
    )
    (princ)
)

;; Block Name -> Effective Block Name  -  Lee Mac
;; blk - [str] Block name

(defun LM:name->effectivename ( blk / rep )
    (if
        (and (wcmatch blk "`**")
            (setq rep
                (cdadr
                    (assoc -3
                        (entget
                            (cdr (assoc 330 (entget (tblobjname "block" blk))))
                           '("acdbblockrepbtag")
                        )
                    )
                )
            )
            (setq rep (handent (cdr (assoc 1005 rep))))
        )
        (cdr (assoc 2 (entget rep)))
        blk
    )
)

(princ)

 

 

Hi Lee,

 

Is there any way to get this to work with Attributes that are populated by a field? I have hundreds of formed flat bars with a LENGTH attribute populated by a Field. The field is linked to the length of the polyline at the centerline of the piece's thickness (to get the flat length of that piece). When I run the bsel command and input the length (ft'-in frac/in") I get no results. I'm assuming that this is because fields populate the attribute as "######" when editing the attribute definition, and that the command doesn't recognize the field as containing a text value matching my input.

 

Anyway, I want to select all of the parts of the same flat length (assuming all other elements are identical) so that I can assign the same piece mark number to all similar pieces without having to manually/individually examine each one and keep track of their properties (which is how I have been doing it and let me tell you it's no walk in the park). Hopefully I can find a better method, as I have several projects similar to this coming in the future and I would like to save as much time as possible.

 

Thanks in advance!

 

Will O

 

Link to comment
Share on other sites

9 hours ago, WillO said:

Is there any way to get this to work with Attributes that are populated by a field? I have hundreds of formed flat bars with a LENGTH attribute populated by a Field. The field is linked to the length of the polyline at the centerline of the piece's thickness (to get the flat length of that piece). When I run the bsel command and input the length (ft'-in frac/in") I get no results. I'm assuming that this is because fields populate the attribute as "######" when editing the attribute definition, and that the command doesn't recognize the field as containing a text value matching my input.

 

Hi Will,

 

There should be nothing preventing this program operating successfully with attributes containing field expressions, since the attribute value contains the field output (not the field code or ####, unless the field is unevaluated or corrupt). Certainly, in my testing, I can populate an attribute value with a field expression referencing the area of a circle, and then successfully select the target block using my bsel program and specifying the target area.

 

Note that the selection is matching the string value of the attribute with the supplied input, and is not performing a numerical match (therefore, the input must match the content exactly as displayed); furthermore, wildcard operators are permitted in the user input (hence, you may not receive the desired results if your input string inadvertently contains a wildcard operator that you wish to be interpreted as a literal - to mark a wildcard operator as a literal, prefix it with a backquote, e.g. to search for the literal string #1 you would need to enter `#1 otherwise you would select any two digit value ending with a 1).

 

Also note that if your length value is surrounded by other text (even whitespace), you'll need to surround your input string with the asterisk wildcard operator to search for a substring within the candidate attribute values, e.g. *ft'-in frac/in"*

Edited by Lee Mac
  • Thanks 1
Link to comment
Share on other sites

16 hours ago, Lee Mac said:

 

Hi Will,

 

There should be nothing preventing this program operating successfully with attributes containing field expressions, since the attribute value contains the field output (not the field code or ####, unless the field is unevaluated or corrupt). Certainly, in my testing, I can populate an attribute value with a field expression referencing the area of a circle, and then successfully select the target block using my bsel program and specifying the target area.

 

Note that the selection is matching the string value of the attribute with the supplied input, and is not performing a numerical match (therefore, the input must match the content exactly as displayed); furthermore, wildcard operators are permitted in the user input (hence, you may not receive the desired results if your input string inadvertently contains a wildcard operator that you wish to be interpreted as a literal - to mark a wildcard operator as a literal, prefix it with a backquote, e.g. to search for the literal string #1 you would need to enter `#1 otherwise you would select any two digit value ending with a 1).

 

Also note that if your length value is surrounded by other text (even whitespace), you'll need to surround your input string with the asterisk wildcard operator to search for a substring within the candidate attribute values, e.g. *ft'-in frac/in"*

 Thanks Lee!

 

It turns out that I had a ID10T error, and was not entering the length in the correct format (transposed the dash or missed a tick). Wasted a lot of time researching just to figure out I was doing it wrong! BSEL command works like a charm! I have been able to accomplish my part numbering very easily this way. You are the LISP master!

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...