Jump to content

Using Lee Mac's ScriptWriter and LISP routine to clean CAD drawings


CAD Geek

Recommended Posts

Hello all,

 

I've been trying to use Lee Mac's current version of ScriptWriter to automate the cleaning of Civil 3D drawings before we send them out of the office. I am trying to use ScriptWriter to execute a lisp file called Clean2.lsp and have run into two different issues.

 

1. The first issue is that no matter whether I have errors in my lisp file or not (I've removed the code that caused me issues in my second question below, but it didn't help), it only cleans one file and does not go onto the next.

 

My script line within the ScriptWriter dialog box is as follows:

_.open *file* (load "CLEAN2.lsp" nil) (if c:CLEAN2 (c:CLEAN2)) _.qsave _.close

 

2. The second issue I'm having is that I seem to not understand how to invoke commands defined in my clean2.lsp routine. I have copied a couple of function definitions, "LAF", and "LAT", to the top of the lisp file in order to have access to them. I want to use those functions to freeze and thaw certain layers before finishing the file cleaning process. I just haven't been able to figure out how to invoke those commands properly in the lines of code below. You can see that I'm trying to freeze off all layers that contain the numbers 30, 40 or 50 in their names, and make sure that the layers with 20 in their names are thawed, but I'm always getting an "Unknown Command" error. I've tried a lot of different syntaxes for ways to invoke the command and have been rummaging through forum pages trying to find a hint of what I might be doing wrong here. This is my lisp code:

 

(defun c:CLEAN2()

(defun C:LAF () 
  (setq txt (strcat "*" (getstring "\nPartial layer name to FREEZE: ") "*"))
  (COMMAND "LAYER" "F" TXT "")
)  

(defun C:LAT () 
  (setq txt (strcat "*" (getstring "\nPartial layer name to THAW: ") "*"))
  (COMMAND "LAYER" "T" TXT "ON" TXT "U" TXT "")
) 

(defun findxref (/ td xrf)
(while (setq td (tblnext "BLOCK" (not td)))
(and (= (logand (cdr (assoc 70 td)) 4) 4)
(setq xrf (cons (strcase (cdr (assoc 2 td))) xrf))))
xrf)

        (setvar "cmdecho" 1)
        (setvar "cmddia" 0)
        (setvar "filedia" 0)
	(command "layer" "t" "*" "")    
        (command "layer" "on" "*" "")
        (command "layer" "u" "*" "")
        (command "layer" "s" "0" "") 
	(if (findxref)
      	(command "xref" "d" "*"))        
        (command "-image" "d" "*")
        (command "purgestyles" "y")
        (command "purge" "a" "*" "n")
        (command "purgestyles" "y")
	(command "purge" "a" "*" "n")
        (command "purgestyles" "y")
	(command "purge" "a" "*" "n")
        (command "-purge" "r" "*" "n")
        (command "-purge" "z")
        (command "-purge" "e")
        (command "-purge" "o")
        (command "snap" "R" "" "0" "snap" "off")
	(command "ucs" "w")
	(command "plan" "c")
        (command "LAF" "30")
	(command "LAF" "40")
	(command "LAF" "50")
        (command "LAT" "20")
        (command "audit" "y")
        (setvar "cmddia" 1)
        (setvar "filedia" 1)
(princ)
)

 

Thank you for any help you can provide to either of my questions, I truly appreciate it!

Link to comment
Share on other sites

Hello CAD Geek

What "cleaning" do you try to automate? There may be a shorter way. I used to use a very short Lisp to purge the drawings and make a "Zoom Extents", than save them in Dxf format. When a project was finished, I used to process at once all the files from within a directory.

Welcome in the forum!

Link to comment
Share on other sites

1. I reckon it is LAF and LAT which will pause the script, asking for use input with 'Getstring', take these out of the process and it should work.

 

