Batch plot to PDF with custom filenames from titleblock attributes

Batch plot to PDF with custom filenames from titleblock attributes

ad_sherratt
Contributor Contributor
3,536 Views
17 Replies
Message 1 of 18

Batch plot to PDF with custom filenames from titleblock attributes

ad_sherratt
Contributor
Contributor

Hi CAD Gurus,

I’m seeking a plugin or routine that will enable advanced, custom pdf filenaming options over and above the standard batchplot/publish function.

 

Specifically, one that will read the drawing number and revision number attribute values from a titleblock and use these to create the pdf filename(s).

 

I’ve trawled the usual channels for an answer to this one but have so far only found half-solutions at best, and certainly none which will plot a bunch of such custom-named pdfs en masse.

 

Does anyone know if such a thing exists? It sure seems long-overdue…

0 Likes
Accepted solutions (2)
3,537 Views
17 Replies
Replies (17)
Message 2 of 18

Sea-Haven
Mentor
Mentor

If you look at a lisp solution then yes can be done, as you open each layout tab read the values from say a title block and use those as plot name. 

 

Here is a start for you 

 

https://www.cadtutor.net/forum/topic/72253-pdf-plott-lisp/

0 Likes
Message 3 of 18

pbejse
Mentor
Mentor

@ad_sherratt wrote:

..Specifically, one that will read the drawing number and revision number attribute values from a titleblock and use these to create the pdf filename(s).

 

The name of the layout tab is the same as the drawing number?  We can modify the layout name to include the revision via lisp. Then Publish will do the rest for you.

 

They are on layout tabs YES?

 

Or ---> Piggybacking Publish

 

Post a sample drawing, we will write a short code for that.

 

 

 

 

0 Likes
Message 4 of 18

Sea-Haven
Mentor
Mentor

As hinted we made our layoutnames D01, D02 and so on so was easy to manage that way.  Did not use publish but lisp plot, could read titleblock and add revision D01-Rev2 to layout name then have choice publish or lisp.

 

(setq pdfname (getvar "ctab")) as per link.

0 Likes
Message 5 of 18

maratovich
Advisor
Advisor
Accepted solution

No problems.
Use this - Revers Automatic batch printing 
Does everything you need.
I can make a video example if you add an example of your file.

---------------------------------------------------------------------
Software development
Automatic creation layouts and viewport. Batch printing drawings from model.
www.kdmsoft.net
0 Likes
Message 6 of 18

ad_sherratt
Contributor
Contributor

Hi Maratovich,

This sounds like just the kind of thing I'm looking for, a straightforward out-of-the-box application. Have already downloaded the trial version from your website but a quick video tutorial would be helpful, thanks!

Basically I want to create a series of individual pdfs (one for each layout tab) with filenames taken from the DWG_NO attribute followed by the REV_NO attribute value in square brackets, i.e. 14689-E-420 [A], 14689-E-421 [A], 14689-E-422 [A] etc (dwg attached).Example.JPG

0 Likes
Message 7 of 18

ad_sherratt
Contributor
Contributor

Hi pbejse,

Thanks, but I think I may have found what I'm looking for already - see my reply to Maratovich earlier today for further explanation, with a sample dwg attached.

However, if the desired result is actually achievable via a lisp routine, I'm all ears!

0 Likes
Message 8 of 18

pbejse
Mentor
Mentor

@ad_sherratt wrote:

Hi pbejse,

However, if the desired result is actually achievable via a lisp routine, I'm all ears!


Sure you can achieve this via lisp. But it  involves changing the layout tab names to:

14689-E-420 [A], 14689-E-421 [A], 14689-E-422 [A]

So when you use publish, it will take those names. You're good with that?

 

Here's a quick code that works on your sample drawing

 

