As an Autolisp kludge, I’m not too accomplished to ask for help – that’s for sure! I am trying to understand how to work with safearrays so that I can modify a dynamic block property reporting tool that I found here on the forums. I’d like to take the following code and filter out the extraneous properties so that the user doesn’t get information overload. Here’s the code that I’m starting with – works nicely:
(defun c:dbinfo (/ obj v vval sal salnth count)
(setq obj (vlax-ename->vla-object (car (entsel "\nSelect Dynamic Block: "))))
(setq v (vla-getdynamicblockproperties obj))
(setq vval (vlax-variant-value v))
(setq sal (vlax-safearray->list vval))
;;;;I‘m thinking of filtering here
(setq salnth (length sal))
(setq count 0)
(while (/= count salnth)
(vlax-dump-object (nth count sal))
(setq count (+ count 1))
)
(setq count nil)
(princ)
(textscr)
)
So, how do I filter the safearray list (down two levels to property names) so I can remove origins and other unimportant properties? Here’s the two property names I am trying to filter out:
(or (= (car y) "Origin") (= (substr (car y) 1 😎 "Position"))
I’m beating my head against the wall trying to figure out how to take sal and redefine it like:
(/= (or (= (car y) "Origin") (= (substr (car y) 1 😎 "Position")))
Of course, that doesn’t work with a safearray.
Anyone know how this is done?
Thanks in advance...
Solved! Go to Solution.
Solved by Lee_Mac. Go to Solution.
Hi Ronald,
Here are a few ways to accomplish your goal:
(defun c:dbinfo ( / ent obj props ) (if (and (setq ent (car (entsel "\nSelect Dynamic Block: "))) (eq "AcDbBlockReference" (vla-get-objectname (setq obj (vlax-ename->vla-object ent)))) (eq :vlax-true (vla-get-isdynamicblock obj)) ) (progn (setq props (vl-remove-if (function (lambda ( prop ) (setq prop (strcase (vla-get-propertyname prop))) (or (eq "ORIGIN" prop) (eq "POSITION" (substr prop 1 8)) ) ) ) (vlax-safearray->list (vlax-variant-value (vla-getdynamicblockproperties obj)) ) ) ) (mapcar 'vlax-dump-object props) ) ) (princ) )
(vl-load-com)
Or, you can use the undocumented vlax-invoke function which will return the data as a native AutoLISP data type (i.e. a List), to avoid dealing with Variants/SafeArrays:
(defun c:dbinfo ( / ent obj props ) (if (and (setq ent (car (entsel "\nSelect Dynamic Block: "))) (eq "AcDbBlockReference" (vla-get-objectname (setq obj (vlax-ename->vla-object ent)))) (eq :vlax-true (vla-get-isdynamicblock obj)) ) (progn (setq props (vl-remove-if (function (lambda ( prop ) (setq prop (strcase (vla-get-propertyname prop))) (or (eq "ORIGIN" prop) (eq "POSITION" (substr prop 1 8)) ) ) ) (vlax-invoke obj 'getdynamicblockproperties) ) ) (mapcar 'vlax-dump-object props) ) ) (princ) )
(vl-load-com)
Or, with a foreach loop:
(defun c:dbinfo ( / ent obj props pname ) (if (and (setq ent (car (entsel "\nSelect Dynamic Block: "))) (eq "AcDbBlockReference" (vla-get-objectname (setq obj (vlax-ename->vla-object ent)))) (eq :vlax-true (vla-get-isdynamicblock obj)) ) (progn (foreach prop (vlax-invoke obj 'getdynamicblockproperties) (setq pname (strcase (vla-get-propertyname prop))) (if (not (or (eq "ORIGIN" pname) (eq "POSITION" (substr pname 1 8)) ) ) (setq props (cons prop props)) ) ) (mapcar 'vlax-dump-object props) ) ) (princ) ) (vl-load-com)
Or, using mapcar:
(defun c:dbinfo ( / ent obj props ) (if (and (setq ent (car (entsel "\nSelect Dynamic Block: "))) (eq "AcDbBlockReference" (vla-get-objectname (setq obj (vlax-ename->vla-object ent)))) (eq :vlax-true (vla-get-isdynamicblock obj)) ) (progn (setq props (apply 'append (mapcar (function (lambda ( prop / pname ) (setq pname (strcase (vla-get-propertyname prop))) (if (not (or (eq "ORIGIN" pname) (eq "POSITION" (substr pname 1 8)) ) ) (list prop) ) ) ) (vlax-invoke obj 'getdynamicblockproperties) ) ) ) (mapcar 'vlax-dump-object props) ) ) (princ) ) (vl-load-com)
There's a few options available
Thanks so much, Lee.
I just got it working when you posted these much more professional solutions! I will eventually use one of these because you've put all the entity proofing in there (such as strcase). Here's what I came up with after finding an example of someone picking apart a dynamic block safearray on a visit to the swamp:
(defun c:dbinfo (/ obj v vval sal tot i)
(setq obj (vlax-ename->vla-object (car (entsel "\nSelect Dynamic Block: "))))
(if (= (vlax-get-property obj 'isdynamicblock) :vlax-true)
(progn
(setq v (vla-getdynamicblockproperties obj)
vval (vlax-variant-value v)
sal (vlax-safearray->list vval)
tot (length sal)
i 0
)
(while (< i tot)
(if (and (/= (vlax-get-property (nth i sal) "PropertyName") "Origin")
(/= (substr (vlax-get-property (nth i sal) "PropertyName") 1 😎 "Position"))
(progn
(vlax-dump-object (nth i sal))
(princ "\n")
(setq i (1+ i))
)
(setq i (1+ i))
)
)
(princ)
(textscr)
)
)
)
I just tried all three of yours and actually, all four of these work flawlessly. I will have to try them on wrong entities to see how they handle it, but I bet yours will work fine. Mine might get hung up due to sloppy code!
I will still tune this up some as a learning exercise. I already see how you moved the argument into a vl-remove-if and really made the code concise. I'm still quite unfamiliar with the vl extensions (and only a novice at autolisp too). I have been to your page a few months ago for the first time and I got a few chunks of code there to put together my own version of a dynamic block property setter which I am using in conjunction with a command tool to insert dyn blocks off the palette while reading my own running variables to control their particular properties.
I have to say a hearty THANK YOU for all you do for guys like me. I love your web page! As I get deeper into progamming I'll be visiting more often!
You're very welcome Ronald; I'm really glad that you can benefit from my website and programs - and of course, if you have any questions about any of the code I have posted here or on my site, just ask.
Lee
Absolutely! Here's the one I settled on (with just a little mod)..
Works exactly as intended even if selection is wrong type.
;;;from Lee Mac on the Autodesk forums as a reply to my question
;;;modified by Rapidcad 12-20-11 for TGW to alert the user upon errors
(defun c:dbinfo ( / ent obj props )
(vl-load-com)
(if
(and
(setq ent (car (entsel "\nSelect Dynamic Block: ")))
(eq "AcDbBlockReference" (vla-get-objectname (setq obj (vlax-ename->vla-object ent))))
(eq :vlax-true (vla-get-isdynamicblock obj))
)
(progn
(setq props
(vl-remove-if
(function
(lambda ( prop )
(setq prop (strcase (vla-get-propertyname prop)))
(or
(eq "ORIGIN" prop)
(eq "POSITION" (substr prop 1 8))
)
)
)
(vlax-safearray->list
(vlax-variant-value (vla-getdynamicblockproperties obj))
)
)
)
(mapcar 'vlax-dump-object props)
(princ)(textscr) )
(alert "\n You'll need to pick again - please select a DYNAMIC block.")
)
)
Hi Lee, thanks for your help .
Last day I dig and dig on Dynamicblocks and reach only to get the Prop names , now I can set a new value to one of them.
Another , as with NENTSEL one can get a simple entity , in a simple block , there is a way to get the prop name just picking on the "simple entity" to get the Prop Name ?
Gabriel.
hi , lee mac
thank you for the program .
i need to change the value of dynamic property which i have seen , can you help me with it for example i have to alter the program . can i need source code fofr it , i cant understand your porgram in the lee mac programming website .
kindly help and reply asap..
my problem , say for instance i have created a rectangle and made it a blocked a, added stretch parameter and made it into a dynamic block, now my query is using your above mentioned code i can view the dynamic block name and its present value, now i need to alter the value of the dynamic block , so i need source code for it , if not lee mac some one else too plse help ... 🙂
hi dear lee ,mac i used the code from your website and i edited it as per my program , wen i run my program it came two few arguments error , plse tel me where i went wrong
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;;my dynamic proerty name is Distance1 i used default name of the dynamic property for my program
(defun c:hanew ( blk Distance1 )
(vl-load-com)
(setq blk ( car (entsel )))
(setq blk (vlax-ename->vla-object blk ))
(setq Distance1 (strcase Distance1))
(vl-some '(lambda ( x ) (if (= Distance1 (strcase (vla-get-propertyname x))) (vlax-get x 'value)))
(vlax-invoke blk 'getdynamicblockproperties)
)
)
plse reply asap 🙂 🙂
Hi inventordeepan,
There is no need to modify the code for my function, simply call the function with the appropriate arguments, e.g.:
(defun c:test ( / sel val ) (if (setq sel (ssget "_+.:E:S" '((0 . "INSERT")))) (if (setq val (LM:getdynpropvalue (vlax-ename->vla-object (ssname sel 0)) "Distance1")) (progn (princ "\nThe value of \"Distance1\" is: ") (princ val) ) (princ "\nThe selected block does not contain the dynamic parameter \"Distance1\".") ) ) (princ) ) ;; Get Dynamic Block Property Value - Lee Mac ;; Returns the value of a Dynamic Block property (if present) ;; blk - [vla] VLA Dynamic Block Reference object ;; prp - [str] Dynamic Block property name (case-insensitive) (defun LM:getdynpropvalue ( blk prp ) (setq prp (strcase prp)) (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'value))) (vlax-invoke blk 'getdynamicblockproperties) ) ) (vl-load-com) (princ)
LM:getdynpropvalue function from here.
hi lee mac thank you for your response can you please check your personal mail , i have sent you a message regarding my requirement , so plse check and help me , thanks a lot for your immediate response
hi dr lee mac i hope you can help me with it ,
i need to do some calculation in excell and use the answer as values to my autolisp prog
i mean lik for instance i need to add cell a1 an a2 value and assign it to a variable in autolisp code say to variable a , frm net i got some source to get data from excell . so i request you dr programmer whether you know any code to input values to cells in a new excel sheet and also perform some addition and den retrive value from excell sheet and assign it to a variable say setq a excel data .
plse some one help asap
thank you in advance ...
Hi Lee,
thanks for all the great lisp you had posted in many forums, as you said is simple to call the function with the apropiate arguments, but for beginers like me is dificult to call the functions when we need them = ).
What I am trying to do is combine one lisp you posted in other blog INSBLKCEN (inserts a block at the centre of selected blocks) which is amazing but, my block works with a lookups values and I would like to try to change automatically the lookup when the block is inserted, therefore I want to store the CANNOSCALE variable and then asociate this value with the lookup in this block. this is just an overall view of what I am trying to achive.
Now I would like to ask you if you could explan or post how to call the function you have in your web site
;; Set Dynamic Block Property Value - Lee Mac ;; Modifies the value of a Dynamic Block property (if present) ;; blk - [vla] VLA Dynamic Block Reference object ;; prp - [str] Dynamic Block property name (case-insensitive) ;; val - [any] New value for property ;; Returns: [any] New value if successful, else nil (defun LM:setdynpropvalue ( blk prp val ) (setq prp (strcase prp)) (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (progn (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x)))) (cond (val) (t)) ) ) ) (vlax-invoke blk 'getdynamicblockproperties) ) )
thank you very much in advance