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

Changing Visibility States in Dynamic Block

31 REPLIES 31
SOLVED
Reply
Message 1 of 32
RaymondLoo
10056 Views, 31 Replies

Changing Visibility States in Dynamic Block

Hello

 

First time poster here. I would like to run a script which sets a dynamic block's visibility state on many drawings. 

 

The block in question is on paper space and titled 'DWA STAMP', which is the same on every drawing,

 

The vis state needs to switch from 'Preliminary' to 'Tender'. There are seven visibility states within the block.

 

Any pointers as to how I may be able to achieve this?

 

Many thanks in advance,

 

Raymond

31 REPLIES 31
Message 2 of 32
Lee_Mac
in reply to: RaymondLoo

The following (untested) code uses functions from my library of Dynamic Block Functions - it should hopefully perform as required:

 

(defun c:changevis ( / blk idx obj sel vis )
    
    (setq blk "DWA STAMP" ;; Block Name
          vis "Tender"    ;; New Visibility State
    )
    (if (setq sel (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "`*U*," blk)) '(410 . "~Model"))))
        (repeat (setq idx (sslength sel))
            (if (= (strcase blk) (strcase (LM:blockname (setq obj (vlax-ename->vla-object (ssname sel (setq idx (1- idx))))))))
                (LM:SetVisibilityState obj vis)
            )
        )
    )
    (princ)
)

;; Block Name  -  Lee Mac
;; Returns the true (effective) name of a supplied block reference
                        
