Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Tutorials on creating PDF files using C# 2.0

0.00/5 (No votes)
16 Mar 2007 19  
Tutorials on creating PDF files using C# (.NET 2.0) and iTextSharp
Screenshot - iTextSharpTutorials.png

Introduction

There are several ways to create PDFs. The hardest of them all is perhaps to create it on your own using C#. However, if you want to learn how to do so, you have to climb a steep learning curve. You can either read the 1300+ page specification document available free from Adobe's PDF Technology Center or use an open source library called iTextSharp. iTextSharp eases the learning curve a fair amount. But learning to use iTextSharp is itself non-trivial. The people behind iTextSharp have done a very nice job of putting together a set of tutorials. If you get through the tutorials, creating a PDF becomes somewhat easier. The tutorials, however, are based on .NET 1.x and cannot be used "out of the box" with .NET 2.0 without a fair amount of code rework.

This project contains the reworked .NET 2.0 code and a friendlier interface

  • to get to the iTextSharp tutorials web site more directly
  • to see the results of each chapter and example more easily (than on the iTextSharp web site)
  • to access the Adobe reference resources a little more quickly

WARNING:

Creating simple PDFs becomes easy once you grasp iTextSharp. But ... creating useful, practical, nice looking PDFs is hard. And hard work. In some ways it makes HTML, CSS, ASP.NET, Javascript and C# look easy! If you've ever struggled with Postscript and SVG you will appreciate why PDFs are so darned hard to master. That is perhaps Adobe's secret of success!

Background

Situation

After completing my XmlStore project (referenced below) I realized it had another useful application. To make a long story short, I needed a way to send tabular data (from DataGridViews and the like) to various friends. Some could deal with HTML, but not Excel. The reverse was true for some of the others. It turns out, the only format all of them can handle is PDF. So, I thought I could programmatically create PDFs from my DataGridViews, etc. Easier said than done!

Complication

It turned out there is no easy way to do this. Because I could not find a satisfactory solution to meet my needs, I decided to investigate the subject. The more I looked into it, the more intrigued I became. Then I stumbled upon iTextSharp. While it looked very promising, it was a challenge, and still is!!!. First because of the .NET version mismatch. Second, because the tutorials web site is out of sync with the downloaded version (as of Mar 14 or so). Third, it was just plain difficult to understand by reading alone.

Solution

Creating a PDF by reading a book is just as hard as creating a Windows application by reading a book. When it comes to things like understanding the quaint under-the-hood stuff of PDFs and such, people like me simply have to write code and try it ad nauseam until one has that epiphanic Aha! moment. So, I built this little application to test out much of the code in the iTextSharp Tutorials web site. Having gone through the tedious code cleanups, I am sharing it with people like you; it might get you up the learning curve a little faster.

DISCLAIMER

I undertook this project to also learn a few things about Visual Studio 2005, C#, XML, DataGridView, etc. Caveat Emptor: Nothing has been properly or adequately tested. More important, there is a good chance, you or someone else can do this better. So, if you do use this code and cannot produce what you expect, there is little I can do to help you. On the bright side, though, you have the source code and all the technical references in the world you will ever need from Adobe and the good people at iTextSharp.

This solution only contains examples for the first six chapters of the tutorial web site. I did not include anything from the remaining chapters in part because they do require you to do some more reading but mostly because I ran out of steam! A couple of examples in Chapter 6 will not work because I was unable to get the required files from SourceForge.net.

Using the application

Be sure to read the DISCLAIMER above before you do anything.

Tutorial Menu

The Tutorial menu contains a command corresponding to each Chapter and Example in the iTextSharp Tutorials web site.

Application Screen Shot - Menus

Simply selecting a chapter and an example will cause the PDF to be generated and displayed in the browser (using the Adobe Acrobat Reader, which one assumes you have). For example, Selecting Tutorial > Chapter 5 > 1: My First Table will execute the code below. The URL just above each such method points to the pertinent page with detailed information in the iTextSharp Tutorial web site. (You can also get to it via the Help menu.)

  //See http://itextsharp.sourceforge.net/tutorial/ch05.html

  public bool Chap0501(string sFilePDF)
  {
      bool bRet = false;

      Debug.WriteLine("Chapter 5 example 1: My First Table");

      // step 1: creation of a document-object

      Document document = new Document();

      try
      {
          // step 2:

          // we create a writer that listens to the document

          // and directs a PDF-stream to a file


          PdfWriter writer = PdfWriter.GetInstance(document, 
                             new FileStream(sFilePDF, FileMode.Create));

          // step 3: we open the document

          document.Open();

          // step 4: we create a table and add it to the document

          Table aTable = new Table(2, 2);    // 2 rows, 2 columns

          aTable.AddCell("0.0");
          aTable.AddCell("0.1");
          aTable.AddCell("1.0");
          aTable.AddCell("1.1");
          document.Add(aTable);           

          bRet = true;
      }
      catch (DocumentException de)
      {
          this.Message = de.Message;
      }
      catch (IOException ioe)
      {
          this.Message = ioe.Message;
      }

      // step 5: we close the document

      document.Close();

      if (bRet)
          this.Message = sFilePDF + " has been created";

      return bRet;
  }

This method along with all the others for chapters 1 through 6 are in the module called VVX_iTextSharp_Tutorials.cs; they are accessed via a class called iTextSharp_Tutorials in the VVX namespace.

The only way to learn is to mess around with the code. If you do, KEEP IN MIND, it is a very good idea to always get past the document.Close(); before you terminate a Debug session.

Help Menu

The Help menu contains links to two important sources of information:

  • iTextSharp Tutorial Home
  • Adobe PDF Specifications (various versions)

