Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Count Dynamic Blocks

16 REPLIES 16
Reply
Message 1 of 17
bdsmls
4473 Views, 16 Replies

Count Dynamic Blocks

I need help with a lisp routine to count the number of dynamic blocks of a specific name ("FD") by windowing an area of the drawing. I have a routine that I've been using to accomplish this, but i don't understand why it doesn't count dynamic blocks.

 

(DEFUN C:LOCATEFD(/ BLKNAME BLOCKSET TOTAL)
(SETQ BLKNAME "FD")
(PROGN(SETQ BLOCKSET(SSGET(LIST(CONS 2 BLKNAME))))
(IF(= BLOCKSET NIL)
(PROGN(SETQ TOTAL 0)
(ALERT(STRCAT "\nTHERE ARE NO FIRE DAMPERS IN THIS DRAWING"))
)))
(SETQ TOTAL(SSLENGTH BLOCKSET))
(SSSETFIRST NIL BLOCKSET)
(IF(= TOTAL 1)(ALERT(STRCAT "\nTHERE IS 1 FIRE DAMPER IN THIS DRAWING")))
(IF(> TOTAL 1)(ALERT(STRCAT "\nTHERE ARE "(ITOA TOTAL)" FIRE DAMPERS IN THIS DRAWING")))
(PRINC))

 

Thanks,

Larry

16 REPLIES 16
Message 2 of 17
Anonymous
in reply to: bdsmls

Good Morning,

 

This problem has happened many times, if you search for this you can find many solutions, the problem is that since dynamic blocks have been introduced the ssget function cannot access them by name, you will get a random name for this block, you must instead sort through them using vla function methods. and get the 'EffectiveName object property.

 

