Simple Lisp Routine Request

Simple Lisp Routine Request

jamaine.murphy
Participant Participant
1,055 Views
13 Replies
Message 1 of 14

Simple Lisp Routine Request

jamaine.murphy
Participant
Participant

Hello AutoCAD community. 

 

LoL so i tried ChatGPT first to see if it could help, but it was unable to produce the  desired affect lol.  Great for us Humanz lol, anyways.

 

I need a list routine/code that does the following.

1. prompts user to select desired blocks

2. change the text field of the attribute tags "SGL" and "DBL" from  "I.E.", to "C.S."

 

Thanks again in advance.

0 Likes
Accepted solutions (1)
1,056 Views
13 Replies
Replies (13)
Message 2 of 14

komondormrex
Mentor
Mentor

hi there,

test this code.

 

(setq attribute_assoc_list nil)
(foreach attribute 
		(vlax-invoke 
			(vlax-ename->vla-object 
				(car 
					(entsel "\Pick your attributed block: ")
				)
			)
			'getattributes
		)
		(setq attribute_assoc_list (append attribute_assoc_list 
					   	(list (cons (vla-get-tagstring attribute) attribute))
			   		   )
		)
)
(vla-put-textstring (cdr (assoc "SGL" attribute_assoc_list)) "C.S.")
(vla-put-textstring (cdr (assoc "DBL" attribute_assoc_list)) "C.S.")

 

0 Likes
Message 3 of 14

jamaine.murphy
Participant
Participant

Fantastic,

It works to change the attribute, but I also need it to allow users to pick 1 or more blocks 1st, and when the user is done can press enter and then the text change happens.

0 Likes
Message 4 of 14

SeeMSixty7
Advisor
Advisor

The -ATTEDIT command provides this functionality out of the box.

 

-ATTEDIT it will prompt you to edit blocks one at a time, say no. then provide the block name (use * for all blocks) then specify the ATTTAG. then update what you want.

 

Good luck

0 Likes
Message 5 of 14

jamaine.murphy
Participant
Participant

Thank you for that input, however it is important for this routine to be as simple and efficient as possible.

Could you revise the code to allow users to select the blocks first, press enter, and then the text would change?

0 Likes
Message 6 of 14

Kent1Cooper
Consultant
Consultant

@jamaine.murphy wrote:

....

2. change the text field of the attribute tags "SGL" and "DBL" from  "I.E.", to "C.S."

....


Do you want to change them that way only if they're currently "I.E.", or do you want to set those Attributes to "C.S." regardless of their current value if any?

 

If the latter,

(foreach att '("SGL" "DBL") (setpropertvalue BlockEntityName att "C.S."))

should do it, since Attribute tags work as "properties" in that system.  But I haven't found yet how to determine in that context whether the Block has an Attribute with a given tag, because if it doesn't, it will get an error.

Kent Cooper, AIA
0 Likes
Message 7 of 14

ronjonp
Mentor
Mentor

@jamaine.murphy 

OOTB Find and replace can accomplish this too.

Message 8 of 14

jamaine.murphy
Participant
Participant

Thank you for the helpful tip.

 

However, since the intent of having this lisp routine available is to allow the users to select specifically the items they want to change, and automate that process, going thru the find & replace steps wouldn't reduce the time spent, and just adds more steps to the task.   I need a  2-click solution.   Click the command, click the block(s).

0 Likes
Message 9 of 14

jamaine.murphy
Participant
Participant

The default text is I.E. in the block.

If you can code it so that the text would be changed to either IE or CS depending on what is already in the attribute text field, that'd be great.

This lisp will be put onto a button on the toolbar, so I would like the process to require as little input from our drafters.  (automation FTW).

0 Likes
Message 10 of 14

Kent1Cooper
Consultant
Consultant
Accepted solution

@jamaine.murphy wrote:

... the text would be changed to either IE or CS depending on what is already in the attribute text field....


Not knowing what or how many possibilities there may be for "already" values, here's a suggested approach [untested]:

(defun C:ATTCHANGE (/ blkss attchanges n blk val)
  (if (setq blkss (ssget '((0 . "INSERT"))))
    (progn ; then
      (setq attchanges '(("I.E." "C.S.") ("Manny" "Moe") ("blue" "green") ("27" "28")))
        ;; list of possible current values paired with what to change them to
      (repeat (setq n (sslength blkss))
        (setq blk (ssname blkss (setq n (1- n))))
        (foreach tag '("SGL" "DBL")
          (if ;; does an Attribute with that tag exist in the Block?
            (not
              (vl-catch-all-error-p (vl-catch-all-apply 'getpropertyvalue (list blk tag)))
                ;; [returns nil if Attribute exists, T if not]
            ); not
            (progn ; then -- check/change its value
              (setq val (getpropertyvalue blk tag)); current value
              (if (assoc val attchanges) ; current value is in list of those to be changed
                (setpropertyvalue blk tag (cadr (assoc val attchanges))); then -- change it
                ;;; [... set it to something else if current value is not in the list? ...] ; else
              ); if [change value]
            ); progn
          ); if [Attribute exists]
        ); foreach
      ); repeat
    ); progn
  ); if [selection]
  (prin1)
)

From your description, I suspect maybe all the second items in the pairing sublists within the 'attchanges' list should be either "I.E." or "C.S.".

 

Note the commented-out something-else place-holder, in case you have a fallback value you want them set to if their current value is not in the list.  As written, it would leave any such Attributes alone.

 

The selection filter at the top could include a Block name or names, if that can limit the selection to only Blocks that you know will always contain those two Attribute tags, eliminating the need to check whether an Attribute is present.

 

As written, it's case-sensitive about the current value, but it could be made to not have that limitation.

Kent Cooper, AIA
0 Likes
Message 11 of 14

jamaine.murphy
Participant
Participant

This is exactly what I needed, Thank you so much for this. 

0 Likes
Message 12 of 14

Kent1Cooper
Consultant
Consultant

[You mean it worked?  That's always a pleasant surprise with untested code.]

Kent Cooper, AIA
0 Likes
Message 13 of 14

jamaine.murphy
Participant
Participant

lol, that's pro-level.

0 Likes
Message 14 of 14

komondormrex
Mentor
Mentor

missed your answer, but  that should do too)  

 

 

 

(defun c:change_attribute_value (/ insert_object_list)
	(vla-startundomark (vla-get-activedocument (vlax-get-acad-object)))
	(setq insert_object_list (mapcar 'vlax-ename->vla-object 
					  (vl-remove-if 
					  	'listp 
							(mapcar 
								'cadr 
									(ssnamex (ssget "_:l" '((0 . "insert") (66 . 1))))
							)
					  )
				)
	)
	(foreach insert_object insert_object_list
	  	(foreach attribute_object (vlax-invoke insert_object 'getattributes)
		  	(if (or
			      	(= "DBL" (vla-get-tagstring attribute_object))
			    	(= "SGL" (vla-get-tagstring attribute_object))
			    )	
				(vla-put-textstring attribute_object "C.S.")  
			)
		)  
	)
	(vla-endundomark (vla-get-activedocument (vlax-get-acad-object)))
  	(princ)
)

 

0 Likes