Batch-processing AutoCAD drawings from LISP without SDI (take 2)

In this recent post we looked at an approach combining AutoLISP with a script generated on-the-fly to get around the fact that (command "_.OPEN" …) does nothing when SDI == 0. As mentioned in a comment in the post, I realised that the approach of using a single master script to do this is more prone to failure: a number of commands can cause scripts to stop executing, for instance, so it would be better practice to minimise the operations contained in a particular script to increase the application's fault tolerance.

This modified approach was suggested by a member of our Engineering team in a recent thread (one that I came across after Monday's post). It uses a data file to store a list of the drawings to process and only creates a script to load – and launch processing on – the next drawing in that list:

(defun C:BATCH(/ dwgs lsp-name data-name)

  (setq dwgs '("C:/A.DWG" "C:/B.DWG" "C:/C.DWG" "C:/D.DWG")

        lsp-name "c:/tmp.lsp"

        data-name "c:/dwgs.tmp"

  )

  (create-drawing-list data-name dwgs)

  (process-next-drawing data-name lsp-name "(create-circle)" T T)

  (princ)

)

 

(defun create-circle()

  (command "_.CIRCLE" "10,10,0" "5")

)

 

(defun create-drawing-list(data dwgs / f dwg)

 

  ;; Create data file containing the DWG names

 

  (setq f (open data-name "w"))

  (foreach dwg dwgs

    (write-line dwg f)

  )

  (close f)

)

 

;; Get the first drawing from the list, removing it

 

(defun get-next-drawing(data / dwg dwgs f)

 

  ;; Read in the whole list of DWGs

 

  (setq f (open data "r")

        dwgs '()

  )

  (while (setq dwg (read-line f))

    (setq dwgs (cons dwg dwgs))

  )

  (close f)

 

  ;; Reverse the list, take the head and write

  ;; back the remainder to the file

 

  (if (> (length dwgs) 0)

    (progn

      (setq dwgs (
reverse dwgs)

            dwg (car dwgs)

            dwgs (cdr dwgs)

      )

 

      (setq f (open data "w"))

      (foreach dwg dwgs

        (write-line dwg f)

      )

      (close f)

    )

  )

  dwg

)

 

;; Process the current drawing and use a script to open

;; the next one in the list

 

(defun process-next-drawing(data lsp func save first / scr)

  (setq scr "c:/tmp.scr")

 

  ;; We only want to run the function if not the first

  ;; time called... the same for save

 

  (if (not first)

    (progn

      (eval (read func))

      (if save

        (command "_.QSAVE")

      )

    )

  )

 

  ;; Get the next DWG name from the file

 

  (setq dwg (get-next-drawing data))

 

  ;; If there is one, create a script to open it, reload

  ;; the application and process our function

 

  (if dwg

    (progn

      (create-script scr data dwg lsp save first)

      (command "_.SCRIPT" scr)

    )

 

    ;; For the last drawing we simply close it and

    ;; delete the now-empty data file

 

    (progn

      (vl-file-delete data)

      (vl-file-delete scr)

      (command "_.CLOSE")

 
;   )

  )

) 

 

;; Create a script to close the current drawing and

;; open the next, calling back to our process function

;; (after having loaded the file that defines it)

 

(defun create-script(scr data dwg lsp save first / f)

  (setq f (open scr "w"))

  (if (not first)

    (write-line "_.CLOSE" f)

  )

  (write-line

    (strcat "_.OPEN \"" dwg "\"") f

  )

  (write-line

    (strcat "(load \"" lsp "\")") f

  )

  (write-line

    (strcat

      "(process-next-drawing \""

      data "\" \"" lsp "\" \"" func "\" "

      (if save "T" "nil") " nil)"

    )

    f

  )

  (close f)

  (princ)

)

I hope this is useful to people – as mentioned before, please do provide feedback on how/whether this works for you…

20 responses to “Batch-processing AutoCAD drawings from LISP without SDI (take 2)”

  1. Kean,
    Do you have any plans for a blog on batch processing for .NET? I have been hopping for one on that topic for a long time.

  2. Kean Walmsley Avatar

    HJohn,

    These posts should help (and, more specifically, this one).

    Or is there something else you're looking for?

    Kean

  3. Stephan Bartl Avatar

    Hi Kean!

    I would like to automatically continue my lisp-program (in the original drawing, which triggered the script) after the execution of the script (or at least (re)start a lisp in that original dwg automatically).
    Both approaches have the problem, that, if I write anything else than an "_.OPEN" after the last "_.CLOSE" in the script, it will not be executed - it acts as if I had not written it into the scriptfile.
    The only solution, that I can think of, is to handle the whole scripting-thing in a new instance of AutoCAD altogether and wait with program-execution of the main-lisp until the whole new AutoCAD-instance is closed again.
    Do you or one of your crew have a better idea?

    Thanks, Stephan

  4. Kean Walmsley Avatar

    Hi Stephan,

    That's a great question. 🙂

    If you look in the code where we handle the last drawing (you can search for "For the last drawing", which is in a comment), you will see that we perform a (command "_.CLOSE"). If you want to have some execution continuation you could - instead - create a script (as we have done for our processing work) that closes the drawing, loads our LISP file and executes a continuation function in the original drawing (should it exist: it is also possible it no longer exists, as the OPEN command will get rid of a brand new drawing from the editor if it hasn't been edited).

    It should be pretty straightforward to implement this - the only possible tricky thing I can imagine will be working our where to delete the script (which may or may not end up being an issue for you).

    Regards,

    Kean

  5. Stephan Bartl Avatar

    Hi Kean!

    Thanks for that idea. I didn't even notice that the last "_.CLOSE"-command here is issued by the lisp-code. That's because I was actually more concentrating on the version from your first article on that subject. Which brings us to the point, that I had already tried to execute some command after the last "_.CLOSE" in a "real" script.

    You write: "create a script ... that closes the drawing, loads our LISP file and executes a continuation function in the original drawing". (Let's assume that the original drawing is still open.) As it seems to me, the script does not honor anything else but an "_.OPEN"-command after a "_.CLOSE". Or in other words, it does not "go back" to the still open original drawing.

    (Besides: I cannot verify the described behavior of ACAD disposing a brand new drawing not having been edited because of an OPEN command. Of course that does not mean that it could not get closed in other ways.)

    Regards, Stephan

  6. Kean Walmsley Avatar

    Hi Stephan,

    Hmm - it seems you're right. I had assumed it would work, but hadn't realised we'd need to call NEW or OPEN after the CLOSE.

    One option would be to save and then reopen the original drawing right at the end - and that might actually be a safe thing to do, thinking about it.

    Regards,

    Kean

  7. Stephan Bartl Avatar

    Thanks for the continuous replies, Kean!

    First: What is safer about it?

    Second: Just in case I want to minimize the possiblity that someone else migth open the drawing while it is closed I thought of this:

    I close the original dwg by way of:
    (vl-load-com)
    (vla-close(vla-Item(vla-get-Documents(vlax-get-acad-object))"filename.dwg"))
    RIGHT BEFORE I close the last batch-processed drawing. This way, when I open the Original again with "_.OPEN" (from a "real" script) - right after the closing of the last bath-processed drawing - it was closed for only a very short time.

    The only drawback for the user is that it looks wired when the drawing is closed for a smidgen bit of a time just to be opened again.

    Therefore I think I will go with opening a new AutoCAD-instance altogether in connection with (acet-sys-command ...) from the Express-Tools. Or do you see any dangers in that, Kean?

    Kind regards, Stephan

  8. Kean Walmsley Avatar

    First: because when batch-processing drawings you never quite know what you're going to get (the drawing could be seriously (unrecoverably) corrupt, for instance).

    Second: Just memory consumption. I also find it a slightly odd approach to solving this problem: I would personally save and close the drawing immediately and open it at the end. Should be simple enough to implement. But the choice is ultimately yours, of course.

    Kean

  9. Stephan Bartl Avatar

    Ok then,
    just to let you know, as far as I am concerned, Autodesk can get rid of SDI now. I am helped enough now so that I can switch to MDI.
    Thank you for all your help.

  10. Will you please tell me how can I close all open drawings with zooming to the extents and saving?
    I used express tool to save & close all the open drawings but it zooms the drawings to the unexpected window.

  11. Kean Walmsley Avatar

    milind -

    Sorry, but this is not a forum for support. Please submit your question to the ADN team, if you're a member, or otherwise the AutoCAD .NET Discussion Group.

    Kean

  12. Hello Kean;
    I have a problem to my AutoCAD 2007. I open a cad file with LISP behind in one folder my cursor which work as a pa doesn't work anymore but instead it change to list of command. Not only that when i reinstall the autocad, still nothing has happen. What should i do to return the cursor of my mouse to Pan command? Please help me.

  13. Hello Kean;
    I have a problem to my AutoCAD 2007. I open a cad file with LISP behind in one folder, my cursor of the mouse which work as a PAN before doesn't work anymore but instead it change to list of command. Not only that when i reinstall the software auto-cad , still nothing has happen. What should i do to return the cursor of my mouse to Pan command? Please help me

  14. Hi Ryan,

    I'm afraid I can't tell what's happening. If you think it's a problem caused by the code in this post, let me know, otherwise I suggest posting a more complete description of the problem to the appropriate online discussion group.

    Regards,

    Kean

  15. Hi to All,
    Just want to know if you're
    aware of the much more powerful
    program that does not require
    any script generation and runs
    any lisp on multiple drawings with
    speed, and it also has a good user
    inteface for files selection, based
    on doslib.arx. It is ranbatch.vlx by plot2000.com. Unfirtunately, no
    latest version avilable for 2010...
    If anybody knows any similar program
    please let me know, I would really
    appreciate it!

  16. I realize this is a fairly old post, but it addresses a need I have at the moment. I ran into a few issues in getting this to run under Windows 7, using AutoCAD Architecture 2014.

    1. The create-drawing-list function has an argument called "data", but then tries to open the file in a variable called "data-name". Either the variable name needs to be changed to "data" or the argument name needs to be changed to "data-name".

    2. Windows 7 did not allow the temporary files to write to the root directory of C:. I created a folder under C: to hold the tmp.lsp file and to receive the temporary data and script files. I will probably use the drawing directory in which the files to be processed reside for the temporary data and script files, to assure that the user will have write permission. The LISP file will be on the network, in our office-standards area.

    3. AutoCAD Architecture would not initially load the tmp.lsp file, because the folder I created was not in a "trusted applications" folder. Once I added the folder to the list of trusted applications, the batch process ran successfully. I will have to remember to add the office-standard LISP folder to the trusted locations when we deploy AutoCAD Architecture 2014.

  17. Kean Walmsley Avatar

    Hi David,

    Thanks for posting this information - I'm sure others will find it helpful.

    Regards,

    Kean

  18. i want to do this
    1.savelayerstate
    2.unlockalllayer
    3.unfrozenalllayer
    4.audit
    5.pu
    6.restorelayerstate
    7.save
    how can i do this with acadcorecommand
    use scr?

    1. Kean Walmsley Avatar
      Kean Walmsley

      I'm sorry - I don't have time to provide support. Please post your question to the relevant Autodesk forum.

      That said, I suggest starting by typing each of the commands you care about into the Core Console, to make sure they work. Then build the script as you would in AutoCAD (there should be lots of resources available to help with that).

      Kean

      1. i think i need crx to do this ,

Leave a Reply

Your email address will not be published. Required fields are marked *