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

Rename Layers with _ to -

13 REPLIES 13
Reply
Message 1 of 14
kevincwalina
3049 Views, 13 Replies

Rename Layers with _ to -

Hello,

    Our company uses underscores to seperate items in layer names. A common layer name might be something like 2D_STAIRS_HANDRAIL  For a project we are working on, we need to be able to batch rename these layers to replace the _ with a -   So the new layer name will be 2D-STAIRS-HANDRAIL. I thought I might be able to use the rename command and just put *_* in for the existing layers, and then put in *-* for the rename to field, but this does not work so I am hoping someone can offer a lisp or script or something that might help out.

 

Thanks!

-Kevin

13 REPLIES 13
Message 2 of 14
Kent1Cooper
in reply to: kevincwalina


@kevincwalina wrote:

..... A common layer name might be something like 2D_STAIRS_HANDRAIL  For a project we are working on, we need to be able to batch rename these layers to replace the _ with a -   So the new layer name will be 2D-STAIRS-HANDRAIL. ....


This does that, in limited testing:
 

(defun C:LNUH (/ lay layobj); = Layer Name Underscores to Hyphens

  (vl-load-com)
  (while (setq lay (tblnext "layer" (not lay)))
    (vla-put-Name
      (setq layobj (vlax-ename->vla-object (tblobjname "layer" (cdr (assoc 2 lay)))))
      (vl-string-translate "_" "-" (vla-get-Name layobj))
    ); vla-put-Name
  ); while
); defun

 

EDIT:  Or, this:
 

(defun C:LNUH (/ lay laylist)
  (vl-load-com)
  (tblsearch "layer" "0" T)
  (foreach x
    (while (setq lay (cdadr (tblnext "layer")))
      (setq laylist (cons lay laylist))
    )
    (command "_.rename" "_Layer" x (vl-string-translate "_" "-" x))
  )
)

Kent Cooper, AIA
Message 3 of 14
kevincwalina
in reply to: Kent1Cooper

Thanks Kent,   I tied it but its givving me the following error.

 

; error: no function definition: VLAX-ENAME->VLA-OBJECT

 

not sure what that means

 

-Kevin

Message 4 of 14
Kent1Cooper
in reply to: kevincwalina


@kevincwalina wrote:

...its givving me the following error.

 

; error: no function definition: VLAX-ENAME->VLA-OBJECT

....


You must have downloaded it before I got back in and edited it to add (vl-load-com) at the beginning.  Try again.

Kent Cooper, AIA
Message 5 of 14
kevincwalina
in reply to: Kent1Cooper

I did, I got excited...This toatly works. Thank you so much, this is going to save us so much time!

 

-Kevin

Message 6 of 14
kevincwalina
in reply to: Kent1Cooper

ok, Everyone if our office is really excited about this lisp so much that the project manager on another job is asking we can add some more functionality to it. For his project he has to bind/bind the drawings (Horriable I know) So I duplicated your code and switched out the "_" "-" for "$0$" "-" which works great. It does stall out on the last layer to be processed I think my hack was not the most eligent. 

 

He also wants to be able to add a prefix to all the layer names. and am not sure how to go about that. Thats something I know I can do with the rename command so I'm sure there must be away to add it into the lisp, just not sure how. 

 

Thanks,

Kevin

 

This is my hack to get rid of the $0$'s in his bound drawings.

 

(defun C:LNUH (/ lay laylist)
(vl-load-com)
(tblsearch "layer" "0" T)
(foreach x
(while (setq lay (cdadr (tblnext "layer")))
(setq laylist (cons lay laylist))
)
(command "_.rename" "_Layer" x (vl-string-translate "_" "-" x))
)

(vl-load-com)
(tblsearch "layer" "0" T)
(foreach x
(while (setq lay (cdadr (tblnext "layer")))
(setq laylist (cons lay laylist))
)
(command "_.rename" "_Layer" x (vl-string-translate "$0$" "-" x))
)


)

Message 7 of 14
Kent1Cooper
in reply to: kevincwalina


@kevincwalina wrote:

....add some more functionality to it. For his project he has to bind/bind the drawings (Horriable I know) So I duplicated your code and switched out the "_" "-" for "$0$" "-" which works great. ....

  

