Change Attribute Tags by their Position instead of the Name

Change Attribute Tags by their Position instead of the Name

Anonymous
Not applicable
1,275 Views
6 Replies
Message 1 of 7

Change Attribute Tags by their Position instead of the Name

Anonymous
Not applicable

Hello, we got alot drawings that we convert from microstation to .DWG and now we have to replace every Attribute-Tag with our own Names - we got a Script, dont really know from where but its pretty straight forward.

 

;;; Rename attributes
(defun RenAttrib ($blk $old $new / blocks bo eo ao)
  ;; Get blocks collection in current drawing
  (setq blocks (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
  ;; Step through all blocks
  (vlax-for bo blocks
    ;; Step through all entities inside block
    (vlax-for eo bo
      (cond
        ;; If attdef & in target block & old tag
        ((and (= (vla-get-ObjectName eo) "AcDbAttributeDefinition")
              (= (strcase (vla-get-Name bo)) (strcase $blk))
              (= (vla-get-TagString eo) $old)
         ) ;_ end of and
         (vla-put-TagString eo $new) ;Change to new name
        )
        
        ;; If block reference & target block
        ((and (= (vla-get-ObjectName eo) "AcDbBlockReference")
              (= (strcase (vla-get-EffectiveName eo)) (strcase $blk))
         ) ;_ end of and
         ;; Step through all attributes
         (foreach ao (vlax-safearray->list (vlax-variant-value (vla-GetAttributes eo)))
           ;; Check if target attrib
           (if (= (strcase (vla-get-TagString ao)) (strcase $old))
             (vla-put-TagString ao $new) ;Change to new name
           ) ;_ end of if
         ) ;_ end of foreach
        )
      ) ;_ end of cond
    ) ;_ end of vlax-for
  ) ;_ end of vlax-for
) ;_ end of defun

and we run it with the command

(RenAttrib "TESTBLK" "OLDTAG" "NEWTAG")

lets jump right at the problem-

The "OLDTAG" does change for the same blocks after every new convert from microstatio.

For example.

 

First DWG

Blockname: KI1

Tagname: KI1_1

Tagname2: KI1_2

 

Second DWG

Blockname: KI1

Tagname: KI1_3

Tagname2: KI1_4

-----------------------------------------

Even tho its the same block the Attribute Tags seem to count up and we cant use a Excel for the Tag names to maximise efficency with the .lsp

 

My Question:

Is it possible to set the reference of the Script to the position of the AttributeTag instead of the old name?

E.g.

(RenAttrib "BLOCKNAME" "FIRST NEW TAG" "SECOND NEW TAG")

Would be awesome if someone could tell me if its possible or how to do it. Or even "just" change the existing script.

 

P.S. if someone knows where the original script came from please post source below for credit.

 

Best regards!

0 Likes
1,276 Views
6 Replies
Replies (6)
Message 2 of 7

ВeekeeCZ
Consultant
Consultant

Would you post some dwg with a block to illustrate the issue? Original block and desired outcome?

Not sure what you mean by 1st new tag, 2nd...

 

Anyway, it looks like the original code was posted by its author HERE

0 Likes
Message 3 of 7

Anonymous
Not applicable
Can't post the dwg, wouldn't anything anyways. I can try to explain it in
more detail.

At first we got the drawing in Microstation let's name it "a" after we
convert it its a.dwg and the block name is "block-a" with 2 different
attribute attached called "block-a-attribute1" and "block-a-attribute2".

So far so good.

Let's convert the drawing "a" another time from Microstation to Autocad -
this time the block name is still "block-a" but the attribute name of the
same block in the same .dwg as above is now "block-a-attribute3" and
"block-a-attribute4".

Let me try to bring it in one sentence.

TL:DR - Block names for the same block doesn't change on the convertion but
every new convertion does count up the number behind attribute Names.

Script should target the position of the attribute name instead of the name
itself.


Im on mobile sorry for not editing and probably hard to understand use of
the English language.
Gonna add the credits on the original script as soon as I'm on desktop.


Best regards
0 Likes
Message 4 of 7

Moshe-A
Mentor
Mentor

@Anonymous  hi,

 

1. the lisp function you post looks good although i can not test it (cause you did not post a dwg) but it has a 'little' drawback...for each block it scan the whole database time and time again so i correct it to be effective (hope you do not (or the author) mind Smiley LOL)

2. in order to base the program on attribute coordinates you have to provide those coordinates to the function and i assume you do not have that beyond that you could not be sure that attributes are not moved from one convert to another. so this still must be base on tag names. 

3. attached my version to solved this called RAT (rename attributes) and it starts by defining a list of blocks and attributes name all strings. you need to populate this list with your blocks name and the attributes old tag and the new tag to be replaced. make sure not to spoil the format, each sub list starts with the block name and continue with repeating old tag and new tag. each name (string) start and ends with double quotes so make sure not to miss that.

by the way do you know in advance what will be the old tags or you have to open each converted drawing and find them?

 

enjoy

Moshe

 

 

(setq data^ '( ("Block1" ("oldTag1" "newTag1")
	                 ("oldTag2" "newTag2")
	                 ("oldTag3" "newTag3")
	       ); list
               ("Block2" ("oldTag1" "newTag1")
	                 ("oldTag2" "newTag2")
	                 ("oldTag3" "newTag3")
	       ); list
             ); list
       
 ); setq

