Lisp to rename Layers, Blocks based on a CSV/TXT File

Lisp to rename Layers, Blocks based on a CSV/TXT File

braudpat
Mentor Mentor
3,072 Views
15 Replies
Message 1 of 16

Lisp to rename Layers, Blocks based on a CSV/TXT File

braudpat
Mentor
Mentor

Hello

 

I am looking for a Lisp Utility to rename Blocks or Layers based on a CSV/TXT File ... And I don't find it !?

 

<<< CSV/TXT File >>> Something like that ... 

old_1 ; new_a

bad 01 ; ok 101

charlie delta ; alpha bravo

etc ...

 

So the separator would be  ";" and the Old and/or New name could contain special caracters (french / german /etc) / blank , etc ...

 

So I see the Lsp Routine like :

 

1) Question : Rename Blocks OR Layers (Default = Block) : ?

2) Question : Ask for the CSV/TXT File ...

3) Begin process

Check that in the current CSV Line, there is NO forbidden caracters ! If YES warning (with old & new name) on the text screen ... Process next line ...

Test if the old name (Block OR Layer) exist ! If NO warning on the text screen with the old name ... Process next line ...

Test if the new name exist ! If YES warning on the text screen with the new name ... Process next line ...

If OK : rename (Block OR Layer) and print old & new name on the text screen 

4) Goto Step 3

 

And if possible at the end, 2 totals :

xx lines processed - xx Blocks/Layers renamed OK 

 

Do you see what I mean ?

 

Thanks in advance, THE HEALTH (Stay Safe), Regards, Patrice

 

 

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Accepted solutions (1)
3,073 Views
15 Replies
Replies (15)
Message 2 of 16

devitg
Advisor
Advisor

@braudpat 

 

For better understanding, and to get further help, please upload such before-sample.dwg, and AFTER-sample. DWG and

the csv. 

 

0 Likes
Message 3 of 16

braudpat
Mentor
Mentor

Hello

 

Please find attached a very OLD DWG to process ...

+ 2 TXT files : Rename Block & Rename Layers

 

Into the 2 TXT files, the last 2 lines are BAD ! And the 3 first are OK !

Unknown Layer / Block OR New Layer / Block already existing !


So the result would be :

-- 3 Renames OK for Blocks & Layers

-- 2 Renames BAD

 

The Blocks can be Classic or Dynamic ! I hope it is not a problem for renaming !?

Into my OLD DWG, there are ONLY Classic Blocks !

 

THANKS for your attention, THE HEALTH (Stay Safe), Regards, Patrice

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 4 of 16

Kent1Cooper
Consultant
Consultant

@braudpat wrote:

....

<<< CSV/TXT File >>> Something like that ... 

old_1 ; new_a

bad 01 ; ok 101

charlie delta ; alpha bravo

etc ...

 

So the separator would be  ";" ....


Maybe it doesn't matter, if you're not actually going to open the file in a spreadsheet program such as Excel, but .CSV stands for Comma-Separated Values -- shouldn't the separator be a comma?  If I change your BLOCK_RENAME.txt to BLOCK_RENAME.csv, and open it in Excel, this is what I get:
SemicolonSeparated.PNG

