[SharePoint 2010] Fill Out and Flatten PDF Forms with iTextSharp
In a recent project I used this solution to take fillable PDF forms, fill them out based on user input, flatten the PDF document and save it back to SharePoint. I can think of a number of uses for this type of solution: filling out contracts, filling out medical or other business forms, or just about any standard document that requires dynamic data inputted. This guide shows the fundamentals for accomplishing this, there are countless ways this could be modified to suit specific requirements.
Prerequisites
- A development environment with SharePoint 2010 and Visual Studio 2010 installed and configured
- A blank site on the SharePoint environment to work with
- A fillable PDF form (at least one), for this example I am using a sample Direct Deposit form from Microsoft Word that I converted to a PDF form. You can download the form here.
- iTextSharp (which can be downloaded here)
Guide
Identify the names of the form fields that will be filled out by the application. (You can do this in Adobe Acrobat while editing the form). The field for our sample form are:
- “Name of Financial Institution”
- “Routing Number”
- “Account Number”
- “Checking”
- “Savings”
In your SharePoint site, create two Document Libraries named “Form Templates” and “Completed Forms”. (In a more complete solution, you might create content types and list definitions for these. For simplicity, we are just creating them on the site manually.)
Upload your PDF form template (i.e. the Sample Form) to the “Form Templates” Document Library.
Start Visual Studio 2010 and create a New Project. Select Visual Web Part for the template (Visual C# > SharePoint > 2010).
Provide a Solution Name; for this guide we are using “PDFFormExample”. Select OK.
Provide the local SharePoint site URL you will be testing with (on my machine I am using “http://localhost:8080/sites/pdfforms/”).
Select Finish.
In the Solution Explorer, right-click References > Add Reference. Browse to and add the iTextSharp DLL referece.
In the “VisualWebPart1UserControl.ascx” user control, add the ASP.NET controls to gather the form information from the user. Here is my completed control:
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %> <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %> <%@ Import Namespace="Microsoft.SharePoint" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart1UserControl.ascx.cs" Inherits="PDFFormExample.VisualWebPart1.VisualWebPart1UserControl" %> <p>Form Template: <br/> <asp:DropDownList ID="ddlTemplate" runat="server"></asp:DropDownList> </p> <p>Financial Institution: <br /> <asp:TextBox ID="txtFinancialInstitution" runat="server"></asp:TextBox> </p> <p>Routing Number: <br /> <asp:TextBox ID="txtRoutingNumber" runat="server"></asp:TextBox> </p> <p>Account Number: <br /> <asp:TextBox ID="txtAccountNumber" runat="server"></asp:TextBox> </p> <p> <asp:CheckBox ID="chkChecking" runat="server" /> Checking <br/> <asp:CheckBox ID="chkSavings" runat="server" /> Savings </p> <p> <asp:Button ID="btnSubmit" runat="server" Text="Submit" /> <asp:Label ID="lblOutput" runat="server"></asp:Label> </p>
Open the “VisualWebPart1UserControl.ascx.cs” code behind file (you will need to expand VisualWebPart1 in the Solution Explorer).
Add an event handler for the “Click” action on the button we added to the user control:
using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; namespace PDFFormExample.VisualWebPart1 { public partial class VisualWebPart1UserControl : UserControl { protected void Page_Load(object sender, EventArgs e) { btnSubmit.Click += new EventHandler(btnSubmit_Click); } void btnSubmit_Click(object sender, EventArgs e) { } } }Add Microsoft.SharePoint, System.IO, iTextSharp.text.pdf, and iTextSharp.text to the using list:
using System; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using Microsoft.SharePoint; using iTextSharp.text; using iTextSharp.text.pdf; using System.IO;
Next, use the following code in the Page_Load function to query the form templates to populate the drop down list:
protected void Page_Load(object sender, EventArgs e) { btnSubmit.Click += new EventHandler(btnSubmit_Click); if(!IsPostBack) { // Clear any items that exist in the drop down list ddlTemplate.Items.Clear(); // Get the collection of list items in the Form // Templates document library SPListItemCollection formTemplates = SPContext.Current.Web.Lists["Form Templates"].Items; // For each list item in the collection, add the item to // drop down list foreach (SPListItem template in formTemplates) { // Get file name and the list item ID string title = template.File.Name; string id = template["ID"].ToString(); // Add new item to the drop down list ddlTemplate.Items.Add( new System.Web.UI.WebControls.ListItem(title, id)); } } }Add the following code to the btnSubmit_Click function. Details on each step are in the code comments:
// Get the selected template ID int templateId = int.Parse(ddlTemplate.SelectedValue); // Get the template file from the document library SPFile template = SPContext.Current.Web.Lists["Form Templates"].GetItemById(templateId).File; // Initialize a new iText document and specify the page size Document document = new Document(PageSize.LETTER); // Initialize a stream to process the new document MemoryStream stream = new MemoryStream(); // Initialize a new iText reader to open the PDF form PdfReader reader = new PdfReader(template.OpenBinaryStream()); // Initialize a new iText stamper to fill out the PDF form PdfStamper pdf = new PdfStamper(reader, stream); // Grab the form fields and set their values from the user controls AcroFields fields = pdf.AcroFields; fields.SetField("Name of Financial Institution", txtFinancialInstitution.Text); fields.SetField("Routing Number", txtRoutingNumber.Text); fields.SetField("Account Number", txtAccountNumber.Text); if (chkChecking.Checked) fields.SetField("Checking", "X"); if (chkSavings.Checked) fields.SetField("Savings", "X"); // Flatten and close the new PDF pdf.FormFlattening = true; pdf.Close(); // Create a unique file name string fileName = Guid.NewGuid() + "_" + txtAccountNumber.Text + ".pdf"; // Upload the file to the Complete Forms library SPContext.Current.Web.Folders["Completed Forms"].Files.Add(fileName, stream.ToArray()); lblOutput.Text = "Form successfully completed " + DateTime.Now;Your completed code should look like:
using System; using System.Web.UI; using System.Web.UI.WebControls.WebParts; using Microsoft.SharePoint; using iTextSharp.text; using iTextSharp.text.pdf; using System.IO; namespace PDFFormExample.VisualWebPart1 { public partial class VisualWebPart1UserControl : UserControl { protected void Page_Load(object sender, EventArgs e) { btnSubmit.Click += new EventHandler(btnSubmit_Click); if(!IsPostBack) { // Clear any items that exist in the drop down list ddlTemplate.Items.Clear(); // Get the collection of list items in the Form // Templates document library SPListItemCollection formTemplates = SPContext.Current.Web.Lists["Form Templates"].Items; // For each list item in the collection, add the item to // drop down list foreach (SPListItem template in formTemplates) { // Get file name and the list item ID string title = template["Name"].ToString(); string id = template["ID"].ToString(); // Add new item to the drop down list ddlTemplate.Items.Add( new System.Web.UI.WebControls.ListItem(title, id)); } } } void btnSubmit_Click(object sender, EventArgs e) { // Get the selected template ID int templateId = int.Parse(ddlTemplate.SelectedValue); // Get the template file from the document library SPFile template = SPContext.Current.Web.Lists["Form Templates"].GetItemById(templateId).File; // Initialize a new iText document and specify the page size Document document = new Document(PageSize.LETTER); // Initialize a stream to process the new document MemoryStream stream = new MemoryStream(); // Initialize a new iText reader to open the PDF form PdfReader reader = new PdfReader(template.OpenBinaryStream()); // Initialize a new iText stamper to fill out the PDF form PdfStamper pdf = new PdfStamper(reader, stream); // Grab the form fields and set their values from the user controls AcroFields fields = pdf.AcroFields; fields.SetField("Name of Financial Institution", txtFinancialInstitution.Text); fields.SetField("Routing Number", txtRoutingNumber.Text); fields.SetField("Account Number", txtAccountNumber.Text); if (chkChecking.Checked) fields.SetField("Checking", "X"); if (chkSavings.Checked) fields.SetField("Savings", "X"); // Flatten and close the new PDF pdf.FormFlattening = true; pdf.Close(); // Create a unique file name string fileName = Guid.NewGuid() + "_" + txtAccountNumber.Text + ".pdf"; // Upload the file to the Complete Forms library SPContext.Current.Web.Folders["Completed Forms"].Files.Add(fileName, stream.ToArray()); lblOutput.Text = "Form successfully completed " + DateTime.Now; } } }Right-click the project name (PDFFormExample) in the Solution Explorer > Deploy. This will deploy your new web part to the local SharePoint site you specificed when creating the project.
Browse to your local SharePoint site. Add your new web part to a SharePoint page (will be under the Custom category).
Submit some data. If all goes well, it should indicate the form was successfully submitted.
You should now have a complete form in the Completed Forms library.
That’s it. You are now able to retrieve a PDF Form, fill it out programmatically, and save it back to SharePoint. Now it’s your turn to find good uses for this.
5 Comments
Leave a comment
Follow John Chapman
SharePoint StackExchange
- http://t.co/d2YzH8q1 - #sharepoint - [SharePoint 2010] Specifying Which Server a Custom Timer Job Will Run On
- Always have your stuff when you need it with @Dropbox. 2GB account is free! http://t.co/kczsnniq
- http://t.co/iLWV2Kwp - #sharepoint - [SharePoint 2010] Web Analytics: Monitors the health of the Report Consolidator component
Recent Posts
- [SharePoint 2010] Specifying Which Server a Custom Timer Job Will Run On
- [SharePoint 2010] Web Analytics: Monitors the health of the Report Consolidator component
- [SharePoint 2010 / SQL Server 2008] Query the SharePoint Object Model from a .NET SQL Server CLR Function
- [SharePoint 2010] Debugging a Custom SharePoint Timer Job
- [SharePoint 2010] Set Access Request Email for All SharePoint Sites

Great stuff. Thanks for the article really helped me out. Had an issue with the itextsharp dll not deploying to the server. Fixed it by adding it to the package.
Can this solution be used to host forms for fill out? I gather that this particular solution, as-coded above, is for inserting data into the form from a data source, or am I mistaken.
I also need to know if this will work with forms created with LC Designer 9. (Dynamic XML Forms)
Greate code sample, thanks!
My only problem now is that I can’t edit the form fields once the form has been migrated over to the completed forms list. The required text is in the field, but the fields arent hi lighted any more. For instance, if the institution name needs changed, it wont allow me to change it.
Should the form fields be left editable? Is there something I am missing?
Thanks,
Mike
Here is the reason why I should do 10 minutes of research before posting replies to code samples::
Fattening is the process of removing the editable fields in a pdf before saving…. I changed the code to pdf.flattening = false; and it worked like a champ….
Thanks again for the useful code!!
Mike
Glad you found what you were looking for