Layer Import from CSV - evaulate if layer exists first?

Layer Import from CSV - evaulate if layer exists first?

Anonymous
Not applicable
7,434 Views
19 Replies
Message 1 of 20

Layer Import from CSV - evaulate if layer exists first?

Anonymous
Not applicable

Hi All -

 

I have a Layer Import routine that I borrowed from the brilliant Lee Mac -- where you import Layer definitions into your drawing from a CSV file. It works beautifully - EXCEPT that if any of the layer properties are modified (color, linetype, etc.) after the layer is imported from the CSV, and you re-import the layers into your drawing again from the CSV, it resets them back to their original properties as defined in the CSV.

 

I would like the command to function such that if it finds that the layer name already exists in the drawing, then it skips over importing it.

 

I thought the code I borrowed from Lee Mac was doing that.... the code is pasted below with the section I thought would have been controlling the feature I was looking for.

 

Any advice or direction would be much appreciated.

 

Thanks!

 

 MRG

 

(defun RM:CSV->Layers  (path / f *error* extract trim activeDoc l
                        layerTable layerName layerItem layerDescription
                        layerColor layerLinetype layerLineweight
                        layerPlottable layerFreeze)
  ;; © RenderMan 2011, CADTutor.net
  ;; Exampe: (RM:CSV->Layers "Z:\\my_layers_folder\\my_layers.csv")
  (vl-load-com)
  (if (and (findfile path)
           (setq f (open path "r")))
    (progn
 
      ;; Error handler
      (defun *error*  (msg)
        (cond
          ((not msg))                                                   ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** "))))                 ; Fatal error, display it
        (if f
          (close f))
        (princ))
 
      ;; Line extraction sub-function
      (defun extract  (l /)
        (substr l 1 (vl-string-search "," l)))
 
      ;; Line trim sub-function
      (defun trim  (v /)
        (vl-string-subst "" (strcat v ",") l))
 
      ;; Main code
      (vla-startundomark
        (cond (activeDoc)
              ((setq activeDoc
                      (vla-get-activedocument
                        (vlax-get-acad-object))))))
      (read-line f)                                                     ; <- Skip first line (headers)
      (setq layerTable (vla-get-layers activeDoc))
 
      ;; Linetype check
      ;; <- Add linetype import code here, to avoid errors
 
      (while (/= nil (setq l (read-line f)))
        (progn
 
          ;; Layer check
          (if (not (tblsearch "layer" (setq layerName (extract l))))
             (setq layerItem (vla-add layerTable layerName))
             (setq layerItem (vla-item layerTable layerName)))
 
          ;; Layer settings
          (setq l (trim layerName))
          (vla-put-description
            layerItem
            (setq layerDescription (extract l)))
          (setq l (trim layerDescription))
          (if (/= 7 (setq layerColor (extract l)))
            (vla-put-color layerItem layerColor))
          (setq l (trim layerColor))
          (vla-put-linetype layerItem (setq layerLinetype (extract l)))
          (setq l (trim layerLinetype))
          (if (= "BYLAYER" (strcase (setq layerLineweight (extract l))))
            (vla-put-lineweight layerItem aclnwtbylayer))
          (setq l (trim layerLineweight))
          (if (/= "YES" (strcase (setq layerPlottable (extract l))))
            (vla-put-plottable layerItem :vlax-false))
          (setq l (trim layerPlottable))
          (if (/= "NO" (strcase (setq layerFreeze (extract l))))
            (vla-put-freeze layerItem :vlax-true))))
      (close f)
      (vla-endundomark activeDoc)))
  (princ))
0 Likes
Accepted solutions (1)
7,435 Views
19 Replies
Replies (19)
Message 2 of 20

hmsilva
Mentor
Mentor
Accepted solution

Hi  MRG,

 

try the RenderMan's quickly modified code:

@BlackBox_

I hope you do not mind...

 

(defun RM:CSV->Layers (path           /              f              *error*        extract        trim
                       activeDoc      l              layerTable     layerName      layerItem      layerDescription
                       layerColor     layerLinetype  layerLineweight               layerPlottable layerFreeze
                      )
  ;; © RenderMan 2011, CADTutor.net
  ;; Exampe: (RM:CSV->Layers "Z:\\my_layers_folder\\my_layers.csv")
  (vl-load-com)
  (if (and (findfile path)
           (setq f (open path "r"))
      )
    (progn

      ;; Error handler
      (defun *error* (msg)
        (cond
          ((not msg)) ; Normal exit
          ((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit)
          ((princ (strcat "\n** Error: " msg " ** ")))
        ) ; Fatal error, display it
        (if f
          (close f)
        )
        (princ)
      )

      ;; Line extraction sub-function
      (defun extract (l /)
        (substr l 1 (vl-string-search "," l))
      )

      ;; Line trim sub-function
      (defun trim (v /)
        (vl-string-subst "" (strcat v ",") l)
      )

      ;; Main code
      (vla-startundomark
        (cond (activeDoc)
              ((setq activeDoc
                      (vla-get-activedocument
                        (vlax-get-acad-object)
                      )
               )
              )
        )
      )
      (read-line f) ; <- Skip first line (headers)
      (setq layerTable (vla-get-layers activeDoc))

      ;; Linetype check
      ;; <- Add linetype import code here, to avoid errors

      (while (/= nil (setq l (read-line f)))
          ;(progn

        ;; Layer check
          ;(if (not (tblsearch "layer" (setq layerName (extract l))))
        (cond ((not (tblsearch "layer" (setq layerName (extract l))))
               (setq layerItem (vla-add layerTable layerName))
          ;(setq layerItem (vla-item layerTable layerName)))

               ;; Layer settings
               (setq l (trim layerName))
               (vla-put-description
                 layerItem
                 (setq layerDescription (extract l))
               )
               (setq l (trim layerDescription))
               (if (/= 7 (setq layerColor (extract l)))
                 (vla-put-color layerItem layerColor)
               )
               (setq l (trim layerColor))
               (vla-put-linetype layerItem (setq layerLinetype (extract l)))
               (setq l (trim layerLinetype))
               (if (= "BYLAYER" (strcase (setq layerLineweight (extract l))))
                 (vla-put-lineweight layerItem aclnwtbylayer)
               )
               (setq l (trim layerLineweight))
               (if (/= "YES" (strcase (setq layerPlottable (extract l))))
                 (vla-put-plottable layerItem :vlax-false)
               )
               (setq l (trim layerPlottable))
               (if (/= "NO" (strcase (setq layerFreeze (extract l))))
                 (vla-put-freeze layerItem :vlax-true)
               )
              )
        )
      )
      (close f)
      (vla-endundomark activeDoc)
    )
  )
  (princ)
)

 

 

Hope this helps,
Henrique

EESignature

Message 3 of 20

BlackBox_
Advisor
Advisor
@hmsilva - Not at all, my friend. *tips hat*

@Anonymous - Not sure that Lee would appreciate the demotion, but I'm glad that you found my code useful. 😉 Haha


Cheers

BlackBox_ (fka RenderMan)


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

Message 4 of 20

Anonymous
Not applicable

@BlackBox_ - my sincerest apologies!   Smiley Embarassed

 

I think I was a bit tangled up in the thread from which I swiped your (awesome) code... and I think I had Lee Mac's Import Linetype bundled in with the routine - so sorry for the mixup! 🙂

 

MRG

0 Likes
Message 5 of 20

Anonymous
Not applicable

Thanks so much @hmsilva

 

I tested it our and it works perfectly! I see that you added a conditional function in there and changed 

 

(vla-item layerTable layerName)

to

(vla-add layerTable layerName)

 

Thanks for commenting out the original code so I could see how you approached it. I am alot more conversant in AutoLISP than anything else so I definintely need to study up a bit more vigorously before I start tweaking code 🙂

 

I also like the ability to reset the layers back to their standard settings, so I think I'll keep @BlackBox_ 's original code and give the user the ability to overwrite and reset any changes to the layers if they need to go that route or just add any layers to the existing set that they may have purged out or deleted.

 

Thanks again to you both!

 

MRG

0 Likes
Message 6 of 20

hmsilva
Mentor
Mentor

You're welcome, muddyrunnergirl
Glad I could help

Henrique

EESignature

0 Likes
Message 7 of 20

BlackBox_
Advisor
Advisor

No worries, @Anonymous; I'm flattered that you found the (admittedly old) code useful.

 

A quick aside regarding the Add() and Item() Methods as applied to the LayerTable; The Item() Method only returns a valid LayerTableRecord Object, otherwise error, whereas the Add() Method gets-or-creates said LayerTableRecord Object. So be sure to simplify your/my code accordingly, or as you please.

 

Cheers


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

0 Likes
Message 8 of 20

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

I have a Layer Import routine... where you import Layer definitions into your drawing from a CSV file. It works beautifully - EXCEPT that if any of the layer properties are modified (color, linetype, etc.) after the layer is imported from the CSV, and you re-import the layers into your drawing again from the CSV, it resets them back to their original properties as defined in the CSV.

 

I would like the command to function such that if it finds that the layer name already exists in the drawing, then it skips over importing it.

.... 


Another way you could do that would be to have a drawing containing all those standard Layers but with nothing actually drawn in it, and simply Insert it into the current drawing [pre-exploded so you won't be asked whether you want to re-define it if you do it more than once in the same drawing].  If any of the same Layer names already exist in the current drawing, their colors, linetypes, etc. will not be affected by those properties of the same Layers in the source drawing, without any need to check whether they exist yet, but any Layers in the source drawing that do not already exist will come into the current drawing with their standard definitions.  Any changes to your standard Layer collection would be made by simply making them in that source drawing, rather than by editing a CSV file.  No code is necessary unless you choose to make a simple macro or define a simple command to perform that Insertion.  A single Insert command is all it takes, no matter how many Layers are involved -- no stepping through a whole series of CSV data.

Kent Cooper, AIA
Message 9 of 20

Anonymous
Not applicable

Hi Kent -

Thanks for you input-- actually, that's the way that my company has done it for the past 20+ years.

 

We are currently overhauling our layer standards and are tweaking them pretty frequently. The CSV(s) will serve a two-fold purpose - in addition to being the main layer definition source for each of our firm's disciplines, I can also use it to create a PDF for distribution to keep the teams updated to what is happening with our layers in a table format. (read: I'm too lazy to generate a secondary reference document for now - lol).

 

Once our layer updates have settled down and we are pretty dialed in, I plan to revert back to using a DWG to hold our layer definitions and serve as our template(s).... I like using the DWG Insert method because I get nervous sometimes that if things are done too programmatically then future generations at my firm may have to re-invent the wheel if they don't know too much LISP or other customization.

 

Also, having the "Layer Reset" feature via @BlackBox_ 's original CSV Layer Import method will help during our transition as we convert legacy drawings that are called back into action that have layers whose names haven't changed, but whose colors have been updated per the new standards and we want to update the old drawings to match our new settings.

 

So yes, you are totally on point (as usual) - once we are out of the woods with this standards update, I'll be doing just as you suggest. 🙂

 

MRG

0 Likes
Message 10 of 20

BlackBox_
Advisor
Advisor

FWIW - Just a bit of back-story:

 

This CSV utility was originally developed for similar reasons to what @Anonymous mentions - as an interim utility amid major standards overhaul - which, for us at the time, was when switching from Land Desktop to Civil 3D, following a corporate acquisition.

 

We did find later, that despite using the same layer names, we ended up wanting different colors (CTB based at the time) for Plan, Profile, Cross Section, etc., thus we ended up having a CSV file that corresponded to each allowing us to maintain once, standardize all on the fly (for those with modify permissions, of course).

 

Cheers


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

Message 11 of 20

arkelec
Collaborator
Collaborator

Hi, could you give me some tips on how to run your routine from AutoCAD?

 

I'm not experienced with LISP so can't fathom which bit to modify.  Or is the above code run from another routine?

 

Thanks anyway.

 

 

0 Likes
Message 12 of 20

arkelec
Collaborator
Collaborator

Update:

 

Can't for the life of me see how to edit my earlier post but for the benefit of anyone coming to this thread seeking an a solution..........

 

I found the answer on the CAD Tutor forum.

 

Add the following code (modified to suit the .csv file name & path) to the top of the previously posted code:

 

(defun c:ImportCSV (/) (RM:CSV->Layers "Z:\\my_layers_folder\\my_layers.csv")  (princ))

 

.....where "ImportCSV" is the name of the lsp file (i.e. ImportCSV.lsp).

 

 

Hell, I wish I'd learned LISP.

 

And thanks to all the peopes who post this stuff for the benefit of the likes of me, I love you all 🙂

 

0 Likes
Message 13 of 20

arkelec
Collaborator
Collaborator

Erm, there is an error on the line of code I posted above.  Replace "ImportCSV" with "RM" & make the file RM.lsp

 

Hope that covers it.

0 Likes
Message 14 of 20

BlackBox_
Advisor
Advisor

Hi @arkelec - 

 

Sorry for the delayed response; I don't have the free time to participate in the forums I used to, and just happened to stumble across the email notifications.

 

 

 

That said, the code here and linked at CADTutor can load any valid .CSV file path/name; they need not be named something specifc (i.e., oldLayers.csv, newLayers.csv, electric.csv, sanitary.csv, drainage.csv, etc.).

 

For this 'mechanism' to work, you need both the supported .CSV format, the RM:CSV->Layers sub-function must be loaded (once per drawing), and then any subsequent calls to same (supplying valid .CSV file path/name) will work.

 

HTH


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

0 Likes
Message 15 of 20

Anonymous
Not applicable

I am trying really hard, but I just can't get this to work for me. I have about 180 layers in a CSV file that I'm trying to import into AutoCAD. I copied the LSP info noted above into an LSP file, set the file in the search path, loaded the LSP using APPLOAD command, and it doesn't do anything. My file name is mylayers.csv.

 

I can't figure out exactly where to put  the file name and path into the LSP file. Or if it even belongs in it. There were two different LSP routines listed in this thread, then another one line modification to be added. I'm just lost.

 

Does anyone have a particular tip that could unlock the secret? It seems really easy.

0 Likes
Message 16 of 20

BlackBox_
Advisor
Advisor

Nothing secret about it - there's just some basics that have to be done; once you learn those the rest come easy. 

 

 

 

There are only a few key components... There's the "RM:CSV->Layers" sub-function (the code that does the work), there's the "ImportCSV" custom command (the single-line code that 'loads' a specific .CSV file), and then there's getting it all loaded for you to use.

 

 

 

Copy the larger "RM:CSV->Layers" code snippet from the first page of this thread, and saved it to a .LSP file.

 

Next copy the "ImportCSV" code, and place it at the bottom of the same .LSP file (and save, of course).

 

Now load that LISP routine - you mentioned AppLoad, I prefer to use AcadDoc.lsp - loading this LISP routine with both code snippets in it loads both the custom command, and the dependent sub-function the custom command uses.

 

Once loaded (in any way you choose), you simply invoke the "ImportCSV" custom command at the command line, and done.

 

 

 

HTH


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

Message 17 of 20

Anonymous
Not applicable

Wow thank you for the clear explanation!!!  I got everything done correctly, and the IMPORTCSV even appears as a suggestion command when I start typing it in on the command line.

 

It looks like the routine loads up like its supposed to except I get this...error: vl-load-com not supported on  "Mac OS X Version 10.11 (x86_64)"

 

This looks like really bad news, it may not work on AutoCAD for MAC 2016?  I found some info saying that the MAC versions don't support Visual LISP. Man, this is bad news. 

0 Likes
Message 18 of 20

BlackBox_
Advisor
Advisor

Bummer - while I'm glad that I was able to help you get to this point, had I known you were using Mac I would have approached this differently. 

 

That said, while I work in Win10, I'm confident that I can refactor this to work with Mac's (alveit limited) AutoLISP API... And if not, I *may* have some tricks up my sleeve. 

 

as an example of what can still be done using LISP for Mac (which also works on Win), here's a routine that adds a prefix to all LayerTableRecords (that are not "0" or "Defpoints", that is):

 

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/batch-rename-layer-lisp-for-autocad-...

 

 

 

Cheers


"How we think determines what we do, and what we do determines what we get."

Chris (BlackBox) Bradley
Managing Partner / Developer / Civil Designer
Quux Software | Sincpac C3D | Style Explorer

0 Likes
Message 19 of 20

Anonymous
Not applicable

I am essentially trying to get the AIA layer standards set up in a drawing template. I'm a small outfit trying to get on board with basic current standards and I can't believe how hard it is to get this accomplished. I've spent hours searching.

 

Why would national AutoCAD layer standards not be something that's readily available to anyone who needs them? How else does it become a standard if its so hard to get it into an AutoCAD drawing template? Without the good will of someone like you on the internet, it would take days to enter them all in by hand and check/double check them for accuracy.

0 Likes
Message 20 of 20

jkreger5P63A
Explorer
Explorer

Do you have an example of the CSV file you were using along with this LISP?

0 Likes