VB.NET batch pdf printer tool


Keywords:vb.net 


Question: 

I'm looking for a tool, but I can't find it. So I thought, maybe I can make one. Seems like a good idea, a program that fits my needs at last! Just one problem.. I don't know how!


Intro

At my work we create production drawings in .dwg format. Once this is done they are exported as .pdf sent to the client for approval. If approved they are issued for production, so they need to be plotted.

So my current workflow is:

  1. Set my default printer preferences (number of copies, paper size, ..)
  2. Go to the folder that has the .pdf files
  3. Select 15 files
  4. Right click print.

The problem here is

  • The files are printed in the order the printer receives them and not the order in the folder. So I would need to sort them out ( this x number times the number of copies sometimes this goes up to 6 times. )
  • I can only do 15 at a time (large projects are +100 documents)
  • I have to reset my preferences each time the sizes change.

Our file numbering system has some "intelligence" into it. Its build like this:

A1-12345-001 rev1

  1. A1 = page size
  2. 12345 = document number, the same within a project. Other project means other number. (mostly irrelevant as I only print a project at a time)
  3. 001 = sequence number, next drawing will be 003,004,005,007,... you get the drift.
  4. rev1 = revision number. Normally only the highest revision should be located in the folder, but it could be used to check for documents with a lower revision.

Now, I would like to automate my happy printing task, as this makes my week very bad if a large projects needs to go into production or, there are revisions mid-production and we need to re-issue them for production.

So far the situation sketch


Program sketch

So I've started to make a sketch of what the program should do.

  1. User should be able to add .pdf files into a list. file browser object for starters, can be drag and drop later (the drawings are in one folder so there is no real need for drag and drop).
  2. The list should contain 4 columns. paper size, document number, sequence, revision. Could be a data-grid view.
  3. The list should be sorted by the drawing sequence. This how I would like to pass the drawing so, no sorting is required anymore! You can look at the sequence as page numbers.
  4. Select the desired printer to do the job. (usually the same but other departments also have a printer so that would be a nice option.)
  5. Set the number of copies. When printed, it shouldn't be 5x -001 then 5x -002 .. it should print them still in order of the sequence number and the re-loop the process x times.
  6. Print the documents.

Adding PDF files

I started out with creating a dialog.. easy enough I guess.(please keep in mind that I'm a very low level programmer and nothing seems easy to me..) I added an open file dialog to my windows-form set multiple select true. Also made a filter to have only .pdf files

added a button with this code:

Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
    ' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
    If FileDialog.ShowDialog() = DialogResult.OK Then
        Dim file As String
        For Each file In FileDialog.FileNames
            Debug.Print(file)
        Next
    End If
End Sub

So this should give me all the info I need from the file. I will edit this later, I know how to access it now!


The document object

I guess it would be wise to use some o.o.p. for this. As each file is a document and have the same required properties to make this work.

So I made a Public class for the document called PDF_Document

Public Class PDF_Document
    Public FullFilePath As String
    Public Property Size As String
    Public Property DocNumber As String
    Public Property Sequence As String
    Public Property Revision As String

    Public Sub New(ByVal oFilePath As String)
        ' Set the FullFilePath
        FullFilePath = oFilePath

        ' Get the filename only without path.
        Dim oFileName As String
        oFileName = Path.GetFileName(oFilePath)

        ' Get the document size from the file name
        Size = oFileName.Substring(0, 2)

        ' Get the document number from the file name
        DocNumber = oFileName.Substring(3, 5)

        ' Get the sequence from the file name
        Sequence = oFileName.Substring(9, 3)

        ' Chop of the .pdf from the name to get access the revision
        Revision = oFileName.Substring(oFileName.Length - 5, 1)
    End Sub
End Class

Well this should result into the info I need from the document..


creating a list(of t)

Wow, it seems to be getting somewhere.. Now to hold the list I'll have this collection I think don't know whats best for this? Public oPrintList As New List(Of PDF_Document)

So I think I should populate my list like this?

Public oPrintList As New List(Of PDF_Document)

Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
    ' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
    If FileDialog.ShowDialog() = DialogResult.OK Then
        Dim oFile As String
        For Each oFile In FileDialog.FileNames
            Dim oPDF As New PDF_Document(oFile)
            oPrintList.Add(oPDF)
        Next
    End If
End Sub

Making things visual for the user

Hmm okay, were getting somewhere, I got a list of all the files I need! But I want to see them in a viewer. I'm gonna use a data-grid view maybe? It should show my properties and it looks good I think.

So I made a binding that binds my List(of T) and added this binding as data-source for the data-grid view. I also change the ADD_FILES_Click a little, the PDF_Document is now added into the binding and not in the List(of T).

Public Class Form1
    Public oPrintList As New List(Of PDF_Document)
    Public oBinding As BindingSource

    Private Sub ADD_FILES_Click(sender As Object, e As EventArgs) Handles ADD_FILES.Click
        ' Show the open file dialog. If user clicks OK, add pdf_document to list(of T)
        If FileDialog.ShowDialog() = DialogResult.OK Then
            Dim oFile As String
            For Each oFile In FileDialog.FileNames
                Dim oPDF As New PDF_Document(oFile)
                oBinding.Add(oPDF)
            Next
        End If
    End Sub

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        oBinding = New BindingSource(oPrintList, Nothing)
        DataGridView1.DataSource = oBinding
    End Sub
End Class

Printing the list

Well I managed to do quite some things now. But.. the main essence still isn't reached! I now got a form with a bunch of buttons that don't work yet, a list of select documents in queue for printing and .. thats it :)

Printer tool form

Now I'm trying to create a method that prints a .pdf file.. easier sad than done. I need some help with this.. I search the net, but I can find samples that don't work, or I don't understand. All users PC's are equiped with acrobat reader.

Also feel free to comment me on the other parts of the program. ( yes I know there is no sorting function yet etc. ) but getting a page from the printer is more important now.

Sorry for the long post!


1 Answer: 

If your users have Adobe Acrobat Reader installed, the following code should do the trick. I recommend Acrobat Reader 11 or lower version. With Acrobat DC the window from Acrobat does not close anymore, that is a "design" decision by Adobe.

Dim pr As New Process()
pr.StartInfo.FileName = "c:\myfile.pdf"
pr.StartInfo.UseShellExecute = True
pr.StartInfo.Verb = "print"
pr.Start()
pr.WaitForExit()

I work with DWG and PDF files for 20+ years. If you are interested in a solution that fully automates all steps you explained in your "wishlist" software and does a ton more feel free to contact me at pdfmagick at gmail dot com

Another way to print PDF files with the Print Drivers dialog is as follows:

 Dim starter As ProcessStartInfo
 starter = New ProcessStartInfo(<pathToAdobeAcrobatExecutable>, String.Format(" /s /N /P ""{0}""", Filename))
 Dim Process As New Process()
 Process.StartInfo = starter
 Process.Start()
 Process.WaitForExit()
 Process = Nothing
 starter = Nothing

More command line switches are explained here Adobe Reader Command Line Reference

Regards