Try them. You will see why they are very important, especially if you are determined to create your own PDFs.

Using the code

Be sure to read the DISCLAIMER above before you do anything.

Prerequisite

This solution was created using Visual Studio 2005 and before building the solution you need to use the VS2005 Project > Add Reference menu command to provide a Reference to iTextSharp.DLL version 4.x. If you don't have this, you can download just the DLL or the source [and build it yourself] using one of these links to SourceForge.net:

Building the solution

If you have Visual Studio 2005 then you should be able to use the project source code "out of the box" - simply build and run. The code itself is not rocket science. It is reasonably documented. More important, you have access to a wealth of information on what the code does via valuable links in the Help menu. If you don't have Visual Studio 2005, you will have to ask a more experienced friend. (Don't ask me, as I don't have a clue! Don't ask Adobe either, as no one there may be able to help as they did not create iTextSharp.)

Code modules

Side benefits of the code for newbies (like myself): The project includes modules with reasonably documented and self-explantory code. With luck, they may help you learn how to use a few features of the sub-systems employed.

VVX_iTextSharp_Tutorials.cs

VVX.iTextSharp_Tutorials is a class that contains about 3300+ lines of code for about 40 examples from the tutorials web site and reworked a bit to make them compatible with the above version of iTextSharp.DLL. The rework included the following:

  • Updating names of methods, such as changing addCell to AddCell

  • Updating names of enum values, such as changing RIGHT to ALIGN_RIGHT

  • Adding a Message property so that I could display the status [of a call to create one of the example PDFs] in the UI's status bar as shown in the pictures above

  • Adding helper methods, such as DoGetImageFile(...) and DoLocateImageFile(...) to help locate and load sample image files used in some of the tutorial examples. (These image files are in the Images folder.) I tend to prefix names of methods I created with a "Do" for two reasons -- first to distinguish them from methods that I did not create and second because they tend to show up together in the Intellisense pop-up

  • Making sure there are explicit references to methods, types, properties, and such in the System.Drawing namespace to eliminate ambiguous references. Note: I also specifically commented out using System.Drawing; and recommend you do the same, as there are some methods and properties that appear to have slightly different meanings in the iTextSharp namespace

  • Modifying the code for some of the examples, mainly to use the methods mentioned above, because both Adobe's PDF Reader and iTextSharp sometimes complain with unhelpful messages if the code fails to "properly" load and create images from these files. In virtually all such cases, I have wrapped my code and the original code in #if ... #else ... #endif

VVX_About.cs

VVX.About is a simple class that provides a "cheap", zero maintenance, "Help | About" message box. If you don't know how to access information in an assembly, it can show you one way of extracting some information from it.

I use VS2005's Project > appname Properties... > Application > Assembly Information ... option to specify/update the relevant information [which is good practice anyway] and then handle the user's Help > About menu request like this:

  private void ctlHelpAboutMNU_Click(object sender, EventArgs e)
  {
      VVX.About.Show();
  }

It is "cheap" and "zero maintenance" because I don't need to create a form and do all the hard work to maintain/update it to get something like this:

Application Screen Shot - About

This message box is displayed simply by invoking the static method VVX.MsgBox.Info(...) from within VVX.About.Show().

VVX_MsgBox.cs

VVX.MsgBox is a class to simplify access to MessageBoxes of different kinds. It helped me learn how to use message boxes more efficiently. For example, the MsgBox.Confirm(...) method allows me to do something like this:

  if (VVX.MsgBox.Confirm("Save changes?"))
      this.DoFileSave();

instead of this:

  if(DialogResult.Yes == MessageBox.Show("Save changes?"
                                        , "Confirm"
                                        , MessageBoxButtons.YesNo
                                        , MessageBoxIcon.Question))
  {
      this.DoFileSave();
  }


VVX_FileDialog.cs

VVX.FileDialog is a class to access OpenFileDialog and SaveFileDialog a little more efficiently. For example, the FileDialog.GetFilenameToOpen(...) method allows me to do something like this:

  string filename = VVX.FileDialog.GetFilenameToOpen(VVX.FileDialog.FileType.XML);
  if (filename.Length > 0)
  {
    this.DoGridPopulate(this.ctlTableDGV);
  }

and

  string filename = VVX.FileDialog.GetFilenameToOpen(VVX.FileDialog.FileType.Image);
  if (VVX.File.Exists(filename))
  {
    img = Image.GetInstance(filename);;
  }

The methods simply takes care of setting up the filters, etc., before displaying the OpenFileDialog or SaveFileDialog to the user.

VVX_File.cs

VVX.File is a class to simplify access to a few File-related methods, such as Exists. Again, it is not rocket science, but I found it was hard to remember that you have to use the System.IO.FileInfo class to test for the existence of a file! I now can check a file with just this.

  if(VVX.File.Exists(filename))
  {
       //... do something

  }

iText

If you want to learn more about iText, on which iTextSharp is based, click here.

There are alternatives

If iTextSharp is too difficult you might consider using one of several commercial PDF solutions, some of them are quite inexpensive. However, I haven't had much success with them. (The only place I have found creating PDFs is a breeze is on my iMac; creating PDFs on it from any application is a no-brainer! And you get beautiful PDFs, too.)

Finally, a word of thanks to you

I have learned a lot from people like you who have anonymously and freely shared your experiences with the world. Perhaps, you gave a little, but I learned a lot. If this utility helps even one person, you've made my day and given me a chance to give back to the community. So, thank you!

Other recent contributions

If any of these have helped you ...

Please consider sending in a donation to one of my favorite charities: Year Up or to any similar NGO (non-governmental organization) in the world that is selflessly doing good work and helping people in need. Give a little, get a lot!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here