gekusei88 Posted July 19, 2013 Posted July 19, 2013 Can anyone tell me whether it's possible to carry forward variables defined in one drawing to another in a batch sequence? I am trying to batch run a routine across a directory of drawings after defining some "master" variables. The routine is to simply change the color of a specific layer to a defined color. I am utilizing Lee Mac's batch code, and the ".-layer" command. We have hundreds of drawings that simply need the single layer color changed; i'd like to be able to define the new color and layer name, then run the .-layer with these parameters globally. I've attached what i've got thus far, thanks everyone. (defun c:BATCHLAY (/ wfile rfile ofile dir bna) (setq mlna (entget (car (entsel)))) (setq lcent (assoc 8 mlna)) (setq lna (cdr lcent)) (setq mcolor (getstring "Enter new layer color name:")) (if (and (setq wfile "C:\\lay_color.scr") (setq rfile (getfiled "\nSelect File from Directory to Read: " "" "dwg" )) (progn (setq ofile (open wfile "w")) (foreach x (vl-directory-files (setq dir (vl-filename-directory rfile)) "*.dwg" 1) (write-line (strcat "open \"" dir "\\" x "\" (c:LAYCLR) qsave close") ofile) ) (close ofile) (command "script" wfile) ) (princ "\n<!> File Selection Error <!>")) (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun c:LAYCLR () (command ".-layer" "C" mcolor lna "") (princ) ) Quote
Shneuph Posted July 19, 2013 Posted July 19, 2013 Try storing the layer name and color varibles in environmental variables like this: (untested) (defun c:BATCHLAY (/ wfile rfile ofile dir bna) (setq mlna (entget (car (entsel)))) (setq lcent (assoc 8 mlna)) (setenv "gek-lna" (cdr lcent)) (setenv "gek-mcolor" (getstring "Enter new layer color name:")) (if (and (setq wfile "C:\\lay_color.scr") (setq rfile (getfiled "\nSelect File from Directory to Read: " "" "dwg" )) (progn (setq ofile (open wfile "w")) (foreach x (vl-directory-files (setq dir (vl-filename-directory rfile)) "*.dwg" 1) (write-line (strcat "open \"" dir "\\" x "\" (c:LAYCLR) qsave close") ofile) ) (close ofile) (command "script" wfile) ) (princ "\n<!> File Selection Error <!>")) (princ) ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun c:LAYCLR () (command ".-layer" "C" (getenv "gek-mcolor") (getenv "gek-lna") "") (princ) ) Quote
Dadgad Posted July 20, 2013 Posted July 20, 2013 Welcome to CADTutor! While not as sexy as a custom lisp, you could do this with the STANDARDS CHECKER, by applying a .dws to the drawings. Quote
irneb Posted July 20, 2013 Posted July 20, 2013 Look into vl-propagate Or also vl-bb-set & vl-bb-ref If you run your code through something like ScriptPro it might not work though. Seeing as ScriptPro starts & stops a new session of ACad for each DWG - which would clear all these variables. In that case I'd advise an external file, or registry. Simplest version as per Shneuph's post. BTW, for this batch file I might rather think of doing it through ObjectDBX. Would run a lot faster, but would require rewriting all the code to use ActiveX. Quote
pBe Posted July 20, 2013 Posted July 20, 2013 If you run your code through something like ScriptPro it might not work though. Seeing as ScriptPro starts & stops a new session of ACad for each DWG - which would clear all these variables. In that case I'd advise an external file, or registry. Not sure about ScriptPro but never had a problem with using vl-propagate thru run-on-the-mill script though. Now that you mentioned ODBX , will vl-propagate work with that? [curious is all] Quote
gekusei88 Posted July 20, 2013 Author Posted July 20, 2013 Thanks for the replies everybody, and thanks for the warm welcome. I tried the environmental variable modification you made Shneuph, it didn't seem to work out of the box, but that is definitely an interesting idea using the environmental variables. I wasn't aware that you could add to them in this way (I've just started using autolisp), so i'll tinker with this idea some more later for sure. As far as using the Standards Checker with a .dws, this is the usual route i suggest our users take. However, to my knowledge you have to run the checker inside of each drawing and there is no batch checker built in. Seeing as this change is so simple, and there are so many drawings, this wouldn't be much of an advantage to doing the change manually. As far as all the other ideas, I will look into each of these! I am not familiar with most listed since i've only been doing this for a few weeks, so that's plenty of learning material to check out. Quote
Lee Mac Posted July 20, 2013 Posted July 20, 2013 For ensuring data is accessible between drawings, I would personally opt for utilising the blackboard namespace (i.e. vl-bb-set / vl-bb-ref) as Irnéb has suggested; indeed, this is in fact the method that I implement in my Batch Attribute Editor program to facilitate transferring attribute data between each drawing processed by the Script (refer lines 1015 & 1023). With regards to the use of environment variables (i.e. setenv / getenv), since these functions write data to the registry [default location: (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\FixedProfile\\General")], I would advise that you use environment variables sparingly to avoid needlessly bloating the registry. As far as using the Standards Checker with a .dws, this is the usual route i suggest our users take. However, to my knowledge you have to run the checker inside of each drawing and there is no batch checker built in. As far as I know, there should be a 'Batch Standards Checker' included with the programs files for most (if not all) AutoCAD versions. Documentation: http://exchange.autodesk.com/autocad/enu/online-help/browse#WS1a9193826455f5ffa23ce210c4a30acaf-4dad.htm Quote
gekusei88 Posted July 21, 2013 Author Posted July 21, 2013 Thanks for the help Lee, I must apologize though, I misspoke about the batch checker. I was aware of it, but as far as i knew it only generated a report of all the discrepancies compared against your .dws file vs. the individual checker which you can actually make the corrections. What I'm trying to achieve here is basically that, but a simplified version for now. However, the "Batch Attribute Editor" lisp you wrote is essentially exactly what i was attempting to manipulate ATTIN to do in my first post on these forums! Obviously you're way more knowledgeable than I, and have developed something greater than the (not so) simple route I was attempting of removing user input and defining file import location using that Express Tools ATTIN function. While it's sort of depressing that I wasn't the first to attempt such a thing, it is at the same time awesome that there has already been a clear need for that! Atleast now i can stop attempting things that are still out of my league and get back to learning lol. I'll check out the "vl-bb-set / vl-bb-ref" suggestions and appreciate the heads up about cluttering up the registry, god knows that gets bad enough on it's own. Quote
irneb Posted July 21, 2013 Posted July 21, 2013 With regards to the use of environment variables (i.e. setenv / getenv), since these functions write data to the registry [default location: (strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\FixedProfile\\General")], I would advise that you use environment variables sparingly to avoid needlessly bloating the registry.Another reason is that you might choose a name for the variable which already exists as a standard setting for ACad. So you might be overwriting something which ACad needs. As far as I know, there should be a 'Batch Standards Checker' included with the programs files for most (if not all) AutoCAD versions.[/url] Unfortunately that only checks and reports, it doesn't do batch changes. Not sure about ScriptPro but never had a problem with using vl-propagate thru run-on-the-mill script though.This is one of the reasons I don't like ScriptPro. IMO it's silly to close the entire ACad, then start a new one for each DWG you want to run through. It's the same principle as some of the old (pre-windows) methods of using a DOS .BAT file to start ACad with a particular DWG and SCR, then close and resart it with the next. There are "better" batch scripting systems which don't close ACad though, e.g. (my favourite) AutoScript, which runs inside acad and doesn't need to start-stop sessions. It even tends to run faster than SprintPro, in my experience at least. [/b] Yep. ODBX means your LSP simply runs inside the current DWG, it never needs to close and open the current Document, so there's no need to share values across name spaces. Quote
irneb Posted July 21, 2013 Posted July 21, 2013 As a sample, here's the ODBX version of your code (vl-load-com) ;;; Gets the ODBX object for use on external DWGs (defun DBX:GetODBX-Object (/ classname Register) (defun Register (classname filename / server acver) (cond ((not (and classname filename)) (Register (strcat "ObjectDBX.AxDbDocument." (itoa (setq acver (atoi (getvar 'ACadVer))))) (strcat "AxDb" (itoa acver) ".dll"))) ((vl-registry-read (strcat "HKEY_CLASSES_ROOT\\" classname "\\CLSID")) classname) ((and (setq server (findfile filename)) (startapp "regsvr32.exe" (strcat "/s \"" dll "\"")) (vl-registry-read (strcat "HKEY_CLASSES_ROOT\\" classname "\\CLSID"))) classname))) (if (setq classname (Register nil nil)) (vla-getinterfaceobject (vlax-get-acad-object) classname))) ;;; Asks user to choose a folder and returns the paths to all DWGs in that folder (defun BLC:GetDWGs (/ path) (if (setq path (getfiled "\nSelect File from Directory to Read: " "" "dwg" 0)) (mapcar (function (lambda (filename) (strcat path "\\" filename))) (vl-directory-files (setq path (vl-filename-directory path)) "*.dwg" 1)))) ;;; Runs a function on each DWG in the list, passing a Document object to the function (defun BLC:RunDWGs (dwgList code / odbx result) (setq result (cond ((vl-catch-all-error-p (setq odbx (vl-catch-all-apply 'DBX:GetODBX-Object))) nil) (t (mapcar (function (lambda (path / result) (cond ((vl-catch-all-error-p (vl-catch-all-apply 'vla-Open (list odbx path))) nil) (t (setq result (vl-catch-all-apply code (list odbx))) (vl-catch-all-apply 'vla-Close (list odbx)) (cons path result))))) dwgList)))) (cond (odbx (vl-catch-all-apply 'vlax-release-object (list odbx)))) result) ;;; Asks user to pick an object & a folder of DWG's to set all their corresponding layers ;;; to the same colour as the object's layer (defun c:BatchLayCol (/ ent lay col files DoChange) (if (and (setq ent (entsel)) (setq files (BLC:GetDWGs)) (setq ent (vlax-ename->vla-object (car ent))) (setq lay (vla-Item (vla-get-Layers (vla-get-Document ent)) (vla-get-Layer ent))) (setq col (vla-get-Color lay))) (progn (defun DoChange (doc / ) (vla-put-Color (vla-Item (vla-get-Layers doc) (vla-get-Name lay)) col) (vla-SaveAs doc (vla-get-Name doc)) "done") (foreach result (BLC:RunDWGs files 'DoChange) (princ "\n") (princ (car result)) (princ "\t") (princ (cond ((vl-catch-all-error-p (cdr result)) (cond ((wcmatch (strcase (setq result (vl-catch-all-error-message (cdr result)))) "*DESCRIPTION WAS NOT PROVIDED*") "File read-only or opened by someone else.") (result))) (t (cdr result))))))) (command "_TextScr") (princ)) Quote
Lee Mac Posted July 21, 2013 Posted July 21, 2013 I must apologize though, I misspoke about the batch checker. I was aware of it, but as far as i knew it only generated a report of all the discrepancies compared against your .dws file vs. the individual checker which you can actually make the corrections. Unfortunately that only checks and reports, it doesn't do batch changes. My apologies, I knew that the Batch Standards Checker utility existed but, being a programmer and not a draftsman, I admit that I have rarely used it. However, the "Batch Attribute Editor" lisp you wrote is essentially exactly what i was attempting to manipulate ATTIN to do in my first post on these forums! Obviously you're way more knowledgeable than I, and have developed something greater than the (not so) simple route I was attempting of removing user input and defining file import location using that Express Tools ATTIN function. While it's sort of depressing that I wasn't the first to attempt such a thing, it is at the same time awesome that there has already been a clear need for that! Atleast now i can stop attempting things that are still out of my league and get back to learning lol. Thank you gekusei, that's very kind of you to say. The Batch Attribute Editor program is my most recent and extensively developed version of a generic attribute editing program; in a previous incarnation: my Global Attribute Editor, I utilised ObjectDBX (as Irnéb has suggested in this thread) to modify attribute values across multiple drawings, however, due to poor GUI design, this program would only permit modification of attribute values within all references of a single block, and not multiple blocks in a drawing. Furthermore, the user could only process an entire directory of drawings, rather than selecting individual drawings to be processed, as permitted by my more recent program. At this point, you may think it odd that for a more recently developed program I would opt to utilise a Script as the batch processing engine over the ostensibly more advanced ObjectDBX technology, however, although ObjectDBX is powerful when extracting data from a set of drawings, this under-developed technology has several disadvantages when used for editing. Autodesk unfortunately never fully developed ObjectDBX (or Visual LISP with ActiveX for that matter), since their efforts moved to the far more powerful .NET framework; consequently, the ObjectDBX interface has several known bugs (and perhaps many more unknown bugs yet to be unearthed). To provide some examples: when saving a drawing through ObjectDBX one cannot specify the version parameter for the ActiveX saveas method and all drawings must subsequently be saved to the native version (i.e. the highest version available in the host application [e.g. running the Global Attribute Editor program in AutoCAD 2013 will result in all processed drawings being saved to 2013 format, which is usually unsuitable for most companies where it is common that company policies involve saving down to a lower version for compatibility]); conversely, note that a Script engine will adhere to the save version specified within the 'Options' menu. Furthermore, saving a drawing using ObjectDBX results in a loss of the drawing thumbnail until the next manual save; this is not usually too detrimental for most users, however, it is a minor annoyance which can again be avoided by using a Script processing engine. More importantly however, the more prominent bugs arise when editing text or attribute objects in drawings processed with ObjectDBX: if the text or attribute object has a justification other than Left, the text or attribute position will not update to reflect the justification setting following modification of the content. In my Global Attribute Editor program I have attempted to account for this known bug by including a separate subfunction to shift the text position by a calculated displacement based upon the content, text size & text style of the object in question – however, this is far from ideal. And again, this issue doesn't arise when using a Script processing engine. In conclusion, ObjectDBX is still a very powerful tool which enables very fast batch processing of drawings and I continue to use this technology for data extraction, but the interface has limited uses in the realm of batch drawing editing in my opinion. Sorry for the essay! I'll check out the "vl-bb-set / vl-bb-ref" suggestions and appreciate the heads up about cluttering up the registry, god knows that gets bad enough on it's own. You're very welcome - if you have any further questions, just ask. Quote
Recommended Posts
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.