Tuesday, May 27, 2008

Creating Pdf's with Adobe Acrobat, C# and ItextSharp

Recently I have been creating a large number of dynamic pdf's for a client. I have learned a lot of ways to poorly create pdf files and have also found some pretty good ones. I'm hoping that this post will help others avoid some of the pitfalls and blocks that I've run into while generating dynamic pdf files.

This post will most likely not cover a solution to all scenarios, but will likely be a solution or at least a starting point to most pdf generation problems.

I have included with this post a sample solution from which I have drawn the example code snippets and screen shots in this post. I've included links to these example files at the end of the post also.

DOWNLOAD

Zipped Example Solution
Sample Pdf Form
Example Excel File

Things you will want to do before you begin:

ItextSharp - An Open Source PDF Creation/Manipulation Library

ItextSharp is a port from another open source project called itext, which is a long running java, open-source pdf library (http://www.lowagie.com/iText/). Between the different projects, there is a pretty good following, and as a result, there are quite a few examples of people accomplishing different tasks between the two projects. Luckily, java code is a lot like C# and is pretty easy to convert over with just a few tweaks.

Adobe Acrobat Professional- A PDF Creation/Manipulation Desktop Application

Acrobat does about anything that you could ever want to do with a pdf file in a desktop application. For this post, It will primarily be used to create pdf forms that we will fill in with our code. To see an example of how to create a form, go to http://www.adobe.com/products/acrobat/solutions/detail/create_form.html.

Starting Out

According to my understanding, most people who have to generate some sort of Pdf will want to do one or more of the following actions:

  • Put text into certain areas of a pdf page (like a gift card)
  • Put dynamic table-style information on a pdf (like an invoice)
  • Put images in certain regions of a pdf page (like a graph)

In this post I cover how to put text into certain areas of a pdf. I will try to cover the other two actions in subsequent posts.

In almost all cases, in order to do any of these things, you will want a "template" pdf to start out with. There are ways to build the entire pdf in code, but having a base to start out with can save a lot of time. Most pdf desktop applications allow you to export documents into a pdf (Word, Excel, etc.). I usually have created my "template" pdf in excel and then have used the print to pdf option to create my pdf.

Creating a Form from a PDF Page

In order to put text in certain regions of a pdf file, I've found it best to create a pdf form (as in the forms you often find online that allow you to type the information directly onto the pdf) which allows you to choose the format and alignment of the text. I will go through the steps you would take if using Adobe Acrobat Professional as your pdf form creation software.

First, open your "template" pdf file to which you want to add text. For my example, I will use a pdf that represents a template for an address change notice that a company might want to send out that I created from excel.

Second, open up the Form toolbar

image

Third, add the form text fields to your pdf and give each of the fields unique, intuitive names according to what text will be put in the field.

image

Fourth, make the appropriate tweaks to the formatting and alignment with the 'Appearance' and 'Options' tabs of the 'Text Field Properties' window.

Note: To have more direct control over the size of the text, use an absolute font size instead of the default 'Auto' size. Also, the options tab will give you the ability to set the alignment of your text and set the field to 'Multiline' (like a textbox in windows forms).

image image

Fifth, make sure that the size and formatting of the text is going to be appropriate for your pdf. Click 'Preview' on the Forms toolbar and type something in each of your form text fields to ensure that the characters are showing up as expected.

Note: Make sure that you delete the text that you have typed into the fields before you save it for good.

image

Show Me Some Code Already!!!

Now you should have a pdf with form text fields in it for each of the areas on the pdf in which you want text displayed. Now let's show you how to put any text from our code into the text fields that we created in our form. Here are the steps you would take to fill the form:

First, you need to add a reference to the ITextSharp library in your project (you can download the library at http://sourceforge.net/project/platformdownload.php?group_id=72954). For my example, I have made a windows form application with fields that correspond with the fields on the pdf form I created.

Second, you create a PdfReader that your code will use to read the pdf form that you created:

PdfReader reader = new PdfReader(<unfilled pdf file path goes here>); 
 

Third, you make a PdfStamper which allows you to put text into your form fields:

PdfStamper formFiller = new PdfStamper(reader, new FileStream(<ouput file path goes here>, FileMode.<file mode>));

Fourth, you get the form text fields (AcroFields) from the pdf file:

AcroFields formFields= formFiller.AcroFields;
 

Fifth, you use the SetField method of the AcroFields object to put your text into the field:

formFields.SetField("<field name from pdf>", <value to insert>);
 

Sixth, you 'flatten' your pdf by removing the fields while leaving the values of the fields in tact:

formFiller.FormFlattening = true;

Seventh, close your PdfStamper and PdfReader objects to make sure that all resources are disposed of:

formFiller.Close();
reader.Close();


Your done! After following these steps, you should now have a pdf filled with any values you specified.


Here is an example windows form code beside:










    1 using System;

    2 using System.Collections.Generic;

    3 using System.ComponentModel;

    4 using System.Data;

    5 using System.Drawing;

    6 using System.Linq;

    7 using System.Text;

    8 using System.Windows.Forms;

    9 using iTextSharp.text.pdf;

   10 using System.IO;

   11 using System.Diagnostics;

   12 

   13 namespace PdfStamperSample

   14 {

   15     public partial class PdfTestForm : Form

   16     {

   17         public PdfTestForm()

   18         {

   19             InitializeComponent();

   20         }

   21 

   22         private void btnCreatePdf_Click(object sender, EventArgs e)

   23         {

   24             // Grab each of the values from our windows form

   25             string accountNumber = txtAccountNumber.Text;

   26             DateTime pdfDate = datePdfDate.Value;

   27             string oldAddress = txtOldAddress.Text;

   28             string newAddress = txtNewAddress.Text;

   29 

   30             string outputFilePath = @"..\..\AddressChangeNotice_filled.pdf";

   31 

   32             // Get pdf from project directory

   33             PdfReader reader = null;

   34             try

   35             {

   36                 reader = new PdfReader(@"..\..\AddressChangeNotice.pdf");

   37 

   38                 // Create the form filler

   39                 using (FileStream pdfOutputFile = new FileStream(outputFilePath, FileMode.Create))

   40                 {

   41                     PdfStamper formFiller = null;

   42                     try

   43                     {

   44                         formFiller = new PdfStamper(reader, pdfOutputFile);

   45 

   46                         // Get the form fields

   47                         AcroFields addressChangeForm = formFiller.AcroFields;

   48 

   49                         // Fill the form

   50                         addressChangeForm.SetField("AccountNumber", accountNumber);

   51                         addressChangeForm.SetField("Date", pdfDate.ToShortDateString());

   52                         addressChangeForm.SetField("OldAddress", oldAddress);

   53                         addressChangeForm.SetField("NewAddress", newAddress);

   54 

   55                         // 'Flatten' (make the text go directly onto the pdf) and close the form

   56                         formFiller.FormFlattening = true;

   57                     }

   58                     finally

   59                     {

   60                         if (formFiller != null)

   61                         {

   62                             formFiller.Close();

   63                         }

   64                     }

   65                 }

   66             }

   67             finally

   68             {

   69                 reader.Close();

   70             }

   71 

   72             // Open the created/filled pdf

   73             if (MessageBox.Show(String.Format("Pdf filled - {0}.\nWould you like to open the filled pdf?",

   74                 Path.GetFullPath(outputFilePath)),

   75                 "PDF Created", MessageBoxButtons.YesNo) == DialogResult.Yes)

   76             {

   77                 Process.Start(outputFilePath);

   78             }

   79 

   80         }

   81     }

   82 }






DOWNLOAD

Zipped Example Solution
Sample Pdf Form
Example Excel File

9 comments:

venkat said...
This comment has been removed by a blog administrator.
matt said...

Sam,

We are seeking a consultant to assist us with developing a method for using iTextSharp to flatten annotations inside a PDF. I was wondering if you would have interest in helping us with this, or if you could recommend others who we could contact.

We need to be able to flatten all annotations inside a PDF. We have found that the setFreeTextFlattening method in iTextSharp will flatten text-based elements, but it does not apply to graphical annotations such as lines, shapes, revisions clouds, and stamps.

We will pay a consulting fee for assistance with this project. Please let me know if you could help or if you could recommend others who we could contact. Thank you.

Matt
Email: ostkm@yahoo.com

PankajLnT said...

Hi
It's very nice Article.
I want to set Image to the Image control in the PDF Form using PDFStamper can it be possible?
How?

Thanks
Pankaj

jhoop2002 said...

Thank you, Thank you, Thank you, Thank you.

This was a very nice article and thank you for taking the time to write it.

I was looking at having to manually creat very complex, rapidly chaning pdf until I saw this. I just can't say how much this will help.

Reynaldo Rivas said...

Hi. You can find a blank fillable PDF forms here.
http://goo.gl/57Thdf

Please feel free to use it. You can fill out the form, save it, fax it, and email it.

Zz Lorreta said...

You can download and try this interesting high quality software on rasteredge page for c# accessible links in pdf http://www.rasteredge.com/how-to/csharp-imaging/pdf-edit-bookmark-outline/


Zz Lorreta said...

c# acrobat print pdf with comments is the most helpful software can be download on rasteredge page http://www.rasteredge.com/how-to/csharp-imaging/pdf-annotate-sticky-note/

Zz Lorreta said...

you may test c# add editable text box to pdf on rasteredge and download this high quality software on rasteredge, get the free trail and vip service on page http://www.rasteredge.com/how-to/csharp-imaging/pdf-annotate-text/

Zz Lorreta said...

rasteredge provide the fast speed c# add annotations to pdf and add text box in pdf document on http://www.rasteredge.com/how-to/csharp-imaging/pdf-annotate-text-box/