Held Editing Multiple Block Attributes using a simple lisp

Held Editing Multiple Block Attributes using a simple lisp

rrevillardHTGWV
Participant Participant
1,044 Views
13 Replies
Message 1 of 14

Held Editing Multiple Block Attributes using a simple lisp

rrevillardHTGWV
Participant
Participant

I have the following code that I use to quickly modify a block attribute. Sometime it doesn't work and I get the following error

 

Type the New Text: 4 ; error: ActiveX Server returned the error: unknown name: TextString

 

**************************************

(defun c:NTag (/ ent obj new)
(vl-load-com)
(if (setq ent (car (nentsel "\nSelect Att Tag to Edit:")))
(progn (setq obj (vlax-ename->vla-object ent))
(setq new (getstring "\nType the New Text: "))
(vla-put-textstring obj new)
(C:NTag)
);progn
(princ)
);if

****************************************************

 

Thank you

RR

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

john.uhden
Mentor
Mentor

I dislike the extra steps in ATTEDIT as well.

Try this:

(defun c:AE ( / *error* e ent old new dummy)
  (defun *error* (err)
    (and dummy (entget dummy)(entdel dummy))
    (princ)
  )
  (while (setq e (car (nentsel "\nSelect attribute to modify: ")))
    (setq ent (entget e))
    (setq old (assoc 1 ent))
    (setq dummy
      (entmakex (list '(0 . "TEXT")'(10 0.0 0.0 0.0)'(11 0.0 0.0 0.0)
      '(7 . "Standard")'(40 . 1.0) old '(60 . 1)) ;; invisible
      )
    )
    (command "_.textedit" dummy "")
    (setq new (assoc 1 (entget dummy)))
    (entmod (subst new old ent))
    (entupd e)
    (entdel dummy)
  )
  (*error* nil)
)

John F. Uhden

0 Likes
Message 3 of 14

rrevillardHTGWV
Participant
Participant

Hi John,

 

Thank you so much for looking at this and responding so quickly. It does work as intended, but would it be possible to edit the attribute through the command line instead of the a text window to quickly modify it. Also, would this lisp work in the attribute of a block imbedded in a custom multi-leader? 

 

I'm using a arrow block w/ one attribute to number photo locations on a plan.  

 

Regards

Ronny

0 Likes
Message 4 of 14

ВeekeeCZ
Consultant
Consultant

You can hold CTRL while double-clicking to quickly edit atts without dlg.

 

Or try this routine. But not for callouts.

(defun c:Att (/ e f)
  
  (or *att-s* (setq *att-s* ""))
  (while (setq e (car (nentsel "\nPick an Attribute: ")))
    (princ "\nUse \\P for paragraph, space for none.")
    (setq f (getstring T (strcat "\nNew Text <" *att-s* ">: ")))
    (setq *att-s* (cond ((= f "")	*att-s*)
			((= f " ") 	"")
			(T		f)))
    (setpropertyvalue e "TextString" *att-s*))
  (princ)
  )

 

0 Likes
Message 5 of 14

ВeekeeCZ
Consultant
Consultant

@rrevillardHTGWV wrote:

... Also, would this lisp work in the attribute of a block imbedded in a custom multi-leader? ...

Ronny


How many atts this block have? It could be an issue to identify which one to edit if there is more than one.

0 Likes
Message 6 of 14

pbejse
Mentor
Mentor

@rrevillardHTGWV wrote:

I have the following code that I use to quickly modify a block attribute. Sometime it doesn't work and I get the following error

 


(defun c:NTag (/ ent obj new)
  (vl-load-com)
  (if (and
	(setq ent (car (nentsel "\nSelect Att Tag to Edit:")))
	(equal (assoc 0 (entget ent)) '(0 . "ATTRIB"))
	(setq new (getstring "\nType the New Text: "))
	(/= "" new)
	)
    (progn (setq obj (vlax-ename->vla-object ent))
	   (vla-put-textstring obj new)
	   (C:NTag)
    )					;progn
    (princ)
  )					;if
)

 HTH

 

0 Likes
Message 7 of 14

john.uhden
Mentor
Mentor

@pbejse 

I don't understand why you are calling c:NTag from within c:NTag.

If you want it to repeat, then why not use a while loop? (Or I am missing something as usual.)

Anyway, your answer is what I think @rrevillardHTGWV would like, except maybe that should be (getstring T) to allow spaces.

Also, you don't need (if (and (progn...))).  Just an (and ...) will suffice with one caveat: (vla-put-*) always returns nil.  So I use the technique (or (vla-whatever ...) 1).  Yes, you should know that I don't like T because you can't be absolutely sure it exists, whereas you can't (setq 1 nil).

 

Meanwhile, I've saved a bundle of millisecs with my c:CN function (Change Number).  It finds the first numeric string in any text, mtext, attribute, or multileader and let's you just type in a new value, leaving the surrounding string intact.  So you don't have to cursor over and delete or backspace and Ctrl+Enter.  Just CN; pick entity; type in new #; hit return.

John F. Uhden

0 Likes
Message 8 of 14

john.uhden
Mentor
Mentor

@rrevillardHTGWV 

Take a look at what @pbejse posted.  I think that will suit you.

John F. Uhden

0 Likes
Message 9 of 14

rrevillardHTGWV
Participant
Participant

Just one attribute. See picture attached. Thank you for your help

0 Likes
Message 10 of 14

ВeekeeCZ
Consultant
Consultant
Accepted solution

Ok, it changes the att that you pick, or the first one if its a MULTILEADER (no matter what you pick).

 

(vl-load-com)

(defun c:QAttEdit (/ e f BLM:setmleaderblockattributevalue)
  
  ;; Set MLeader Block Attribute Value  -  Lee Mac, edited by Beekee
  ;; mld - [vla] MLeader object with attributed block content
  ;; tag - [str] Attribute tag whose value will be modified
  ;; val - [str] New attribute value
  
  (defun BLM:setmleaderblockattributevalue ( mld val )
    (if (= acblockcontent (vla-get-contenttype mld))
      (vl-catch-all-error-p
	(vl-catch-all-apply
	  '(lambda ( / oid )
	     (vlax-for obj
		       (vla-item
			 (vla-get-blocks (vla-get-document mld))
			 (vla-get-contentblockname mld)
			 )
	       (if (and (= "AcDbAttributeDefinition" (vla-get-objectname obj))
			(= :vlax-false (vla-get-constant obj))
			)
		 (progn
		   (if (vlax-property-available-p obj 'objectid32)
		     (setq oid (vla-get-objectid32 obj))
		     (setq oid (vla-get-objectid   obj))
		     )
		   (if (vlax-method-applicable-p mld 'setblockattributevalue32)
		     (vla-setblockattributevalue32 mld oid val)
		     (vla-setblockattributevalue   mld oid val)
		     )
		   (exit)))))))))
  
 ; ------------------------------------------------------------------------------- 
  
  (or *att-s* (setq *att-s* ""))
  (while (setq e (car (nentsel "\nPick an Attribute: ")))
    (princ "\nUse \\P for paragraph, space for none.")
    (setq f (getstring T (strcat "\nNew Text <" *att-s* ">: ")))
    (setq *att-s* (cond ((= f "")	*att-s*)
			((= f " ") 	"")
			(T		f)))
    
    (if (= "MULTILEADER" (cdr (assoc 0 (entget e))))
      (BLM:setmleaderblockattributevalue (vlax-ename->vla-object e) *att-s*)
      (setpropertyvalue e "TextString" *att-s*)))
  (princ)
  )

 

Message 11 of 14

rrevillardHTGWV
Participant
Participant

Thank you so much. This works great. 

 

Just one question as I'm not very familiar with lisp yet. I thought GetString allows for both [Enter] and [Spacebar] input, but when I press the [Spacebar] it adds a space and only accepts the new attribute text after [Enter] is pressed. 

 

Is there additional code that could add this functionality?

 

Thank you again for all the help

0 Likes
Message 12 of 14

ВeekeeCZ
Consultant
Consultant

It's the T from (getstring T) that makes a difference.

If you don't need spaces within atts it's convenient to remove it.

You can also remove the note about paragraphs if you don't use a multiline att.

0 Likes
Message 13 of 14

rrevillardHTGWV
Participant
Participant
Awesome, thank you again for all your help. This lisp we'll make a huge difference. Cheers
0 Likes
Message 14 of 14

pbejse
Mentor
Mentor

@rrevillardHTGWV wrote:

Just one attribute. See picture attached. Thank you for your help


A Multileader attribute!

Hey!, who knew?

 

who knew.png

 

0 Likes