Jump to content

Redefine PLOT command to stop if it finds non-printable layers


X11start

Recommended Posts

I would like to redefine the "PLOT" command, to make sure that a check is made before plotting: if non-printable layers are found, it asks the user whether to continue or stop printing.
(I use https://jtbworld.com/autocad-layer-state-lsp by Jimmy Bergmark to find non-plottable layers)

 

The problem arises from the fact that it is not difficult to execute commands BEFORE (command "_plot"); As also done in this threed

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/plot-with-message-option/m-p/6866640#M349621

 

... but in my case the commands (the verification to be done), are AFTER (command "_plot")... and this doesn't work for me!

Link to comment
Share on other sites

;;; https://www.cadtutor.net/forum/topic/91391-redefine-plot-command-to-stop-if-it-finds-non-printable-layers/
;;; stolen & modified from here :
;;; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/plot-with-message-option/td-p/6862537

(vl-load-com)
(command "_.undefine" "PLOT")
(defun c:plot  (/ wsobj)
 (if (and (vl-consp (layer-state 8)) (= 7 (vlax-invoke (setq wsobj (vlax-get-or-create-object
      "wscript.shell")) 'popup "Non-plotable layers detected, continue anyway??" 5 "Plot Warning" 4)))
    (progn (vlax-invoke wsobj 'popup "Ok, goodbye" 5 "Plot Warning" 0)(vlax-release-object wsobj))
    (progn (initdia) (command "._plot"))
  )
  (princ)
)

;;; https://jtbworld.com/autocad-layer-state-lsp : List layers according to state
;;; By Jimmy Bergmark, Copyright (C) 1997-2006 JTB World, All Rights Reserved
;;; Website: www.jtbworld.com, E-mail: info@jtbworld.com, 2000-05-15
;;; Argument: state: 1 frozen, 2 thawed, 3 on, 4 off, 5 lock, 6 not locked, 7 plottable, 8 not plottable
;;; Example: (layer-state 1) , Return values: list of layers
(defun layer-state (state / typ names tf skip) (setq names nil)
  (vlax-for layer (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))
    (setq skip nil)
    (cond
      ((= 1 state) (setq typ (vla-get-freeze layer) tf :vlax-true))
      ((= 2 state) (setq typ (vla-get-freeze layer) tf :vlax-false))
      ((= 3 state) (setq typ (vla-get-layeron layer) tf :vlax-true))
      ((= 4 state) (setq typ (vla-get-layeron layer) tf :vlax-false))
      ((= 5 state) (setq typ (vla-get-lock layer) tf :vlax-true))
      ((= 6 state) (setq typ (vla-get-lock layer) tf :vlax-false))
      ((= 7 state) (setq typ (vla-get-plottable layer) tf :vlax-true))
      ((= 8 state) (setq typ (vla-get-plottable layer) tf :vlax-false))
      (t (setq skip T))
    )
    (if (and (null skip) (eq typ tf))
      (setq names (cons (vla-get-name layer) names))
    )
  )
  (reverse names)
)

 

Edited by rlx
added Jimmy's layer-state & changed state from lock to non plottable
Link to comment
Share on other sites

Thank you for the answer RLX, but my problem was just to do the layer check AFTER running the 'Plot', but BEFORE the printing starts. This is because there may be non-printable layers, but it's not a problem if I don't include them in the print area.

 

... so I should do the layer check AFTER...

(initdia) (command "._plot")

... but before the plotter starts printing, because only now I have defined the area to be printed.

 

Sorry if I don't explain myself correctly: my English is shaky!

Link to comment
Share on other sites

Maybe its better to do a pagesetup first?

something like :

(if (= (getvar "tilemode") 0);paperspace
  (command
   ".-Plot"             ;command
   "Yes"                ;detailed
   ""                   ;layout name
   prtname              ;printername
   papsize              ;papersize
   "Millimeters"        ;millimeters
   Orientation          ;landscape/portrait
   plotupsidedown       ;plot upside down
   "E"                  ;plotarea (Display/Extends/Layout...) , in ps 1 kader!
   "Fit"                ;plotscale
   "0,0"                ;offset OR center ;;;;;;;;;
   "Yes"                ;plot with styles
   pstname              ;plotstyle name
   "Yes"                ;plot with lineweights
   "No"                 ;scale lineweights with scale
   "No"                 ;plot paperspace last
   "No"                 ;remove hidden lines
   "No"                 ;write plot to a file
   "No"                 ;save changes to lay-out
   "No"                 ;proceed with plot
  )
  (command
   ".-Plot"             ;command
   "Yes"                ;detailed
   ""                   ;layout name
   prtname              ;printername
   papsize              ;papersize
   "Millimeters"        ;millimeters
   Orientation          ;landscape/portrait
   plotupsidedown       ;plot upside down
   "E"                  ;plotarea (Display/Extents/Limits/View/Window)
   "Fit"                ;plotscale
   "Center"             ;offset
   "Yes"                ;plot with styles
   pstname              ;plotstyle name
   "Yes"                ;plot with lineweights
   ""                   ;shade plot setting [As displayed/Wireframe/Hidden/Rendered] <as displayed>
   "No"                 ;write plot to a file
   "No"                 ;save changes to model-tab
   "No"                 ;proceed with plot
  )
 )
)

 

Link to comment
Share on other sites

Of course: I could pass parameters of a plot configuration without DCL... but it's inconvenient: it seems to go back to Autocad version 1

 

Or you could create a 'simple' DCL, which only asks me the area to print, then I do the layer check and if it finds everything ok, it launches the complete PLOT command...

Edited by X11start
Link to comment
Share on other sites

This will give a list of layers for a selection:

 

(defun c:ObjLayers ( / acount MySS MyEnt MyLayer layers)
;;Set up
  (setq acount 0)                      ; just a counter
  (setq layers (list))                 ; empty list for layers
;;End set up

;;Do stuff
  (setq MySS (ssget))                  ; Select objects. Add filters if required
  (while (< acount (sslength MySS))    ; Loop through selection set
    (setq MyEnt (ssname MySS acount))  ; nth entity in selection set
      (setq MyLayer (cdr (assoc 8 (entget MyEnt))) ) ; entity is on layer...
      (if (member MyLayer layers)      ; If layer is recorded in list
        ()                             ; do nothing
        (setq layers (append (list MyLayer) layers) ) ; else add to list
      ) ; end if
    (setq acount (+ acount 1))         ; increment counter
  ) ; end while
  layers                               ; return layers list
)

 

Add this into RLX code above for the layers list should work? The layers are listed from a selection set of objects (ssget) which works well if you are selecting the plotting area from modelspace. If you are in paperspace you'll need to switch to modelspace and assess the layers from objects shown in viewports Modifying this:

https://jtbworld.com/autocad-vp-outline-lsp

to give you the viewport area in model space, and run my code above with 'ssget' modified to include 'CP' (see Lee Macs ssget reference page)

 

If you are whichever way you are plotting I would perhaps use "CP" in the ssget anyway, and add a couple of lines in the code to get plot araa points. Cary those points through the code to the ssget line and the plot line

 

 

Link to comment
Share on other sites

1 hour ago, X11start said:

Of course: I could pass parameters of a plot configuration without DCL... but it's inconvenient: it seems to go back to Autocad version 1

 

Or you could create a 'simple' DCL, which only asks me the area to print, then I do the layer check and if it finds everything ok, it launches the complete PLOT command...

 

As an example my plotpdf routine has a bespoke DCL - I generally don't need all the functions of the AutoCAD plot dialogue - it is all set. For a batch LISP to plot many drawings I have no dialogue box. Having the custom DCL means all the settings I always use are set, the options are there for the ones I occasionally use but generally do "Plotpdf - 'enter' " - very fast for my standard plotting, so I wouldn't discard RLX 2nd answer above.

 

Different paper sizes are 'plota3' 'plota2' and so on for example with suffix 'm' for monochrome

Link to comment
Share on other sites

I tried to put together the advice of RLX and STEVEN (whom I thank!). The attached lisp is not complete because it checks the non-printable layers on the ALL drawing, instead of doing it only on the selected window: you need to change the 'IF' of RLX, but I don't know how to use the VL-XXX commands... I should write a much longer code!

plot.lsp

Link to comment
Share on other sites

If you are printing a layout with a viewport, couldn't you just check if the layers within the layout's viewport are set to plot and warn if not?

Link to comment
Share on other sites

... I didn't say that in our company it is 'forbidden' to use layouts: the 'boss' doesn't know how to use them.... so i can only use 'Model space' !!

Link to comment
Share on other sites

Time to change the boss to make it easier for the people who do the actual work? Should be able to use the code from mine and RLX fairly straight forwrad but I haven't had change today to look

  • Like 1
Link to comment
Share on other sites

Try this:

(it used the above with a small addition in jtbworld code to check if the plot selection contains locked layers)

 

Couple of notes of things to check in there which you can think about

 

 

(defun c:APlot  (/ wsobj)
  (vl-load-com)
;;Sub Routines
;;Get list of entity description by 'key'
  (defun mAssoc ( key lst / result ) ;;https://www.cadtutor.net/forum/topic/27914-massoc-implementations/
   (foreach x lst
     (if (= key (car x))
       (setq result (cons (cdr x) result))
     )
   )
   (reverse result)
  )

;;Get object layers within rectangle pt1, pt3
  (defun ObjLayers ( pt1 pt3 / acount MySS MyEnt MyLayer layers)
  ;;Set up
    (setq acount 0)                      ; just a counter
    (setq layers (list))                 ; empty list for layers
  ;;End set up
  ;;Do stuff
    (setq MySS (ssget "_C" pt1 pt3))     ; Select objects. Add filters if required. Fails if user zooms into crossing area
    (while (< acount (sslength MySS))    ; Loop through selection set
      (setq MyEnt (ssname MySS acount))  ; nth entity in selection set
        (setq MyLayer (cdr (assoc 8 (entget MyEnt))) ) ; entity is on layer...
        (if (member MyLayer layers)      ; If layer is recorded in list
          ()                             ; do nothing
          (setq layers (append (list MyLayer) layers) ) ; else add to list
        ) ; end if
      (setq acount (+ acount 1))         ; increment counter
    ) ; end while
    layers                               ; return layers list
  )


;;; https://www.cadtutor.net/forum/topic/91391-redefine-plot-command-to-stop-if-it-finds-non-printable-layers/
;;; stolen & modified from here :
;;; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/plot-with-message-option/td-p/6862537
;;; https://jtbworld.com/autocad-layer-state-lsp : List layers according to state
;;; By Jimmy Bergmark, Copyright (C) 1997-2006 JTB World, All Rights Reserved
;;; Website: www.jtbworld.com, E-mail: info@jtbworld.com, 2000-05-15
;;; Argument: state: 1 frozen, 2 thawed, 3 on, 4 off, 5 lock, 6 not locked, 7 plottable, 8 not plottable
;;; Example: (layer-state 1) , Return values: list of layers
;;  (defun layer-state (state / typ names tf skip) (setq names nil)
  (defun layer-state (state layers / typ names tf skip) (setq names nil) ;; added 'layers'
    (vlax-for layer (vla-get-Layers (vla-get-ActiveDocument (vlax-get-acad-object)))
      (setq skip nil)
      (if (member (vla-get-name layer) layers)(progn ;; Added this
      (cond
        ((= 1 state) (setq typ (vla-get-freeze layer) tf :vlax-true))
        ((= 2 state) (setq typ (vla-get-freeze layer) tf :vlax-false))
        ((= 3 state) (setq typ (vla-get-layeron layer) tf :vlax-true))
        ((= 4 state) (setq typ (vla-get-layeron layer) tf :vlax-false))
        ((= 5 state) (setq typ (vla-get-lock layer) tf :vlax-true))
        ((= 6 state) (setq typ (vla-get-lock layer) tf :vlax-false))
        ((= 7 state) (setq typ (vla-get-plottable layer) tf :vlax-true))
        ((= 8 state) (setq typ (vla-get-plottable layer) tf :vlax-false))
        (t (setq skip T))
      )
      (if (and (null skip) (eq typ tf))
        (setq names (cons (vla-get-name layer) names))
      )
      )) ; end if ; end progn ; Added this
    )
    (reverse names)
  )

  (defun aplot ( pt1 pt3 / ) ;; Do a check that for example a plotter is specified for the layout
    (command
       ".-Plot";command
       "_Yes"  ;detailed
       ""      ;layout name
       ""      ;printername
       ""      ;papersize
       "_Millimeters" ;millimeters
       ""      ;landscape/portrait
       ""      ;plot upside down
       "_W"    ;plotarea (Window)
       pt1
       pt3
       ""      ;plotscale
       "0,0"   ;offset OR center ;;;;;;;;;
       "_Yes"  ;plot with styles
       ""      ;plotstyle name
       "_Yes"  ;plot with lineweights
       ""      ;Wireframe
       "_No"   ;write plot to a file
      "_Yes"   ;save changes to lay-out
       "_No"   ;proceed with plot
    )
    (princ "\nPlotted")
  )

;;End sub routines

;; Do check for modelspace / paperspace here
;; if modelspace....

;;Get plot area. Verticies 1 & 3
  (princ "\nSelect Print Area\n")
  (command "rectangle" pause pause)
  (setq PlArea (entget (entlast)))
  (setq PlArea (massoc 10 PlArea))
  (entdel (entlast))
  (setq pt1 (car PlArea))
  (setq pt3 (caddr PlArea))

;;Get layers
  (setq layers (ObjLayers pt1 pt3))

;;Check if layers are non-plotting
  (if (and
        (vl-consp (layer-state 8 layers))
        (= 7 (vlax-invoke (setq wsobj (vlax-get-or-create-object "wscript.shell")) 'popup "Non-plotable layers detected, continue anyway??" 5 "Plot Warning" 4)))
    (progn (vlax-invoke wsobj 'popup "Ok, goodbye" 5 "Plot Warning" 0)(vlax-release-object wsobj))
    (progn (initdia) (aplot pt1 pt3))
  )

  (princ)
)

 

Edited by Steven P
Link to comment
Share on other sites

10 hours ago, X11start said:

... I didn't say that in our company it is 'forbidden' to use layouts: the 'boss' doesn't know how to use them.... so i can only use 'Model space' !!

That might be the worst thing I've ever heard.

Thing about bosses is, from time-to-time, they need to be reminded they don't always have the answers. 

  • Like 2
Link to comment
Share on other sites

There is so much out there about automating making layouts, depending on the type of dwg it can be pick a point and plot scale the layout is made and the mview created at the desired scale. I did lots of road works so pick a road pline and scale, layouts were then made. Same with plotting just choose output type A3 A1 or pdf then watch plots come out.

 

Post at least an image of your model dwg. Can make more comments so will others.

Link to comment
Share on other sites

I improved the data input a bit (I adding from initial version of RLX and Steven, a functions by Terry Miller - Lee Mac and other "Gurus" of the lisp language!), and made an Italian/English version of it.

 

For 30 years now I have been a designer and I enjoy making lisp programs... without however reaching the levels of you of the forum, whom I thank for your generosity, in dedicating time to us "eternal rookies".

 

As for my 'boss', I can quote a great of our Italian language... Dante Alighieri: "Don't care about them... but look and pass".

 

Thank's all

plot.lsp

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...