Needed! Script To Batch SAVEAS DWG Files To Text Located In Drawing Number Attribute Field

Needed! Script To Batch SAVEAS DWG Files To Text Located In Drawing Number Attribute Field

wanda.keightleyUNM49
Observer Observer
702 Views
8 Replies
Message 1 of 9

Needed! Script To Batch SAVEAS DWG Files To Text Located In Drawing Number Attribute Field

wanda.keightleyUNM49
Observer
Observer

Hi!

Our lovely client is known for changing the rules on drawings, and they've done it again!

 

This time they want hundreds of drawings, which they've previously specified needed to have their number in the file name, changed to their client's number prior to the current submission.

 

I've been playing with scripts to automate tasks, due to the client constantly changing their minds, and I figure there HAS to be a way to do this!

 

The number each file needs to be saved to is located in an Attribute, field name DRAWING NUMBER, so I'm thinking a script that will copy that number & saveas to that number is what's required. But I have no idea of how to begin writing the script (*.scr). Does anyone here have the capability please? 😄

0 Likes
703 Views
8 Replies
Replies (8)
Message 2 of 9

komondormrex
Mentor
Mentor

hi,

what is exactly that 'Drawing Number Attribute Field'?

this one?

komondormrex_0-1695280139374.png

 

0 Likes
Message 3 of 9

wanda.keightleyUNM49
Observer
Observer

It's DRAWING_NUMBER

wandakeightleyUNM49_1-1695280575670.png

 

0 Likes
Message 4 of 9

paullimapa
Mentor
Mentor

And what’s the name of the Block this Attribute Definition is found under? Would there be only one of these blocks found in each dwg?


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 5 of 9

wanda.keightleyUNM49
Observer
Observer

Hi, 

There is only one in each file. The block name is PTA_A1

0 Likes
Message 6 of 9

paullimapa
Mentor
Mentor

Since the client # for example is: 12345 is always the same stored under Block: PTA_A1 under Attribute Tag: DRAWING_NUMBER, when 12345 is retrieved, how do you want to save each drawing as to a unique name ? Do you want to place 123435 as a prefix before the currrent drawing file name?


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 7 of 9

daniel_cadext
Advisor
Advisor

sorry off topic... UNM as in Albuquerque?

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 8 of 9

Sea-Haven
Mentor
Mentor

Whilst others are looking into the block for you it may be worthwhile to use Accoreconsole to modify the dwg's as it very fast, as it does not open the dwg, rather amends the dwg database. Not sure if Getproperty is supported in Accoreconsole as would make getting info much easier.

 

The obvious though is before you start back everything up or do small number of dwg's at a time. 

 

Could you post 1 sample dwg with the block and where it would normally be found. Makes testing easier.

0 Likes
Message 9 of 9

MrJSmith
Advocate
Advocate

@wanda.keightleyUNM49 Unsure where you wanted the files so I just stuck them in a folder under temp files. 

 

 

(defun ngn ( / blk attrs name dest)
	(if (not (vl-catch-all-error-p (setq blk (vl-catch-all-apply '(lambda () (vlax-ename->vla-object (ssname (ssget "_A" '((2 . "PTA_A1"))) 0))) nil))))
		(progn
			(setq attrs (mapcar '(lambda (x) (cons (vla-get-tagstring x) (vla-get-textstring x))) (vlax-invoke blk 'getattributes))
				name (cdr (assoc "DRAWING_NUMBER" attrs))
				dest (strcat (getvar "TempPrefix") "Output Dwgs\\")
			)
			(if (not (vl-file-directory-p dest))
					(vl-mkdir dest)
			)
			(setq dest (strcat dest name ".dwg"))
			(if (findfile dest)
				(vl-file-delete dest)
			)
			(vl-file-copy (vla-get-fullName (vla-get-ActiveDocument (vlax-get-acad-object))) dest)
			(print (strcat "New file has been saved too: " dest))
		)
		(print "Block PTA_A1 not found")
	)	
	(princ)
)

 

 

The easiest way to call the script would be through a script writer. Not sure if you have one, but here is a really simplified version of a basic one that will work as an example.

 

 

