Author Topic: Replace part of attribute  (Read 5522 times)

0 Members and 1 Guest are viewing this topic.

V-Man

  • Bull Frog
  • Posts: 343
  • I exist therefore I am! Finally Retired!
Replace part of attribute
« on: December 08, 2010, 09:12:35 AM »

Can some show me how to replace only part of an attribute? For instance, "3021920" is an attribute and I want to change "30" to "GF" but leave the rest of the attribute as is so the final result would be "GF21920". I have numerous blocks with this and I need a simplified way to globally make the change. Any help appreciated.

Thanks
AutoCAD 9 - 2023, AutoCADMap 2008 - 2010, Revit 2012 - 2022, Autocad Civil 3D 2023

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Replace part of attribute
« Reply #1 on: December 08, 2010, 09:21:26 AM »
I thought  Lee or Tim had a "Find and Replace" that worked on attributes and allowed wild cards.
(Replace "30*" "GF")

But you may need to use the block name and / or attribute Tag Name as a filter too to prevent text from getting hit.


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.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #2 on: December 08, 2010, 09:30:57 AM »
Something like this?

Code: [Select]
(defun c:test ( / *error* RegEx ss ) (vl-load-com)
  ;; © Lee Mac 2010

  (defun *error* ( msg )
    (LM:ReleaseObject RegEx)
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **")))
    (princ)
  )

  (if (ssget "_X" '((0 . "INSERT") (66 . 1)))
    (progn
      (setq RegEx (vlax-create-object "VBScript.RegExp"))

      (mapcar '(lambda ( x ) (vlax-put-property RegEx (car x) (cdr x)))
        (list
          (cons 'pattern  "^30(.*)")
          (cons 'global     acfalse)
          (cons 'ignorecase acfalse)
        )
      )
     
      (vlax-for obj
        (setq ss
          (vla-get-ActiveSelectionSet
            (vla-get-ActiveDocument (vlax-get-acad-object))
          )
        )

        (mapcar
          (function
            (lambda ( a / s n )
              (if (not (eq (setq s (vla-get-TextString a))
                           (setq n (vlax-invoke RegEx 'replace s "GF$1"))))

                (vla-put-TextString a n)
              )
            )
          )
          (vlax-invoke obj 'GetAttributes)
        )
      )

      (vla-delete ss)
      (LM:ReleaseObject RegEx)
    )
  )

  (princ)
)

;;------------------=={ Release Object }==--------------------;;
;;                                                            ;;
;;  Releases a VLA Object from memory via plentiful error     ;;
;;  trapping                                                  ;;
;;------------------------------------------------------------;;
;;  Author: Lee Mac, Copyright © 2010 - www.lee-mac.com       ;;
;;------------------------------------------------------------;;
;;  Arguments:                                                ;;
;;  obj - VLA Object to be released from memory               ;;
;;------------------------------------------------------------;;
;;  Returns:  T if Object Released, else nil                  ;;
;;------------------------------------------------------------;;

(defun LM:ReleaseObject ( obj ) (vl-load-com)
  ;; © Lee Mac 2010
  (and obj (eq 'VLA-OBJECT (type obj)) (not (vlax-object-released-p obj))
    (not
      (vl-catch-all-error-p
        (vl-catch-all-apply
          (function vlax-release-object) (list obj)
        )
      )
    )
  )
)


EDIT:  Had it the wrong way round ...
« Last Edit: December 08, 2010, 10:00:26 AM by Lee Mac »

GDF

  • Water Moccasin
  • Posts: 2081
Re: Replace part of attribute
« Reply #3 on: December 08, 2010, 11:42:48 AM »
Lee

I can make use of this.

Quick question, how would I update all patterns containing the following:
          (cons 'pattern  "^1-1-1-1(.*)")
          (cons 'pattern  "^2-1-1-1(.*)")
          (cons 'pattern  "^2-1-3-1(.*)")         
within one the same argument of the routine?
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #4 on: December 08, 2010, 11:50:22 AM »
I would say use:

Code: [Select]
"^[12]-1-[13]-1(.*)"
but this would include:

Code: [Select]
"^1-1-3-1(.*)"

among others.

GDF

  • Water Moccasin
  • Posts: 2081
Re: Replace part of attribute
« Reply #5 on: December 08, 2010, 12:09:15 PM »
Thanks Lee

I can use this routine to update my room name with floor finsh block. I would replace all of the floor finishes:
1-1-1-1, 2-1-3-1 and so on with a blank setting.

(cons 'pattern  "^[123456]-[123456]-[123456]-[123456](.*)")

(setq n (vlax-invoke RegEx 'replace s "$1"))))

This is really neat, a simple way to update all of the floor finishes with a unit or building plan with a (nil) finishes, but still keepig the block room names intact.

Thanks
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #6 on: December 08, 2010, 12:13:15 PM »
You're welcome Gary, glad you could get some use out of it  :-)

You could replace:

Code: [Select]
(cons 'pattern  "^[123456]-[123456]-[123456]-[123456](.*)")
With:

Code: [Select]
(cons 'pattern  "^[1-6]-[1-6]-[1-6]-[1-6](.*)")
to achieve the same result. 

Reference here  :-)

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #7 on: December 08, 2010, 12:15:53 PM »
I can use this routine to update my room name with floor finsh block. I would replace all of the floor finishes:
1-1-1-1, 2-1-3-1 and so on with a blank setting

By 'blanking' do you mean setting the attribute to an empty string?  ( "" )

If so, this could be done using wcmatch:

Code: [Select]
(if (wcmatch (vla-get-TextString a) "[1-6]-[1-6]-[1-6]-[1-6]*")
  (vla-put-TextString a "")
)

And you wouldn't need to go the RegExp route.

GDF

  • Water Moccasin
  • Posts: 2081
Re: Replace part of attribute
« Reply #8 on: December 08, 2010, 12:24:27 PM »
Yes, "" is my blank

How would you modify it to include all characters, for example:
1-1(2)-4-1
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #9 on: December 08, 2010, 12:29:17 PM »
I'm not sure what you mean by 'all characters', but maybe some combination of this?

Code: [Select]
(defun c:test ( / ss ) (vl-load-com)
  ;; © Lee Mac 2010

  (if (ssget "_X" '((0 . "INSERT") (66 . 1)))
    (progn     
      (vlax-for obj
        (setq ss
          (vla-get-ActiveSelectionSet
            (vla-get-ActiveDocument (vlax-get-acad-object))
          )
        )
        (mapcar
          (function
            (lambda ( a / s n )
              (if (wcmatch (vla-get-TextString a) "[color=red]#-*-#-#*[/color]")
                (vla-put-TextString a "")
              )
            )
          )
          (vlax-invoke obj 'GetAttributes)
        )
      )
      (vla-delete ss)
    )
  )
  (princ)
)

If need be, you could also add extra conditions on the attribute involving the Tag String.

GDF

  • Water Moccasin
  • Posts: 2081
Re: Replace part of attribute
« Reply #10 on: December 08, 2010, 12:32:27 PM »
Wow, now that is kool.

I should have said any character.
That did the job.

I have got to lean this vla-complictedstuff and wildcards.

Thanks again
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #11 on: December 08, 2010, 12:46:48 PM »
Thanks Gary :-)

The VLIDE has quite a good entry on wcmatch, certainly enough to help you understand my example above  :-)

ronjonp

  • Needs a day job
  • Posts: 7527
Re: Replace part of attribute
« Reply #12 on: December 08, 2010, 05:42:24 PM »
You're welcome Gary, glad you could get some use out of it  :-)

You could replace:

Code: [Select]
(cons 'pattern  "^[123456]-[123456]-[123456]-[123456](.*)")
With:

Code: [Select]
(cons 'pattern  "^[1-6]-[1-6]-[1-6]-[1-6](.*)")
to achieve the same result. 

Reference here  :-)

That RexExp is some cool schtuff  :-)

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #13 on: December 08, 2010, 05:56:33 PM »
That RexExp is some cool schtuff  :-)

Definitely  :-)

GDF

  • Water Moccasin
  • Posts: 2081
Re: Replace part of attribute
« Reply #14 on: December 08, 2010, 06:35:14 PM »
Thanks again you guys, I can make good use of this routine.

Modified it to cover many different combinations:

Code: [Select]
(defun ARCH:Finish (1st 2nd / *error* ss ) (vl-load-com)
  ;; © Lee Mac 2010 
  (defun *error* ( msg )
    (or (wcmatch (strcase msg) "*BREAK,*CANCEL*,*EXIT*")
        (princ (strcat "\n** Error: " msg " **")))
    (princ)
  )
  (if (ssget "_X" '((0 . "INSERT") (66 . 1)))
    (progn     
      (vlax-for obj
        (setq ss
          (vla-get-ActiveSelectionSet
            (vla-get-ActiveDocument (vlax-get-acad-object))
          )
        )
        (mapcar
          (function
            (lambda ( a / s n )
              (if (wcmatch (vla-get-TextString a) 1st)
                (vla-put-TextString a 2nd)
              )
            )
          )
          (vlax-invoke obj 'GetAttributes)
        )
      )
      (vla-delete ss)
    )
  )
  (princ)
)
(defun c:TileFinish ()(ARCH:Finish "2-1-1-1" "4-1-1-1"))
(defun c:VCTFinish ()(ARCH:Finish "4-1-1-1" "2-1-1-1"))
(defun c:HallcarpetFinish ()(ARCH:Finish "3-*-1-1" "1-1(4)-1-1"))
(defun c:HallconcreteFinish ()(ARCH:Finish "1-*-1-1" "3-1(4)-1-1"))
(defun c:RoomFinishNil ()(ARCH:Finish "#-*-#-#*" ""))
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #15 on: December 08, 2010, 06:39:37 PM »
Nice one Gary, I like it  :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: Replace part of attribute
« Reply #16 on: December 09, 2010, 08:29:17 AM »
Just being picky but s and n seem to be artifacts, no?

Code: [Select]
            (lambda ( a /[color=red] s n [/color])
              (if (wcmatch (vla-get-TextString a) 1st)
                (vla-put-TextString a 2nd)
              )
            )
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.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: Replace part of attribute
« Reply #17 on: December 09, 2010, 08:32:12 AM »
Just being picky but s and n seem to be artifacts, no?

Good catch Alan  :-)

Pad

  • Bull Frog
  • Posts: 342
Re: Replace part of attribute
« Reply #18 on: December 09, 2010, 10:55:16 AM »
I'm glad I saw this thread.
I've been having a problem blanking null value attributes since upgrading autocad.  In 2005 I could use find and then replace with nothing.
Since upgrading to 2009 you can't replace with nothing, a value has to be entered in the "replace with" box.

but
(defun c:nv ()(nullvalues "-999.00" ""))
works a treat thanks Lee and GDF!