and here is the whole program.

 

(defun C:RAT (/ RenAttrib ; local function
	        data^)

 ;;; Rename attributes
 (defun RenAttrib ($blk $old $new / blocks bo eo ao)
  ;; Get blocks collection in current drawing
  (setq blocks (vla-get-Blocks (vla-get-ActiveDocument (vlax-get-acad-object))))
  ;; Step through all blocks
  (if (setq bo (vla-item blocks $blk))
   ;; Step through all entities inside block
   (vlax-for eo bo
    (cond
     ;; If attdef & in target block & old tag
     ((and (= (vla-get-ObjectName eo) "AcDbAttributeDefinition")
           (= (strcase (vla-get-Name bo)) (strcase $blk))
           (= (vla-get-TagString eo) $old)
      ) ;_ end of and
      (vla-put-TagString eo $new) ;Change to new name
     )
        
     ;; If block reference & target block
     ((and (= (vla-get-ObjectName eo) "AcDbBlockReference")
           (= (strcase (vla-get-EffectiveName eo)) (strcase $blk))
      ) ;_ end of and
      ;; Step through all attributes
      (foreach ao (vlax-safearray->list (vlax-variant-value (vla-GetAttributes eo)))
       ;; Check if target attrib
       (if (= (strcase (vla-get-TagString ao)) (strcase $old))
        (vla-put-TagString ao $new) ;Change to new name
       ) ;_ end of if
      ) ;_ end of foreach
     )
    ) ;_ end of cond
   ) ;_ end of vlax-for
  ); if  
 );_ end of defun

  
 ; here start C:RAT  
 (setq data^ '( ("Block1" ("oldTag1" "newTag1")
	                  ("oldTag2" "newTag2")
	                  ("oldTag3" "newTag3")
	        ); list
                ("Block2" ("oldTag1" "newTag1")
	                  ("oldTag2" "newTag2")
	                  ("oldTag3" "newTag3")
	        ); list
              ); list
       
 ); setq

 (foreach blk data^
  (foreach item blk
   (RenAttrib blk (car item) (cadr item))
  ); foreach
 ); foreach

 (princ) 
); C:RAT

 

 

0 Likes
Message 5 of 7

Anonymous
Not applicable

First of all - Thanks for your work.

 

Second - doesn't really solve my problem. The range of the AttributeNames (Tags) are very wide something between one and 50.000 - so anything that needs the old name to replace the current one is pretty useless. I could make an excel sheet with 50.000 variations of every Attribute name just with a diffrent number behind it but we're talking about around 150 diffrent blocks and i think with such big data it will just crash. (7.5Mil different attributenames).

 

Don't really get the coordinate part. Another try to explain it with my broken English-

autocad-tips-attributes-battman-1.png

This opens up with the BATTMAN function and the Tags "NO" and "DATE" are always in this exect order.

 

Goal is to target the order direct with the script - say - 

(setq data^ '( ("Block1" ("Tag_Order_Position1" "newTag1")
	       ); list
               ("Block2" ("Tag_Order_Position2" "newTag1")
       
 ); setq

Maybe its just not possible to make it this way :x

I also don't have acces to AutoCAD right now to test anything tho..

 

Still thank you very much for your effort I appreciate!

 

( A script that changes every attribute name globaly to "XY" would also work tho - atleast i can name them without open every BATTMAN on the block to write them down)

 

Best regards

0 Likes
Message 6 of 7

Moshe-A
Mentor
Mentor

@Anonymous  hi,

 

if you don't give us the exact info on what we are facing and what it's extents we can't help you. attributes tags can be replaced by two methods:

a) you supply the oldTag and the newTag

b) scan the attribute by their order (as they appears in the block definition) and change them but still for each block attributes you have to supply the newTags (or set something base on a serial number) but relaying  on the attribute order is not 100% safe.

 

post your most complicated drawing so i can take a look and a list of block names and attributes.

 

Moshe

 

0 Likes
Message 7 of 7

Anonymous
Not applicable

@Moshe-A wrote:

b) scan the attribute by their order (as they appears in the block definition) and change them but still for each block attributes you have to supply the newTags (or set something base on a serial number) but relaying  on the attribute order is not 100% safe.


 

 

Sounds exactly what i need. Cant post a .dwg cuz

Confidentiality Agreement

Best regards

0 Likes