Jump to content

Change attribute via lisp?


nonifo

Recommended Posts

Hello everyone,

As a newcomer to the forum, I'm reaching out for assistance on a task. I'm looking for guidance on efficiently updating attribute values in the provided file using Lisp. The block consistently bears the name EPCB000 and appears only once in each DWG file. Additionally, I'd appreciate insights on extracting values from the fields for targeted 'find and replace' operations. I'm grateful for any advice and examples you can share. Thank you in advance for your help.

Best regards,
Tony

Drawing1.dwg

Link to comment
Share on other sites

What do you want to do maybe one of these.

 

Copy atts in block to all similar blocks in layouts, fill in one 1 block attributes and blocks are updated in all layouts.

Update sheet X of Y

Update 1 attribute in all blocks using a dcl to select

 

Please explain more.

 

Ps make an Index from title blocks.

Edited by BIGAL
Link to comment
Share on other sites

I have my block EPCB000, which is my title block. I want to change all the text inside this block to new text. The drawing is a copy of an electric cabinet, but it needs new text details as it's for a new customer.

Inside my block EPCB000, there are a few attributes: D12, D13, GODK_DAT, and so on. I want to update the value of those tags in bulk, and apply a few rules, such as using today's date. For example, if D12 holds the value "G11 This is a drawing", I want to update it to G12, and so on.

However, I can't figure out how to read and write to those values.

Link to comment
Share on other sites

Ignore multiple dwg's for moment.

 

As you say only have title block once then its easy.