He also wants to be able to add a prefix to all the layer names. .... 

....


I expect that translation isn't working quite as great as you think, if you look closely at the result.  It is probably replacing each $ with -, but leaving the 0 between two of those.  That's because of the way (vl-string-translate) works, wanting a set of characters and another equal-length set of characters to replace those with [see the AutoLISP Reference entry about it].  You want (vl-string-stubst) instead, for that aspect of bound Layer names, provided binding doesn't put more than one "$0$" in a Layer name [we'll hope there aren't already bound Layers in the Xref you're binding], and providing none of them include "$1$" etc., instead.
 

It should be doable in just one pass through the Layer names.  Try something like this [untested this time]:
 

(defun C:ProbablyOughtToGetADifferentName (/ lay laylist)
  (vl-load-com)
  (tblsearch "layer" "0" T)
  (foreach x
    (while (setq lay (cdadr (tblnext "layer")))
      (setq laylist (cons lay laylist))
    )
    (command

      "_.rename" "_Layer" x

      (strcat

        "YourLayerNamePrefix"

        (vl-string-subst

          "-" "$0$"

          (vl-string-translate "_" "-" x)

        ); vl-string-subst
      ); strcat

    ); command

  ); foreach

); defun

 

But if you have a lot of Layers, you may find that the approach that doesn't use (command) is detectably faster:

 

(defun C:WhateverYouWantToCallThis (/ lay layobj)

  (vl-load-com)
  (tblsearch "layer" "0" T)

  (while (setq lay (tblnext "layer" (not lay)))
    (vla-put-Name
      (setq layobj (vlax-ename->vla-object (tblobjname "layer" (cdr (assoc 2 lay)))))

      (strcat

        "YourLayerNamePrefix"

        (vl-string-subst

          "-" "$0$"

          (vl-string-translate "_" "-" (vla-get-Name layobj))

        ); vl-string-subst
      ); strcat

    ); vla-put-Name
  ); while
); defun

 

All of this assumes that none of the resultant names are the same as any Layers already in the drawing.

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

Thanks! Thats great. 

 

Do you have any sugestions for books or websites I should check out to learn how to write these? I would love to really understand all thats going on so I can write my own lisp, but not sure where to start. 

 

-Kevin

Message 9 of 14
Kent1Cooper
in reply to: kevincwalina


@kevincwalina wrote:

.... 

Do you have any sugestions for books or websites I should check out to learn how to write these? I would love to really understand all thats going on so I can write my own lisp, but not sure where to start. 

....


That question has been asked many times here -- search for terms like Books or Resources or Learn.  Personally, I've learned most of what I know from topics here, and from poking around the AutoLISP Reference, but others have suggested lots of books and other websites.

Kent Cooper, AIA
Message 10 of 14
Ghostship
in reply to: Kent1Cooper

Can I ressurect this thread?

 

This lisp routine is great but I've encountered two problems:

 

It seems to choke on the bar in xref layer names.

It fails if the conversion from underscore to hyphen would create duplicate layer name.

 

Ideally we would use this to clean up user naming habits.  There is already a great uppercase/lowercase one.  Now if we can sort out hyphen underscore.

 

I was thinking that it would be great to be able to append the layer name with something like -222 or "DUPLICATE" if the resulting layer could create a duplicate name.

 

I'm not even sure if that's possible.

Message 11 of 14
Kent1Cooper
in reply to: Ghostship


@Ghostship wrote:

.... 

It seems to choke on the bar in xref layer names.

It fails if the conversion from underscore to hyphen would create duplicate layer name.

 

Ideally we would use this to clean up user naming habits.  ....


I assume from "clean up" in your description that you do not require the Prefix element in the previous version.  [If you do, replace the word new at the end of the (vla-put-name) function with:  (strcat "YourLayerNamePrefix" new).]

 

Try something like this [untested]:

 

