There are multiples elements in the autocad i need to update my date in this format DD/MM/YYYY.
The selected element inclusive of text, mtext and value in a attribute.
The below code is not working for me
(defun c:replaceTextWithDate (/ dateStr ss)
(setq dateStr (strcat
(rtos (getvar "DAY") 2 0) "/"
(rtos (getvar "MONTH") 2 0) "/"
(rtos (getvar "YEAR") 2 0)))
(if (setq ss (ssget '((0 . "TEXT,MTEXT,INSERT"))))
(progn
(vl-cmdf "_.undo" "_begin")
(foreach obj (mapcar 'cadr (ssnamex ss))
(cond
((eq (cdr (assoc 0 (entget obj))) "TEXT")
(entmod (subst (cons 1 dateStr) (assoc 1 (entget obj)) (entget obj))))
((eq (cdr (assoc 0 (entget obj))) "MTEXT")
(entmod (subst (cons 1 dateStr) (assoc 1 (entget obj)) (entget obj))))
((eq (cdr (assoc 0 (entget obj))) "INSERT")
(setq atts (entget obj)
attList (cdr (assoc -1 atts)))
(foreach att attList
(if (= (cdr (assoc 2 att)) "date")
(setq atts (subst (cons 1 dateStr) att (entget obj)))
)
)
(entmod atts)
)
)
)
(vl-cmdf "_.undo" "_end")
(princ "\nText replaced with today's date.")
)
(princ "\nNo text entities selected."))
(princ)
)
Solved! Go to Solution.
Solved by Sea-Haven. Go to Solution.
you cant use getvar day, month, year.
you need to use cdate instead, for example like this:
(setq cdate (rtos (getvar "cdate") 2 0))
(setq dateStr (strcat (substr cdate 7 2) "/" (substr cdate 5 2) "/" (substr cdate 1 4)))
also beware that ssnamex will also return a list at the end wich will also error in your current code
Is this, perhaps, a ChatGPT or other AI effort? It has the earmarks of something that makes incorrect assumptions about what AutoLisp can do and how it works.
Where did the idea come from that there are System Variables called "DAY" and "MONTH" and "YEAR"?
(mapcar 'cadr (ssnamex ss)) will return a list of just entity names only if the objects are selected in certain limited ways.
What it thinks is going to be a list of Attributes will be only the Block entity name again. And what if a Block has more than one Attribute? Surely you don't want to put the date into every one -- shouldn't there be a check for the Tag?
There are fixes for a lot of these, but I gotta go....
here would be my approach.
Looping it with (while (< i (sslength ss))..)
(defun c:replaceTextWithDate (/ cdate dateStr ss ent atts attList)
(setq cdate (rtos (getvar "cdate") 2 0)
dateStr (strcat (substr cdate 7 2) "/" (substr cdate 5 2) "/" (substr cdate 1 4))
ss (ssget '((0 . "TEXT,MTEXT,INSERT")))
i 0
)
(vl-cmdf "_.undo" "_begin")
(while (and ss (< i (sslength ss)))
(setq ent (ssname ss i))
(cond
((eq (cdr (assoc 0 (entget ent))) "TEXT")
(entmod (subst (cons 1 dateStr) (assoc 1 (entget ent)) (entget ent)))
)
((eq (cdr (assoc 0 (entget ent))) "MTEXT")
(entmod (subst (cons 1 dateStr) (assoc 1 (entget ent)) (entget ent)))
)
((eq (cdr (assoc 0 (entget ent))) "INSERT")
(setq atts (entget ent)
attList (cdr (assoc -1 atts))
)
(foreach att attList
(if (= (cdr (assoc 2 att)) "date")
(setq atts (subst (cons 1 dateStr) att (entget ent)))
)
)
(entmod atts)
)
)
(setq i (1+ i))
)
(vl-cmdf "_.undo" "_end")
(if ss (princ "\nText replaced with today's date.")
(princ "\nNo text entities selected.")
)
(princ)
)
also as Kent1Cooper said, changing your attributes like that will not work
Thanks for the code it works for the Text and Mtext. It is not working for the value in the attribute
yes, i did not change anything of that part from your original code. And as said, that part was originally not working as intended.
@karthikeyanskm wrote:
.... It is not working for the value in the attribute
As I sort of obliquely requested in Message 3: What is the Tag of the Attribute that you want changed to contain the date text?
@Kent1Cooper wrote:
.... What is the Tag of the Attribute that you want changed to contain the date text?
If we assume the Attribute's Tag is "DATE," this [incorporating @EnM4st3r's extraction of the date text] seems to work in limited testing:
(defun C:DateText (/ cdate dateStr ss ent atts attList)
(setq
cdate (rtos (getvar 'cdate) 2 0)
dateStr (strcat (substr cdate 7 2) "/" (substr cdate 5 2) "/" (substr cdate 1 4))
); setq
(if
(setq ss
(ssget "_:L" ; only on unlocked Layer(s)
'( ; filter list
(-4 . "<OR")
(0 . "TEXT,MTEXT"); any
(-4 . "<AND") (0 . "INSERT") (66 . 1) (-4 . "AND>"); only with Attribute(s)
(-4 . "OR>")
); filter list
); ssget
); setq
(progn ; then
(repeat (setq n (sslength ss))
(setq
ent (ssname ss (setq n (1- n)))
edata (entget ent)
etype (cdr (assoc 0 edata))
); setq
(if (wcmatch etype "*TEXT"); Text or Mtext
(entmod (subst (cons 1 dateStr) (assoc 1 edata) edata)); then
(if ; else -- Block
(not ; returns T if Block contains Attribute whose Tag is "DATE"
(vl-catch-all-error-p (vl-catch-all-apply 'getpropertyvalue (list ent "DATE")))
); not
(setpropertyvalue ent "DATE" dateStr); then
); if [no else -- do nothing if doesn't have that Attribute]
); if
); repeat
); progn [then]
(prompt "\nNo eligible object(s) selected."); else
); if
(prin1)
); defun
Since (ssget) filtering can't look at whether the Block has the appropriate Attribute, it must allow selection of all Blocks with Attributes, but at least can prohibit selection of Blocks without any. The test for whether the Block contains an Attribute tagged "DATE" means it will change only the right one if the Block has more than one Attribute. And while it must allow selection of Blocks with other Attributes but not that one, it will leave the others alone.
It also allows selection of any Text/Mtext object(s), and will change their entire content, no matter what it is, to the date text. Consider whether you might want to limit that in some way, if appropriate ones would always have some filterable properties, such as by their Layer and/or Style and/or Paper vs. Model space.
It could get the usual enhancements such as Undo begin/end wrapping.
Kent,
For MText, I think that won't work, because the line:
"(entmod (subst (cons 1 dateStr)(assoc 1 edata) edata))"
Will write the date string only back to the MText value ignoring the additional Formatting
portion of the existing value. What if that MText is say 2 lines of text ?
Just a thought. Of course, there's always the UNDO.
ECCAD
@ec-cad wrote:
.... For MText, I think that won't work, because the line:
"(entmod (subst (cons 1 dateStr)(assoc 1 edata) edata))"
Will write the date string only back to the MText value ignoring the additional Formatting
portion of the existing value. What if that MText is say 2 lines of text ? ....
Certainly it will work, in just the same way their original code was written to do. That dumping of any existing internal formatting which is a "feature" of both is why I pointed out that it will replace the entire content no matter what it is [including internal formatting, multiple lines, columns, whatever]. Since they didn't include or ask anything about limiting selection to only objects that are appropriate, it's up to them to not select objects they don't want changed in that way, or to follow up on my other suggestion, to build in such a limit on selection.
My primary purpose in Message 8 was simply for it to work with Block Attributes as well as Text/Mtext [their concern in Message 5].
As we are talking about Text, Mtext or Attribute then why not.
(defun c:wow (/ edata cdate datestr)
(setq edata (entget (car (nentsel "\nPick Text Mtext or Attribute"))))
(setq
cdate (rtos (getvar 'cdate) 2 0)
dateStr (strcat (substr cdate 7 2) "/" (substr cdate 5 2) "/" (substr cdate 1 4))
)
(entmod (subst (cons 1 dateStr)(assoc 1 edata) edata))
(princ)
)
Even text in a block will change.
@Sea-Haven wrote:
As we are talking about Text, Mtext or Attribute then why not.
.... (setq edata (entget (car (nentsel "\nPick Text Mtext or Attribute")))) ....
....
[That may be good for one-at-a-time picks, which for date text may be fine -- how many things would one want to have that text content in the same drawing? -- but not for multiple selection such as with (ssget), as seems to be the desired approach since it is used in Message 1.]
Kent,
Of course it works, I didn't notice your precautions
"" Since they didn't include or ask anything about limiting selection to only objects that are appropriate, it's up to them to not select objects they don't want changed in that way, or to follow up on my other suggestion, to build in such a limit on selection."" My Bad.
ECCAD
Sea-Haven,
Here's my take on the WOW function, renamed it as DATE. Checks a couple of things - like what type of
entity did they pick (if not ATTRIB, TEXT or MTEXT) just alerts and exits. For those MText picks, just
wipes out any formatting, puts the DateStr in without any precautions. Seems to work on my text_test drawing
attached. Hope you don't mind me changing the code.
ECCAD
(defun C:DATE (/ edata cdate datestr)
(setq edata (nentsel "\nPick Text Mtext or Attribute"))
(if edata
(progn
(setq edata (entget (car edata)))
(setq etype (cdr (assoc 0 edata))); Entity Type
(if (or (= etype "ATTRIB")(= etype "TEXT")(= etype "MTEXT"))
(progn
(setq
cdate (rtos (getvar 'cdate) 2 0)
dateStr (strcat (substr cdate 7 2) "/" (substr cdate 5 2) "/" (substr cdate 1 4))
); setq
(entmod (subst (cons 1 dateStr)(assoc 1 edata) edata))
(command "_regen"); case of Attribute within a block
); progn
(Alert "Entity selected not Text Mtext or Attribute: Exiting")
); if
); progn
); if
(if (not edata)
(Alert "Nothing Selected: Exiting:")
); if
(princ)
)
Should probably rename that Function C:TODAY, since 'DATE' is an internal function of Acad,
and will be rewritten if C:DATE is the function name and the lisp is loaded.
Just a head's up for those whom use the DATE function.
ECCAD
As you say did not check what it is. Rely on end user picking correct object, also a quick answer.
Thanks for update.
As you say Kent the original post is for a ssget and that is strange that you would have 3 options to choose from, in say a Title block you may have a date revision attribute that makes sense, same with say a text used as part of a title block. But I can not understand why you would have multiples to update in one go ?
I think Karthikeyan needs to explain more the task.
Can't find what you're looking for? Ask the community or share your knowledge.