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

looking for the best way to run a Lisp routine on a full directoy w 100+ DWGs

23 REPLIES 23
Reply
Message 1 of 24
AVFx1410
2227 Views, 23 Replies

looking for the best way to run a Lisp routine on a full directoy w 100+ DWGs

Hello everyone,

 

I recently managded to create my very first Lisp routine, a little simple but I would have not been able to do this without all of your help.

 

Now that I have created this lisp and I have a command alias for it, I thought why should I open every single file and run the command? When there should be a way to have my Routine run on a full set of drawings...

 

Now... Does anybody here know what the best way to do this is? Your help is very much appreciated.

 

Here is my code pretty much all it does is run other custom commands in my start up suite.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QuickPlot
(defun c:QP ( / )
(command "-vbarun" "SavedPath" "-XREF" "RELOAD" "*")
(command "Purge" "All" "*" "no")
(command "AUDIT" "Y")
(c:XS_AD)
(c:XS_plotprep)
(c:XS_PF)
(command "QSAVE" "Close")
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;End of command

 

Thanks,

Victor

23 REPLIES 23
Message 2 of 24
DannyNL
in reply to: AVFx1410

There are two different ways to batch run a LISP on multiple drawings.

 

The most advanced way is through ObjectDBX, but in short and without going into detail that means your LISP should've been written with VL* commands and using the application and document ActiveX objects.

 

Your LISP isn't, so in this case the only way to run it on multiple drawings would be to build and use a SCRIPT.

Your script would look something like this (assuming your LISP is in the startup suite):

 

.OPEN
drawing1.dwg
C:QP
.OPEN
drawing2.dwg
C:QP
...
...

 

https://www.google.nl/search?q=autocad+script&oq=autocad+script

 

There are also multiple tools available to help you generate script files based on file and/or folder selection.

Message 3 of 24
Sea-Haven
in reply to: DannyNL

c:QP will possibly fail (c:QP) will work. There are vairious ways to make a file list using old fashioned DOS commands from windows CMD option

 

Dir *.dwg /s /b > dwglist.txt

Then I use Word and take advantage of the ability to replace end of line which is ^p so

replace ^p with Open ^p 

then ^p ^p(c:QP)^p

dwg1 .. dwg2 etc becomes

open dwg1 

(c:qp)

open dwg2

(c:qp)

 

 

 

Message 4 of 24
AVFx1410
in reply to: Sea-Haven

Hello,

I don't have the knowledge to translate this from lisp to any other language.

 

Actually I'm trying to figure this one out which seems to be pointed in the right direction 🙂

Is there anything that I would need to edit on this one?

 

Dir *.dwg /s /b > dwglist.txt  *Should I replace Dir with the folder path*

Then I use Word and take advantage of the ability to replace end of line which is ^p so *I would delete this*

replace ^p with Open ^p 

then ^p ^p(c:QP)^p

dwg1 .. dwg2 etc becomes*And delete this*

open dwg1 

(c:qp)

open dwg2

(c:qp)

I'm thinking this dwg 1 and dwg 2 will be a loop so that it will process all files within a folder?

 

So mine would be something like this?

 

Dir *.dwg /s /b > dwglist.txt 

replace ^p with Open ^p 

then ^p ^p(c:QP)^p

open dwg1 

(c:qp)

open dwg2

(c:qp)

 

And finally what extension will this file be? would it be a .bat file?

 

Thanks for your help! 🙂

Message 5 of 24
john.uhden
in reply to: DannyNL

That ain't necessarily so.

With SDI off you can have a blank drawing find and open an unlimited number of other drawings (just one at a time will do) and have acaddoc.lsp do all the grunt work.  I did it years ago for over 13,000 drawings in various branches of a directory tree for Philadelphia Gas Works.

John F. Uhden

Message 6 of 24
AVFx1410
in reply to: john.uhden

Hello,

 

That sounds more complex that would know how to handle.

 

What do you mean by SDI off and where could I find information on acaddoc.lsp to run this lisp on multiple drawings?

 

Thanks,

Victor

Message 7 of 24
john.uhden
in reply to: AVFx1410

SDI is a term we use for "Single Document Interface."  It is the opposite of MDI ("Mutiple Document Interface").

With SDI off (0), AutoCAD can open multiple documents in the same session.

A recursive function can call (vl-directory files ...) to find all the drawings in a folder with subfolders and store them in a list, and then each one is opened, which automatically loads acaddoc.lsp which can perform a plethora of operations and save and close, which reverts focus to the original drawing so it can continue to process the list of drawings.

John F. Uhden

Message 8 of 24
ArchD
in reply to: AVFx1410

Give SmartPurge from JTB World a shot. You'll need a script, but it should be an easy one, just two lines:

 

 

(c:qp)
qsave
<blank line>

 Save it as qp.scr

 

or lose the function and save it as a new lisp, load that one into SmartPurge:

 

(command "-vbarun" "SavedPath" "-XREF" "RELOAD" "*")
(command "Purge" "All" "*" "no")
(command "AUDIT" "Y")
(c:XS_AD)
(c:XS_plotprep)
(c:XS_PF)
(command "QSAVE" "Close")

That was it'll load the list and run it since there is no need to invoke the command.

Archie Dodge
Applications Expert - Infrastructure Solutions Division
IMAGINiT Technologies
Message 9 of 24
AVFx1410
in reply to: ArchD

Hi,

 

Thanks again for your help.

 

working with a script would require to load every time manually right? I will look into the smart purge application you have mentioned.

 

Victor.

Message 10 of 24
ArchD
in reply to: AVFx1410

The SmartPurge application allows you to select a group of drawings, then run a script or lisp on them all one after another automating the process. You can even set a timer so that the process kicks off at a time you specify so that you can leave the office and let it do it's thing running your script/lisp on all of the selected drawings.

Archie Dodge
Applications Expert - Infrastructure Solutions Division
IMAGINiT Technologies
Message 11 of 24
Shneuph
in reply to: john.uhden

I agree with @john.uhden  I batch process files using a temporary acaddoc.lsp file in a working directory.

---sig---------------------------------------
'(83 104 110 101 117 112 104 64 71 109 97 105 108 46 99 111 109)
Message 12 of 24
roland.r71
in reply to: DannyNL

@DannyNL, no, there's a third way easier way.

 

Create a list of files

Set SDI to 1

Make sure LISPINIT is off (0)

& (file)open, edit & save each drawing inside the list. (or load a lisp with each to do the 'edit')

 

See the other topic for my example code:

edit: I'll just add it here, too...

 

(defun C:MF (/ filelist file)
   (setq filelist 
      (list 
         "C:/Lisp/TestDWG/TT049-1ARK03-SET.dwg" 
         "C:/Lisp/TestDWG/TT049-1ARK04-SET.dwg" 
         "C:/Lisp/TestDWG/TT049-1ARK05-SET.dwg" 
         "C:/Lisp/TestDWG/TT049-1ARK06-SET.dwg"
      )
   )
   (setvar "SDI" 1)
   (setvar "LISPINIT" 0)
   (foreach file filelist
      (command "_.fileopen" file)
      (command "Zoom" "e")
      (command "Qsave")
   )
)

This will do the job.

 

Of course there are many ways to create the list with filenames, and the (command ...) functions are just for example. you can run ANY lisp code on each drawing.

Message 13 of 24
AVFx1410
in reply to: roland.r71

Hi Roland.r71

 

What you have shared seems very interesting, however I have a question. When you say create a list of files would I have to manually enter the names on the code?

 

Also this portion of the code I don't really understand if it is written in a template way to replace with real paths and drawing names?

 

I believe since I have standard drawing names I could add them all to the list but when I need to plot 10 drawings I don't want to get an error because the one of the drawing names was not found,

 

Again thanks for all the help and I'm sorry about all the questions! 🙂

 

Message 14 of 24
roland.r71
in reply to: AVFx1410


@AVFx1410 wrote:

Hi Roland.r71

 

What you have shared seems very interesting, however I have a question. When you say create a list of files would I have to manually enter the names on the code?

 


Only if you want to Smiley Wink

As I said, there are many ways to create such a list.

Especially if you use DOSlib (a very usefull Autocad Runtime eXtention)

 

The easiest way would be to read all files from a single directory.

I have a function that does just that, optionally includes sub-directories. However, it requires DOSlib.

note: you will still need to ask for a directory first (unless its always the same) & suply this directory to the function.

 

   (defun get_files ( dr rc / dt tl fp i l filelist)
      ; Takes a path and 1 for recursive (nil or 0 if not), returns list of files
      ; dr       = Directory [ Drive: | \\server] \path\to\files
      ; rc       = Recursive [ 1 = yes ]
      ; filelist = List of files (including full path) to be returned
      (setq filelist nil)
      (if (= rc 1)
         ; Include subdirs
         (progn
            ; Get the directory tree
            (setq dt (DOS_DIRTREE dr))
            (setq i 0)
            (while (< i (length dt))
               ; get the drawings for each (sub)directory'
               (setq tl (DOS_DIR (strcat (nth i dt) "*.dwg")))
               (setq l 0)
               (while (< l (length tl))
                  (setq fp (strcat (parse_path (nth i dt)) (nth l tl)))
                  (setq filelist (append filelist (list fp)))
                  (setq l (1+ l))
               )
               (setq i (1+ i))
            )
         )
         ; Current dir only
         (progn
            ; get the drawings for current directory
            (setq tl (DOS_DIR (strcat dr "*.dwg")))                      
            (setq i 0)
            (while (< i (length tl))
               (setq fp (strcat (parse_path dr)(nth i tl)))
               (setq filelist (append filelist (list fp)))
               (setq i (1+ i))
            )
         )
      )
      filelist
   )

   (defun parse_path (path2Filename / temp i)
      ; takes path, changes \ to /
      (setq i 1 temp "")
      (repeat (strlen path2Filename)
         (if (= (substr path2Filename i 1) "\\")
            (setq temp (strcat temp "/"))
            (setq temp (strcat temp (substr path2Filename i 1)))
         )
         (setq i (1+ i))
      )
      temp
   )

 

 


Also this portion of the code I don't really understand if it is written in a template way to replace with real paths and drawing names?



Yes, it is just an example you need to replace with 'hardcoded' paths & filenames, -OR- code like above, that will allow the user to select the files/directories to process (& create a list of those)

 


I believe since I have standard drawing names I could add them all to the list but when I need to plot 10 drawings I don't want to get an error because the one of the drawing names was not found,

Besides not being found, files can be read-only or open by another user. You might need to check all that to properly close & open files to prevent errors.

 

I have a function for that too, but I've been working on that part of code for a while, to rewrite it for easier sharing. Still need to finnish that.

 


Again thanks for all the help and I'm sorry about all the questions! 🙂

 


No problem. Happy to help Smiley Happy

Message 15 of 24
john.uhden
in reply to: AVFx1410

It turned out to be easy to find the file-finding function (because I use ZTree).

I'm sure it could be a lot sleeker, but though it's about 14 years old, I'm pretty sure it still works.

It creates a list of all DWG files in a given path including subdirectories.

;;-------------------------------------------------------------------------------------
;; Function to build a list of drawings found in the specified path and subdirectories:
;; By John Uhden, c.2004 (defun @find_dwgs (path / spec files spaces dirs @dirs)
(vl-load-com) (cond ((or (/= (type path) 'STR)(= path "")) (setq path (strcase (vl-filename-directory (findfile (car (vl-directory-files "" "*.*" 1)) ) ) ) ) ) ((wcmatch path ",*/,*\\")) (1 (setq path (strcat path "\\"))) ) (setq spec "*.dwg") (setq spaces " ") (defun @dirs (path / dirs found) (princ (strcat "\rSearching " path (substr spaces (strlen path)))) (princ) (and (setq found (vl-directory-files path spec 1)) (setq found (mapcar (function (lambda (x)(strcat path x))) found)) (setq files (append files found)) ) (and (setq dirs (vl-directory-files path "*.*" -1)) (setq dirs (vl-remove-if (function (lambda (x)(vl-position x '("." "..")))) dirs) dirs (mapcar (function (lambda (x)(strcat path x "\\"))) dirs) ) ) (foreach dir dirs (@dirs dir)) ) (terpri) (@dirs path) (reverse files) )
Example: (@find_dwgs "c:/projects")