(vlax-get obj 'EffectiveName)

 

 

Message 3 of 17
hgasty1001
in reply to: bdsmls

Hi,

 

Dynamic blocks are special ones, if they have some of its dynamic properties active, then ssget will not find it as usual, as the name of the block reference is changed to  "*XX..." , but if the dynamic block is inserted with no active dynamic property then the original block name is preserved until you change some dynamic property on it.

 

Try this:

(defun countblk(blkName / ss s i n ent obj)
  (vl-load-com)
  (setq ss (ssget "X" '((0 . "INSERT"))))
  (setq s 0)
  (if ss
    (progn
      (setq i 0)
      (setq n (sslength ss))
      (while (< i n)
	(setq ent (ssname ss i))
	(setq obj (vlax-ename->vla-object ent))
	(if (= blkName (vlax-get obj 'EffectiveName))
	  (setq s (+ s 1))
	)
	(setq i (+ i 1))
      )
     )
  )
 s
)

(defun c:countblk()
  (setq blkName (getstring "\Block Name: "))
  (alert (strcat "Block Count:=" (itoa (countblk blkName))))
  (princ)
)  

 

Gaston Nunez

Message 4 of 17
bdsmls
in reply to: hgasty1001

Thanks Gaston, that worked great.

 

Now for part two, am i also able to have the blocks selected after being counted as in my original routine (SSSETFIRST NIL BLOCKSET)?  I wasn't able to figure out what the selection set is in your routine or if there is a selection set of the specified blocks.

What i was using my routine for was to 1) get a count of the specific blocks and 2) be able to globally change attribute values. Thus the reason for (SSSETFIRST NIL BLOCKSET)

 

Larry

 

Message 5 of 17
hgasty1001
in reply to: bdsmls

Hi,

 

You can't select dynamic blocks using a name filter, so you have to select *all* the inserts in the dwg, and then get the effective name of the block references and compare it to the search name. If you need a selection set with the founded blocks, you have to add it "manually" as in:

 

(defun countblk(blkName / ss s i n ent obj)
  (vl-load-com)
  (setq ss (ssget "X" '((0 . "INSERT"))))
  (setq s 0)
  (if ss
    (progn
      (setq MyBlocksSS (ssadd)) ;The SS with the found blocks
      (setq i 0)
      (setq n (sslength ss))
      (while (< i n)
	(setq ent (ssname ss i))
	(setq obj (vlax-ename->vla-object ent))
	(if (= blkName (vlax-get obj 'EffectiveName))
          (progn
	   (setq s (+ s 1))
           (ssadd ent MyBlocksSS) ;; Add the found block to the SS
          )
	)
	(setq i (+ i 1))
      )
     )
  )
 s
)

Now you have the blocks in the MyBlocksSS selection set 

 

 

Gaston Nunez

 

Message 6 of 17
bdsmls
in reply to: hgasty1001

Thank you very much Gaston. That worked perfectly.

Now I don't want to push my luck, but is there anyway to search for blocks by their name AND visibility state?

 

Message 7 of 17
hgasty1001
in reply to: bdsmls

Hi,

 

You can get the dynamic properties from a block using this nice function from Lee Mac:

 

;;------------=={ Get Dynamic Property Value }==--------------;;
;;                                                            ;;
;;  Returns the value of a Dynamic Block Property, if present ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2010 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  block - VLA Dynamic Block Reference Object                ;;
;;  prop  - Dynamic Block Property Name                       ;;
;;------------------------------------------------------------;;
;;  Returns: Value of property, else nil                      ;;
;;------------------------------------------------------------;;

(defun LM:GetDynamicPropValue ( block prop )
    (setq prop (strcase prop))
    (vl-some
        (function
            (lambda ( _prop )
                (if (eq prop (strcase (vla-get-propertyname _prop)))
                    (vlax-get _prop 'Value)
                )
            )
        )
        (vlax-invoke block 'GetDynamicBlockProperties)
    )
)

 Gaston Nunez

Message 8 of 17
pbejse
in reply to: bdsmls


@bdsmls wrote:

Thank you very much Gaston. That worked perfectly.

 


You can reduce the number of selected blocks by using a wildcard match

 

(setq ss (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat blkName ",`*U*")))))

 


@bdsmls wrote:

.....

Now I don't want to push my luck, but is there anyway to search for blocks by their name AND visibility state?


 

Unfortunately there is no easy way to "catch" those without knowing the specific visibility parameter name, not saying there is none. Parameter names may vary from one DB to another, the Visibiity parameter name may or may not be be "Visibility" , depending on the DB's author.

 

Anyhoo. to count DB and their respective visility state

 

(defun DbVisName (bname vis / ss data i e pname vis vname inc)
(vl-load-com)
(if 
    (setq data nil
          ss   (ssget "_X"
                      (list (cons 0 "INSERT")
                            (cons 2 (strcat bname ",`*U*")))))
        (progn    
	(repeat (setq i (sslength ss))
            (cond  ((and
			(eq (strcase
                                  (vla-get-EffectiveName
                                        (setq e    (vlax-ename->vla-object
                                                         (ssname
                                                               ss
                                                               (setq i (1- i)))))))
                            (strcase bname))
                        (setq Pname (car (vl-remove-if-not '(lambda (j)
                                 (eq (strcase (vla-get-PropertyName j)) (strcase vis)))             
                                               (vlax-invoke e 'GetDynamicBlockProperties))))
	                (setq vname (vlax-get Pname 'Value))
	                (if (setq inc (assoc vname data))
	                    (setq data (subst (list vname (1+ (cadr inc))) inc data))
	                    (setq data (cons (list vname 1) data)))
                        )))
              )
        (princ (strcat "\nTotal \"" bname "\" Blocks Found: " (itoa (apply '+ (mapcar 'cadr data)))))
        (foreach itm data (print itm))
        )
        
    )(if (null data) (princ "\nBlock/Parameter Name not found"))
 (princ)
 )

 

 command (dbvisname "FD" "visibility")

Total "FD" Blocks Found: 11

("VisState1" 3)

("VisState1" 1)

("VisState3" 😎

 

command (dbvisname "FDX" "visibility2")

Total "FDX" Blocks Found: 0
Block/Parameter Name not found

 

HTH

Message 9 of 17
bdsmls
in reply to: pbejse

Thank you. Worked great

 

Larry

Message 10 of 17
pbejse
in reply to: bdsmls


@bdsmls wrote:

Thank you. Worked great

 

Larry


You are  welcome Larry, glad i could help

 

Cheers

 

Message 11 of 17
Anonymous
in reply to: bdsmls

I'm getting a "Too Few Arguments" error when I try using the 'DbVisName' function. I added a c: to make it a command - am I doing something wrong? Apologies, I'm new to Lisp. Thanks!

 

Chris

Message 12 of 17
hmsilva
in reply to: Anonymous

Welcome to the Autodesk Discussion Groups, Chris!

 

Pebejse's function DbVisName, have two arguments,

bname -> the block name

vis -> the visibility parameter name

 

you'll kneed to load the code and run the code with something like this

(dbvisname "YourBlockName" "TheVisibilityParameterName")

 

or to use the function at the commandline as a command, without changing the original code, perhaps something like this

Not tested, I don't have AutoCAD in this pc...

 

(defun c:test ( / blkname parname) 

;; by pbejse
;; http://forums.autodesk.com/t5/Visual-LISP-AutoLISP-and-General/Count-Dynamic-Blocks/m-p/3738778#M308...
(defun DbVisName (bname vis / ss data i e pname vis vname inc)
(vl-load-com)
(if 
    (setq data nil
          ss   (ssget "_X"
                      (list (cons 0 "INSERT")
                            (cons 2 (strcat bname ",`*U*")))))
        (progn    
	(repeat (setq i (sslength ss))
            (cond  ((and
			(eq (strcase
                                  (vla-get-EffectiveName
                                        (setq e    (vlax-ename->vla-object
                                                         (ssname
                                                               ss
                                                               (setq i (1- i)))))))
                            (strcase bname))
                        (setq Pname (car (vl-remove-if-not '(lambda (j)
                                 (eq (strcase (vla-get-PropertyName j)) (strcase vis)))             
                                               (vlax-invoke e 'GetDynamicBlockProperties))))
	                (setq vname (vlax-get Pname 'Value))
	                (if (setq inc (assoc vname data))
	                    (setq data (subst (list vname (1+ (cadr inc))) inc data))
	                    (setq data (cons (list vname 1) data)))
                        )))
              )
        (princ (strcat "\nTotal \"" bname "\" Blocks Found: " (itoa (apply '+ (mapcar 'cadr data)))))
        (foreach itm data (print itm))
        )
        
    )(if (null data) (princ "\nBlock/Parameter Name not found"))
 (princ)
 )
  
  (if (and
	(setq blkname (getstring T "\nEnter the Block Name: "))
	(setq parname (getstring "\nEnter the Visibility Parameter Name: "))
	);; and
    (dbvisname blkname parname)
    );; if
  (princ)
  )

HTH

Henrique

EESignature

Message 13 of 17
hmsilva
in reply to: Anonymous

Chris,

If the above solution is suitable to you, change

(setq parname (getstring "\nEnter the Visibility Parameter Name: "))

to

(setq parname (getstring T "\nEnter the Visibility Parameter Name: "))

to allow strings with empty spaces...

 

HTH

Henrique

EESignature

Message 14 of 17
Anonymous
in reply to: hmsilva

Wow, thanks for the quick response!

 

The code you wrote worked for what it was supposed to do but what I'm trying to do is audit the drawing for dynamic blocks with a specific visability perameter name. Your code is great if you already know the exact block name, but I'm trying to find out the block names of the blocks with the visability perameter called "OBJECT". Basically I'm trying to run the routine with one arguement: visability name is "OBJECT". 

 

I tried removing this bit of the code that prompted for the blockname but I get '; error: bad argument type: stringp nil:"

 

Thanks again for your help! 

 

Chris 

 

here is the line of code I tried removing to no success:

 

(and
	(setq blkname (getstring T "\nEnter the Block Name: "))
Message 15 of 17
hmsilva
in reply to: Anonymous

@ pbejse
Sorry, 'm murdering your code... Smiley Embarassed

 


@Anonymous wrote:

Wow, thanks for the quick response!

 

The code you wrote worked for what it was supposed to do but what I'm trying to do is audit the drawing for dynamic blocks with a specific visability perameter name. Your code is great if you already know the exact block name, but I'm trying to find out the block names of the blocks with the visability perameter called "OBJECT". Basically I'm trying to run the routine with one arguement: visability name is "OBJECT". 

 

I tried removing this bit of the code that prompted for the blockname but I get '; error: bad argument type: stringp nil:"

 

Thanks again for your help! 

 

Chris 

 

here is the line of code I tried removing to no success:

 

(and
	(setq blkname (getstring T "\nEnter the Block Name: "))

@ Chris

the code isn't mine, is from pebejse, I just add some code lines in order to use pebejse's function at the commandline as a command.

 

when our doubts/difficulties, are not the same as the original post, is always preferable to start a new thread with a new title because you'll get more help than in a old thread, and the help you receive will be directed to your doubt/difficulty...

 

I have a deadline to meet today and I don't have much free time, just a quick one, minimally tested and as a "demo" and "ruining pebejse's code"

 

(defun c:test (/ BNAME DATA E I PNAME SS VIS)
  (if (setq data nil
	    vis	 (getstring T "\nEnter the Visibility Parameter Name: ")
	    ss	 (ssget	"_X"
			(list (cons 0 "INSERT")
			      (cons 2 "`*U*")
			)
		 )
      )
    ;; setq
    (progn
      (repeat (setq i (sslength ss))
	(cond ((and (setq bname	(vla-get-EffectiveName
				  (setq	e (vlax-ename->vla-object
					    (ssname
					      ss
					      (setq i (1- i))
					    )
					  )
				  )
				)
		    )
		    (setq Pname	(car (vl-remove-if-not
				       '(lambda	(j)
					  (eq (strcase (vla-get-PropertyName j))
					      (strcase vis)
					  )
					)
				       (vlax-invoke e 'GetDynamicBlockProperties)
				     )
				)
		    )
		    (not (member bname data))
	       )
	       (setq data (cons bname data))
	       (foreach itm data (print itm))
	      )
	);; cond
      );; repeat
    );; progn
  );; if
  (if (null data) (princ "\nBlock/Parameter Name not found"))
  (princ)
)

 

HTH

Henrique

 

EESignature

Message 16 of 17
Anonymous
in reply to: hmsilva

Thanks so much and sorry if I'm out of line with the code. I'll start a new post with the final search perimeter being case sensitivity: "OBJECT vs. Object."

Chris
Message 17 of 17
hmsilva
in reply to: Anonymous


@Anonymous wrote:
... sorry if I'm out of line with the code...
...

What I tried to say, was that it should be easier to receive some help in a new thread...

 


@Anonymous wrote:
Thanks so much ...
...


You're welcome, Chris

 

Henrique

EESignature

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost