Author Topic: Attribute change  (Read 20947 times)

0 Members and 1 Guest are viewing this topic.

Biscuits

  • Swamp Rat
  • Posts: 502
Attribute change
« on: January 03, 2006, 02:21:50 PM »
This macro allows me to update any attribute I mouse-pick to read "2006 C-n-R CORPORATION" (an attribute used for our copyright year). This will work on attributes burried within blocks that are embedded within blocks. Unfortunately some of our titleblocks were set up this way. This is the only "quick" routine I've been able to find. I'm looking for a simple way to find this attribute and automatically update it to the current year without actually selecting the attribute in question. The tag used is "copyright" or "copyrightyear" depending which titleblock was used. We are still using ACAD 2002. We are dealing with thousands of drawings each year that require an update for this copyright year. Any ideas out there?
Thanks and Happy New Year!

Code: [Select]
_-ATTEDIT;;;;;\ _VALUE _REPLACE $(EVAL, 2006 C-n-R CORPORATION)^H;;

uncoolperson

  • Guest
Re: Attribute change
« Reply #1 on: January 03, 2006, 02:27:31 PM »
Code: [Select]
(DEFUN attmod (tagstring textstring / block-ent attribute-value attribute-list)
  (COMMAND "-LAYER" "u" "border" "")
  (SETQ block-ent (CAR (LAST (NENTSELP '(29 0 0)))))
  (SETQ attribute-list
(VLAX-SAFEARRAY->LIST
   (VLAX-VARIANT-VALUE
     (VLA-GETATTRIBUTES
       (VLAX-ENAME->VLA-OBJECT block-ent)
     )
   )
)
  )
  (FOREACH attribute attribute-list
    (IF (= tagstring (VLA-GET-TAGSTRING attribute))
      (VLA-PUT-TEXTSTRING attribute textstring)
    )
  )
  (COMMAND "-layer" "lo" "border" "")
)

I use something like this... the border layer is always locked... and the corner of it is at (29 0 0)
it's not clean or perfect, but it works


Edit: the above code doesn't handle nested attributes... jeez i should read things more thoroughly
« Last Edit: January 03, 2006, 03:45:13 PM by uncoolperson »

Biscuits

  • Swamp Rat
  • Posts: 502
Re: Attribute change
« Reply #2 on: January 03, 2006, 02:42:48 PM »
Thanks for the quick response, UNCOOL. But I have no clue how to use your coding

uncoolperson

  • Guest
Re: Attribute change
« Reply #3 on: January 03, 2006, 02:59:40 PM »
you're wanting to use lisp right? if not just ignore all this.

change '(29 0 0) to some point that only your title block would be at '(0 0 0) is pretty good too
this is assuming your attributes are part of your title block

if your title block layer (the one containing the stuff we want to play with) is always locked (like mine) change border in these two lines to whatever you border layer is

Code: [Select]
(COMMAND "-LAYER" "u" "border" "")
(COMMAND "-layer" "lo" "border" "")

otherwise delete them

then to change and attribute with the tag of "DATE" to today use
(attmod "DATE" "01/03/06")

deegeecees

  • Guest
Re: Attribute change
« Reply #4 on: January 03, 2006, 03:30:35 PM »
Here is something similar. It handles embedded entities.

Code: [Select]
(defun c:underliner ()
(setq en1 (nentsel "\nPlease choose an object:" ))
(setq en1-2 (car en1))
(setq en3 (entget (car En1)))
(setq en4 (cdr (assoc 1 en3)))
(setq txt1 (strcat "%%u" en4));;;;<-------Just change %%u to C-n-C Corp...

   (setq en3
                   (subst(cons 1 txt1)
                         (assoc 1 en3)
                         en3))
       (entmod en3)
        (entupd en1-2)
(command "regen")
(princ)
)

You could use a number of ways to accomplish your task. Use something like this for selecting the right attribute:

Code: [Select]
(SETQ isrev11 (SSGET "X" '((2 . "rev-att-cntr"))));;<------------change rev-att-cntr to your block name
(IF isrev11
(PROGN
(setq qtyisrev (sslength isrev11))
(if (= 1 qtyisrev)
(progn
(SETQ isrev21 (SSNAME isrev11 0))
(setq isrev2-1 (entnext isrev21));;;;;;;;;coding keeps going but had to cut off for sake of making sense.

Of course I may be confusing the issue here, so I'll stop now. If you are totally confused, let me know, and I'll try to spend more time on it for you.


Ok, while I was writing this, uncool posted something that needs to be clarified before we keep going. This is the AutoLISP forum, so it is assumed that by posting a question here it is Lisp oriented. What are you trying to do Mr. Buscuits? Please elaborate a bit.



Biscuits

  • Swamp Rat
  • Posts: 502
Re: Attribute change
« Reply #5 on: January 03, 2006, 04:13:44 PM »
Ok Deegeecees. Here goes. Using ACAD 2002, we have tons of existing drawings that use one of two title blocks. These title blocks contain an attribute used to indicate the year (at the time) & copyright. The tags for these would either be "copyright" or "copyrightyear". As each new year comes about, this attributes value needs updating when older drawings get modified. Example: "2005 C-n-R Corporation" nows needs to read "2006 C-n-R Corporation"
As you can imagine, we go through this every year. Problem is, at one time, a large portion of existing drawings had the titleblock attribute in question embedded (nested?) within another block. In recent drawings, embedding within blocks was corrected to just typical attributes. My macro as earlier posted, would allow next-to-automatic updating for this attribute (embedded or not). All I had to do was pick the button containing the macro then select each attribue requiring the change. We use multiple titleblocks within a single drawing  and almost always use model space (very seldom layouts). I'm trying to avoid selecting each attribute requiring the change. I admit I'm lazy and looking for a simple means. I don't care if lisp, VBA, or diesel is used. I have toyed with lisp but get nowhere with this one. I'm not sure what I need to complete Uncoolperson's routine. I will experiment with your coding and see what happens.
Thanks alot

deegeecees

  • Guest
Re: Attribute change
« Reply #6 on: January 03, 2006, 04:28:46 PM »
You are welcome, and thanks for the elaboration.

The first thing that came to mind was "XREF". I cannot tell you how invaluable this little aspect of AutoCAD is. I think they made it just for your situation. If you have an xrefed titleblock, it is very easy to change the initial titleblock drawing, then all other drawings that reference this will update automatically.

What I would do is this:

1. Create a copy of the titleblock (only static entites, or entities that will not change from dwg to dwg).
2. Copy/paste to original coordinates the dynamic entities (basically, the attributes that will change from dwg to dwg).
3. Write a routine that will replace the old inserted block with the new xrefed one and the attributes.

Does this sound like something you would like to do?

Biscuits

  • Swamp Rat
  • Posts: 502
Re: Attribute change
« Reply #7 on: January 03, 2006, 04:47:51 PM »
I agree with you DeeGeeCee. We thought about XRef's and for the life of me I can not remember why management said no to the idea. I tried your "underliner" routine and it works great. It essentially does the same thing as my macro. Simply put, I'm trying to eliminate having to actually select each attribute requiring the change (especially in the case of multiple titleblocks). Like I said I'm lazy and going for further automation.
Thanks again for your responses.

uncoolperson

  • Guest
Re: Attribute change
« Reply #8 on: January 03, 2006, 04:52:47 PM »
if your attributes are ALWAYS at the same location you could throw attedit command some pick points

(now hows that for dangerous....)

deegeecees

  • Guest
Re: Attribute change
« Reply #9 on: January 03, 2006, 04:55:13 PM »
if your attributes are ALWAYS at the same location you could throw attedit command some pick points

(now hows that for dangerous....)

Cookin with fire!

Ok, well my next suggestion is to take the above posted code and add a while loop to it to step through the blocks entities until it finds the correct one, then change it. To automate all this just add a function that calls it in an .MNL file or ACAD200X.DOC.

Biscuits

  • Swamp Rat
  • Posts: 502
Re: Attribute change
« Reply #10 on: January 03, 2006, 05:00:41 PM »
That's livin on da edge there UNCOOL! Nice try though.

DeeGeeCees yer talkin beyond my skill level.

By the way, what is that Avatar yer using?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Attribute change
« Reply #11 on: January 03, 2006, 05:11:05 PM »
If you want it animated, then you need to provide the names of the title blocks that you use.  Each one.  The main one that is in the drawing, and the ones that are nested (embedded) in them, until you get to the block where the attributes are.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

dan19936

  • Guest
Re: Attribute change
« Reply #12 on: January 03, 2006, 05:34:09 PM »
<snip>This will work on attributes burried within blocks that are embedded within blocks.

I'm not sure I understand. When I use ATTEDIT on an attribute in a block in a block, I get the error "That block has no editable attributes".

Wish I had a direct solution, but the best I can do it search my list archive (using TextPad wildcard ssget.*insert)
The following code had an attribute search & replace function

Code: [Select]
;;; From: Jon Fleming (jonf@fleming-group.com)
;;; Subject: Re: Titleblock & updating attribute woes.
;;; Newsgroups: autodesk.autocad.customization
;;; Date: 2001-12-22 05:38:18 PST
(defun UpdatePlotDateReactor (CallingReactor CommandList /
                              TitleBlockEList AttribDXFList SelSet
                              Counter DateWasUpdated DateTime
                              DrawingFileName
                             )
  ;; If we are about to run the PLOT commmand ...
  (if (= "PLOT" (car CommandList))
    (progn
      ;; Initialize a flag for how many plot dates were changed
      (setq DateWasUpdated 0
            ;; Get the current date as a string
            DateTime       (menucmd "M=$(edtime,$(getvar,date),M/D/YY HH:MM:SSAM/PM)")
      ) ;_ end setq
      ;; Get the file ename if there is one
      (if (= (getvar "DWGTITLED") 0)
        (setq DrawingFileName "<none>")
        (setq DrawingFileName (getvar "DWGNAME"))
      )
      ;; If there is a title block (a BLOCK, named Title Block, with
      ;; attributes)
      (if (setq SelSet (ssget "X" '((0 . "INSERT") (2 . "A1-TITLE") (66 . 1))))
        (progn
          (setq Counter (sslength SelSet))
          ;; For all title blocks (may be a multiple sheet drawing)
          (while (<= 0 (setq Counter (1- Counter)))
            ;; Get the title block
            (setq TitleBlockEList (entget (ssname SelSet Counter))
                  ;; Look for the plot date attribute
                  AttribDXFList (get_subentity
                                    TitleBlockEList
                                    '(2 . "PLOT_DATE_&_TIME")
                                  ) ;_ end get_subentity
            ) ;_ end setq
            ;; If the attribute was found (if it wasn't found,
            ;; AttribDXFList will contain a SEQEND entity) ...
            (if (= "ATTRIB" (cdr (assoc 0 AttribDXFList)))
              ;; If its value is out of date ...
              (if (/= DateTime (cdr (assoc 1 AttribDXFList)))
                (progn
                  ;; Update it
                  (entmod
                    (list
                      (assoc -1 AttribDXFList)
                      (cons 1 DateTime)
                    ) ;_ end list
                  ) ;_ end entmod
                ) ;_ end progn
              ) ;_ end if
            ) ;_ end if
            ;; Look for the file name attribute
            (setq AttribDXFList (get_subentity
                                    TitleBlockEList
                                    '(2 . "CAD_FILENAME")
                                  ) ;_ end get_subentity
            ) ;_ end setq
            ;; If the attribute was found (if it wasn't found,
            ;; AttribDXFList will contain a SEQEND entity) ...
            (if (= "ATTRIB" (cdr (assoc 0 AttribDXFList)))
              ;; If its value is out of date ...
              (if (/= DrawingFileName (cdr (assoc 1 AttribDXFList)))
                (progn
                  ;; Update it
                  (entmod
                    (list
                      (assoc -1 AttribDXFList)
                      (cons 1 DrawingFileName)
                    ) ;_ end list
                  ) ;_ end entmod
                  ;; Update the screen
                  (entupd (cdr (assoc -1 TitleBlockEList)))
                  ;; Update the flag for how many we've changed
                  (setq DateWasUpdated (1+ DateWasUpdated))
                ) ;_ end progn
              ) ;_ end if
            ) ;_ end if           
          ) ;_ end while
        ) ;_ end progn
      ) ;_ end if
      ;; If we did any updates, tell the user
      (if (/= 0 DateWasUpdated)
        (if (< 1 DateWasUpdated)
          (progn
            (prompt
              (strcat "\nUpdated \"Plotted\" in "
                      (itoa DateWasUpdated)
                      " title blocks"
              ) ;_ end strcat
            )
            (princ)
          )
          (progn (prompt
                   "\nUpdated \"Plotted\" in the title block"
                 )
                 (princ)
          )
        ) ;_ end if
      ) ;_ end if
    ) ;_ end progn
  ) ;_ end if
  (prin1)
) ;_ end defun


deegeecees

  • Guest
Re: Attribute change
« Reply #13 on: January 03, 2006, 05:36:33 PM »
Wow! Thats some great notation. Jon Fleming, my hat goes off to you wherever you are.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Attribute change
« Reply #14 on: January 03, 2006, 05:49:23 PM »
Give this a try.
Code: [Select]
;;=======================[ cUpdate.lsp ]=======================
;;; Author: Copyright© 2006 Charles Alan Butler
;;; Version:  1.0 Jan. 03, 2006
;;; Purpose: To update attributes in a drawing, nested blocks & xref
;;;          Ignores locked or Frozen layers
;;; Sub_Routines: -None
;;; Requirements: -None
;;; Returns: -None
;;;==============================================================
;;
(defun c:cupdate (/ ss ent obj attributes att)
  (setq newtext "2006 C-n-R CORPORATION")
  (setq ss (ssget "_X" '((0 . "INSERT"))))
  (setq i -1)
  (if ss
    (while (setq ent (ssname ss (setq i (1+ i))))
      (if (and (setq obj (vlax-ename->vla-object ent))
               (= (vla-get-objectname obj) "AcDbBlockReference")
               (= (vla-get-hasattributes obj) :vlax-true)
          )
        (progn
           (setq attributes (vlax-invoke obj 'getattributes))
           (foreach att attributes
             (if (or (= "COPYRIGHT" (vla-get-tagstring att))
                     (= "COPYRIGHTYEAR" (vla-get-tagstring att))
                 )
               (progn
                 (vla-put-textstring att newtext)
                 (vla-update att)
               )
             )
           )
        )
      )
    )
  )

  (or *doc* (setq *doc* (vla-get-activedocument (vlax-get-acad-object))))
  (if (< 0 (vla-get-count (setq blks (vla-get-blocks *doc*))))
    (progn
      (vlax-for blk blks
        (if (/= (vla-get-name blk) "*Model_Space")
          (vlax-for ent blk
            (if (and (vlax-property-available-p ent 'hasattributes)
                     (= (vla-get-hasattributes ent) :vlax-true)
                )
              (progn
                (setq attributes (vlax-invoke ent 'getattributes))
                (foreach att attributes
                  (if (or (= "COPYRIGHT" (vla-get-tagstring att))
                          (= "COPYRIGHTYEAR" (vla-get-tagstring att))
                      )
                    (progn
                      (vla-put-textstring att  newtext)
                    )
                  )
                )
              )
            )
          )
        )
      )
      (vla-regen *doc* acactiveviewport)
    )
  )
  (princ)
)
(prompt "\nCopyright Update Loaded, Enter cupdate to run.")
(princ)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.