Visual LISP, AutoLISP and General Customization
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Selected value to change into today's date

16 REPLIES 16
SOLVED
Reply
Message 1 of 17
karthikeyanskm
767 Views, 16 Replies

Selected value to change into today's date

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

16 REPLIES 16
Message 2 of 17
EnM4st3r
in reply to: karthikeyanskm

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

Message 3 of 17

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

Kent Cooper, AIA
Message 4 of 17
EnM4st3r
in reply to: karthikeyanskm

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

Message 5 of 17
karthikeyanskm
in reply to: EnM4st3r

Thanks for the code it works for the Text and Mtext. It is not working for the value in the attribute

Message 6 of 17
EnM4st3r
in reply to: karthikeyanskm

yes, i did not change anything of that part from your original code. And as said, that part was originally not working as intended.

Message 7 of 17


@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?

Kent Cooper, AIA
Message 8 of 17
Kent1Cooper
in reply to: Kent1Cooper


@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 Cooper, AIA
Message 9 of 17
ec-cad
in reply to: Kent1Cooper

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

Message 10 of 17
Kent1Cooper
in reply to: ec-cad


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

Kent Cooper, AIA
Message 11 of 17
Sea-Haven
in reply to: karthikeyanskm

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.

Message 12 of 17
Kent1Cooper
in reply to: Sea-Haven


@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 Cooper, AIA
Message 13 of 17
ec-cad
in reply to: Kent1Cooper

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

Message 14 of 17
ec-cad
in reply to: Sea-Haven

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

  

Message 15 of 17
ec-cad
in reply to: ec-cad

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

Message 16 of 17
Sea-Haven
in reply to: ec-cad

As you say did not check what it is. Rely on end user picking correct object, also a quick answer. 

 

Thanks for update.

  

Message 17 of 17
Sea-Haven
in reply to: Kent1Cooper

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.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report