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

Layer extract

24 REPLIES 24
Reply
Message 1 of 25
egutierrez.cr
6994 Views, 24 Replies

Layer extract

Hello!

 

This is the situation: I have a drawing with some layer and I need to extract each one and save it as a dwg or dxf file. Is there any possibility to do it by LISP? My intention is to do it automatically.

 

Thanks,

 

Esteban G.

24 REPLIES 24
Message 2 of 25
Kent1Cooper
in reply to: egutierrez.cr


@egutierrez.cr wrote:

.... I have a drawing with some layer and I need to extract each one and save it as a dwg or dxf file. ....


This seems to do that, in limited testing under model-space-only circumstances:

 

(defun C:DPL (/ lay laylist base locked); = Drawings Per Layer
;;  Makes a separate drawing of the contents of each Layer in the
;;  current drawing, with file names constructed thus:
;;  CurrentDrive:\CurrentFilePath\CurrentDrawing_Layer.dwg
;;  *Does* take things on Layers that are Off or Frozen, and they
;;  will be so in resulting drawings.  Things on Locked Layers
;;  will also be taken, but those Layers will *not* be Locked in
;;  resulting drawings.
;;  Kent Cooper, January 2011
  (while (setq lay (cdadr (tblnext "layer" (not lay))))
    (setq laylist (cons lay laylist))
  ); end while
  (setq base
    (strcat
      (getvar 'dwgprefix)
      (substr (getvar 'dwgname) 1 (- (strlen (getvar 'dwgname)) 4))
      "_"
    ); end strcat
  ); end setq
  (foreach lay laylist
    (if (= (logand 4 (cdr (assoc 70 (tblsearch "layer" lay)))) 4); locked
      (progn
        (command "_.layer" "_unlock" lay "")
        (setq locked T)
      ); end progn
    ); end if
    (if
      (setq laycont (ssget "_X" (list (cons 8 lay))))
      (command
        "_.wblock"
        (strcat base lay)
        ""
        (getvar 'insbase)
        laycont ""
        "_.oops"
      ); end command
    ); end if
    (if locked
      (progn
        (command "_.layer" "_lock" lay "")
        (setq locked nil)
      ); end progn
    ); end if
  ); end foreach
); end defun

The situation with Locked Layers is more complicated than I had expected.  I was pleasantly surprised that it would take things on Layers that are Off or Frozen, without needing to turn On or Thaw those Layers.  But it wouldn't take things on Locked Layers without Unlocking them.

 

At first, I tried simply unlocking/thawing/turning on each Layer to work with it, to avoid having to check its status, and then using Layerp afterwards to put it back as it was.  But Layerp wasn't doing what I expected, but rather seems to take back the previous Layer situation from outside the routine.  [It makes me want to test other routines I have that may use Layerp -- I hope I wasn't just doing something wrong, but I tried several times.]

 

The fact that it doesn't care about Off or Frozen Layers is nice in that those Layers will also be in the same state in the drawings that are extracted.  But I couldn't figure out a way to have Locked Layers be that way in the extracted drawings.

 

Be aware that Blocks will be taken into the drawing for the Layer they are inserted on, not for the Layer(s) of any of the Block-definition contents.  So any resulting drawing extracted from a Layer that has inserted Blocks could have content on Layers other than its own.

 

I did not test it in a drawing with Layouts, but only in a plain-and-simple drawing in Model Space.

Kent Cooper, AIA
Message 3 of 25

Kent,

 

I have been testing your LISP routine with drawings like the attached (if you want to try!!), and it worked PERFECTLY. This routine take each layer in a drawing and save it as a dwg file.

 

You are a genious!!! thanks a lot once again.

 

Best,

 

Esteban G.

Message 4 of 25

Kent,

 

I`ve been trying to edit your LISP routine to get layers in dxf format (you made it for dwg format). I have made this changes:

  1. 'dwgprefix to 'dxfprefix 
  2. 'dwgprefix to '*.dxfprefix
  3. 'dwgprefix yo 'DXF (*.dxf)prefix

And tha same for 'dwgname, but did not worked.

 

Original LISP

(defun C:SL (/ lay laylist base locked); = Drawings Per Layer
;;  Makes a separate drawing of the contents of each Layer in the
;;  current drawing, with file names constructed thus:
;;  CurrentDrive:\CurrentFilePath\CurrentDrawing_Layer?.dwg
;;  *Does* take things on Layers that are Off or Frozen, and they
;;  will be so in resulting drawings.  Things on Locked Layers
;;  will also be taken, but those Layers will *not* be Locked in
;;  resulting drawings.
;;  Kent Cooper, January 2011


  (while (setq lay (cdadr (tblnext "layer" (not lay))))
    (setq laylist (cons lay laylist))
  ); end while
  (setq base
    (strcat
      (getvar 'dwgprefix)
      (substr (getvar 'dwgname) 1 (- (strlen (getvar 'dwgname)) 4))
      "_"
    ); end strcat
  ); end setq
  (foreach lay laylist
    (if (= (logand 4 (cdr (assoc 70 (tblsearch "layer" lay)))) 4); locked
      (progn
        (command "_.layer" "_unlock" lay "")
        (setq locked T)
      ); end progn
    ); end if
    (if
      (setq laycont (ssget "_X" (list (cons 8 lay))))
      (command
        "_.wblock"
        (strcat base lay)
        ""
        (getvar 'insbase)
        laycont ""
        "_.oops"
      ); end command
    ); end if
    (if locked
      (progn
        (command "_.layer" "_lock" lay "")
        (setq locked nil)
      ); end progn
    ); end if
  ); end foreach
); end defun

Message 5 of 25
Kent1Cooper
in reply to: egutierrez.cr


@egutierrez.cr wrote:

.... I`ve been trying to edit your LISP routine to get layers in dxf format (you made it for dwg format). I have made this changes:

  1. 'dwgprefix to 'dxfprefix 
  2. 'dwgprefix to '*.dxfprefix
  3. 'dwgprefix yo 'DXF (*.dxf)prefix

