Jump to content

Recommended Posts

Posted

I am new to this forum and LISP programming so please bear with my lack of knowledge.

 

I have a couple of hundred blocks which I'm interested in changing the values of specific tags using lisp (or something else).

 

I have lots of different blocks, and they all have two attributes.

 

The tag for attribute 1 is "X", with a value of "100"

The tag for attribute 2 is "Y", with a value of "200"

 

Is is possible to change all the blocks in the drawing, such that the attribute 1 value is renamed from "100" to "1", and the attribute 2 value is renamed from "200" to "2".

 

I would like, if possible, to preserve and leave unchanged the tags associated with the respective attributes, and change only the value. So basically, once the script is done, I will still have the blocks with the same attributes, just different tag values.

 

To clarify; I'm interested in replacing attribute values rather than changing attribute tag names.

 

I hope this makes sense and that it is possible.

 

Many Thanks

  • Replies 33
  • Created
  • Last Reply

Top Posters In This Topic

  • BlackBox

    11

  • Lee Mac

    5

  • alanjt

    4

  • Lt Dan's legs

    4

Posted

Check this out , and you should select the tag in the Attributed Block ...

 

(defun c:Test (/ newTag ss e)
 ; Tharwat 18. Feb, 2011
(if (and
     (setq newTag (getstring "\n New string :"))
     (setq ss (car (nentsel "\n Select tag in Attribute Block :")))
     (eq "ATTRIB" (cdr (assoc 0 (entget ss))))
     )
 (progn
    (setq e (entget ss))
      (entupd (cdr (assoc -1 (entmod (subst (cons 1 newTag) (assoc 1 e) e)))))
   )
 (princ "\n Please select Attributed Block Only ")
 )
 (princ)
 )

 

Tharwat

Posted (edited)
 