2. To send a value to a LISP or command it has to be able to accept it, so in this case (command "LAF" "30") is sending '30' to LAF , however LAF is going "?" when it gets 30 sent to it. In your defun line try:

(defun LAF ( AValue / )

 

where 'AValue' will be a single thing that you send it (in this example, 30). Also good practice is to put local variables (here 'txt') after the /. Before the / are values you are sending and after for local variable names (ie within that LISP only)

 

Might be that this works better: (and change your LAT similarly)

(defun C:LAF ( AValue / txt)
;;  (setq txt (strcat "*" (getstring "\nPartial layer name to FREEZE: ") "*"))
  (setq txt (strcat "*" AValue "*"))
  (COMMAND "LAYER" "F" TXT "")
) 

 

Noting that since the command (command "LAF" "30") has the 30 within " " indicating it is a string and not a number this will work as it is. If it was (command "LAF" 30) - no " " this is a number you are sending and so would need to convert to a string to use in the strcat

Link to comment
Share on other sites

12 hours ago, fuccaro said:

Hello CAD Geek

What "cleaning" do you try to automate? There may be a shorter way. I used to use a very short Lisp to purge the drawings and make a "Zoom Extents", than save them in Dxf format. When a project was finished, I used to process at once all the files from within a directory.

Welcome in the forum!

Hello Fuccaro,

 

Thanks for the welcome and reply! The reason I'm trying to automate this is that I often want to send out groups of stripped-down files to consultants and it would be much easier to run one routine and have 10 files be cleaned up than to go through them one by one. We generally just want to send out the reference files rather than sheet/layout files and to either keep them in the current format or sometimes export to AutoCAD 2000 format if we want to strip out all Civil 3D data. I think I'm getting much closer now on the clean2 lisp routine from the responses, but still need to figure out how to get the ScriptWriter routine to work with it.

 

Thanks again!

 

4 hours ago, Steven P said:

1. I reckon it is LAF and LAT which will pause the script, asking for use input with 'Getstring', take these out of the process and it should work.

 

2. To send a value to a LISP or command it has to be able to accept it, so in this case (command "LAF" "30") is sending '30' to LAF , however LAF is going "?" when it gets 30 sent to it. In your defun line try:

(defun LAF ( AValue / )

 

where 'AValue' will be a single thing that you send it (in this example, 30). Also good practice is to put local variables (here 'txt') after the /. Before the / are values you are sending and after for local variable names (ie within that LISP only)

 

Might be that this works better: (and change your LAT similarly)

(defun C:LAF ( AValue / txt)
;;  (setq txt (strcat "*" (getstring "\nPartial layer name to FREEZE: ") "*"))
  (setq txt (strcat "*" AValue "*"))
  (COMMAND "LAYER" "F" TXT "")
) 

 

Noting that since the command (command "LAF" "30") has the 30 within " " indicating it is a string and not a number this will work as it is. If it was (command "LAF" 30) - no " " this is a number you are sending and so would need to convert to a string to use in the strcat

 

Hello Steven,

 

Thanks so much! What you've written makes a lot of sense and has helped me to better understand what the lisp code is doing. I now see that it wasn't necessary to copy in the command as it was since it was expecting the user to type at the prompt and hit enter, but you've written it so that the variable is passed into the command. I rewrote the lisp as recommended but for some reason I'm still getting output toward the end of the routine that says:

 

LAF Unknown command "LAF". Press F1 for help.

30 Uknown command "30". Press F1 for help

LAF Unknown command "LAF". Press F1 for help.

40 Uknown command "40". Press F1 for help

LAF Unknown command "LAF". Press F1 for help.

50 Uknown command "50". Press F1 for help

LAF Unknown command "LAT". Press F1 for help.

20 Uknown command "20". Press F1 for help

 

My code currently looks like this:

 

(defun C:LAF ( AValue / TXT)  
  (setq TXT (strcat "*" AValue "*"))
  (COMMAND "-LAYER" "F" TXT "")
)  

(defun C:LAT ( AValue / TXT) 
  (setq TXT (strcat "*" AValue "*"))
  (COMMAND "-LAYER" "T" TXT "ON" TXT "U" TXT "")
) 

(defun findxref (/ td xrf)
(while (setq td (tblnext "BLOCK" (not td)))
(and (= (logand (cdr (assoc 70 td)) 4) 4)
(setq xrf (cons (strcase (cdr (assoc 2 td))) xrf))))
xrf)

        (setvar "cmdecho" 1)
        (setvar "cmddia" 0)
        (setvar "filedia" 0)
    	(command "layer" "t" "*" "")    
        (command "layer" "on" "*" "")
        (command "layer" "u" "*" "")
        (command "layer" "s" "0" "") 
    	(if (findxref)
      	(command "xref" "d" "*"))        
        (command "-image" "d" "*")
        (command "purgestyles" "y")
        (command "purge" "a" "*" "n")
        (command "purgestyles" "y")
    	(command "purge" "a" "*" "n")
        (command "purgestyles" "y")
    	(command "purge" "a" "*" "n")
        (command "-purge" "r" "*" "n")
        (command "-purge" "z")
        (command "-purge" "e")
        (command "-purge" "o")
        (command "snap" "R" "" "0" "snap" "off")
    	(command "ucs" "w")
    	(command "plan" "c")
    	(command "LAF" "30")
    	(command "LAF" "40")
	    (command "LAF" "50")
    	(command "LAT" "20")
        (command "audit" "y")
        (setvar "cmddia" 1)
        (setvar "filedia" 1)
(princ)
)

 

I'm sure it's something very obvious that I'm doing wrong - if anyone can show me where I went astray that would be greatly appreciated. I'm definitely a newbie to this and will be reading/studying a lot in the coming weeks to try to attain at least a basic level of proficiency with the language. Much appreciated!

 

4 hours ago, Lee Mac said:

You can still use the LAF program as written, but you'll need to supply the string argument from the script rather than from the LISP file.

 

Thank you for letting me know that, Lee! That's good for me to think about the different ways this could be done. For some reason, even if I remove the code for the freezing and thawing of layers toward the end of my Lisp routine, I am still running into trouble with ScriptWriter not continuing past the first drawing. I think it might be that once the purge and purge styles commands have removed everything and then the commands are repeated again (which is sometimes required a few times to get rid of all dependent styles), or the command to remove images runs and there aren't any images in that file, it seems to short circuit the WScript routine, whereas if I run the lisp on a single drawing it will just give the error for that line and keep chugging along to finish the rest of the commands. I imagine that I may be able to get around this by doing a query of whether there are images attached to the current drawing and whether there are any styles to be purged before proceeding with those commands. If you see anything else off of the top of your head that I might be doing wrong, please let me know, and thanks for providing these tools to the CAD community!

Link to comment
Share on other sites

Ahh, yes, missed that bit, try

 

(C:LAT "30")

 

Don't need to add the 'command' to run a LISP within a LISP and remember to use exactly as the LISP name is (here including the C).

 

Link to comment
Share on other sites

16 minutes ago, Steven P said:

Ahh, yes, missed that bit, try

 

(C:LAT "30")

 

Don't need to add the 'command' to run a LISP within a LISP and remember to use exactly as the LISP name is (here including the C).

 

Thank you Steven, I should have refreshed before posting my last message. I'll give it a shot!

Link to comment
Share on other sites

1 hour ago, CAD Geek said:

For some reason, even if I remove the code for the freezing and thawing of layers toward the end of my Lisp routine, I am still running into trouble with ScriptWriter not continuing past the first drawing.

 

My point is that if you need to respond to a LISP prompt from a Script, the response cannot be in the LISP routine, it must be part of the Script; hence moving the commands within your LISP routine will have no effect on the outcome.

Instead, a better approach is to either:

  • Develop an entirely autonomous LISP program which requires no user input and can therefore simply be loaded & run.
    OR
  • Remove all of the command calls from your LISP program and perform these from the Script instead.
  • Like 1
Link to comment
Share on other sites

1 hour ago, CAD Geek said:

Thank you Steven, I should have refreshed before posting my last message. I'll give it a shot!

Thanks again Steven, what you mentioned was what I needed to do to fix the code in my lisp routine! Onward and upward 🙂.

 

1 hour ago, Lee Mac said:

 

My point is that if you need to respond to a LISP prompt from a Script, the response cannot be in the LISP routine, it must be part of the Script; hence moving the commands within your LISP routine will have no effect on the outcome.

Instead, a better approach is to either:

  • Develop an entirely autonomous LISP program which requires no user input and can therefore simply be loaded & run.
    OR
  • Remove all of the command calls from your LISP program and perform these from the Script instead.

Hello Lee,

 

That makes complete sense. I was able to get a script to run through the ScriptWriter program once I removed the "-purgestyles" command and replaced it with simply "purgestyles", where the user just needs to press enter when the dialog box pops up a few times, until no styles are left when running the script. I'm not sure how to bypass that dialog box and get the script to work automatically with that command but this scenario is much better than having my script not work at all. I just need to learn more so this is good motivation. Thanks again!

Link to comment
Share on other sites

how about to use ETRANSMIT basic command.

it can do, save as older version, purge, audit, xref binding also.

if you want to purge with another custom option by lisp (layer or something), you just add that into startapp in appload.

Link to comment
Share on other sites

Have you also allowed for Purging CIV3D styles it is separate to the normal purge command and should be ran before running normal PURGE. I am trying to remember I think its purgestylesandsettings. Like purge run at least twice, same with purge.

  • Like 1
  • Agree 1
Link to comment
Share on other sites

47 minutes ago, BIGAL said:

I am trying to remember I think its purgestylesandsettings. Like purge run at least twice, same with purge.

 

simple purge command I use.

;;----------------------------------------------------------------------------;;
;; Purge 3 Times
(defun C:P3 ()
  (repeat 3 (vl-cmdf "_.Purge" "A" "*" "N"))
)

 

  • Like 1
Link to comment
Share on other sites

Mhupp CIV3D has an extra purge just for the CIV3D stuff, it removes a heap of stuff like used CIV3D styles, description keys and more, if you have a block linked to a description key and not used, normal PURGE will not remove, so you still have lots of unused blocks in your dwg. 

 

image.thumb.png.9a1a0877ecd34deb55bedcd460539816.png

 

PURGESTYLES ?

Link to comment
Share on other sites

Hello all, 

 

Thank you for your replies! Using e-transmit can certainly be helpful and I appreciate the ideas and example code. I think the big issue is just getting the civil 3D purgestyles to function without user input. I can get it to work well on a single drawing, since it just continues on if there are no styles left to purge, even if it throws an error and doesn't recognize the next asterisk to purge all styles, but I haven't been able to get it to work on multiple drawings without user input.  It doesn't slow me down much to press the enter keys as soon as the dialog box pops up but it would be nice to have it breeze through while Someone takes a quick break and have it done when they return without further input. Thanks again, I really appreciate all of the good ideas and help!

Link to comment
Share on other sites

Hello BigAl,

 

My apologies for the late reply. If I set filedia to 0 and run purgestyles or -purgestyles it still brings up the "Style Purge Confirmation" dialog box. I'm sure there is some way to bypass it but I'm not sure yet.

 

Thanks!

 

 

Link to comment
Share on other sites

I don't have a "Purgestyles" command in vanilla AutoCAD so I can't test, but maybe try (setvar "cmddia" 0) and (setvar "nomutt" 1)? Make sure you set them back to default again before you close each drawing.

 

P.S. - if that doesn't work, try (setvar "QAFLAGS" 4). MAKE SURE this gets set back to 0 before closing the script.

Edited by pkenewell
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...