And tha same for 'dwgname, but did not worked.

....


You don't want to change those parts [well, maybe you want to, but you shouldn't] -- they're getting information from the current drawing about its location and name, in order to construct the path and name of the file the routine will create for each Layer's contents.  They need those System Variable names spelled right, and they're about the drawing you are in, so dwg is a necessary part of them.  It's in giving Wblock the name of the file to make that you specify the .dxf format.

 

I haven't tested it in the routine, but I think all you should need to do is to change this line [constructing the file name]:

 

(strcat base lay)
 

to this:

 

(strcat base lay ".dxf")
 

to add the file type for the resulting file [it uses .dwg if you don't specify .dxf instead, as the original routine didn't]; and, change the line below that one from a single to a double Enter:

 

"" ""

 

to accept both the decimal-places-of-accuracy and define-a-new-drawing default options.  The first of those questions is not asked unless you say you're making a .dxf file.  You could change whatever you want about the answer to it, if appropriate to your needs, but first at least see whether it works using the default.

 

And presumably you would want to change the first few lines at the top to something more like this:

 

(defun C:SL (/ lay laylist base locked); = Separate Layers
;;  Makes a separate DXF file of the contents of each Layer in the
;;  current drawing, with file names constructed thus:
;;  CurrentDrive:\CurrentFilePath\CurrentDrawing_Layer​.dxf

Kent Cooper, AIA
Message 6 of 25

What an awesome routine, could I ask is it possible to change the target destination of the output? would it be in redefining the "base" variable. The reason I ask is I will be batching this and if files are all in one folder the batch will try and process the files already extracted!

Thanks in advance.

Message 7 of 25


@shaunfarrell5867 wrote:

What an awesome routine, could I ask is it possible to change the target destination of the output? would it be in redefining the "base" variable. ....


Yes, redefine the base variable, though I assume you would want to keep the drawing-name portion of that, and change only the path part.  I think it should work if you change

 

    (getvar 'dwgprefix)
 
to something like:

 

   "Drive:/Your/File/Path/"

Kent Cooper, AIA
Message 8 of 25

I have to admit that I did try that and got a syntax error 😞

Message 9 of 25

I could use the code before to export dxf's instead and then get my script to only process DWG's but it seems a shame when it would be nice and near to target another folder for output.

 

Message 10 of 25

Did you have the path in the format "P:\\Standard Cad Files\\Autocad\\" or "P:/Standard Cad Files/Autocad/" making sure to put the end forward slash or double back slash in?



If a post provides a fix for your issue, click on "Accept as Solution" to help other users find solutions to problems they might have that are similar to yours.

Andrew Puller
Maitland, NSW, Australia
Windows 10 Enterprise 64bit
Intel core i7 11800 @ 2.30 GHz with 32GB Ram
Civil 3d 2021
Message 11 of 25

**** I am rusty, thought I had done that but even when I did no joy

 

 

(defun C:PL (/ lay laylist base locked); = Drawings Per Layer
;;  Makes a separate drawing of the contents of each Layer in the
;;  current drawing, with file names constructed thus:
;;  CurrentDrive:\CurrentFilePath\CurrentDrawing_Layer?.dwg
;;  *Does* take things on Layers that are Off or Frozen, and they
;;  will be so in resulting drawings.  Things on Locked Layers
;;  will also be taken, but those Layers will *not* be Locked in
;;  resulting drawings.
;;  Kent Cooper, January 2011
  (while (setq lay (cdadr (tblnext "layer" (not lay))))
    (setq laylist (cons lay laylist))
  ); end while
  (setq base
    (strcat
      ("c:/extract/")
      (substr (getvar 'dwgname) 1 (- (strlen (getvar 'dwgname)) 4))
      "_"
    ); end strcat
  ); end setq
  (foreach lay laylist
    (if (= (logand 4 (cdr (assoc 70 (tblsearch "layer" lay)))) 4); locked
      (progn
        (command "_.layer" "_unlock" lay "")
        (setq locked T)
      ); end progn
    ); end if
    (if
      (setq laycont (ssget "_X" (list (cons 8 lay))))
      (command
        "_.wblock"
        (strcat base lay)
        ""
        (getvar 'insbase)
        laycont ""
        "_.oops"
      ); end command
    ); end if
    (if locked
      (progn
        (command "_.layer" "_lock" lay "")
        (setq locked nil)
      ); end progn
    ); end if
  ); end foreach
); end defun

Message 12 of 25


@shaunfarrell5867 wrote:

**** I am rusty, thought I had done that but even when I did no joy

 

....

  (setq base
    (strcat
      ("c:/extract/")
....


Try it without the parentheses around the filepath:

....

  (setq base
    (strcat
      "c:/extract/"
....

Kent Cooper, AIA
Message 13 of 25

Genius 🙂

Message 14 of 25
borge.johnsen
in reply to: Kent1Cooper

This is an old subject, but it turned out useful for me. Could the creator, or someone else, edit it so it keeps layer 0 in all dwg files? So dwg1 contains layer 0 &1, dwg2 contain layer 0 & 2, dwg3 layer 0 & 3 and so on.

Message 15 of 25
Kent1Cooper
in reply to: borge.johnsen


@borge.johnsen wrote:

.... Could the creator, or someone else, edit it so it keeps layer 0 in all dwg files? So dwg1 contains layer 0 &1, dwg2 contain layer 0 & 2, dwg3 layer 0 & 3 and so on.


Try [untested] changing this line:

 

(setq laycont (ssget "_X" (list (cons 8 lay))))

 

to this:

(setq laycont (ssget "_X" (list (cons 8 (strcat "0," lay)))))

 

EDIT:  A curiosity for you....  If there are Layer names in the drawing that don't have anything drawn on them, it will still make external drawings of the contents of Layer 0 [only] under drawing names referencing those Layer names.  If that seems likely but pointless, it could be adjusted to not do that.

Kent Cooper, AIA
Message 16 of 25
borge.johnsen
in reply to: Kent1Cooper

Thanks! That did the trick! I appreciate Your help.

There are not so many, so it's not a big job removing them. But stopping those "nothing-to-see-here + layer 0"-drawings from being generated would have been nice.

Message 17 of 25
Kent1Cooper
in reply to: borge.johnsen


@borge.johnsen wrote:

.... stopping those "nothing-to-see-here + layer 0"-drawings from being generated would have been nice.


Try this [untested]:

....

    (if
      (ssget "_X" (list (cons 8 lay))); anything on the Layer [alone]?

      (progn ; then

        (setq laycont (ssget "_X" (list (cons 8 (strcat "0," lay))))); get it, and also Layer 0
        (command
          "_.wblock"
          (strcat base lay)
          ""
          (getvar 'insbase)
          laycont ""
          "_.oops"
        ); command

      ); progn
    ); if

....

Kent Cooper, AIA
Message 18 of 25
jallen
in reply to: Kent1Cooper

Kent,

 

Using this script, How would I extract one particular layer (layername =  "shape") to a dxf with the filename of the parent dwg?

 

Most lower left of object in the new dxf need to be set at the origin (0,0,0).

 

I need to do this for about 800 drawings from out manufacturer.

 

Thanks in advance,

 

James III

AutoCAD 2018, 64 bit

Message 19 of 25
Kent1Cooper
in reply to: jallen


@Jallen wrote:

.... 

Using this script, How would I extract one particular layer (layername =  "shape") to a dxf with the filename of the parent dwg?

 

Most lower left of object in the new dxf need to be set at the origin (0,0,0).

 

....

It's not a Script -- that word has a specific, and different, meaning in AutoCAD.

 

For all but the insertion-base part, I hope this does it [untested]:

(defun C:CallItWhatYouLike (/ laycont)
;;  Kent Cooper, August 2017
  (if
    (setq laycont (ssget "_X" '((8 . "shape"))))
    (command
      "_.wblock"
      (strcat

        (getvar 'dwgprefix)

        (substr (getvar 'dwgname) 1 (- (strlen (getvar 'dwgname)) 4))

        ".dxf"

      ); strcat

      ""

      (getvar 'insbase); as before -- to be modified

      laycont ""
      "_.oops"
    ); command
  ); if
); defun

 

The insertion-base part is more complicated -- I may take a shot at that later.

Kent Cooper, AIA
Message 20 of 25
jallen
in reply to: Kent1Cooper

Almost there Kent...

 

Upon running lisp routine (not script...:-) we must...

 

1. Specify insertion base point:

 

then

 

2. Select objects"

 

then the routine happens flawlessly; creating the dxf of the object selected. GREAT START!!!

 

Now can we use that insertion point of the object to place the object at the origin (0,0,0) in the new dxf file.

I don't understand why we must select the object though it is on the "SHAPE" layer.

 

Thank you in advance Kent,

 

James III

 

 

 

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

Post to forums  

Autodesk Design & Make Report

”Boost