(setq ss (ssget "X" '((0 . "INSERT")(cons 2 "EPCB000"))))

You now have a selection set containing the block.

(setq obj (vlax-ename->vla-object (ssname ss 0)))
(setq atts (vlax-invoke obj 'Getattributes))

The variable atts holds all the attributes. You can then say change the value in each attribute, as you want to change many it makes it easy. You can just loop trough the attributes and change the "TEXTSTRING" the value of the attribute, you can also check for a particular attribute and say change G11 to G12.

 

Ok next question how do you propose to supply the new values ? One way is to make a list of the new values say keep the code in a lisp file and just change the 1 line with the new answers, or keep the values in a text file change it and then run on multiple dwg's if required. This is the type of question linked to excel  which can read say a row of details. The excel containing multiple dwg names.

 

 

 

 

 

  • Like 1
Link to comment
Share on other sites

On 4/27/2024 at 12:37 AM, BIGAL said:

Ignore multiple dwg's for moment.

 

As you say only have title block once then its easy.

(setq ss (ssget "X" '((0 . "INSERT")(cons 2 "EPCB000"))))

You now have a selection set containing the block.

(setq obj (vlax-ename->vla-object (ssname ss 0)))
(setq atts (vlax-invoke obj 'Getattributes))

The variable atts holds all the attributes. You can then say change the value in each attribute, as you want to change many it makes it easy. You can just loop trough the attributes and change the "TEXTSTRING" the value of the attribute, you can also check for a particular attribute and say change G11 to G12.

 

Ok next question how do you propose to supply the new values ? One way is to make a list of the new values say keep the code in a lisp file and just change the 1 line with the new answers, or keep the values in a text file change it and then run on multiple dwg's if required. This is the type of question linked to excel  which can read say a row of details. The excel containing multiple dwg names.

 

 

 

 

 


With use of ChatGPT I got this code to write to my tags value, and it works, almost. 
It can't handel UTF-8 (swedish charter like ÅÄÖ), any tip how to solve that? 

This code let me write to the value:

;; Function to convert UTF-8 to ANSI
(defun utf8-to-ansi (str)
  (vl-string-translate "\xC3\x84\xC3\x85\xC3\x96" "\x84\x85\x96" str)
)

;; Function to convert ANSI to UTF-8
(defun ansi-to-utf8 (str)
  (vl-string-translate "\x84\x85\x96" "\xC3\x84\xC3\x85\xC3\x96" str)
)

;; Set the coding system to UTF-8
(setq *coding-system* 'utf-8)

;; Retrieve all block references with type "INSERT" and name "EPCB000"
(setq ss (ssget "X" '((0 . "INSERT")(2 . "EPCB000"))))
(setq obj (vlax-ename->vla-object (ssname ss 0)))
(setq atts (vlax-invoke obj 'Getattributes))

;; Loop through the attributes and print their values
(while atts
  (setq att (car atts))
  (setq atts (cdr atts))
  (setq tag (vla-get-tagstring att))
  ;; Use utf8-to-ansi to convert character encoding
  (setq value (utf8-to-ansi (vla-get-textstring att)))
  ;; Check if the tag matches any of the attributes you want to update
  (cond
    ((equal tag "D8") (vla-put-textstring att (ansi-to-utf8 "ÅPA")))
    ((equal tag "D7") (vla-put-textstring att (ansi-to-utf8 "ÖPPNA")))
    ((equal tag "D6") (vla-put-textstring att (ansi-to-utf8 "STÄNG")))
  )
)

(princ) ; Display the message in the command prompt

 

 

This code let me read the tag and their value:

;; Function to read strings directly in UTF-8
(defun read-utf8-string (str)
  str
)

;; Set the coding system to UTF-8
(setq *coding-system* 'utf-8)

(setq ss (ssget "X" '((0 . "INSERT")(2 . "EPCB000"))))
(setq obj (vlax-ename->vla-object (ssname ss 0)))
(setq atts (vlax-invoke obj 'Getattributes))

;; Loop through the attributes and print their values
(while atts
  (setq att (car atts))
  (setq atts (cdr atts))
  ;; Use read-utf8-string to read strings directly in UTF-8
  (princ (strcat (read-utf8-string (vla-get-tagstring att)) ": " (read-utf8-string (vla-get-textstring att)) "\n"))
)

(princ) ; Display the message in the command prompt

 

Link to comment
Share on other sites

I think this is kind of what you are trying to do:

It might do odd things if the block has 2 tags with the same name

 

 

I've split this into 2 parts, the block updating part (UpdateBlock) which might be a useful one to have that can be used for several functions and test. Test is a dotted pair list, 'tag name . text string', I find this way easier to updated. You might be want a little function that can generate all this from a few user inputs or a dialog box.

Note the first line of the list

(cons "C2" "Project Name") ;; Project name

is how you want it to be if the list is created via LISP otherwise the other format is OK if you edit the LISP file. I'd also add the note "Project Name" at the end of each to remind yourself what each line does

 

 

Swedish characters: If they are in the character set used in the block then it should work OK - tested with Å

 

 

(defun c:test ( / NewTitles )
  ;;Tag Name : New Text
  (setq NewTitles (list ; create a list of block tags and their values
    (cons "C2" "Project Name") ;; Project Name
    '( "D3" . "Object Name")
    '( "D4" . "Function")
    '( "D12" . "File Name")
    '( "C10" . "Number")
    '( "D13" . "Another Number")
    '( "C11" . "Construction")
    '( "D6" . "ÅÅ")
    '( "D7" . "Date")
    '( "BLAD" . "Blad")
    '( "D10" . "Revision")
    '( "D25" . "Forts Blad")
  )) ; end list ; end setq
  (UpDateBlock NewTitles) ; use this list in 'UpDateBlock' function
  (princ) ; exit quietly
)
(defun UpdateBlock ( NewTitles / ss obj atts att tag NewText)
  ;; Retrieve all block references with type "INSERT" and name "EPCB000"
  (setq ss (ssget "X" '((2 . "EPCB000"))))          ; find the title block (here no need for (1 . "INSERT") )
  (setq obj (vlax-ename->vla-object (ssname ss 0))) ; Get title block as VLA- object
  (setq atts (vlax-invoke obj 'Getattributes))      ; List the VLA- tags / attributes names

  (foreach att atts                                 ; Loops through tags / attributes
    (setq tag (vla-get-tagstring att))              ; Get the 'real' tag name
    (setq NewText (assoc tag NewTitles))            ; Find tag dotted pair in the supplied list
    (if (= Newtext nil)                             ; Check if the tag is in the supplied list
      (progn
        (princ "\nTag: ")(princ tag)(princ ", ")(princ (vla-get-textstring att)(princ " not updated") ; report if the tag wasn't updated
      ) ; end progn
      (progn
        (setq NewText (cdr NewText))                    ; get the new tag value
        (vla-put-textstring att NewText)              ; update the tag
      ) ; end progn
    ) ; end if
  ) ; end foreach
)

 

 

EDIT:

Apologies if my translation in the list isn't quite what the tags mean in English.

Edited by Steven P
Link to comment
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
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...