John F. Uhden

Message 16 of 24
DannyNL
in reply to: roland.r71


@roland.r71 wrote:

@DannyNL, no, there's a third way easier way.

 

Create a list of files

Set SDI to 1

Make sure LISPINIT is off (0)

& (file)open, edit & save each drawing inside the list. (or load a lisp with each to do the 'edit')

 

Oops....yes, of course you are right.

Sometimes you take some things for granted that you forget Smiley Happy

Message 17 of 24
roland.r71
in reply to: roland.r71

As its probably going to take a while (before i find the little time i need to finnish rewriting)

I might as well share the old files, as far as they work on their own (i did use a modular approach)

& on the selection part i hardly had to change a thing, and i did recently update some of the files, so...

 

I have a function (scrGenFiles) to create a list of files to process, in prety much any way possible.

It uses a global variable to store the list, instead of returning it. I did that to preserve memory (on BIG lists) amongst others.

As it can save/load a list, you can even edit the list with notepad, or read a directory to a file (using DOS (cmd)) make a few changes and load that for further use.

I did my best to make it as flexible and complete as possible.

 

...for that i did need to use DOSlib though. In fact, this is what it was made for Smiley Wink

I don't have many functions requiring DOSlib, but this is definately their "mother". I've tried to do without on several attempts, but although some can be replaced using ACET or ActiveX and such there are no alternatives for all of its functions. (afaik)

 

