@CodeDing wrote:
....@Moshe-A
Also, if @Kent1Cooper is willing to critique my code here, I enjoy hearing his feedback lol.
....
My one critique is a repeat, that it looks again like it finds every Block insertion, and then digs into each insertion individually, to find out first whether it's one with any Attributes at all, and then what their Tags are and whether any of them have (one of) the right Tag name(s).
The way I'd approach it is to look at Block definitions, [which typically would be far fewer than insertions] for those that contain the right Tag(s), and once that has been determined, find not all Block insertions, but first narrow that down in selection to only those that contain Attributes [typically far fewer than all Block insertions], and then check each of those, not digging inside for what Tags are in it, but simply looking at whether it is of one of the [Effective] Block names that are already known to contain the designated Tag(s).
If not for the fact that some could be Dynamic Blocks, it could be simpler -- it wouldn't even need to find all Block insertions with Attributes, but could just directly find and highlight all Blocks of the determined names. Because a Block's being Dynamic spoils the "name" on its insertions, (ssget) can't find them by Block name, but it's necessary to look at their Effective name, which can't be filtered for in selection but needs to be checked individually.
The (wcmatch) function can look at multiple strings at once, so a single string of Tag names and a single string of Block names can be used, rather than a list of Tag names.
[And it's quite a bit shorter!]
Try this [minimally tested]:
(defun C:BWST ; = Blocks With Specified Tag(s)
(/ atts blknames blks blk blkname ent edata foundit n)
(setq
atts (strcase (getstring "\nTag name(s) {comma-separated if more than one}: "))
blknames "" ; initially empty string
blks (ssadd); initially empty selection set
); setq
(while (setq blk (tblnext "block" (not blk))); step through Block table
(setq
ent (tblobjname "block" (setq blkname (cdr (assoc 2 blk))))
foundit nil ; reset for each Block definition
); setq
(while (and (not foundit) (setq ent (entnext ent)))
;; haven't found Tag(s) yet, still another object
(setq edata (entget ent))
(if (and (member '(0 . "ATTDEF") edata) (wcmatch (cdr (assoc 2 edata)) atts))
(setq ; then -- this Block contains (one of the) specified Attribute Tag(s)
blknames (strcat blknames blkname ",")
foundit T
); setq
); if
); while - Block definition parts
); while - Block table entries
(setq blkstemp (ssget "_X" '((0 . "INSERT") (66 . 1))))
;; find all Blocks with Attributes [only because of possibility of Dynamic Blocks]
(repeat (setq n (sslength blkstemp)); look for those of correct name(s)
(if
(wcmatch ; of [one of the] correct name[s]?
(strcase (vla-get-EffectiveName (vlax-ename->vla-object (setq blk (ssname blkstemp (setq n (1- n)))))))
(strcase blknames)
); wcmatch
(ssadd blk blks); then - put it in selection set
); if
); repeat
(if (> (sslength blks) 0) (sssetfirst nil blks))
;; select/grip/highlight all Blocks of names with any specified Tag(s) [if any]
(princ)
); defun
EDIT: [If you got this in the first ten minutes or so after posting, copy it again -- I noticed some things that needed fixing.]
Kent Cooper, AIA