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

Block Redefine with a Difference

8 REPLIES 8
Reply
Message 1 of 9
jason.estas
493 Views, 8 Replies

Block Redefine with a Difference

Ladies & Gentlemen,

 

I am trying to redefine Block A to Block B, Block C & Block D based off the value of an Attribute in Block A.

 

If the Attribute in Block A is "1" then redefine to Block B

 

If the Attribute in Block A is "2" then redefine to Block C

 

If the Attribute in Block A is "3" then redefine to Block D

 

I know it should be able to be done using If and Cond functions within a lisp routine, but I am in a hurry with it and don't have the time to research it anymore.

 

Thank you for your helps peeps.

 

Jason

 

8 REPLIES 8
Message 2 of 9
_Tharwat
in reply to: jason.estas

Hi .

 

What do you mean by ( redifine ) Block B , or C or D .... ?

Does it mean to match the value in the other selected attributed blocks ?

 

Tharwat

Message 3 of 9
acwtzwegers
in reply to: jason.estas

So you want to read a particular attrib in the various instances of Block A and rename the instances according to the outcome?

 

Start with this bit of code by pbejse

 

(defun c:test  (/ atb_blk)
    (vl-load-com)
    (if (setq atb_blk (car (entsel)))
      (progn
        (setq atb_blk (vlax-ename->vla-object atb_blk) txt_val nil)
        (if
          (and
            (eq (vla-get-objectname atb_blk) "AcDbBlockReference")
            (eq (vla-get-hasattributes atb_blk) :vlax-true))
           (foreach
              txt_str  (vlax-invoke atb_blk 'GetAttributes)
             (setq  txt_val (cons (vla-get-TextString txt_str) txt_val))
             (princ (strcat "\nTag Name: " (vla-get-TagString txt_str)))
             (princ (strcat "\n\t\t\t" (vla-get-TextString txt_str))))
             
           (princ "\nNo attribuets found:"))
        )
    
      (princ "\nNothing selected"))
    (princ))


then mod it by letting it retreive the blocks from the database instead of by selection etc. (remember: Google is your friend (and so is Lee Mac) )

 

But ok.. I'm in a hurry too. Hope to at least have pointed you in the correct direction

Message 4 of 9
jason.estas
in reply to: _Tharwat

_Tharwat,

 

For instance lets say I have 30 blocks of Block A within the drawing.

 

10 of those 30 have an attribute value "1" therefore I want to Redefine those blocks to Block B

 

10 of those 30 have an attribute value "2" therefore I want to Redefine those blocks to Block C

 

10 of those 30 have an attribute value "3" therefore I want to Redefine those blocks to Block D

 

Therefore leaving 0 Block A's

 

I also would like to change it globally without having to select individual blocks.

 

Jason

Message 5 of 9
_Tharwat
in reply to: jason.estas

Hi ,

 

Can you upload a copy of your drawing that contains the three of these attributed blocks ?

 

Tharwat

Message 6 of 9
Kent1Cooper
in reply to: jason.estas


@jason.estas wrote:

.... 

For instance lets say I have 30 blocks of Block A within the drawing.

 

10 of those 30 have an attribute value "1" therefore I want to Redefine those blocks to Block B

10 of those 30 have an attribute value "2" therefore I want to Redefine those blocks to Block C

10 of those 30 have an attribute value "3" therefore I want to Redefine those blocks to Block D

 

Therefore leaving 0 Block A's

I also would like to change it globally without having to select individual blocks.

....


Very minimally tested, but try this.  Substitute real values for the blue parts.
 

(defun C:TEST (/ attvallist ent foundit attdata attval)

  (setq attvallist '("1" "2" "3"))
  (foreach blk
    (mapcar 'cadr (ssnamex (ssget "X" '((2 . "BlockA")))))
    (setq ent blk foundit nil)
    (while
      (and
        (not foundit)
        (setq attdata (entget (setq ent (entnext ent))))
        (= (cdr (assoc 0 attdata)) "ATTRIB")
      ); and
      (if
        (and
          (= (cdr (assoc 2 attdata)) "TAGNAME")
          (member (setq attval (cdr (assoc 1 attdata))) attvallist)
        ); and
        (progn
          (setq foundit T)
          (vla-put-Name
            (vlax-ename->vla-object blk)
            (nth
              (vl-position attval attvallist)
              '("BlockB" "BlockC" "BlockD")
            ); nth
          ); vla-put-Name
        ); progn
      ); if
    ); while
  ); foreach

); defun

 

