I'm creating a drawing set that has over 100 sheets with varying amounts of viewports on each sheet (from one to four). Each sheet is its own file, so there is only one layout per file. For each section of the drawing set, the viewports will have the same layer state.
Is there were a way to update the layerstate of each viewport through a batch LISP routine? This would save me DAYS in opening each file, importing the layer state, and restoring it for each viewport. It seems straight forward, but I have no idea where to start with batch routines. Any help or reference is appreciated.
Thanks!
Given that LayerState-Restore takes an ENAME parameter, presumably (as I have not tested for myself) there's a chance that ObjectDBX *might* be able to perform this operation, with the use of Vlax-Vla-Object->Ename function... Again, that's *if* this API feature is exposed to ObjectDBX Documents.
If not, then the only other way I can think of... Again having not tried, so I could be mistaken... Would be to batch process each drawing by opening as a side Database via ReadDwgFile() in .NET API, cull the applicable Viewport ObjectIds (skipping the first) for each Layout via GetViewports() Method, and then call the RestoreLayerState() Method on each of said ObjectIds.
HTH
"How we think determines what we do, and what we do determines what we get."
BlackBox, excellent suggestions! I nailed the lisp with help from MSasu on one of CADTutor's old threads (see code).
I tried running it with LeeMac's ScriptWriter; although, acad crashes on the third file it runs through. I'm sure it's the large external references that are are overlaid. The uLS lisp is loaded with acaddoc.lsp thanks for that hint!
Is there anything other than .NET that can run through a directory and run the routine (not familiar with .net)? Parital open in a lisp - does that exist?
(defun c:uLS ( / vportlist vport) (layerstate-import "P:\\AutoCAD\\Layer States\\L1.las") (if (/= (getvar "ctab") "model") (progn (setq vportlist (vl-sort (vports) '(lambda (v1 v2) (< (car v1) (car v2))))) (if (> (length vportlist) 1) (progn (command "_mspace");activate vport (foreach vport (cdr vportlist) (setvar "cvport" (car vport)) (layerstate-restore "L1" (vlax-vla-object->ename (vla-get-activepviewport (vla-get-activedocument (vlax-get-acad-object)))) 4);restore );foreach (command "pspace");deactivate vport );progn );if );progn );if );defun
You're welcome; I'm happy to help.
Sorry for the delay in getting back to you - I'm actually a CAD production guy by day, and have several deadlines to meet this week.
I did throw some code together in my spare time, but need to do more testing to be certain... In preliminary, it doesn't appear the ObjectDBX will be an option, but I do not receive any exceptions (errors) when calling LayerState-Restore on each Viewport via DBX, so I want to re-confirm.
*If* in fact DBX cannot be used to keep this in LISP, I'll look into putting together a .NET option for you.
For the time being, this may help with drawings opened in the editor, and will apply the selected layer state to each Viewport, on every Layout (with exception to the first - the Layout), for the current drawing:
(vl-load-com) (defun c:LayerStateRestoreAll (/ *error* ss layouts options lastRestored option acDoc n i found) (defun *error* (msg) (if acDoc (vla-endundomark acDoc) ) (cond ((not msg)) ; Normal exit ((member msg '("Function cancelled" "quit / exit abort"))) ; <esc> or (quit) ((princ (strcat "\n** Error: " msg " ** "))) ; Fatal error, display it ) (princ) ) (if (and (setq ss (ssget "_x" '((0 . "VIEWPORT")))) (< (length (setq layouts (layoutlist))) (sslength ss)) (setq options (layerstate-getnames)) (not (initget (setq options (vl-string-right-trim " " (apply 'strcat (mapcar (function (lambda (x) (strcat x " "))) options ) ) ) ) ) ) (or (setq option (getkword (strcat "\nEnter layer state to restore to all viewports [" (vl-string-translate " " "/" options) "]" (if (setq lastRestored (layerstate-getlastrestored)) (strcat "<" lastRestored ">:") ":" ) ) ) ) (setq option (cond (lastRestored lastRestored) ((= 1 (length options)) (car options)) ) ) ) ) (progn (vla-startundomark (setq acDoc (vla-get-activedocument (vlax-get-acad-object))) ) (foreach layout layouts (setq found (setq ss nil)) (if (setq ss (ssget "_x" (list '(0 . "VIEWPORT") (cons 410 layout))) ) (progn (repeat (setq i (setq n (sslength ss))) (if found (layerstate-restore option (ssname ss (setq i (1- i))) 4 ) (setq found (setq i (1- i))) ) ) (prompt (strcat "\nLayer state \"" option "\" applied to " (itoa (setq n (1- n))) " viewport" (if (= 1 n) "" "s" ) " on \"" layout "\" tab. " ) ) ) ) ) ) (cond (ss (prompt "\n** No layer states found ** ")) ((prompt "\n** No viewports found ** ")) ) ) (*error* nil) )
Cheers
"How we think determines what we do, and what we do determines what we get."
Hello
I too would love to be able to change layerstates per viewport in each tab, where the tab has more than 1 viewport, bu the layerstate is a differnet one based on the first letter of the TAB name
A tab may be named P 93 ( Plan that starts at 93+00)
or
A tab may be named s 93 ( Striping that starts at 93+00)
so if the LSP open the next tab the viewports in the P xx tab would be layerstate PLAN
and if
the LSP opens the next tab the viewports in the S xx tab would be layerstate Striping
and then
the LSP opens the next tab the viewports in the X xx tab would be layerstate Xsections
so this LSp would change layerstates based on the TAB 1st letter.
I hope this can be done as I now have to visit every darn tab, open the viewports and then
I use a button I made with this ^C^C(layerstate-restore "_PLAN" (acet-currentviewport-ename))
Its a real pain for a 4.5 mile road with viewports for each layerstate every 600 feet
Thanks for any help / Ed
I have the same situation as the first poster, wanting to be able to update layerstates once through-out the entire drawing. This seems like something Autodesk could fix. Instead of editing one layerstate and then having to go to every viewport that the layerstate pertains to and manually restore is a huge time killer. I should only need to edit a layerstate once and then that should filter to all viewports it applies to.
I tried running this code and it does work, "however" it applies the same layerstate to all viewports--regardless of their current layerstate. Which isn't something I'd want since all viewports have layerstates based on different needs.
Can the code be altered so it applies the restore (of the LS you enter at the command line) only if it matches a viewport's current layerstate?
Also note: in order for this to run your layerstate names cannot contain any spaces. If they do you'll need to rename them.
Hi,
I am hoping you can help me. I use ACAD 2016. I am trying to find a lisp routine that could restore a given layer state to all viewports on all layout tabs at the same time. I came across this but when I run it I get this error right after I pick the layer state name that I want to restore.
Invalid option keyword
Can you help me? Did I misunderstand the intended use of this lisp?
Thank you.
Henry, this routine has developed quite a bit in the years. The command runs as part of a script that recognizes the drawing name and associates it with a layerstate name then applies it to each viewport on the layout tab. There's a particular workflow and naming convention associated with this as well.
If you can list out how you prefer this operation to work, I can help you out.
A few comments I gathered from your post: First, a lisp routine will not "run in the background" or operate "all at the same time." If you're looking for something to do this, I suggest looking into .NET. Next, I have not experimented with the routine running on multiple layout tabs, but I believe it cycles through them. Thrid, the layerstate name can vary as long as there is a condition that is unique to each name. Finally, If you're looking to modify the appearance across all viewports, you may want to check out the variable VISRETAIN.
Cool, I believe I follow you. Can you send over an example file that has multiple tabs set up with each layerstate saved?
I'll relay back what I got from you and see if this matches the overall goal and command processes:
There is one drawing with multiple layouts.
There are three layerstates saved within the drawing that represent different stages of construction or submittals as the case may be.
Your ideal procedure is to...
1. be prompted with a list of layerstates saved within the current drawing and user selects the desired layerstate;
2. be prompted with a list of layout tabs within the current drawing and users selected the desired layouts;
3. the selected layerstate is applied to the user selected layouts.
Also, are you using external references, or is all the linework drawn within the current drawing?
Hi,
I replied to your last post on 2/11 but haven't heard back yet. Just checking to see if you even saw that reply.
Thanks again.
Hi Black box
I have 74 layouts with 2 viewport in each one, I need to update the Layer State only in one viewport which is on the top left (Key View). At the moment I am using the Action Recorder, pick Layer State name & Restore (see attachment) for each layout, can this be batch updated with a lisp routine?
Thanks