Forms
PDF documents that include fillable fields are referred to as PDF forms. A typical example is an IRS tax form such as the W-4.
Fields
In general, a PDF form has different types of fields. E.g. text fields to enter you first and last name, a group of radio buttons to select your marital status and a checkbox to indicate whether you filed the same tax form last year.
The class TallComponents.PDF.Forms.Fields.Field represent a PDF form field. It is an abstract base class that has the following inheritance hierarchy:
Fields hierarchy (UnknowmField and UnknowBarcodeField omitted)
All fields in a PDF document can be accessed through the Document.Fields property. It returns an instance of type TallComponents.PDF.Forms.Fields.FieldCollection. You may be surprised that the collection of fields is contained by a Document instead of by a Page. This is explained in the next section.
Widgets
A widget is an annotation that provides the visual representation of a field. It also allows the user to interact with the field, e.g. to enter a text or select a date from a calendar control. In general, a field can have multiple widgets but in most cases it only has one. A field is contained by a document. A widget is contained by a page.
Document, fields, pages and widgets
The following diagram shows the Widget inheritance hierarchy.
Widget inheritance hierarchy
As said, a field is associated with one or more widgets. The following table shows what type of field corresponds to what type of widget.
Correspondence between Field and Widget type
Field | Widget | Remarks |
---|---|---|
SignatureField | SignatureWidget | The SignatureWidget has additional properties to customize the appearance, e.g. display text only, image only, both. Display the date or not, display the reaon or not, etc. |
PushButtonField | PushButtonWidget | The PushButtonWidget has additional properties that allow you to specify a label, an icon and how the label and the icon should laid out (label above icon, icon only, label only, etc.). |
CheckBoxField | CheckBoxWidget | The CheckBoxWidget has an additional appearance to specify the check mark (diamond, check, start, etc.). |
RadioButtonField | RadioButtonWidget | Just like the CheckBoxWidget, the RadioButtonWidget has a property to specify the appearance of the chek mark. In addition, it has a property Option that represents one of the radio button options that can be selected. |
DateTimeField, DropDownListField, ImageField, ListBoxField, NumericField, PasswordField, TextField, Code128BarcodeField, Code2of5InterleavedBarcodeField, Code3of9BarcodeField | Widget | These fields are all visually represented by the same Widget class. |
All widget types have a common base class Widget. Widget in turn inherits from Annotation, see Annotations. The table below lists the members that are specific to Widget annotations.
Public Widget members
Public properties | |
---|---|
Field | The field that is associated with this widget. Read-only. |
Font, FontSize, TextColor, HorizontalAlignment, VerticalAlignment | Properties that specify how text is displayed. |
Invisible, Orientation, BackgroundColor | Appearance properties. |
Persistency | Allows you to specify how a widget is persisted when the document is written. You can leave a widget unchanged, you can remove it and finally it can be flattened. This means that after writing the document, the widget is replaced by static, non-interactive content. |
GotFocusActions, LostFocusActions | Actions to be executed when the widget gets or loses keyboard focus. |
MouseDownActions, MouseUpActions, MouseEnterActions, MouseExitActions | Actions to be executed per mouse event. |
The following code snippet creates new document with a single page and a text field:
// create new document
Document document = new Document();
Page page = new Page( PageSize.Letter );
document.Pages.Add( page );
// add a new text field and add it to the new document
TextField textField = new TextField( "text1" );
textField.Value = "Hello!";
document.Fields.Add( textField );
// add a new widget and connect the widget to the text field and the page
Widget widget = new Widget( 200, 400, 200, 50 );
widget.TextColor = RgbColor.Red;
widget.BorderColor = RgbColor.Black;
widget.BorderStyle = BorderStyle.Solid;
widget.BorderWidth = 2;
textField.Widgets.Add( widget );
page.Widgets.Add( widget );
// save the new document
using ( FileStream file = new FileStream(
@"..\..\textfield.pdf",
FileMode.Create, FileAccess.Write ) )
{
document.Write( file );
}
Code sample: Create a new document with a single page and a text field (AddTextField)
Textfield as created by Code sample Create a new document with a single page and a text field
Fill Fields
Filling a form field is as simple as setting the Value property of a field. Depending on the type of field, special XxxValue properties exist. Here are some code samples that show how to fill form fields:
using ( FileStream fileIn = new FileStream(
@"fields.pdf", FileMode.Open, FileAccess.Read ) )
{
Document document = new Document( fileIn );
TextField textField = document.Fields[ "Text1" ] as TextField;
textField.Value = "Hello";
CheckBoxField checkBox = document.Fields[ "Check Box2" ] as CheckBoxField;
checkBox.CheckBoxValue = CheckState.On;
RadioButtonField radioButton = document.Fields[ "Radio Button4" ]
as RadioButtonField;
radioButton.RadioButtonValue = radioButton.Options[1]; // second option
ListBoxField listBox = document.Fields[ "List Box7" ] as ListBoxField;
listBox.ListBoxValue =
new ListOption[] { listBox.Options[1] }; // second option
DropDownListField dropDown = document.Fields[ "Combo Box8" ]
as DropDownListField;
dropDown.DropDownListValue = dropDown.Options[1]; // second option
using ( FileStream fileOut = new FileStream(
@"out.pdf", FileMode.Create, FileAccess.Write ) )
{
document.Write( fileOut );
}
}
Code sample: Fill fields (FillFields)
Form Data
At each point a field has a value. This can be text entered into a text field or the signature state of a signature field. The collection of all values of all fields of a document is referred to as form data. Form data can be persisted in different formats (e.g The Acrobat JavaScript Scripting Reference mentions a form data format called ‘XFD’. We have no idea what this format is and we suspect that it is a typo (from XFDF which is included as well)), the most known being Form Data Format (FDF). The class FormData is the abstract base class of all classes that each represent one format of persisted form data. The following inheritance hierarchy shows the different FormData classes.
FormData inheritance hierarchy
Export
Exporting form data in any of the supported format is really easy. Simply call the method Document.Export and specify what format you want:
using ( FileStream pdfFile = new FileStream(
"fw4.pdf", FileMode.Open, FileAccess.Read ) )
{
Document document = new Document( pdfFile );
// fill two fields
TextField firstName = document.Fields["f1_09(0)"] as TextField;
firstName.Value = "Chris";
TextField lastName = document.Fields["f1_10(0)"] as TextField;
lastName.Value = "Sharp";
// export as FDF
FdfFormData fdf = document.Export( FormDataFormat.Fdf ) as FdfFormData;
fdf.Path = "fw4.pdf";
// save FDF
using ( FileStream fdfFile = new FileStream(
"fw4.fdf", FileMode.Create, FileAccess.Write ) )
{
fdf.Write( fdfFile );
}
}
Code sample: Export form data as FDF (ExportFdf)
Import
Importing existing form data into a PDF document is just as easy. Simply create a FormData instance from persisted form data (can be in memory) and pass this instance to Document.Import:
// open PDF file
using ( FileStream fileIn = new FileStream(
"fw4.pdf", FileMode.Open, FileAccess.Read ) )
{
Document document = new Document( fileIn );
// open FDF file
using ( FileStream fdfFile = new FileStream(
"fw4.fdf", FileMode.Open, FileAccess.Read ) )
{
FdfFormData fdfData = new FdfFormData( fdfFile );
// import FDF data
document.Import( fdfData );
// save modified PDF file
using ( FileStream fileOut = new FileStream(
"fw4_afterimport.pdf", FileMode.Create, FileAccess.Write ) )
{
document.Write( fileOut );
}
}
Code sample: Import form data from FDF (ImportFdf)
Adobe LiveCycle Designer Support
Dynamic XFA documents are not supported. If you open such a document with, an UnsupportPdfException is thrown. Static XFA documents are supported.
Numeric field, DateTime field, Image field and Barcode field are represented by the corresponding classes in the TallComponents.PDF.Forms.Fields namespace. These field types cannot be created. It is not possible to add these field types to an existing non-XFA (classic) PDF document. It is not possible to add new fields/widgets to static XFA document.
The property Document.DocumentType reflects the type of PDF document. Possible values are: Classic, StatcXfa and DynamicXfa. The enum value DynamicXfa will never be returned because an exception is already thrown at construction time.
To summarize, we support Adobe LiveCycle Designer document with the following restrictions:
- We support static XFA only (no dynamic XFA).
- We do not support repeated subforms. See ‘repeat subform for each data item’ flag in Binding properties.
- You cannot add new fields/widgets.
- You cannot remove fields by calling the FieldCollection.Remove() method. You can however remove fields by setting widget.Persistency to WidgetPersistency.Flatten or WidgetPersistency.Remove.
- When adding a page from a XFA document to an other document, the XFA fields are automatically converted to classic types (e.g. NumericField will be TextField).
- We do not support data-bindings. The default binding must be ‘Normal’. You can set field values through property ValueField.Value.
- We do not support events and script objects/variables.
The following table describes the relationship between the different versions of the Adobe LiveCycle Designer product, the different versions of the XFA format and the different versions of the Adobe PDF Reader and which ones are supported by PDFKit.NET 2.0 and 3.0.
Adobe (LiveCycle) Designer | Produces XFA version | Requires Adobe PDF Reader | Requires PDFKit.NET |
---|---|---|---|
6.0 | 2.0 | 6.02 | 2.0 |
7.0 | 2.1 | 6.02 | 2.0 |
7.0 BETA | 2.2 | 7.05 | 2.0 |
7.1 | 2.4 | 7.05 | 2.0 |
8.0 | 2.5 | 8.0 | 2.0 |
8.1 | 2.6 | 8.1 | 3.0 |
8.1.2 | 2.7 | 8.2 | 3.0 |
ES 8.2 | 2.8 | 9.0 | 3.0 |
No public release | 3.0 | 9.1 | Not supported yet |