Using Visual Basic to Create PDFs from Images

PDF files have become part and parcel of being able to use a computer productively. PDF (Portable Document Format) is a file format used to present documents independent of application software, hardware, and operating systems. A PDF file contains a complete description of a fixed-layout flat document, as well as fonts, text, and graphics. Today, I will show you how to convert images to a PDF document and how to combine two PDF documents into one.


PDFsharp is an Open Source library that creates PDF documents from any .NET language. PDFSharp can use either GDI+ or WPF and it includes support for Unicode in PDF files. Download PDSharp here and you can find a few samples here to get you started.

Our Project

Create a new Visual Basic Windows Forms project. Feel free to name it anything you like, but keep in mind that my objects may be named differently. All you need to add to the form is a BackgroundWorker object. Make sure that you have downloaded PDFSharp and add a Reference to it in the Project, Add References box, as shown in Figure 1:

Figure 1: References

Add the following namespaces to your code:

Imports System.Windows.Forms
Imports System.Configuration
Imports System.IO
Imports PdfSharp.Drawing
Imports PdfSharp.Pdf
Imports PdfSharp.Pdf.IO
Imports System.Threading

The references to PdfSharp are necessary because we will be using capabilities from each library in our project. We reference it here as well so that we can properly make use of each library inside our project. Add the following private variable:

   Private _sync As SynchronizationContext = _

The SynchronizationContext object will allow one thread to communicate with another thread. Have a look here for a better explanation.

Add the following code into your Form's Load event:

   Private Sub frmPOD_Load(sender As Object, e As EventArgs)
      _sync = System.Threading.SynchronizationContext.Current
   End Sub

The BackgroundWorker object gets started in the Form Load event. Add the following code:

   Private Sub worker_DoWork(sender As Object, e As DoWorkEventArgs)


         For Each file As String In Directory.GetFiles _
            ("C:\PDF Files To Import")

            ConvertPDF(file.ToString(), "C:\File.pdf")
            CombinePDF(file.ToString(), "PDF File2.pdf")
      Catch ex As System.Exception
      End Try
   End Sub

The DoWork event loops through a supplied directory (C:\PDF Files To Import) and calls the ConvertPDF and CombinePDF subs for each file in the directory, respectively. Add the ConvertPDF sub procedure now:

   Private Sub ConvertPDF(_srcFile As String, _destFile As String)

         Dim srcFile = _srcFile
         Dim destFile = (Convert.ToString(Path.GetDirectoryName(srcFile) + _
            "\") & _destFile) + ".pdf"

         Dim doc As New PdfDocument()

         doc.Pages.Add(New PdfPage())
         Dim xgr As XGraphics = XGraphics.FromPdfPage(doc.Pages(0))
         Dim img As XImage = XImage.FromFile(srcFile)

         xgr.DrawImage(img, 0, 0)



         LogError(Nothing, "PDF Created: " + _
      Catch ex As Exception
      End Try
   End Sub

The ConvertPDF sub procedure takes two arguments: one for the source file, which will be converted to a PDF document; and the resulting file, which will be saved at the same location as the input document. A PdfDocument gets created and instantiated. A Page gets added to the newly created PDF document. The XGraphics object draws an XImage object, which hosts the image file that was supplied onto the PDF page. Lastly, the PDF document gets saved.

Now, add the CombinePDF sub:

   Private Sub CombinePDF(ExistingPDF As String, NewPDF As String)
         Dim outputDocument As PdfDocument = PdfReader.Open(NewPDF)
         Dim inputDocument As PdfDocument = PdfReader.Open(ExistingPDF, _
         Dim count As Integer = inputDocument.PageCount

         For idx As Integer = 0 To count - 1
            Dim page As PdfPage = inputDocument.Pages(idx)



         LogError(Nothing, "PDF Created: " + Path.GetFileName(NewPDF))
      Catch ex As Exception
      End Try
   End Sub

The CombinePDF sub takes two arguments as well: one for the input document and one for the output document. First, the Output document gets opened up in memory. An Input document then gets created and indicates that it will be used as an Import document. A Loop gets created and it loops through all the pages inside the input document and adds them one by one into the output document. Lastly, the resulting document gets physically saved under a supplied name.

You will notice that, inside the Catch block, a sub procedure named LogError gets called. Let's add that now:

   Private Sub LogError(ex As Exception, Optional msg As String = "")
      If ex Is Nothing Then
         Dim message As String = String.Format("Time: {0}", _
            DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
         message += Environment.NewLine
         message += String.Format("Message: {0}", msg)

         Dim path As String = ErrorLogLocation & _
         Using swriter As New StreamWriter(path, True)
         End Using

         Dim message As String = String.Format("Time: {0}", _
            DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
         message += Environment.NewLine
         message += "-----------------------------------------------------------"
         message += Environment.NewLine
         message += String.Format("Message: {0}", ex.Message)
         message += Environment.NewLine
         message += String.Format("StackTrace: {0}", ex.StackTrace)
         message += Environment.NewLine
         message += String.Format("Source: {0}", ex.Source)
         message += Environment.NewLine
         message += String.Format("TargetSite: {0}", ex.TargetSite.ToString())
         message += Environment.NewLine
         message += "-----------------------------------------------------------"
         message += Environment.NewLine
         Dim path As String = ErrorLogLocation & _
         Using writer As New StreamWriter(path, True)
         End Using
      End If
   End Sub

This sub serves a dual purpose. The first is obviously to log a detailed exception and the other is simply to display a message that gets supplied.


PdfSharp is very powerful and easy to use with the .NET Framework, as you can see. It makes any file conversion into a PDF format very quick and easy.

About the Author

Hannes DuPreez

Hannes du Preez is a Microsoft MVP for Visual Basic for the ninth consecutive year. He loves technology and loves Visual Basic. He loves writing articles and proving that Visual Basic is more powerful than what most believe. His ultimate dream is to write a Visual Basic book, hopefully one day that dream will come true. You are most welcome to reach him at:

Related Articles


  • Response

    Posted by Hannes on 11/08/2016 05:56am

    Hi. Please ensure that you have created a Backgroundworker object in the design view and named it 'worker'

  • developer

    Posted by Seán on 10/27/2016 02:12am

    Hi I am getting an error for the following worker.RunWorkerAsync() saying that worker is undeclared. How do I get around this problem? Regards Seán

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date