with all the content of each line within a single cell in the spreadsheet [i.e. the semicolons are not  separators, are visible, and don't  separate old and new into different cells].  But if I change the semicolons to commas, and do the same, I get what I would expect:

CommaSeparated.PNG

with the old and the new from each line in separate cells, and the commas not visible.

And if I start a blank Excel spreadsheet and fill in cells:

ExcelForCSV.PNG

and then go to Save it from there as a .CSV file, when I open that in a plain-text editor, it comes out with comma separators:
Old1,New1
Old2,New2
Old3,New3

So if you're generating a .CSV file from  a spreadsheet, you won't get semicolon separators.

 

As I say, it may not matter, since the procedure in AutoLisp would be the same whatever the separator character is, as long it's known what that is to be.  And semicolons are fine as long as the origin of the files is not  by saving to .CSV format from spreadsheet files.

Kent Cooper, AIA
Message 5 of 16

braudpat
Mentor
Mentor

Hello 

 

OK for the comma !

 

Regards, Patrice 

 

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 6 of 16

O_Eckmann
Mentor
Mentor

Hi @Kent1Cooper ,

 

It depends on your regional settings in Windows.

In my case, I use semicolon for separator of list

image.png

So when I export from Excel, CSV format use semicolon.

image.png

 

image.png

You could use this code to know windows settings for list's separator

(vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList")

 

Olivier

Olivier Eckmann

EESignature

0 Likes
Message 7 of 16

braudpat
Mentor
Mentor

Hello @O_Eckmann , @Kent1Cooper 

 

+1 with Olivier !

 

Semicolon is my prefered separator for list ...

 

So maybe an other question : Which separator comma or semi colon ?

 

Thanks in advance, Regards, Patrice

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 8 of 16

O_Eckmann
Mentor
Mentor

Hit Pat,

 

You could try with this code. CSV file must be stored in ANSI (with french accent it's OK)

oe:RenBlock function is inspired from this discussion : https://www.cadtutor.net/forum/topic/46160-rename-block/?tab=comments#comment-377278 

 

;; gc:str2lst
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaîne
;; sep : le séparateur
(defun gc:str2lst (str sep / pos)
  (if (setq pos (vl-string-search sep str))
    (cons (substr str 1 pos) (gc:str2lst (substr str (+ (strlen sep) pos 1)) sep))
    (list str)
  )
)


(defun oe:RenBlock (old new)
 (if
   (and
     (tblsearch "BLOCK" old)
     (not (tblsearch "BLOCK" new))
     (snvalid new)
   )
    (progn
       (if
         (vl-catch-all-error-p
           (vl-catch-all-apply
             'vla-put-name
             (list
               (vla-item (vla-get-blocks
                           (cond (*AcadDoc*)
                                 ((setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))))
                           )
                         )
                         old
               )
               new
             )
           )
         )
          (princ (strcat "\nBlock: " old " could not be renamed to: " new))
          (princ (strcat "\nBlock: " old " renamed to: " new))
      )
    )
  )
)

(defun C:RenBlock ( / sFile oFile sInfos)
  (if (and
	(setq sFile (getfiled "Select a CSV File" (getvar "DWGPREFIX") "CSV" 8))
	(setq sFile (findfile sFile))
      )
    (progn
      (setq sSep (vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList"))
      (setq oFile (open sFile "r"))
      (while (setq sLine (read-line oFile))
	(setq sInfos (gc:str2lst sLine sSep))
	(if (= (length sInfos) 2)
	  (oe:RenBlock (car sInfos) (cadr sInfos))
	)
      )
      (close oFile)
    )
  )
  (princ)
)

 

 

 

Olivier

Olivier Eckmann

EESignature

Message 9 of 16

braudpat
Mentor
Mentor

Hello @O_Eckmann 

 

1) Thanks for this "Block" routine !

 

2) Now waiting for the SAME routine on "Layers" ...

 

THE HEALTH (Stay Safe), Regards, Patrice

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 10 of 16

john.uhden
Mentor
Mentor

Hallo, Pat.

Your original instructions were almost perfect, so I was thinking of building your code, no matter what separator.

But I see that @O_Eckmann has donated half of what you want and appears perfectly capable of providing the other half.

Except (and your original post is off my screen now), but how does one differentiate a block name from a layer name?

Or is each pair of names to be applied to both blocks and layers?

Nevermind.  I looked back and found the "OR", meaning done separately, and edited this post.

Let me know if you don't get what you want.  I suggest that you name your CSV files uniquely so that one doesn't apply layer names to blocks and vice versa.

John F. Uhden

Message 11 of 16

braudpat
Mentor
Mentor

Hello @john.uhden 

 

1) Thanks for your attention !

 

2) Please I need a separate routine for Layers !
Because now I have a routine for Blocks from Olivier ...

 

3) So I imagine it will be easier to write ONLY for Layers !?

 

4) But if you want to write for Blocks and Layers, why not !?

With a question at beginning : Process Blocks or Layers (Default Block) ??

 

THE HEALTH (Stay Safe), Regards, Patrice

 

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 12 of 16

john.uhden
Mentor
Mentor

Hallo again, @braudpat .

I don't like intruding on others' work.  I am betting that @O_Eckmann will come through for you.  I'll be watching.

John F. Uhden

0 Likes
Message 13 of 16

O_Eckmann
Mentor
Mentor
Accepted solution

Hi @braudpat ,

 

I'm sure you could have done it.