That would leave un-replaced any such Blocks with values in that Attribute other than the listed ones.  It could use a lot of other controls, etc.  It could also be simplified if such Blocks would never have more than one Attribute.  And the list of values and Block names and the Tag name could be arguments to a function.  And so on....

Kent Cooper, AIA
Message 7 of 9
jason.estas
in reply to: Kent1Cooper

Kent,

 

Thank you fro helping me with this.

 

I copied your code and substituted the values your mentioned in Blue. Initially I was getting a bad selection error (bad argument type: lselsetp nil), so I modified the code to as below with my values used:

 

(defun C:TEST (/ attvallist ent foundit attdata attval)
  (setq attvallist '("1" "2" "3"))
  (foreach blk
    (mapcar 'cadr (ssget "X" '((0 . "INSERT") (2 . "E-C-OUTLET-1"))))
    (setq ent blk foundit nil)
    (while
      (and
        (not foundit)
        (setq attdata (entget (setq ent (entnext ent))))
        (= (cdr (assoc 0 attdata)) "ATTRIB")
      ); and
      (if
        (and
          (= (cdr (assoc 2 attdata)) "ATT1")
          (member (setq attval (cdr (assoc 1 attdata))) attvallist)
        ); and
        (progn
          (setq foundit T)
          (vla-put-Name
            (vlax-ename->vla-object blk)
            (nth
              (vl-position attval attvallist)
              '("E-C-DATA-1" "E-C-DATA-2" "E-C-DATA-3")
            ); nth
          ); vla-put-Name
        ); progn
      ); if
    ); while
  ); foreach
); defun

 

Changing the code got rid of the selection set error and now the program runs and just display "nil" in the command line without the blocks changing. I assume that by this error that there were no blocks selected with the program?

 

I have attached a copy of the dwg which I am using.

 

Jason

Message 8 of 9
Kent1Cooper
in reply to: jason.estas


@jason.estas wrote:

....

  (foreach blk
    (mapcar 'cadr (ssget "X" '((0 . "INSERT") (2 . "E-C-OUTLET-1"))))
.... 

Changing the code got rid of the selection set error and now the program runs and just display "nil" in the command line without the blocks changing. I assume that by this error that there were no blocks selected with the program?

....


You've omitted part of it -- the return from the (ssnamex) function, with (cadr) applied across it by (mapcar), is what makes the selection set into a list, which can then be processed by (foreach):

 

  (foreach blk
    (mapcar 'cadr (ssnamex (ssget "X" '((0 . "INSERT") (2 . "E-C-OUTLET-1")))))
....

 

You can do it with just the red parts, but you'd have to process things differently than via (foreach), which isn't an appropriate function for stepping through a selection set.

Kent Cooper, AIA
Message 9 of 9
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:
.... the return from the (ssnamex) function, with (cadr) applied across it by (mapcar), is what makes the selection set into a list, which can then be processed by (foreach):

  (foreach blk
    (mapcar 'cadr (ssnamex (ssget "X" '((0 . "INSERT") (2 . "E-C-OUTLET-1")))))
....


By the way, that (mapcar 'cadr (ssnamex (ssget "X" .... approach works when (ssget) is finding things from the whole drawing [the "X"].  If you use (ssget) involving user selection, via picking or windows or whatever, because of the different nature of what (ssnamex) returns in that case, you will need to use a different approach to turning the selection set into a list, if that's the way you want to step through it.

Kent Cooper, AIA

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

Post to forums  

Autodesk Design & Make Report

”Boost