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

Obtaining Dynamic Block Property Information With AutoLISP

24 REPLIES 24
SOLVED
Reply
Message 1 of 25
markash
5961 Views, 24 Replies

Obtaining Dynamic Block Property Information With AutoLISP

Hello All:

 

I'm interested in creating a bit of code that will retrieve a list of property information from a dynamic block.  I can already get a list of properties and their current value.  What I'm after here is obtaining more information...the best example I can offer:  A list of increments or the list of assigned distances for a distance parameter.

 

Any help would be appreciated.

 

Mark

Tags (1)
24 REPLIES 24
Message 2 of 25
hmsilva
in reply to: markash

Hi Mark,

 

a starting point, look at the "AllowedValues" property

 

(defun c:demo (/ obj sel)
  (if (and (setq sel (car (entsel)))
	   (setq obj (vlax-ename->vla-object sel))
	   (vlax-property-available-p obj 'isdynamicblock)
      )
    (foreach p (vlax-safearray->list
		 (vlax-variant-value (vla-getdynamicblockproperties obj))
	       )
      (vlax-dump-object p T)
    )
    (prompt "\nNot a DynaBlock!")
  )
  (princ)
)

 

hope that helps

Henrique

 

EESignature

Message 3 of 25
markash
in reply to: hmsilva

Hello Henrique

You response gets me very close to what I need but so far I have not found a
way to do anything but print that info to the screen. I'd like to be able
to use the presented data in a lisp routine. I attempted to port the output
to a file so that I could open and read it line by line but had no success
doing that.



Do you have any other tricks?



Thanks,



Mark
Message 4 of 25
Lee_Mac
in reply to: markash

Message 5 of 25
markash
in reply to: Lee_Mac

Hello Lee:

 

Thanks very much for your reply.  I think your function LM:getdynpropallowedvalues should do exactly what I'm after but I have not yet gotten it to work.  I'm passing BLK in this form:  #<VLA-OBJECT IAcadBlockReference 0000000033a293b8> which I got from the entity name of the block.

 

Does this appear correct because the function's currently returning nil every time.

 

Thanks,

 

Mark

Message 6 of 25
Lee_Mac
in reply to: markash

Hi Mark,

 

Yes, it looks like you are supplying the function with the required block reference vla-object; are you also passing a dynamic block parameter name as the second argument?

 

Here is a quick example for you to try:

 

(defun c:test ( / sel str )
    (if
        (and
            (princ "\nSelect dynamic block: ")
            (setq sel (ssget "_+.:E:S" '((0 . "INSERT"))))
            (setq str (getstring "\nSpecify dynamic parameter name: "))
        )
        (LM:getdynpropallowedvalues
            (vlax-ename->vla-object (ssname sel 0))
            str
        )
    )
)

;; Get Dynamic Block Property Allowed Values  -  Lee Mac
;; Returns the allowed values for a specific Dynamic Block property.
;; blk - [vla] VLA Dynamic Block Reference object
;; prp - [str] Dynamic Block property name (case-insensitive)
;; Returns: [lst] List of allowed values for property, else nil if no restrictions

(defun LM:getdynpropallowedvalues ( blk prp )
    (setq prp (strcase prp))
    (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'allowedvalues)))
        (vlax-invoke blk 'getdynamicblockproperties)
    )
)

(vl-load-com) (princ)
Message 7 of 25
hmsilva
in reply to: markash


@markash wrote:
Hello Henrique

You response gets me very close to what I need but so far I have not found a
way to do anything but print that info to the screen. I'd like to be able
to use the presented data in a lisp routine. I attempted to port the output
to a file so that I could open and read it line by line but had no success
doing that.



Do you have any other tricks?



Thanks,



Mark

You're welcome, Mark

As a "demo"...

 

(defun c:demo (/ a b lst obj sel)
  (if (and (setq sel (car (entsel)))
	   (setq obj (vlax-ename->vla-object sel))
	   (vlax-property-available-p obj 'IsDynamicBlock)
	   (eq (vla-get-IsDynamicBlock obj) :vlax-true)
      )
    (progn
      (foreach p (vlax-safearray->list
		   (vlax-variant-value (vla-getdynamicblockproperties obj))
		 )
	(if (and (setq a (vlax-get p 'PropertyName))
		 (setq b (vlax-get p 'AllowedValues))
	    )
	  (setq lst (cons (list a b) lst))
	)
      )
      (if lst
	(princ lst)
      )
    )
    (prompt "\nNot a DynaBlock!")
  )
  (princ)
)

 

Hope that helps,

Henrique

EESignature

Message 8 of 25
markash
in reply to: Lee_Mac

Lee:

 

Thanks again for your help on this.  I was passing a property name along...obviously as a string.  Something was not working but it was probably on my end.  In the meantime, the solution posted below by hmsilva does the trick nicely.

 

Mark

Message 9 of 25
markash
in reply to: hmsilva

Hello hmsilva:

 

Thanks very much for that...it does exactly what I'm after.

 

Mark

Message 10 of 25
hmsilva
in reply to: markash


@markash wrote:

Hello hmsilva:

 

Thanks very much for that...it does exactly what I'm after.

 

Mark


You're welcome, Mark

Glad I could help

 

Henrique

EESignature

Message 11 of 25
jack.foster
in reply to: hmsilva

I know this is quite old but if possible I could really use some help.  I have copied and run the second "demo" program you posted and it gives me the visibility1 values and that is all.  I have a dynamic block that has a bunch of parameters in it and I need the distance for each of those parameters.  Running the first demo program it displays all of the parameters and their distance value which is great.  Problem is I don't know how to get specific parameter distance values?  If someone could post or send me some code that I can use and modify for my application I would very much appreciate it.  I have attached 1 of the blocks that I need the parameter distance for if that might help.  Parameters such as MV2 or MV3 are part of the bunch in the dwg.  Thank you very much for any and all help.

Message 12 of 25
dlanorh
in reply to: jack.foster

Allowed values are where a dynamic property is constrained (think named visibility states). If the parameter is not constrained there won't be any allowed values. If you want the current value you should use Lee's property value code instead of the allowed value code.

 

(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)
    )
)

 

     

I am not one of the robots you're looking for

Message 13 of 25
jack.foster
in reply to: dlanorh

Thank you for replying.  I have tried using examples from Lee Mac for several years and I have never ever gotten one of his routines to work.  Usually I get an error like "too few arguments" and I give up.  I did find a program written by a C. Witt on the CAD forums that gets me close.  His program does a PUT to change a parameter value and it works and moves whatever is tied to the parameter.  I copied and beat on it for a while and was able to use a GET and it comes back with "#<variant 5 14.6666667> and I just want the numeric value of 14.66667.  I need to do that for about 20 linear parameters.  I am going to beat on the keyboard and surf some more and see if I can't figure it out.  I guess if I can't stumble on the solution I may post the code here and hope you have some time to help me.  I don't like to impose too much on other people and try and figure it out from many trials and errors.  

Message 14 of 25
dlanorh
in reply to: jack.foster

Apologies, I've been at the hospital all day.

 

Visual lisp can be a bit daunting at times as there are several ways to access (get and put) properties. Some return the properties as variants or require the value to be a variant, whereas others don't.

 

I have amended Henrique's code from above to print out the property names and their current values.

 

(defun c:demo (/ a b lst obj sel)
  (if (and (setq sel (car (entsel "Select Dynamic Block : ")))
           (setq obj (vlax-ename->vla-object sel))
           (vlax-property-available-p obj 'isdynamicblock)
           (eq :vlax-true (vlax-get-property obj 'isdynamicblock))
      )
    (progn
      (foreach p (vlax-invoke obj 'getdynamicblockproperties); Gets a list of the properties
        (if (and (setq a (vlax-get p 'propertyname)); gets the properties name (text)
                 (setq b (vlax-get p 'value)); gets the properties value 
            )
            (setq lst (cons (list a b) lst))
        )
      )
      (if lst
        (foreach pr lst (princ (strcat "\n" (car pr) " : " (vl-princ-to-string (cadr pr)))))
      )
    )
    (alert "Not a Dynamic Block!")
  )
  (princ)
)

 

 

If this isn't what you require then post the code you have and give a detailed description of what you require and I'm sure someone will jump in and help.

 

 

I am not one of the robots you're looking for

Message 15 of 25
jack.foster
in reply to: dlanorh

I took the code that Henrique sent before you as he had added in the (cond statements that I had already created.  Letting you know as I don't want either of you to feel slighted by me.  I am loving the help that both of you are giving me.  I am pasting in that code which works great but there is a new problem that doesn't make any sense.  When the holes are moved by the dynamic block grips the parameters they are tied to should also change and have a new "distance" value.  I move some holes, save the drawing and do a regenall, hoping everything will update.  Unfortunately the values that are extracted are still  the default values and not the new location values.  Now I am lost as a regenall usually updates everything.  I put some of the vars in the top line of the code thinking that might somehow affect things but it didn't.  I am watching these values using the Watch window and running in debug animated so I can see each one.  I also added 2 additional parameters into my condition and there value never shows up.  When I run your version of the program I see those two displayed.  They are MV2 and MV3 and are identical to VH12 AND VH23.  It was just an additional check for me.  I am attached another dwg with an unmodifed block and a modified block.  Also is a screen capture of the values from the watch window.  I hope this will help you as you are certainly helping me a whole bunch.

 

The type block and parameters may be the reason why.  When the upper right corner of the block is gripped and moved in any direction all of the holes move a proportional distance so they stay equally spaced vertical or horizontal.  However; in some instances a row or column of holes have to be moved and can be moved.  The dimensions when shown in the viz state are correct and update as holes are moved.  I am beginning to think I am trying to do way too much?  

 

(defun c:demo3 (/ a b lst obj sel valL valH valhh12 valhh23 valvh12 valvh23)
(if (and (setq sel (car (entsel)))
(setq obj (vlax-ename->vla-object sel))
(vlax-property-available-p obj 'IsDynamicBlock)
(eq (vla-get-IsDynamicBlock obj) :vlax-true)
)
(progn
(foreach p (vlax-safearray->list
(vlax-variant-value (vla-getdynamicblockproperties obj))
)
(setq xxname (vlax-get p 'PropertyName)xxvalue (vlax-get p 'value))
(cond
((= xxname "Origin") (princ "."))
((= xxname "LENGTH") (setq valL (rtos xxvalue 2 4)))
((= xxname "HEIGHT") (setq valH (rtos xxvalue 2 4)))
((= xxname "HH12") (setq valhh12 (rtos xxvalue 2 4)))
((= xxname "HH23") (setq valhh23 (rtos xxvalue 2 4)))
((= xxname "HH34") (setq valhh34 (rtos xxvalue 2 4)))
((= xxname "HH45") (setq valhh45 (rtos xxvalue 2 4)))
((= xxname "HH56") (setq valhh56 (rtos xxvalue 2 4)))
((= xxname "HH67") (setq valhh67 (rtos xxvalue 2 4)))
((= xxname "HH78") (setq valhh78 (rtos xxvalue 2 4)))
((= xxname "HH-OA") (setq valhh-oa (rtos xxvalue 2 4)))
((= xxname "VH12") (setq valvh12 (rtos xxvalue 2 4)))
((= xxname "MV2") (setq valmv2 (rtos xxvalue 2 4)))
((= xxname "VH23") (setq valvh23 (rtos xxvalue 2 4)))
((= xxname "MV3") (setq valmv3 (rtos xxvalue 2 4)))
((= xxname "VH-OA") (setq valvh-oa (rtos xxvalue 2 4)))
((= xxname "RightEndHoriz") (setq valREH (rtos xxvalue 2 4)))
((= xxname "TopRowVert") (setq valTRV (rtos xxvalue 2 4)))
((= xxname "BtmRowVert") (setq valBRV (rtos xxvalue 2 4)))
((= xxname "LeftEndColHoriz") (setq valLECH (rtos xxvalue 2 4)))
))
)))

Message 16 of 25
dlanorh
in reply to: jack.foster

Could you save the drawing as AutoCAD 2012 or earlier and repost. Unfortunately I don't have access to a later version at the moment.

I am not one of the robots you're looking for

Message 17 of 25
jack.foster
in reply to: dlanorh

Attached saved as 2010 version.  Thank you for so much help!

Message 18 of 25
dlanorh
in reply to: jack.foster

OK. I've had a chance to look at the block. The block is the problem, not the lisp. There are linked actions that don't seem to be working. Some of the dynamic properties are excluded from stretch actions that effect them. I focused on VH23 which should have been updating, but wasn't. It is shown as linked, but when I selected stretch action 18 it didn't appear in the selection set. I can only summize that stretch action 9 is linked to stretch action 18, as it has no grip to affect it. As stretch action 18 is associated with the grips the linked action (if any) doesn't look as though it is altering VH23 which is why the reported length doesn't change.

I am not one of the robots you're looking for

Message 19 of 25
jack.foster
in reply to: dlanorh

Thank you for confirming what I was afraid of.  I made some of the actions chained to other actions or parameters.  The holes all move as you would expect including the auto-centering which was the great(?) idea for this.  When you change the viz state all of the dimensions are correct so I thought everything is fine.  The dims are associated with the holes and if the hole moves the dim updates with it.  I am going to go back to your code and change the parameters to the companion parameters and see if they will change the distance value.  Worth a try.  This project has a total of 32 panels with anywhere from 1 row with 2 holes to 4 rows with 9 holes each row.  Then there are 32 similar vertical panels for a total of 64 panels.  Monumental job to try and fix all of them.  

 

Can you think of a way to programmatically get each of the dimension values?  They are basically the same values that are in the parameters.  I doubt it and if so they would need to be accessed in the same order every time.  The dimensions were not placed on the panels in the same order which makes me believe it would be really difficult to do.  Current practice is extract all the data and look for multiple rows of a panel mark# and see what data is different.  Then add a suffix to the panels so they are uniquely labeled and no problems.

 

I really want to THANK YOU and Henrique for helping me with this programming problem.  You did provide a solution and I learned a lot.  I will keep this code and maybe use it for another project.  

Message 20 of 25
dlanorh
in reply to: jack.foster


@jack.foster wrote:

Thank you for confirming what I was afraid of.  I made some of the actions chained to other actions or parameters.  The holes all move as you would expect including the auto-centering which was the great(?) idea for this.  When you change the viz state all of the dimensions are correct so I thought everything is fine.  The dims are associated with the holes and if the hole moves the dim updates with it.  I am going to go back to your code and change the parameters to the companion parameters and see if they will change the distance value.  Worth a try.  This project has a total of 32 panels with anywhere from 1 row with 2 holes to 4 rows with 9 holes each row.  Then there are 32 similar vertical panels for a total of 64 panels.  Monumental job to try and fix all of them.  

 

Can you think of a way to programmatically get each of the dimension values?  They are basically the same values that are in the parameters.  I doubt it and if so they would need to be accessed in the same order every time.  The dimensions were not placed on the panels in the same order which makes me believe it would be really difficult to do.  Current practice is extract all the data and look for multiple rows of a panel mark# and see what data is different.  Then add a suffix to the panels so they are uniquely labeled and no problems.

 

I really want to THANK YOU and Henrique for helping me with this programming problem.  You did provide a solution and I learned a lot.  I will keep this code and maybe use it for another project.  


Getting the dimension values is not problematic, just iterate the block reference objects and query the measurement property of every dimension. The problem would be associating an extracted measurement with what it is measuring. One way around this would be to add an attribute and link it via a field to each individual dimension. These could be invisible so they would remain hidden. Knowing which attribute links to which dim via its tag name, allows multiple known dims measurements to be extracted as attribute values. A regenall or similar would be needed prior to extraction to ensure everything was correctly updated. See attached block where I have linked attribute MH2 to the dimension associated with parameter MH2. This is large and visible in visibility state "dims" off the bottom left corner for display purposes and work for newly inserted and altered instances of the block.

 

Hope this helps.

 

I am not one of the robots you're looking for

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

Post to forums  

Autodesk Design & Make Report

”Boost