I'll attach the lisp & dcl files etc. to do the selection in my next post.

It should be noted that it does require a few other (common) functions, i'll need to collect  & a INI file + a few globals (for locations / directories).

Message 18 of 24
roland.r71
in reply to: roland.r71

These files come from what used to be my scriptGenerator, as i used to do this by using scripts in the past.
(as i was unaware it could be done without)

The first step in the process would be to ask the user what lisp file should be loaded with each drawing.
& what to do in various situations. (skip read-only files or not, save changes or not, log files or not, etc.)
& where to save the *.scr file

That part is not included here, as it is specific for using a script.

The second step would be to select the files. The part we are talking about.

In the finall step it would ask for confirmation to start. At which point it would generate & execute the script. Again, this part is specific for using a script.

 

During the first part, a few globals get set which are important for the file selection.

I'll add that code right here:

; By default it is set to use subdirectories of the main scrGen path set.
; In case this is a shared network location, you should set the location of
; the DATA directory and scrGen.ini file to a local path, or use a user specific
; network location, to avoid conflicts.

; Set path to this script - NOTE: use either \\ or / instead of \
(setq *scrGen_files* "c:/Lisp/scrGen/")

; Paths to the scrGen.ini config file. Must be writeable
(setq *scrGen_ini* (strcat *scrGen_files* "scrGen.ini"))