(defun c:test ( / ss_id revise_at *error* l )
 (vl-load-com)
;|¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-;
;- Revise attributes                                                                        ;
;- ename = entity name                                                                      ;
;- _list = A list of attribute tags and changes  (list (tag . new value))                   ;
;-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-;
; Example:                                                                                  ;
;   (revise_at (car (entsel)) (list (cons "x" "1")(cons "y" "2")))                          ;
; Returns:                                                                                  ;
;   nil                                                                                     ;
;-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤|;
 (defun revise_at ( ename _list )
   (foreach x _list
     (foreach l 
       (vlax-invoke 
         (vlax-ename->vla-object ename)
         'GetAttributes
       )
       (if 
         (eq 
           (strcase 
             (vla-get-TagString l)
           )
           (strcase 
             (car x)
           )
         )
         (vla-put-TextString
           l
     (cdr x)
         )
       )
     )
   )
 )
;|¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-;
;- Turns a selection set into a list of entity names                                        ;
;- ss = selection set                                                                       ;
;-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-;
; Example:                                                                                  ;
;   (ss_id (ssget))                                                                         ;
; Returns:                                                                                  ;
;   (<Entity name: 7c3b3910> <Entity name: 7c3b3918>)                                       ;
;-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤|;
 (defun ss_id ( ss / id _list )
   (if 
     (eq 'PICKSET 
       (type ss)
     )
     (repeat 
       (setq id 
         (sslength ss)
       )
       (setq _list
         (append
           _list
           (list
             (ssname ss 
               (setq id 
                 (1- id)
               )
             )
           )
         )
       )
     )
   )
   _list
 )
;|¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤-¤|;
 
 (defun *error* ( msg )
   (setvar' nomutt 0)
   (princ)
 )

 (princ "\nSpecify blocks to modify: ")
 (setvar' nomutt 1)
 (if
   (setq l
     (ss_id 
       (ssget 
         (list
           (cons 0 "insert")
         )
       )
     )
   )
   (foreach x l
     (revise_at x 
       (list 
         (cons "X" "100")
         (cons "Y" "200")
       )
     )
   )
   (princ "\nNothing selected!")
 )

 (setvar' nomutt 0)
 (princ)
)

Edited by Lt Dan's legs
Posted

Just for fun...

 

(defun c:FOO (/ acadDoc ss blkDef textString)
 (vl-load-com)
 (vla-startundomark
   (setq acadDoc (vla-get-activedocument (vlax-get-acad-object))))
 (if (setq ss (ssget "_x" '((0 . "INSERT"))))
   (progn
     (vlax-for x (setq ss (vla-get-activeselectionset acadDoc))
       (if (= :vlax-true (vla-get-hasattributes x))
         (progn
           (setq blkDef
                  (vla-item
                    (cond
                      (blockTable)
                      ((setq blockTable (vla-get-blocks acadDoc))))
                    (vla-get-name x)))
           (foreach att (vlax-invoke x 'getattributes)
             (vlax-for item blkDef
               (if (and (= "AcDbAttributeDefinition" (vla-get-objectname item))
                        (= (vla-get-tagstring att) (vla-get-tagstring item))
                        (cond
                          ((= "100" (setq textString (vla-get-textstring att)))
                           (setq textString "1"))
                          ((= "200" textString)
                           (setq textString "2"))
                          [color=blue];; <- Add more options here
[/color]                           ))
                 (vla-put-textstring att textString)))))))
     (vla-delete ss)))
 (vla-endundomark acadDoc)
 (princ))

Posted

Nice routine Renderman.

 

How about adding more filters to catch the (wanted) one. :D

 

(setq ss (ssget  "_x" '((0 . "INSERT")[color=white](66 . 1)[/color])))

Posted
Nice routine Renderman.

 

Thanks. :)

 

 

How about adding more filters to catch the (wanted) one. :D

 

(setq ss (ssget "_x" '((0 . "INSERT")[color=white](66 . 1)[/color])))

 

Same difference - I don't use DXF codes for very much, I forgot all about (66 . 1) :oops:

Posted

Another approach:

 

(defun c:test ( / ss ) (vl-load-com)
   
   (if (ssget "_:L" '((0 . "INSERT") (66 . 1)))
       (progn
           (vlax-for block
               (setq ss
                   (vla-get-ActiveSelectionSet
                       (vla-get-ActiveDocument (vlax-get-acad-object))
                   )
               )
               (mapcar
                   (function
                       (lambda ( attrib )
                           (if (member (vla-get-TagString attrib) '("X" "Y"))
                               (vla-put-TextString attrib (chr (ascii (vla-get-TextString attrib))))
                           )
                       )
                   )
                   (vlax-invoke block 'GetAttributes)
               )
           )
           (vla-delete ss)
       )
   )

   (princ)
)

Renderman,

 

Not picking on you, but I noticed a few things:

 

 (if (setq ss (ssget "_x" '((0 . "INSERT"))))
   (progn
     (vlax-for x (setq ss (vla-get-activeselectionset acadDoc))

 

No need for the first 'setq' expression.

 

           (setq blkDef
                  (vla-item
                    (cond
                      (blockTable)
                      ((setq blockTable (vla-get-blocks acadDoc))))
                    (vla-get-name x)))
           (foreach att (vlax-invoke x 'getattributes)
             (vlax-for item blkDef
               (if (and (= "AcDbAttributeDefinition" (vla-get-objectname item))
                        (= (vla-get-tagstring att) (vla-get-tagstring item))
                        (cond
                          ((= "100" (setq textString (vla-get-textstring att)))
                           (setq textString "1"))
                          ((= "200" textString)
                           (setq textString "2"))
                          [color=blue];; <- Add more options here
[/color]                           ))
                 (vla-put-textstring att textString)))))))

 

Why do you dig through the Block Definition?

Posted

You could also step through the attributes with foreach (doesn't require anonymous function to be defined)...

 

(foreach attrib (vlax-invoke block 'GetAttributes)
 (if (vl-position (vla-get-TagString attrib) '("X" "Y"))
   (vla-put-TextString attrib (chr (ascii (vla-get-TextString attrib))))
 )
)

I don't see the reason to use mapcar+lambda unless you have more than one list to simultaneously step through or you want a list of each item's end result.

 

Not sure what's quicker, but you could also use

(substr (vla-get-TextString attrib) 1 2)

(might not have my numbers 100%; I don't have AutoCAD to check).

  • 1 month later...
Posted

I'm going to ressurect this thread in hopes someone's bored....

 

I have sort of the same issue as above, and while I'm learning LISP, I'm not really to the point of being able to handle blocks.

 

I have one block that has 2 attributes that need to be changed. One of the attributes will always be one of two things, a small "C" for cable-mounted, or a small "P" for panel-mounted. The other attribute will need to be a variety of things, so it will be manual entry. I'm assuming it's going to be easiest to make these two different commands? Would any of the above items get me close?

Posted

if you have express tools loaded just use the gatte command

Posted (edited)

Wow... I never knew that was there. I've definitely never used that command.

 

Now, here's a dumb question, is there a code located somewhere for that command? I'd really like to alter it so it works a little better. I.e., the block we're trying to modify is set up so that it's REALLY hard to select the block without selecting an attribute with the first prompt. But that 2 attributes that are really prominent aren't the ones that I'm trying to modify, so it's a little difficult to use for my purposes.

 

Maybe I'm just going to have to get better at LISP and write my own code.

Edited by resullins
Misleading typo... It's a Monday.
Posted

for a simple change the gatte works fine and if you want to chang the code its in the express folder (not sure about newer versions)

you can change it for personel use but not for sharing. i would copy it before making any changes.

but there are a ton of good block lisp here and there is no better way to learn lisp than to start writting your own

Posted
I.e., the block we're trying to modify is set up so that it's REALLY hard to select the block without selecting an attribute with the first prompt. But that 2 attributes that are really prominent aren't the ones that I'm trying to modify, so it's a little difficult to use for my purposes.

 

Maybe I'm just going to have to get better at LISP and write my own code.

 

I'm curious to know how you "set up [a block] so that it's really hard to select... without selecting an attribute with the first prompt"...?

 

Why can't you simply step through a selection set of attributed blocks using DXF code (66 . 1) in your SSGET filter, then using VLAX-FOR on the ActiveSelectionSet Property of the ActiveDocument Object?

Posted
Why can't you simply step through a selection set of attributed blocks using DXF code (66 . 1) in your SSGET filter, then using VLAX-FOR on the ActiveSelectionSet Property of the ActiveDocument Object?

First, you may as well be speaking Greek to me. I very recently found out how naive I am about this program... so forgive me, I'm trying to learn, but that made NO sense to me.

 

The block is three pieces of text with a small ellipse and a line running around them. And we often need to select forty or fifty at a time.

Posted
First, you may as well be speaking Greek to me. I very recently found out how naive I am about this program... so forgive me, I'm trying to learn, but that made NO sense to me.

 

The block is three pieces of text with a small ellipse and a line running around them. And we often need to select forty or fifty at a time.

 

No worries, we all start somewhere... I am by no means an expert myself. :)

 

That said, become familiar with the Developer Documentation (hit F1 in the VLIDE)

 

Without going into too much detail, as I understand this is 'Greek' to you, here is an example of what I posted previously:

 

:: Make a selection set of attributed blocks ::

 

[Make] a selection set of attributed blocks using DXF code (66 . 1) in your SSGET filter

 

(setq ss (ssget "_x"                                                    [color=teal]; The "_x" selects all objects that match the following filter[/color]
               (list '(0 . "INSERT")                                   [color=teal]; This indicates blocks[/color]
                     '(2 . "[color=red]BlockName[/color]")                                [color=teal]; This is the non-dynamic block's name[/color]
                     '(66 . 1)                                         [color=teal]; This indicated an attributed block[/color]
                     (cons 410 (getvar 'ctab)))))                      [color=teal]; This specifies the current tab[/color]

 

 

:: Step through the selection set ::

 

simply step through [the] selection set of attributed blocks ... using VLAX-FOR on the ActiveSelectionSet Property of the ActiveDocument Object

 

(vl-load-com)                                                           [color=teal]; This loads the visual lisp extensions to autolisp[/color]

[color=blue];; If there is a valid selection set:[/color]
(if (setq ss (ssget "_x"
                   (list '(0 . "INSERT")
                         '(2 . "[color=red]BlockName[/color]")
                         '(66 . 1)
                         (cons 410 (getvar 'ctab)))))

 [color=blue];; Then do this:[/color]
 (progn

   [color=teal];; Foreach block in the active selection set[/color]
   (vlax-for block (setq ss (vla-get-activeselectionset
                              (vla-get-activedocument
                                (vlax-get-acad-object))))

     [color=blue];; <- Add code to search through block attributes here[/color]
     )

   [color=teal];; Delete the selection set from memory[/color]
   (vla-delete ss))

 [color=teal][color=blue];; Else do this:[/color]
 ;; Inform the user nothing selected
[/color] (prompt "\n** Nothing selected ** "))

 

Again, as this may read to you as 'Greek' simply try to absorb the 'anatomy' of the function's tasks, and it will make (more?) sense later when you become more familiar.

 

Hope this helps!

Posted
why (setq ss at all?

 

For the filter' date=' of course... ss = nil.

 

The purpose of the [b']GATTE[/b] command is to "Globally change attribute values for all insertions of a specific block". (^^ Hence the ssget call ^^)

 

With a valid selection set, one can quickly step through, and evaluate the block's attributes only making changes to the values as needed.

 

The (one?) alternative would be to step through the entire block collection, and conditionally identify the desired block, then evaluate the attributes. Skipping blocks that are not desired. That seems very inefficient to me (not that the above example is perfect by any means!).

Posted

forgive me for not being clear

 

I understand the use of ssget

Why (Setq ss in the first place?

 

you setq ss here

 

(setq ss (vla-get-activeselectionset
                              (vla-get-activedocument
                                (vlax-get-acad-object))))

 

only to

(vla-delete ss))

Posted (edited)
forgive me for not being clear

 

I understand the use of ssget

Why (Setq ss in the first place?

 

you setq ss here

 

(setq ss (vla-get-activeselectionset
(vla-get-activedocument
(vlax-get-acad-object))))

 

only to

(vla-delete ss))

 

This (multi page) thread may help explain: VLAX-FOR: Xref Table?

Edited by BlackBox

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

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