(defun SimpleScriptWriter (dwgFiles funcsToLoad lispToRun save / body scrName sn)
	(setq body "")
	(if (= 'LIST (type dwgFiles))
		(progn
			(foreach dwgFilePath dwgFiles
				(setq body ;Normal operation
					(strcat 
						body
						"_.open "
						"\"" dwgFilePath "\" "
						"(setvar \"filedia\" 1) "
					)
				)
				(if (= 'LIST (type funcsToLoad))
					(foreach it funcsToLoad 
						(setq body 
							(strcat
								body
								"(lispLoad \"\" \"" it "\") "
							)	
						)
					)
				)
				(setq body ;Normal operation
					(strcat 
						body
						lispToRun 
						" (setvar \"filedia\" 0) "
					)
				)
				(if save
					(setq body (strcat body "(command \"qsave\")\n"))
					(setq body (strcat body "\n"))
				)
			)
			(setq body (vl-string-right-trim "\n" body))
			(setq body (vl-string-right-trim "\n" body))
			(setq body (vl-string-right-trim " " body))
			(setq scrName (strcat (getvar "TempPrefix") "SimpeScript.scr"))
			(setq sn (open scrName "w"))
			(write-line body sn)
			(close sn)
			; (openAnything scrName) ;for debug purposes
			(setvar "filedia" 0)
			(vl-cmdf "_.script" scrName)
		)
		(notifyExit "No list of files found for SimpleScriptWriter")
	)
)

 

 

Since I don't know where these files are located, I am going to once again assume you stick them all in temp files under "Input Dwgs". In this case, you would call the script like so:

 

 

(defun c:copyDWGsWithNewNames ( / dwgsLocation dwgFiles )
	(setq dwgsLocation (strcat (getvar "TempPrefix") "Input Dwgs\\"))
	(setq dwgFiles (mapcar '(lambda (x) (strcat dwgsLocation x)) (vl-directory-files dwgsLocation "*.dwg" 1)))
	(SimpleScriptWriter dwgFiles nil "(ngn)" nil)
)

 

 

Note: The script writer is so basic that it doesn't close previous files. If you run it on too many drawings, CAD may crash at some point. A better method would be to use the objectDB method. This would require a small modification to the code. 

 

 

(defun ngn ( doc / blk attrs name dest)
	(vlax-for layout (vla-get-layouts doc)
		(vlax-for blk (vla-get-block layout)
			(if
				(and
					(= "AcDbBlockReference" (vla-get-objectname blk))
					(= :vlax-true (vla-get-hasattributes blk))
					(= (vla-get-name blk) "PTA_A1")
				)
				(progn
					(setq attrs (mapcar '(lambda (x) (cons (vla-get-tagstring x) (vla-get-textstring x))) (vlax-invoke blk 'getattributes))
						name (cdr (assoc "DRAWING_NUMBER" attrs))
						dest (strcat (getvar "TempPrefix") "Output Dwgs\\")
					)
					(if (not (vl-file-directory-p dest))
							(vl-mkdir dest)
					)
					(setq dest (strcat dest name ".dwg"))
					(if (findfile dest)
						(vl-file-delete dest)
					)
					(vl-file-copy (vla-get-Name doc) dest)
					(print (strcat "New file has been saved too: " dest))
				)
			)
		)
	)
	(if (not dest) (print "Block PTA_A1 not found"))		
	(princ)
)

 

 

You'd then need to call it via an objectDB wrapper. For example, Lee Mac has one: http://www.lee-mac.com/odbxbase.html. You could then call it in a similar fashion as above.

 

 

(defun c:copyDWGsWithNewNames ( / dwgsLocation dwgFiles )
	(setq dwgsLocation (strcat (getvar "TempPrefix") "Input Dwgs\\"))
	(setq dwgFiles (mapcar '(lambda (x) (strcat dwgsLocation x)) (vl-directory-files dwgsLocation "*.dwg" 1)))
	(LM:ODBX 'ngn dwgFiles nil)
)

 

 

 Note: I don't have his wrapper installed so I was unable to test it. 

 

Lastly, I do not recommend Accoreconsole. It is extremely hard to use. I also disagree with the idea that it "amends" the database. It opens CAD without a GUI. This allows you to use CAD commands which can be useful. However, it doesn't let you load LISPs nor use any VLA type functions. Plus it is slower than ObjectDB method which is actually "amending" the database. ObjectDB basically opens up the drawing as a text file with the limitations being you are unable to use any CAD commands, ssget function, getvars, etc. Everything has to be in VLA or pure LISP.

0 Likes