As mentioned in this previous post, there has been some discussion internally around the future of SDI. Given the change this will bring to applications, SDI is going to be around until we next deliberately choose to break binary application compatibility (something we just did with AutoCAD 2010 and typically try to do only every three releases).
That said, SDI is very likely to go away at some point, so it does seem worth drilling further into the reasons for using it and trying to determine an appropriate way to remove current dependencies on it.
Thanks to all of you who responded to my previous post and provided input on your use of SDI. The most common theme was around the use of SDI to batch-process sets of drawings: opening each one, performing an operation and (optionally) saving before opening the next.
My understanding is that SDI makes life easier, in this situation, because the closing of one drawing is taken care of automatically when opening the next and so LISP applications can operate more easily across multiple drawings.
I did some tests, to see how it helps, but the LISP part of my brain has unfortunately atrophied, over the years: I wasn’t able to get a simple SDI-only, batch processing application to work, as it always stopped once a new drawing was open. It may be that some use of script files is needed – and this certainly can make life easier, as we’ll see below – but it would be good if someone could help me out by posting a comment or dropping me an email. I’m sure I’m missing something very simple.
Anyway, irrespective of whether I was able to use SDI successfully, or not, I was able to get something working from an MDI environment that I hope to be equivalent, functionality-wise.
Thanks to guidance from Wayne Brill, a member of DevTech Americas, I was able to put together some LISP code that makes use of a temporary script file to handle the opening, processing, (saving) and closing of drawings.
Here’s the LISP application:
(defun C:BATCH(/ dwgs scr-name lsp-name)
(setq dwgs '("C:/A.DWG" "C:/B.DWG" "C:/C.DWG" "C:/D.DWG")
scr-name "c:/tmp.scr"
lsp-name "c:/batch.lsp"
)
(create-script scr-name dwgs lsp-name "(CreateCircle)" T)
(command "_.SCRIPT" scr-name)
(vl-file-delete scr-name)
(princ)
)
(defun CreateCircle()
(command "_.CIRCLE" "0,0,0" "30")
)
(defun create-script(scr dwgs lsp cmd save / f dwg)
(setq f (open scr "w"))
(foreach dwg dwgs
(progn
(write-line
(strcat "_.OPEN \"" dwg "\"") f
)
(write-line
(strcat "(load \"" lsp "\")") f
)
(write-line cmd f)
(if save
(write-line "_.QSAVE" f)
)
(write-line "_.CLOSE" f)
)
)
(close f)
(princ)
)
The script handles the opening of each drawing, reloading the LISP file (which I have saved in c:/tmp.lsp – this file is pointed at by the lsp-name variable in the C:BATCH function) inside each one and running the specified command/function before saving & closing. In this case we’re running a simple function that uses a command to create a circle – if we were doing something that didn’t require the drawing to be saved (if we were just querying data, for instance) we could pass nil instead of T into the (create-script) function.
To take a look at the script being used behind the scenes, you can simply comment out the call to (vl-file-delete) and open up the contents in your favourite text editor:
_.OPEN "C:/A.DWG"
(load "c:/tmp.lsp")
(CreateCircle)
_.QSAVE
_.CLOSE
_.OPEN "C:/B.DWG"
(load "c:/tmp.lsp")
(CreateCircle)
_.QSAVE
_.CLOSE
_.OPEN "C:/C.DWG"
(load "c:/tmp.lsp")
(CreateCircle)
_.QSAVE
_.CLOSE
_.OPEN "C:/D.DWG"
(load "c:/tmp.lsp")
(CreateCircle)
_.QSAVE
_.CLOSE
I hope this approach goes some way towards helping people batch-process drawings from LISP without having to move to a different language. I’d really appreciate your feedback on this subject, as it would be good to get a more definitive approach nailed down before this change (eventually) becomes a requirement.