(defun C:WhateverYouWantToCallThis (/ lay layname base new n)
  (vl-load-com)
  (tblsearch "layer" "0" T)
  (while (setq lay (tblnext "layer" (not lay))); still another Layer left
    (if (not (wcmatch (setq layname (cdr (assoc 2 lay))) "*|*")); not Xref-dependent
      (progn ; then -- proceed
        (setq
          base ; first shot at new name
            (vl-string-subst
              "-" "$0$"
              (vl-string-translate "_" "-" layname)
            ); vl-string-subst
          new base
          n 0 ; for incremented suffix on duplicate name if needed
        ); setq
        (while (tblsearch "layer" new); already a Layer with that name?
          (setq new (strcat base "-" (itoa (setq n (1+ n)))))
            ; add -1, or if that's also already used, -2, etc.
        ); while -- when it gets to an as-yet-unused name:
        (vla-put-Name (vlax-ename->vla-object (tblobjname "layer" layname)) new)
      ); progn
    ); if
  ); while
); defun

 

Also, if just cleaning up non-standard User naming habits, you may not need the deal-with-"$0$" part from the earlier version.  If you keep that, the same caveat applies -- if you've done multiple bindings that result in names with $1$, $2$, etc. in them, this won't catch those, but it could be made to if necessary.

Kent Cooper, AIA
Message 12 of 14
Ghostship
in reply to: Kent1Cooper

Wow thanks for that.

 

Can the part for bound layers exist and the lisp routine still be used in a drawing without bound layers?  If so, it's only great to keep it.

 

Regardless, I get

 

; error: Automation Error. Invalid input.

 

Whereas with the old ones up thread, I get, error - duplicate record name.

 

We're on AutoCAD 2017 in windows 10 if that matters.

Message 13 of 14
Kent1Cooper
in reply to: Ghostship


@Ghostship wrote:

.... 

Can the part for bound layers exist and the lisp routine still be used in a drawing without bound layers?  If so, it's only great to keep it.

 

Regardless, I get

 

; error: Automation Error. Invalid input.

....


Well, duh on me -- that's what I get for not testing it.  I think the problem must be that it tries to do its thing to all Layers [so far excepting only Xref-dependent ones], and therefore when it looks at Layer 0, the string substitution doesn't find any bound-layer characters or underscores to replace, so it keeps the "0" name, and since there's already a Layer called that, it goes for 0-1.  You can't rename Layer 0, which I suspect is the cause of the error.

 

Add this check for whether a Layer name has any underscores or a bound-Layer indicator in it:

....

    (if
      (and
        (not (wcmatch (setq layname (cdr (assoc 2 lay))) "*|*")); not Xref-dependent
        (or
          (wcmatch layname "*_*"); name contains underscore(s)
          (wcmatch layname "*$0$*"); bound Layer
        ); or

      ); and
      (progn ; then -- proceed

....

 

[And I did test it, however lightly.]

 

You can leave the $0$ thing in there even if you don't always have bound Layers -- the part that substitutes for that will just return the same string unaltered if it doesn't contain that.  The same caveat applies about whether there might be $1$ [etc.] Layers.

Kent Cooper, AIA
Message 14 of 14
Kent1Cooper
in reply to: Kent1Cooper


@Kent1Cooper wrote:

....

Add this check for whether a Layer name has any underscores or a bound-Layer indicator in it:

....


That's still worthwhile to keep it from doing work on Layer names that don't need it, but now I realize something else about the Layer-0 problem.  This first operational line:

 

  (tblsearch "layer" "0" T)

 

was [if I recall correctly] put in to make the second line:

  (while (setq lay (tblnext "layer" (not lay))); still another Layer left

 

start at the beginning [in case there had been some other (tblsearch)/(tblnext) functions putting the place it looks further down the list], but with the Layer after 0 [so it won't try to Rename that].  BUT given that intent, the second line should not have the (not lay) part in it, but should be just:

 

  (while (setq lay (tblnext "layer")); still another Layer left

 

which would start with the subsequent Layer as intended.  Putting the (not lay) thing in there is from some other routine where what's wanted is to force the search to start at the beginning of the Layer table on the first look [if the variable hasn't yet been established, it returns T to do that -- read about (tblnext) in Help].  So that counteracts the first line's intent, because it takes it back to starting at Layer 0 anyway.

 

I expect that omitting the (not lay) would have fixed the error problem in earlier versions.  But with the content check in place, it could be left in there, because there's no reason for it not to start with Layer 0, and that first line can be omitted, because (tblnext) is going to start at the beginning anyway.

Kent Cooper, AIA

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost