Jump to content
Nomad

Setting Visibility State based on Attribute value

Recommended Posts

Nomad

Hi,

 

I have a dwg with a bunch of the same block in it (called Cabinet). This particular block has a number of visibility states.

 

I have assigned an attribute (called SetVisState) to the block that I can modify via ATTOUT and ATTIN. I want a LISP routine to check this attribute in each block, then update it's visibility state based on this attribute.

 

Unfortunately I have next to no experience with LISP, so any guidance would be appreciated. I have tried looking around this forum and others, but so far have only managed to run a LISP that checks the current visibility state and then toggles between states (I need it to check attribute value then change vis state accordingly). I tried Lee Macs code for getting attributes, but couldn't figure out how to apply that to my scenario either.

 

Thanks in advance.

Share this post


Link to post
Share on other sites
iconeo

Lee Mac has some helper functions on his website for manipulating the visibility states of blocks.

Share this post


Link to post
Share on other sites
Lee Mac

Consider the following example:

(defun c:test ( / i o s )
   (if (setq s (ssget "_X" '((0 . "INSERT") (66 . 1) (2 . "`*U*,Cabinet"))))
       (repeat (setq i (sslength s))
           (setq o (vlax-ename->vla-object (ssname s (setq i (1- i)))))
           (if (and (vlax-property-available-p o 'effectivename)
                    (= "cabinet" (strcase (vla-get-effectivename o) t))
               )
               (if (setq v (LM:vl-getattributevalue o "SetVisState"))
                   (LM:setvisibilitystate o v)
               )
           )
       )
   )
   (princ)
)
(vl-load-com) (princ)

You will need to first download & load the required attribute & dynamic block functions from my site.

 

@iconeo, thank you for the recommendation :thumbsup:

Share this post


Link to post
Share on other sites
Nomad

Thanks for the responses.

 

Lee, I haven't been able to get that code to work yet.

 

I copied the code above into a text file and renamed it Test.LSP. I then copied all of the subfunctions from the two links you provided beneath the provided code in the Test.LSP file. I dragged and dropped this file into the dwg. I typed Test in the command line. Literally nothing happens haha.

 

Am I doing something obviously wrong? Or should I start learning how to debug LISP haha.

 

Thanks again for your help.

Share this post


Link to post
Share on other sites
Lee Mac

No problem - the following updated code will print a number of messages to the command-line to let you know what's going on:

(defun c:test ( / i o s )
   (if (setq s (ssget "_X" '((0 . "INSERT") (66 . 1) (2 . "`*U*,Cabinet"))))
       (repeat (setq i (sslength s))
           (setq o (vlax-ename->vla-object (ssname s (setq i (1- i)))))
           (if (and (vlax-property-available-p o 'effectivename)
                    (= "cabinet" (strcase (vla-get-effectivename o) t))
               )
               (progn
                   (princ (strcat "\nFound cabinet block \"" (vla-get-handle o) "\"."))
                   (if (setq v (LM:vl-getattributevalue o "SetVisState"))
                       (progn
                           (princ (strcat "\nValue of \"SetVisState\" attribute = " v))
                           (if (LM:setvisibilitystate o v)
                               (princ (strcat "\nVisibility state set to \"" v "\"."))
                               (princ (strcat "\nUnable to set visibility state to \"" v "\"."))
                           )
                       )
                       (princ "\n\"SetVisState\" attribute not found in Cabinet block.")
                   )
               )
           )
       )
       (princ "\nNo attributed 'Cabinet' blocks found in the drawing.")
   )
   (princ)
)
(vl-load-com) (princ)

Share this post


Link to post
Share on other sites
Nomad

Thanks Lee.

 

I am still getting nothing. I have copied the following code from your reply above, and the subfunctions from the links you provided above, into a single .LSP file named "Test.LSP". I've dragged and dropped this into the dwg. I then type "Test" in the command line. All that shows up in the command line once is as follows:

 

Command: (LOAD "C:/Users/.../Desktop/Data Extract/Test.LSP") LM:SETVISIBILITYSTATE

Command: TEST

 

 

(defun c:test ( / i o s )
   (if (setq s (ssget "_X" '((0 . "INSERT") (66 . 1) (2 . "`*U*,Cabinet"))))
       (repeat (setq i (sslength s))
           (setq o (vlax-ename->vla-object (ssname s (setq i (1- i)))))
           (if (and (vlax-property-available-p o 'effectivename)
                    (= "cabinet" (strcase (vla-get-effectivename o) t))
               )
               (progn
                   (princ (strcat "\nFound cabinet block \"" (vla-get-handle o) "\"."))
                   (if (setq v (LM:vl-getattributevalue o "SetVisState"))
                       (progn
                           (princ (strcat "\nValue of \"SetVisState\" attribute = " v))
                           (if (LM:setvisibilitystate o v)
                               (princ (strcat "\nVisibility state set to \"" v "\"."))
                               (princ (strcat "\nUnable to set visibility state to \"" v "\"."))
                           )
                       )
                       (princ "\n\"SetVisState\" attribute not found in Cabinet block.")
                   )
               )
           )
       )
       (princ "\nNo attributed 'Cabinet' blocks found in the drawing.")
   )
   (princ)
)
(vl-load-com) (princ)

;; Get Attribute Value  -  Lee Mac
;; Returns the value held by the specified tag within the supplied block, if present.
;; blk - [vla] VLA Block Reference Object
;; tag - [str] Attribute TagString
;; Returns: [str] Attribute value, else nil if tag is not found.

(defun LM:vl-getattributevalue ( blk tag )
   (setq tag (strcase tag))
   (vl-some '(lambda ( att ) (if (= tag (strcase (vla-get-tagstring att))) (vla-get-textstring att)))
       (vlax-invoke blk 'getattributes)
   )
)

;; Set Attribute Value  -  Lee Mac
;; Sets the value of the first attribute with the given tag found within the block, if present.
;; blk - [vla] VLA Block Reference Object
;; tag - [str] Attribute TagString
;; val - [str] Attribute Value
;; Returns: [str] Attribute value if successful, else nil.

(defun LM:vl-setattributevalue ( blk tag val )
   (setq tag (strcase tag))
   (vl-some
      '(lambda ( att )
           (if (= tag (strcase (vla-get-tagstring att)))
               (progn (vla-put-textstring att val) val)
           )
       )
       (vlax-invoke blk 'getattributes)
   )
)

;; Set Attribute Values  -  Lee Mac
;; Sets attributes with tags found in the association list to their associated values.
;; blk - [vla] VLA Block Reference Object
;; lst - [lst] Association list of ((<tag> . <value>) ... )
;; Returns: nil

(defun LM:vl-setattributevalues ( blk lst / itm )
   (foreach att (vlax-invoke blk 'getattributes)
       (if (setq itm (assoc (vla-get-tagstring att) lst))
           (vla-put-textstring att (cdr itm))
       )
   )
)

;; Get Attributes  -  Lee Mac
;; Returns an association list of attributes present in the supplied block.
;; blk - [vla] VLA Block Reference Object
;; Returns: [lst] Association list of ((<Tag> . <Value>) ... )

(defun LM:vl-getattributes ( blk )
   (mapcar '(lambda ( att ) (cons (vla-get-tagstring att) (vla-get-textstring att)))
       (vlax-invoke blk 'getattributes)
   )
)

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

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


;; Get Dynamic Block Properties  -  Lee Mac
;; Returns an association list of Dynamic Block properties & values.
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [lst] Association list of ((<prop> . <value>) ... )

(defun LM:getdynprops ( blk )
   (mapcar '(lambda ( x ) (cons (vla-get-propertyname x) (vlax-get x 'value)))
       (vlax-invoke blk 'getdynamicblockproperties)
   )
)

;; Set Dynamic Block Properties  -  Lee Mac
;; Modifies values of Dynamic Block properties using a supplied association list.
;; blk - [vla] VLA Dynamic Block Reference object
;; lst - [lst] Association list of ((<Property> . <Value>) ... )
;; Returns: nil

(defun LM:setdynprops ( blk lst / itm )
   (setq lst (mapcar '(lambda ( x ) (cons (strcase (car x)) (cdr x))) lst))
   (foreach x (vlax-invoke blk 'getdynamicblockproperties)
       (if (setq itm (assoc (strcase (vla-get-propertyname x)) lst))
           (vla-put-value x (vlax-make-variant (cdr itm) (vlax-variant-type (vla-get-value x))))
       )
   )
)

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

;; Toggle Dynamic Block Flip State  -  Lee Mac
;; Toggles the Flip parameter if present in a supplied Dynamic Block.
;; blk - [vla] VLA Dynamic Block Reference object
;; Return: [int] New Flip Parameter value

(defun LM:toggleflipstate ( blk )
   (vl-some
      '(lambda ( prp / rtn )
           (if (equal '(0 1) (vlax-get prp 'allowedvalues))
               (progn
                   (vla-put-value prp (vlax-make-variant (setq rtn (- 1 (vlax-get prp 'value))) vlax-vbinteger))
                   rtn
               )
           )
       )
       (vlax-invoke blk 'getdynamicblockproperties)
   )
)

;; Get Visibility Parameter Name  -  Lee Mac
;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Name of Visibility Parameter, else nil

(defun LM:getvisibilityparametername ( blk / vis )  
   (if
       (and
           (vlax-property-available-p blk 'effectivename)
           (setq blk
               (vla-item
                   (vla-get-blocks (vla-get-document blk))
                   (vla-get-effectivename blk)
               )
           )
           (= :vlax-true (vla-get-isdynamicblock blk))
           (= :vlax-true (vla-get-hasextensiondictionary blk))
           (setq vis
               (vl-some
                  '(lambda ( pair )
                       (if
                           (and
                               (= 360 (car pair))
                               (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))))
                           )
                           (cdr pair)
                       )
                   )
                   (dictsearch
                       (vlax-vla-object->ename (vla-getextensiondictionary blk))
                       "ACAD_ENHANCEDBLOCK"
                   )
               )
           )
       )
       (cdr (assoc 301 (entget vis)))
   )
)

;; Get Dynamic Block Visibility State  -  Lee Mac
;; Returns the value of the Visibility Parameter of a Dynamic Block (if present)
;; blk - [vla] VLA Dynamic Block Reference object
;; Returns: [str] Value of Visibility Parameter, else nil

(defun LM:getvisibilitystate ( blk )
   (LM:getdynpropvalue blk (LM:getvisibilityparametername blk))
)

;; Set Dynamic Block Visibility State  -  Lee Mac
;; Sets the Visibility Parameter of a Dynamic Block (if present) to a specific value (if allowed)
;; blk - [vla] VLA Dynamic Block Reference object
;; val - [str] Visibility State Parameter value
;; Returns: [str] New value of Visibility Parameter, else nil

(defun LM:SetVisibilityState ( blk val / vis )
   (if
       (and
           (setq vis (LM:getvisibilityparametername blk))
           (member (strcase val) (mapcar 'strcase (LM:getdynpropallowedvalues blk vis)))
       )
       (LM:setdynpropvalue blk vis val)
   )
)

Share this post


Link to post
Share on other sites
Lee Mac

Are you certain that is the full command-line output? What happens if you press F2 to view the text window?

Share this post


Link to post
Share on other sites
Nomad

Lee,

 

I checked through everything again and it turns out I had actually named the block "Cabient" :oops:

 

Thanks so much for your help - it works perfectly.

Share this post


Link to post
Share on other sites
Lee Mac

You're welcome :thumbsup:

Share this post


Link to post
Share on other sites
morgancain

Hi,

 

Sorry for hijacking an old thread, I would like to achieve the same as the OP.

 

I have copied the code and changed all instances of the OP's block reference (Cabinet) so it calls for my block (Revision Table) however it doesn't work. When I then rename my block to be called cabinet it works perfectly.

 

So I am clearly missing something, would someone be able to assist with this please as its driving me mad.

 

Thanks!

Share this post


Link to post
Share on other sites
Roy_043

Make sure that on this line the block name is lower case:

(= "cabinet" (strcase (vla-get-effectivename o) t))

Share this post


Link to post
Share on other sites
morgancain

That has worked a treat! Thank you very much!

Share this post


Link to post
Share on other sites
Ecko

Hi Lee,

I know the threat is old... but the problem is still there. :-)

Maybe you can help me!

 

I created an block named 'cabinet' with an attribute "SetVisState" with two values: state1 und state2

Then I drag an droped the test.lsp with the code up there into my DWG

and I got the following messages:

 

Command:(LOAD "C:/.../Desktop/test.lsp") 

Command:
LM:SETVISIBILITYSTATE

 

Command:test

 

Found cabinet block "44D4".
Value of "SetVisState" attribute = State2
Unable to set visibility state to "State2".

 

 

Hm... what went wrong?

 

Thanks for help!

Ecko

 

 

Share this post


Link to post
Share on other sites
Lee Mac

To get the obvious question out of the way, I assume that your block 'Cabinet' has a Visibility Parameter with a Visibility State called 'State2'?

Share this post


Link to post
Share on other sites
Ecko

Yo that's right.

 

Visibility Parameter with a Visibility State called 'State2' and another one with 'State1'

 

 

image.png.b034b96cf39453d5de823ac62d6c6356.png

 

 

 

 

 

Share this post


Link to post
Share on other sites
Ecko

Maybe I did not understand how to use it!? (My english is bad.)

Share this post


Link to post
Share on other sites
dlanorh

Upload an example of your block so everyone knows what they are dealing with. It is near impossible to correctly diagnose a problem without seeing the "patient"

 

Share this post


Link to post
Share on other sites
dlanorh

The problem is the block is called "circle", not "cabinet". Either rename the block "cabinet" or change every instance of "cabinet" to "circle" in the lisp.

 

Just noticed you have a "cabinet" block. When this is used the lisp works. If you don't have all the required "bits", I've attached a complete lisp and your drawing set up to test.

 

test1.dwg test.lsp

Edited by dlanorh
attachments

Share this post


Link to post
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
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  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...