;; gc:str2lst
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaîne
;; sep : le séparateur
(defun gc:str2lst (str sep / pos)
  (if (setq pos (vl-string-search sep str))
    (cons (substr str 1 pos) (gc:str2lst (substr str (+ (strlen sep) pos 1)) sep))
    (list str)
  )
)


(defun oe:RenBlock (old new)
 (if
   (and
     (tblsearch "BLOCK" old)
     (not (tblsearch "BLOCK" new))
     (snvalid new)
   )
    (progn
       (if
         (vl-catch-all-error-p
           (vl-catch-all-apply
             'vla-put-name
             (list
               (vla-item (vla-get-blocks
                           (cond (*AcadDoc*)
                                 ((setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))))
                           )
                         )
                         old
               )
               new
             )
           )
         )
          (princ (strcat "\nBlock: " old " could not be renamed to: " new))
          (princ (strcat "\nBlock: " old " renamed to: " new))
      )
    )
  )
)

(defun oe:RenLayer (old new)
 (if
   (and
     (tblsearch "LAYER" old)
     (not (tblsearch "LAYER" new))
     (snvalid new)
   )
    (progn
       (if
         (vl-catch-all-error-p
           (vl-catch-all-apply
             'vla-put-name
             (list
               (vla-item (vla-get-layers
                           (cond (*AcadDoc*)
                                 ((setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))))
                           )
                         )
                         old
               )
               new
             )
           )
         )
          (princ (strcat "\nLayer: " old " could not be renamed to: " new))
          (princ (strcat "\nLayer: " old " renamed to: " new))
      )
    )
  )
)

(defun C:RenBlock ( / sFile oFile sInfos)
  (if (and
	(setq sFile (getfiled "Select a block CSV File" (getvar "DWGPREFIX") "CSV" 8))
	(setq sFile (findfile sFile))
      )
    (progn
      (setq sSep (vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList"))
      (setq oFile (open sFile "r"))
      (while (setq sLine (read-line oFile))
	(setq sInfos (gc:str2lst sLine sSep))
	(if (= (length sInfos) 2)
	  (oe:RenBlock (car sInfos) (cadr sInfos))
	)
      )
      (close oFile)
    )
  )
  (princ)
)

(defun C:RenLayer ( / sFile oFile sInfos)
  (if (and
	(setq sFile (getfiled "Select a layer CSV File" (getvar "DWGPREFIX") "CSV" 8))
	(setq sFile (findfile sFile))
      )
    (progn
      (setq sSep (vl-registry-read "HKEY_CURRENT_USER\\Control Panel\\International" "sList"))
      (setq oFile (open sFile "r"))
      (while (setq sLine (read-line oFile))
	(setq sInfos (gc:str2lst sLine sSep))
	(if (= (length sInfos) 2)
	  (oe:RenLayer (car sInfos) (cadr sInfos))
	)
      )
      (close oFile)
    )
  )
  (princ)
)

 

Olivier

Olivier Eckmann

EESignature

Message 14 of 16

braudpat
Mentor
Mentor

Hello @O_Eckmann , @john.uhden , @Kent1Cooper 

 

THANKS for your effort & attention !

 

THE HEALTH (Stay Safe), Regards, Patrice (The Old French EE Froggy)

 

PS1 : I will retire the 30 September 2020 after 36 years of ACAD (beginning end of 1984 with ACAD R1.4), 26 years of ACAD MAP, 4 years of REVIT / InfraWorks, etc ... 

 

PS2: But I will remain active ! So you will have to support me !?

 

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes
Message 15 of 16

john.uhden
Mentor
Mentor

Just curious...

In what way would a EE use AutoCAD Map?

Hmm, maybe for a regional or country-wide grid?

John F. Uhden

0 Likes
Message 16 of 16

braudpat
Mentor
Mentor

Hello @john.uhden 

 

Why ACAD MAP ... Because : Maps, GIS, Cartography, Geomatic, etc ...

 

AND because I like beautiful Maps ... Especially Old Maps ...

 

See the beautiful Map attached ... As a sailor I hope you will appreciate !?

 

THE HEALTH (Stay Safe), Regards, Patrice

 

Manche__Van_Loon_1753.jpg

Patrice ( Supporting Troops ) - Autodesk Expert Elite
If you are happy with my answer please mark "Accept as Solution" and if very happy please give me a Kudos (Felicitations) - Thanks

Patrice BRAUD

EESignature


0 Likes