(defun LM:blockname ( obj )
    (if (vlax-property-available-p obj 'effectivename)
        (defun LM:blockname ( obj ) (vla-get-effectivename obj))
        (defun LM:blockname ( obj ) (vla-get-name obj))
    )
    (LM:blockname obj)
)

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

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

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

(vl-load-com) (princ)

 

If the dynamic block visibility parameter name is known, and the new visibility state name is valid, you can omit the Set Dynamic Block Visibility StateGet Visibility Parameter NameGet Dynamic Block Property Allowed Values functions, and simply use the Set Dynamic Block Property Value function to set the value as required.

 

The above will change the visibility state for all references of the block residing in all paperspace layouts of the active drawing; if batch processing is required, you can look to run the above program automatically using an AutoCAD Script. For this, you may want to read my post here & consider my Script Writer application.

 

I hope this helps.

 

Lee

Message 3 of 32
RaymondLoo
in reply to: Lee_Mac

Thanks a million Lee. Tested it out and worked to a charm. 

 

Now back to my challenge in getting the ExportLayout command in script form to work across over 300 drawings 🙂

 

Raymond

Message 4 of 32
Lee_Mac
in reply to: RaymondLoo

Excellent to hear Raymond, I'm glad the code works well for you.

 

Since the code solves your original question, I have marked my post as the Accepted Solution to effectively close the thread.

 

Good luck with your other tasks!

 

Lee

Message 5 of 32
straitline
in reply to: Lee_Mac

Lee, This is just what i need. How can i get a copy of this lisp? 

Message 6 of 32
Lee_Mac
in reply to: straitline

straitline wrote:

Lee, This is just what i need. How can i get a copy of this lisp? 

 

Hi straitline,

 

Sorry, which program are you referring to?

 

The code for changing the dynamic block visibility state is posted above.

 

Lee

Message 7 of 32
straitline
in reply to: Lee_Mac

I was refering to the changevis.lsp. but i didnt want to just copy it from the internet without permission.

Message 8 of 32
Lee_Mac
in reply to: straitline

straitline wrote:

I was refering to the changevis.lsp. but i didnt want to just copy it from the internet without permission.

 

That's very courteous of you, thank you Smiley Happy

 

You are of course welcome to copy & use the posted code, and indeed any code that I have published around the web or on my site, I would only ask that you retain any code headers or author notices with the code, but I'm sure this goes without saying.

 

Cheers,

 

Lee

Message 9 of 32
straitline
in reply to: straitline

Thanks I will let you know how it works.

Michael Cottet
AutoCadd Technician
Electrical Consultants, Inc.
"Engineering with Distinction"

3521 Gabel Road
Billings, MT 59102
Office: (406) 259-9933 ext 2064
FAX: (406) 259-3441
Cell: (406) 544-2677
michael.cottet@eciblgs.com
www.electricalconsultantsinc.com
Message 10 of 32
straitline
in reply to: straitline

I copied the changevis, saved as .lsp looks good, loads in autocad with appload, comes up at command line but nothing happens. No prompt for block or anything. Suggestions? attached is the lisp i am attempting to run.

Message 11 of 32
Lee_Mac
in reply to: straitline

The current program as it stands is not designed to prompt for a block or visibility state (though, such options could be quite easily added); the block name and new visibility state name are both defined & commented at the very top of the program code - you will need to change these values to suit your block/visibility state names.

 

Lee

Message 12 of 32
jpCADconsulting
in reply to: Lee_Mac

Lee,

 

This is just what I need at the moment.  However, I'd like it to change the last inserted block, not a named block.  So, I changed:

 

    (setq blk "DWA_STAMP" ;; Block Name

 

to

 

    (setq blk (entlast) ;; Last Object

 

Now when I run it I get:

 

; error: bad argument type: stringp <Entity name: 7ffffb6b890>

 

Any thoughts?

Message 13 of 32
Lee_Mac
in reply to: jpCADconsulting

jpCADconsulting wrote:

Lee,

 

This is just what I need at the moment.  However, I'd like it to change the last inserted block, not a named block.  So, I changed:

 

    (setq blk "DWA_STAMP" ;; Block Name

 

to

 

    (setq blk (entlast) ;; Last Object

 

Now when I run it I get:

 

; error: bad argument type: stringp <Entity name: 7ffffb6b890>

 

Any thoughts?

 

In the current code the 'blk' variable is assigned a string value corresponding to the block name, hence, changing this to an entity name as returned by the entlast function will inevitably result in an error.

 

However, since you already have the entity name corresponding to the block reference to be modified, you can simply call the LM:setvisibilitystate function directly, supplying the VLA-Object representation of entity name, and the name of the new visibility state, e.g.:

 

(LM:SetVisibilityState (vlax-ename->vla-object (entlast)) "NewState")

 

Message 14 of 32
jpCADconsulting
in reply to: Lee_Mac

Thanks as always Lee.  Working like a charm!!!  Here's the whole code FYI.

 

(defun C:ADB( / CL COSM FRAD CAS NHS PLW)

;;;;; Collect current layer, and OSMODE settings
(setq CL (getvar "CLAYER"))
(setq COSM (getvar 'osmode))

;;;;; Set OSPMODE to ENDPOINT and MIDPOINT only
(setvar 'osmode 4131)

;;;;; Collect current annotation scale value and create Values for POLYLINE WIDTH width and FILLET RADIUS
(setq CAS (getvar 'cannoscalevalue))
(setq NHS (/ 1 CAS))
(setq PLW (* NHS 0.0625))
(setq FRAD (* 10 PLW))


;;;;; Create layer for the detail box and make it current
(command "_.-Layer" "m" "L-DTL-BOX" "c" "5" "L-DTL-BOX" "l" "DASHED" "L-DTL-BOX" "")
(setvar 'CLAYER "L-DTL-BOX")

;;;;; Draw the box using pline width and fillet radius values
(command "_.rectang" "_f" FRAD (while (> (getvar 'CmdActive) 0) (command pause)))
(command "_.PEDIT" "L" "L" "on" "w" PLW "")
(command "_.rectang" "_f" "0")
(command)

;;;;; Create the layer fo the detail tag and make it current
(command "_.-Layer" "m" "L-ANNO-SYMB" "c" "3" "L-ANNO-SYMB" "")
(setvar 'CLAYER "L-ANNO-SYMB")


;;;;; Bring in block Detail Callout IMP r03 block from MVVA Callouts_Imperial r01.dwg
(defun open_dbx (dwg / dbx)
(if (< (atoi (substr (getvar "ACADVER") 1 2)) 16)
(setq dbx (vlax-create-object "ObjectDBX.AxDbDocument"))
(setq dbx (vlax-create-object
(strcat "ObjectDBX.AxDbDocument."
(substr (getvar "ACADVER") 1 2)
)
)
)
)
(vla-open dbx dwg)
dbx
)
(setq Dbx (open_dbx "//ny-fs01/cad_common$/AutoCAD 2014/Drawings/MVVA Callouts_Imperial r01.dwg"))
(vla-CopyObjects
Dbx
(vlax-safearray-fill
(vlax-make-safearray vlax-vbObject '(0 . 0))
(list (vla-item (vla-get-blocks dbx) "Detail Callout IMP r03"))
)
(vla-get-blocks
(vla-get-activedocument (vlax-get-acad-object))
)
)
(vlax-release-object dbx)


;;;;; Insert Detail Callout IMP r03 block ;;;
(command ".-insert" "Detail Callout IMP r03" PAUSE "1" "1" "0")


;;;;; Retuen current layer and OOMODE to original values
(setvar 'CLAYER CL)
(setvar 'OSMODE COSM)


;;;;; change visibility state of Detail Callout IMP r03 block to "None"
(defun CHGDYNPROP (Ename propname newval /  lo obj v vval sal tot i)
       ;; Changes a given variable in your block
       ;; Passed: Ename, Property Name, New value for Property
       ;;
       (setq obj (if (= (type Ename) 'vla-object)
    Ename
    (vlax-ename->vla-object Ename))
     v (vla-getdynamicblockproperties obj)
     vval (vlax-variant-value v)
     sal (vlax-safearray->list vval)
     tot (length sal)
     i 0)
       (while (< i tot)
         (if (= (vlax-get-property (nth i sal) "PropertyName") propname)
           (progn
             (vlax-put-property (nth i sal) "Value" newval)
             (setq i tot)
           )
           (setq i (1+ i))
         )
       )
     )
(CHGDYNPROP (entlast) "Visibility1" "None") ;none is the visibility state name
(princ)
)

 

Message 15 of 32

Hi to everyone. I want to use this routine for all blocks in the drawing:

 

(defun CHGDYNPROP (Ename propname newval / lo obj v vval sal tot i)
(setq obj (if (= (type Ename) 'vla-object)
Ename
(vlax-ename->vla-object Ename))
v (vla-getdynamicblockproperties obj)
vval (vlax-variant-value v)
sal (vlax-safearray->list vval)
tot (length sal)
i 0)
(while (< i tot)
(if (= (vlax-get-property (nth i sal) "PropertyName") propname)
(progn
(vlax-put-property (nth i sal) "Value" newval)
(setq i tot)
)
(setq i (1+ i))
)
)
)
(CHGDYNPROP (entlast) "Scale" "1")
(princ)

 

 

but because of (entlast) function, it affects only last object in the drawing. what can i do for this lisp routine to affect all blocks?

Message 16 of 32

I have upgraded to AutoCAD 2016 and the changevis.lsp will not load is there a fix to get it working in AutoCAD 2016?

Message 17 of 32
paul.johnsson
in reply to: Lee_Mac


@Lee_Mac wrote:

 

The above will change the visibility state for all references of the block residing in all paperspace layouts of the active drawing


Hi Lee

 

Is there a way to make this lisp change the visibility state of the blocks in model space as well?

 

Cheers

Paul

Message 18 of 32
DJPiper
in reply to: paul.johnsson

to be able to work for both model and paper space, just change the line from this....

(if (setq sel (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "`*U*," blk)) '(410 . "~Model"))))

 

to this...

(if (setq sel (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "`*U*," blk)))))

Message 19 of 32
charles_44
in reply to: DJPiper

@Lee_Mac 

 

Is there a way to modify this code so that it will change multiple dynamic blocks. In your code it works for DWA STAMP, but could it also change a second or third block similar to below? I tried just adding it but obviously there is more to it. 

 

(setq blk "DWA STAMP" ;; Block Name
vis "Tender" ;; New Visibility State)

 

(setq blk "DWA STAMP2" ;; Block Name
vis "Tender2" ;; New Visibility State)

Message 20 of 32
Lee_Mac
in reply to: charles_44


@charles_44 wrote:

@Lee_Mac 

Is there a way to modify this code so that it will change multiple dynamic blocks?


Try replacing the c:changevis function with the following:

 

(defun c:changevis ( / idx lst obj sel vis )
    (setq lst
       '(
            ("DWA STAMP"  . "Tender")
            ("DWA STAMP2" . "Tender2")
        )
    )
    (if
        (setq sel
            (ssget "_X"
                (append
                   '(
                        (000 . "INSERT")
                        (-04 . "<OR")
                        (002 . "`*U*")
                    )
                    (mapcar '(lambda ( x ) (cons 2 (car x))) lst)
                   '(
                        (-004 . "OR>")
                        (410 . "~Model")
                    )
                )
            )
        )
        (repeat (setq idx (sslength sel))
            (if (setq idx (1- idx)
                      obj (vlax-ename->vla-object (ssname sel idx))
                      vis (cdr (assoc (strcase (LM:blockname obj)) lst))
                )
                (LM:SetVisibilityState obj vis)
            )
        )
    )
    (princ)
)

You can add as many entries to the list as required; note that the block name should be uppercase.

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

Post to forums  

Autodesk Design & Make Report

”Boost