; Paths to the scrGen.dcl dialog file.
(setq *scrGen_dcl* (strcat *scrgen_files* "scrGen.dcl"))

; Set path for data files. Must be writeable (see Note in header!)
; Used for storing logfile & filelist
(setq *scrGen_data* (strcat *scrGen_files* "DATA/"))

; set path to scrGen modules
(setq *scrGen_mods* (strcat *scrGen_files* "MODULES/"))

; Optional path to be used to find/load doslib
(setq *DLpath* "C:/Lisp/DOSLIB/")

 

 

Next you need a few common functions, for loading DOSlib (on any version of acad (each has it's own .arx name!)), changing paths ( \ to /) & to get the read-only attribute. (the DOSlib function used changed its output from one version to the next. This will work with both) - these are inside "scrGenCommon.lsp"

 

Then you'll need the "scrGenFiles.lsp" for selecting the files,

Which in turn needs the "scrGen.dcl" file for the scrGenFiles dialog.

 

Last but not least, you need a scrGen.ini file, for storing settings.

Here you can set the options for filehandling manually (as i did not include the first part where these can be set using a dialog)

As i can attach only 3 files, i'll add the ini as code.

Note: Some of it is obsolete, as there's no script generator in this case, but i just added the complete thing.

; ==============================================================================
;                        *** AutoCAD scrGen v3.0 ***
;                Copyleft ;) 2004-2018 | Roland Rothenhöfer
; ==============================================================================
; Configuration file

; ------------------------------------------------------------------------------
[config]
; ------------------------------------------------------------------------------
; Last used *.lsp file, to run on selection
; STRING : [Drive: | //Network]/path/to/file.ext
lispFile=C:/Lisp/test/zea.lsp

; logfile for skipped files
; STRING : [Drive: | //Network]/path/to/file.ext
logFile=C:/Lisp/scrGen/DATA/scrGen_log.csv

; Location of lisp file with fileopen function
; STRING : [Drive: | //Network]/path/to/file.ext
openFun=C:/Lisp/scrGen/MODULES/scrGenOpen.lsp

; Location to create the script
; STRING : [Drive: | //Network]/path/
scrPath=C:/Lisp/scrGen/DATA/

; Show progression bar
; BOOLEAN : 0 = no, 1 = yes
progBar=1

; log skipped filenames
; BOOLEAN : 0 = no, 1 = yes
logSkip=1

; number of skipped files
; INTEGER
NumSkip=0

; warn user when file not found
; BOOLEAN : 0 = no, 1 = yes
warn_notfound=1

; warn user when file open (network)
; BOOLEAN : 0 = no, 1 = yes
warn_fileopen=1

; warn user when file Read-Only
; BOOLEAN : 0 = no, 1 = yes
warn_readonly=1

; don't open files (as) read-only
; BOOLEAN : 0 = no, 1 = yes
skip_readonly=0

; don't save changes to file
; BOOLEAN : 0 = no, 1 = yes
skip_savefile=0

; Initial Single Document Mode
; BOOLEAN : 0 = off, 1 = on
SDI =0

; Initial FILEDIA mode
; BOOLEAN : 0 = off, 1 = on
FILEDIA =1

; ------------------------------------------------------------------------------
[scrGenFiles]
; ------------------------------------------------------------------------------
; Last used directory to add file(s)
; STRING : [Drive: | Network]\path\to\files\
lastdir=C:\acad_test\dwg\ztm2\

; Last used directory to add files in directory (tree)
; STRING : [Drive: | \\Network]\path\to\files\
userpath=C:\acad_test\dwg\ztm2\

; DOS style wildcard for filenames, when adding files in directory (tree)
; STRING : DOS style filename filter. *=all files ( with the extension : .DWG and/or .DXF )
wildcard=*

; Whether to include files inside sub-directories
; BOOLEAN : 0 = no, 1 = yes
recursive=0

; Whether to automatically order files (alphanumeric)
; BOOLEAN : 0 = no, 1 = yes
autosort=0

; Whether to "remember" the list. This will save the list on exit to DATA\scrGenFiles.lst
; the next time scrGenFiles is called, this list will be (re)loaded
; BOOLEAN : 0 = no, 1 = yes
autosave=1

; Whether to allow duplicate (2 or more times the same) file names
; BOOLEAN : 0 = no, 1 = yes
noDuplicate=1

; Whether to allow '_recover' files
; BOOLEAN : 0 = no, 1 = yes
noRecover=1

; Which filetype(s) to include
; INTEGER : 1 = DWG, 2 = DXF, 3 = Both
filetype=1
Message 19 of 24
dbroad
in reply to: AVFx1410

It looks like you've gotten some good answers.  If you could recode the VBA parts, a better option than all of the previous suggestions, however is for you to download ScriptPro from Autodesk and to use it to run the AutoCAD Core Console.  ObjectDBX is not as good as the core console at processing drawings.  ObjectDBX was as good as it got 6 years ago.  The core console is much faster than batch processing via the user interface.  Scriptpro provides an easy interface to pick which files to process, and to select a simple command script that contains the code to process for each drawing.

 

Here is a link that contains a download package for scriptpro:

https://knowledge.autodesk.com/support/autocad/downloads/caas/downloads/content/autodesk-customizati...

 

Here is a link that contains an explanation of the core console:

http://through-the-interface.typepad.com/through_the_interface/2012/02/the-autocad-2013-core-console...

 

 

 

Architect, Registered NC, VA, SC, & GA.
Message 20 of 24
roland.r71
in reply to: dbroad


@dbroad wrote:

It looks like you've gotten some good answers.  If you could recode the VBA parts, a better option than all of the previous suggestions, however is for you to download ScriptPro from Autodesk and to use it to run the AutoCAD Core Console.  ObjectDBX is not as good as the core console at processing drawings.  ObjectDBX was as good as it got 6 years ago.  The core console is much faster than batch processing via the user interface.  Scriptpro provides an easy interface to pick which files to process, and to select a simple command script that contains the code to process for each drawing.

 

Here is a link that contains a download package for scriptpro:

https://knowledge.autodesk.com/support/autocad/downloads/caas/downloads/content/autodesk-customizati...

 

Here is a link that contains an explanation of the core console:

http://through-the-interface.typepad.com/through_the_interface/2012/02/the-autocad-2013-core-console...

 

 

 


If only it was still supported/updated & the installer would be compatible with modern day windows ... yes Smiley Frustrated

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

Post to forums  

Autodesk Design & Make Report

”Boost