(Defun c:DwgNumberAndRevToTab (/ aLayouts ss i AttData DwgNo RevNo)
  (setq	aLayouts (vla-get-layouts
		   (vla-get-ActiveDocument (vlax-get-acad-object))
		 )
  )
  (if (setq ss (ssget "_X"
		      '((0 . "INSERT") (2 . "TTLBLK_ATTS_A1H") (66 . 1))
	       )
      )
    (progn
      (repeat (setq i (sslength ss))
	(setq AttData
	       (mapcar
		 '(lambda (at)
		    (list (Vla-get-tagstring at)
			  (vla-get-textstring at)
		    )
		  )
		 (Vlax-invoke
		   (vlax-ename->vla-object
		     (setq e (ssname ss (setq i (1- i))))
		   )
		   'GetAttributes
		 )
	       )
	)
	(and (setq DwgNo (Cadr (assoc "DWG_NO" AttData)))
	     (setq RevNo (Cadr (assoc "REV_NO" AttData)))
	     (not (member (setq layTabName (strcat DwgNo " [" RevNo "]"))
			  (layoutlist)
		  )
	     )
	     (Vla-put-name
	       (Vla-item aLayouts (Cdr (assoc 410 (entget e))))
	       layTabName
	     )
	)
      )
    )
  )(princ)
)

 

Another option is, a program to change the pdf name to reflect the drawing number and latest revision based on a database like a drawing register or even your drawing schedule.

 

You can also try the @Sea-Haven suggested link on top of the code posted above to use the DWG_NO and REV_NO, you may need to modify this bit here with your specific settings.

 

 (COMMAND "-PLOT"  "Y"  "" "dwg to Pdf"
	"Iso full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE"  "N"   "W"  "-6,-6" "807,560" "1=2"  "C"
	 "y" "Acad.ctb" "Y" "n" "n" "n" pdfName "N" "y"
    )

 

 

The possibilites are endless

Or you can just go ahead with Maratovich has a very extensive plot routine. I'm sure  its worth the greenbacks.

HTH

Message 9 of 18

maratovich
Advisor
Advisor
Here's a video.
Attached is a description file.
 
 
 
 
 
---------------------------------------------------------------------
Software development
Automatic creation layouts and viewport. Batch printing drawings from model.
www.kdmsoft.net
0 Likes
Message 10 of 18

Sea-Haven
Mentor
Mentor

I would look at maratovich solution has lots more than you want.

 

Anyway a solution but you can work out how to use it in code provided

(setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 "TTLBLK_ATTS_A1H") (cons 410 (getvar 'ctab)))))
(setq blk (vlax-ename->vla-object (ssname ss 0)))
(setq att_list (vlax-invoke blk 'Getattributes))

(foreach att att_list
(if (=  (vla-get-tagstring att) "DWG_NO" )(setq str1 (vla-get-textstring att)))
)
(foreach att att_list
(if (=  (vla-get-tagstring att) "REV_NO" )(setq str2 (vla-get-textstring att)))
)
(setq pdfname (strcat str1 "-" str2))

 

Message 11 of 18

maratovich
Advisor
Advisor

Have you watched the video?

 

 

---------------------------------------------------------------------
Software development
Automatic creation layouts and viewport. Batch printing drawings from model.
www.kdmsoft.net
0 Likes
Message 12 of 18

ad_sherratt
Contributor
Contributor

Hi Maratovich,

Sorry for the late reply, I've been off the grid for the past few days. Just followed the instructions on your video and it worked a treat. Will activate the full version post-haste!

Also, big shout out to sea.haven and pbejse, many thanks for all your lisp-oriented help guys. Most of it is a bit beyond me to be honest, as I intimated I was really looking for a quick, out-of-the-box-type solution and this one simply ticked all my boxes.

0 Likes
Message 13 of 18

ad_sherratt
Contributor
Contributor

Hi sea.haven,

Your approach (thank you, btw) intrigued me, and from my very limited knowledge of lisp programming it seemed quite elegant. As I had a rare quiet period at work for a few hours, I couldn't help but go back and have another look at it, if only for my own edification.

After much head-scratching and several cups of tea I managed to tweak your code to suit my needs, at least partially. So I now have a routine that will plot a pdf (with the correct naming) to the same folder as the dwg, however this will only work with the active layout tab; I haven't figured out how to do this across multiple layout tabs yet. Any ideas..?

(defun c:PDFA3()

(setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 "TTLBLK_ATTS*") (cons 410 (getvar 'ctab)))))
(setq blk (vlax-ename->vla-object (ssname ss 0)))
(setq att_list (vlax-invoke blk 'Getattributes))

(foreach att att_list
(if (=  (vla-get-tagstring att) "DWG_NO" )(setq str1 (vla-get-textstring att)))
)
(foreach att att_list
(if (=  (vla-get-tagstring att) "REV_NO" )(setq str2 (vla-get-textstring att)))
)
(setq pdfname (strcat (getvar "dwgprefix") str1 " [" str2 "]"))

(COMMAND "-PLOT"  "Y"  "" "DWG To PDF.pc3" "ISO full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE"  "N"   "W"  "0,0" "841,594" "1=2"  "C" "y" "Inovo_Full.ctb" "Y" "n" "n" "n" pdfName "N" "y")
)

 

0 Likes
Message 14 of 18

Sea-Haven
Mentor
Mentor

This is the easiest way to explain it, Multigetvals.lsp as well as Ghostscript to join the single pdfs back to a single 1 as well. The Marotovich solution has more  scope on various title block plotting.

 

;Plots layouts by range
; By Alan H Feb 2014
(defun AH:pltlays ( / lay numlay numend)
(SETVAR "PDMODE" 0)

(setvar "fillmode" 1)
(setvar "textfill" 1)

(setq alllays (vla-get-Layouts (vla-get-activedocument (vlax-get-acad-object))))
(setq count (vla-get-count alllays))
(if (not AH:getvalsm)(load "Multi Getvals.lsp"))
(setq vals (AH:getvalsm  (list "Enter plot range" "Enter start tab number" 6 4 "1" "Enter end tab number" 6 4 (RTOS COUNT 2 0))))

(setq numlay (atoi (nth 0 vals)))
(setq numend (atoi (nth 1 vals)))

(setq len (+ (- numend numlay) 1))

(setq dwgname (GETVAR "dwgname"))
(setq lendwg (strlen dwgname))
(setq dwgname (substr dwgname 1 (- lendwg 4)))

(repeat len
(vlax-for lay alllays
(if (= numlay (vla-get-taborder lay))
  (setvar "ctab" (vla-get-name lay))
) ; if
(setq pdfname (strcat (getvar "dwgprefix") "pdf\\" dwgname "-" (getvar "ctab")))

) ; for
(setq lay nil)
(setvar "textfill" 1)
(setvar "fillmode" 1)
    (COMMAND "-PLOT"  "Y"  "" "DWG To PDF"
	       "Iso full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE"  "N"   "W"  "-6,-6" "807,560" "1=2"  "C"
	       "y" "Acad.ctb" "Y"	"n" "n" "n" pdfName "N" "y"
    )
    
(setq numlay (+ numlay 1))
) ; end repeat
) ; defun

(AH:pltlays)

for range selection, for all use like 1 & 99 

0 Likes
Message 15 of 18

ad_sherratt
Contributor
Contributor

Thanks again sea.haven

 

To be honest I went a bit cross-eyed trying to follow all those lines of code, call me backward but I think it's safe to say this is where my already-limited understanding of lisp breaks down. Also I feel it's probably more complicated than for what I'm trying to achieve.

 

I had a near-success simply by wrapping a 'foreach' loop around the plot command (see below) - it plotted a pdf from the first layout tab, but choked upon hitting the 2nd for some reason.

 

And yes you're right, Maratovich's out-of-the-box solution does exactly what I want it to and alot more (and for a very reasonable price). As I say, I'm just having a crack at doing it this way for personal improvement purposes while I have a rare lull in my day-to-day workload.

 

(foreach lay (layoutlist)
(setvar 'ctab lay)
(COMMAND "-PLOT" "Y" "" "DWG To PDF.pc3" "ISO full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE" "N" "W"

"0,0" "841,594" "1=2" "C" "y" "Inovo_Full.ctb" "Y" "n" "n" "n" pdfname "N" "y")
); end foreach

 

0 Likes
Message 16 of 18

Sea-Haven
Mentor
Mentor

Only bit to change pdfname as it will only ever be 1 name, so you need something like this, or read layout name which is lay.

 

(setq pdfname (strcat (getvar "dwgprefix") "pdf\\" dwgname "-" (getvar "ctab")))

dgwprefix is the directory where the dwg is located

add "PDF"

dwgname is the drawingname 

(getvar 'ctab) or lay in your case is the layout name.

 

So the pdfname is a full path location to save the pdf in and a name.

In our office the pdf's went into a PDF directory that was auto made if not exist at the same location as the dwg, this way say 88 pdfs went into their own directory.

 

pdfname d:\\mydwgs\\workstuff\\forum-layout1pdf\\

 

(setvar 'ctab lay)
(setq pdfname (strcat "dwg-" (rtos (setq x (+ x 1)) 2 0)))

 

0 Likes
Message 17 of 18

ad_sherratt
Contributor
Contributor
Accepted solution

Ok, once again thanks for everyone's help, but after another big bout of head-scratching and alot of trial and error I finally produced a simple and (if I may say so myself) elegant solution to suit my needs.

As mentioned previously, I'm still very much a beginner when it comes to Lisp programming so I'm justifiably chuffed with the end result. Here it is:

;;------------------------------------------------------------------------------------
;;Plot Single PDF (current layout tab) to dwg source folder with filenaming convention
;;------------------------------------------------------------------------------------
(defun c:PDFA3()

;;Get attribute values that will form PDF name

(setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 "TTLBLK_ATTS*") (cons 410 (getvar 'ctab)))))
(setq blk (vlax-ename->vla-object (ssname ss 0)))
(setq att_list (vlax-invoke blk 'Getattributes))

(foreach att att_list
(if (=  (vla-get-tagstring att) "DWG_NO" )(setq str1 (vla-get-textstring att)))
)
(foreach att att_list
(if (=  (vla-get-tagstring att) "REV_NO" )(setq str2 (vla-get-textstring att)))
)

;;Define PDF name and save location

(setq pdfname (strcat (getvar "dwgprefix") str1 " [" str2 "]"))

(COMMAND "-PLOT"  "Y"  "" "DWG To PDF.pc3" "ISO full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE"  "N"   "W"  "0,0" "841,594" "1=2"  "C" "y" "Inovo_Full.ctb" "Y" "n" "n" "n" pdfname "N" "y")
)

;;end

;;------------------------------------------------------------------------------------
;;Plot Multiple PDFs (all layout tabs) to dwg source folder with filenaming convention
;;------------------------------------------------------------------------------------
(defun c:PDFA3M()

;;Start FOREACH loop to run through all layout tabs

(foreach lay (layoutlist)
  (setvar "ctab" lay)

;;Get attribute values that will form PDF name

(setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 "TTLBLK_ATTS*") (cons 410 (getvar 'ctab)))))
(setq blk (vlax-ename->vla-object (ssname ss 0)))
(setq att_list (vlax-invoke blk 'Getattributes))

(foreach att att_list
(if (=  (vla-get-tagstring att) "DWG_NO" )(setq str1 (vla-get-textstring att)))
)
(foreach att att_list
(if (=  (vla-get-tagstring att) "REV_NO" )(setq str2 (vla-get-textstring att)))
)

;;Define PDF name and save location

(setq pdfname (strcat (getvar "dwgprefix") str1 " [" str2 "]"))

   (COMMAND "-PLOT"  "Y"  "" "DWG To PDF.pc3" "ISO full bleed A3 (420.00 x 297.00 MM)" "m" "LANDSCAPE"  "N"   "W"  "0,0" "841,594" "1=2"  "C" "y" "Inovo_Full.ctb" "Y" "n" "n" "n" pdfname "N" "y")
); end FOREACH loop
)

;;end

 

0 Likes
Message 18 of 18

Sea-Haven
Mentor
Mentor

Good to see someone having a go that way you learn.

 

You don't need to do foreach twice looking for tagname can do in one foreach just have the if's one after each other.

 

 

(foreach att att_list
(if (=  (vla-get-tagstring att) "DWG_NO" )(setq str1 (vla-get-textstring att)))
(if (=  (vla-get-tagstring att) "REV_NO" )(setq str2 (vla-get-textstring att)))
)

 

 Could have more IF's because they are individual Tagnames. 

 

The Pdf plot range example can do 1 or all happy for you to use the Multi getvals.lsp you can put start and end range layout numbers so 5 - 5 would only plot layout 5, 1 - 99 I put last layout to correct number so a big number means replace with last layout as limit.

0 Likes