Jump to content

Recommended Posts

Posted (edited)

Hi, sorry if the title is too global, I couldn't find a precise way to describe this.

 

I am learning AutoLISP, and sometimes I test my luck by asking ChatGPT for the code; 99% of the time this just leads me to failure, but I once got a code that I got to work with some little mods:

 

(defun changeAttribute (block attribute newValue / ss i en ed att)
  (setq ss (ssget "X" (list (cons 2 block)))) ; Select every block with the name stored in "block"
  (if ss ;If selection set exists:
    (progn
      (setq i 0) ;Starts "i" to be used as counter in while loop
      (while (< i (sslength ss))     ; Activate while loop until it reaches end of selection set (all blocks have been affected
        (setq en (ssname ss i))      ; Get block entity name
        (setq ed (entget en))        ; Get block entity data through its name
        (setq i (1+ i))              ; Add 1 to the counter
        (setq att (entnext en))      ; Get to the first attribute in the block (???)
        (while (and att (eq (cdr (assoc 0 (entget att))) "ATTRIB")) ;(???)
          (if (eq (cdr (assoc 2 (entget att))) attribute) ; If attribute name is the same as the string stored in "attribute" (???)
            (entmod (subst (cons 1 newValue) (assoc 1 (entget att)) (entget att))) ; Change its value with "newValue" (???)
          )
          (setq att (entnext att))   ; Get to the next attribute
        )
      )
      (princ "\nAttributes updated.") ;This gets printed on command prompt after while loop
    )
    (princ "\nNo blocks were found.") ;Second list on if statement so this gets printed if selection set fails
  )
  (princ) ;Function doesn't return anything so it doesn't consume memory
)

Basically I don't understand what's going on in the parts where I comment (???). Can anyone shed some light on this topic for me? I feel like this is way too important to just ignore, since blocks are a great way for non-lisp users to store values, and that can get really helpful in my working environment. Thanks!

 

Edit: adding some clarifications:

 

The function is supposed to search for every block with "x" name, then take every attribute with "y" value and change it to "z" value. It does its job wonderfully.

 

What I don't understand:

(setq att (entnext en))      ; Get to the first attribute in the block (???)

From what I've seen in the Autodesk help page, entnext gets the entity in the drawing that has been placed after the entity I put there in "en"; how does this get an attribute? I thought the attributes would be a property of the entity that is the block, but apparently they are their own entity?

 

 

(while (and att (eq (cdr (assoc 0 (entget att))) "ATTRIB")) ;(???)

I may actually understand this one: first it sees if att contains anything, then checks if the property 0 of att is "ATTRIB", which would mean that this is an attribute. The thing that always confuses me here is how properties are managed, is there any way to see what that 0 represents? Because it is quite easy for this one, but I remember that getting the property of a text background color was a pain in the ass.

 

(if (eq (cdr (assoc 2 (entget att))) attribute) ; If attribute name is the same as the string stored in "attribute" (???)

We checked in the while loop if this was an attribute, now we check if what this attribute contains corresponds to what we are trying to change (assoc looks for an association list with a "2" in the att entity, cdr returns the second value which is the value that corresponds that 2, eq compares it to attribute, because that 2 stores the value of the attribute). Same problem than before, how can I know that the attribute is stored in that value?

 

(entmod (subst (cons 1 newValue) (assoc 1 (entget att)) (entget att))) ; Change its value with "newValue" (???)

entmod confuses my head in ways I have never experienced before, the example I get from Autodesk help page is this:

image.thumb.png.62bc62b8a23372e14195c06a2c1bad65.png

 

I think I kind of understand it, at least the general concept, but that "cons" also gets me lost; I can barely explain what's happening here.

 

Hope this helps, any info on any of this is really appreciated!

Edited by EIA
Posted

Hi EIA.
I'm sure there's someone who can explain it better than me.
But I'll try:

The code '0' is associated with the object type.
Therefore, if '(cdr (assoc 0 en))' returns 'ATTRIB', it means that the object being analyzed is an attribute.
In the database, blocks are always stored in this way: first the main container entity, then the entities that compose it up to an object type 'ENDBLK' that serves to end the main entity.
Since objects in AutoCAD are stored in order, to access the objects that compose a block, after obtaining the entity name of the main container entity, you must use 'ENTNEXT' successively until the returned object is an 'ENDBLK' object.

  • Like 1
Posted

As for how to get the value contained in the attribute, once you have obtained the list of data from the entity 'ATTRIB', you should be able to get it with '(cdr (assoc 1 listEntityATTRIB))'

Posted
  On 1/29/2025 at 9:17 AM, GLAVCVS said:

Hi EIA.
I'm sure there's someone who can explain it better than me.
But I'll try:

The code '0' is associated with the object type.
Therefore, if '(cdr (assoc 0 en))' returns 'ATTRIB', it means that the object being analyzed is an attribute.
In the database, blocks are always stored in this way: first the main container entity, then the entities that compose it up to an object type 'ENDBLK' that serves to end the main entity.
Since objects in AutoCAD are stored in order, to access the objects that compose a block, after obtaining the entity name of the main container entity, you must use 'ENTNEXT' successively until the returned object is an 'ENDBLK' object.

Expand  

So, the way I see it;

AutoLISP gets a selection set (ssget), from that set you can get an object (ssname), and from that object you can get its entities (entget, actually I am now seeing that this part is not used at all in the code, thanks ChatGPT).

 

But, when you get an object, a block in this case (with ssname), you don't really get the whole block, but only what you call the "container entity", which is only the first entity, so with entnext you can cycle through all its entities, eventually reaching to its attributes (those where its property 0 is "ATTRIB") and finally to the last entity (with a property 0 of "ENDBLK").

 

I made an attempt to draw the way I think all of this works:
image.thumb.png.8e35b136778a12d3661d188cc9c01c24.png

 

Is this any correct? I think I may be wrong in the fact that ssname gets directly the object type instead of a global intermediate thing that contains every element of the block.

 

Also thanks a lot for the answer! Even though I still have many questions, that clarifies some things.

Posted

'ssname' gets the object (entity name) whose index is given as an argument for a given selection set. One important detail I must stress is that 'ssget' only does sets of 'parent' graphical objects. That is, it will never include the objects included in any of those 'parent' objects.

Posted

You may be better for this task to look at VL coding. yes similar approach, get a ssget, then look at the block, you can do a check "hasattributes" to make sure the block does have attributes if so then (setq atts (valx-get obj 'attributes)) this makes a list of the attributes, you can use (foreach att atts and get the attribute 'Tagname check against your tagname and if a match (vlax-put att 'textstring newvalue). 

 

Will try to find a simple example.

(setq x (sslength ss))
(foreach att (vlax-invoke (vlax-ename->vla-object (ssname SS (setq x (1- x))) 'getattributes)
        (if (= tagname (strcase (vlax-get att 'tagstring)))
           (vla-put-textstring att newstr)
        )
      )
)

 

 

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