Interactive Forms in PDF Documents

  • 17 minutes to read

A PDF document can contain interactive forms (AcroForms) with fillable form fields (text fields, buttons, list boxes, and so on).

FormBeforeFlattening

PDF Document API allows you to create, fill, flatten, and delete fillable PDF forms. You can import or export AcroForm data to various formats.

Create Interactive Form Fields

Read Tutorial: Add Interactive Form Fields as Graphic Content

The table below lists available form fields and API used to create each type.

Form Field Class Method
Check Box PdfAcroFormCheckBoxField PdfAcroFormField.CreateCheckBox
Combo box PdfAcroFormComboBoxField PdfAcroFormField.CreateComboBox
Group PdfAcroFormGroupField PdfAcroFormField.CreateGroup
List Box PdfAcroFormListBoxField PdfAcroFormField.CreateListBox
Radio Group PdfAcroFormRadioGroupField PdfAcroFormField.CreateRadioGroup
Signature PdfAcroFormSignatureField PdfAcroFormField.CreateSignature
Text Box PdfAcroFormTextBoxField PdfAcroFormField.CreateTextBox

This example creates a text box and radio button group fields, and adds them to a document.

added fields

using DevExpress.Pdf;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a document:
    processor.LoadDocument("..\\..\\Document.pdf");

    // Create a text box field:
    PdfAcroFormTextBoxField textBox =
         new PdfAcroFormTextBoxField("text box", 1, new PdfRectangle(230, 690, 280, 710));

    // Specify text box text and appearance:
    textBox.Text = "Text Box";
    textBox.Appearance.BackgroundColor = new PdfRGBColor(0.8, 0.5, 0.3);
    textBox.Appearance.FontSize = 12;

    // Create a radio group field:
    PdfAcroFormRadioGroupField radioGroup =
         PdfAcroFormField.CreateRadioGroup("Gender Group", 1);


    // Add the first radio button to the group and specify its location:
    radioGroup.AddButton("button1", new PdfRectangle(230, 635, 250, 655));

    // Add the second radio button to the group:
    radioGroup.AddButton("button2", new PdfRectangle(310, 635, 330, 655));

    // Specify radio group's selected index and appearance:
    radioGroup.SelectedIndex = 0;
    radioGroup.Appearance.BorderAppearance = new PdfAcroFormBorderAppearance()
    { Color = new PdfRGBColor(0.8, 0.5, 0.3), Width = 3 };

    // Add form fields to the page:
    processor.AddFormFields(textBox, radioGroup);

    // Save the resulting document:
    processor.SaveDocument("..\\..\\Result.pdf");
}

Field Name Collisions

When you add a form field to the document, make sure that it’s name is unique. Otherwise, a conflict may occur.

Use API from the table below to prevent and resolve field name conflicts:

API Description
PdfDocumentProcessor.CheckFormFieldNameCollisions Checks whether the form field name already exists.
PdfAcroFormFieldNameCollision.Field Retrieves a conflicting form field.
PdfAcroFormFieldNameCollision.ForbiddenNames Gets the collection of forbidden names.

The code sample below checks whether the created field names already exist in the loaded document and renames the conflicting field.

List<PdfAcroFormField> fields = new List<PdfAcroFormField>();
fields.Add(textBox);
fields.Add(radioGroup);
// Check whether new form fields' names already exist in the document
IList<PdfAcroFormFieldNameCollision> collisions =
     processor.CheckFormFieldNameCollisions(fields);
if (collisions.Count == 0)
    Console.WriteLine("No name conflicts are detected");
else
{
    foreach (var collision in collisions)
    {
      // Rename conflicting field
      Console.WriteLine("The specified form field name ({0}) already exist in the document. Renaming...",
         collision.Field.Name);
      while (collision.ForbiddenNames.Contains(collision.Field.Name))
          collision.Field.Name = Guid.NewGuid().ToString();
    }
}
// Add fields to the document
// and save the result
processor.AddFormFields(fields);
processor.SaveDocument("Result.pdf");

Change Form Field Properties

The PdfDocumentFacade class allows you to change the PDF document without access to its inner structure. Use the PdfDocumentFacade.AcroForm property to get interactive form field options. You can change form field and appearance properties.

Utilize one of the following methods to get form field properties:

Method Description
GetFields() Retrieves all AcroForm fields.
GetFormField() Obtains properties of a field with a specific name.
GetButtonFormField()
GetCheckBoxFormField()
GetComboBoxFormField()
and so on
Returns properties of a specific form field type.
GetNames() Gets a list of form field names.

The code sample below changes available form field parameters:

View Example: How to Change Form Field Parameters

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");

    PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
    PdfAcroFormFacade acroForm = documentFacade.AcroForm;

    // Obtain text form field properties:
    PdfTextFormFieldFacade visaField = acroForm.GetTextFormField("VisaNo");

    // Divide field text into equally spaced positions:
    visaField.InputType = PdfTextFieldInputType.Comb;
    visaField.Multiline = false;

    // Limit number of inserted characters:
    visaField.MaxLength = 8;

    // Enable multiline text in the text field:
    PdfTextFormFieldFacade addressField = acroForm.GetTextFormField("Address");
    addressField.Multiline = true;

    addressField.Scrollable = true;
    addressField.SpellCheck = false;

    // Set radio group options:
    PdfRadioGroupFormFieldFacade genderField = acroForm.GetRadioGroupFormField("Gender");
    genderField.RadiosInUnison = true;
    genderField.ToggleToOff = false;


    PdfComboBoxFormFieldFacade nationalityField = acroForm.GetComboBoxFormField("Nationality");
    // Disable user input in the combo box:
    nationalityField.Editable = false;

    // Sort list items alphabetically:
    nationalityField.Sorted = true;

    pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");
}

Change Widget Annotation Properties

A widget annotation contains a form field’s display properties. One field can be related to multiple widget annotations. The PdfWidgetFacade class contains widget options that apply to all form fields.

The code sample below retrieves all fields and changes their color settings:

changed appearance

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
  pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");

  PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
  PdfAcroFormFacade acroForm = documentFacade.AcroForm;

  // Change color settings for all form fields:
  var fields = acroForm.GetFields();
  foreach (PdfFormFieldFacade field in fields)
  {
    ChangeFormFieldColor(field);
  }
  pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");
}

  private static void ChangeFormFieldColor(PdfFormFieldFacade field)
  {
    foreach (PdfWidgetFacade pdfWidget in field)
    {
      // Change color and border settings
      // for all form fields:
      pdfWidget.BorderWidth = 1;
      pdfWidget.BackgroundColor = new PdfRGBColor(0.81, 0.81, 0.81);
      pdfWidget.BorderColor = new PdfRGBColor(0.47, 0.44, 0.67);
      pdfWidget.FontColor = new PdfRGBColor(0.34, 0.25, 0.36);

      // Change border style for text form fields:
      if (field.Type == PdfFormFieldType.Text)
      {
        pdfWidget.BorderStyle = PdfBorderStyle.Underline;
      }
    }
  }

Each form field type has its own widget annotation properties. Use the PdfFormFieldFacade<T, V>.Widgets property to retrieve the widget settings.

The code sample below changes the push button’s icon and radio group’s marker settings:

changed appearance button

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");

    PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
    PdfAcroFormFacade acroForm = documentFacade.AcroForm;

    // Obtain button form field parameters:
    PdfButtonFormFieldFacade pushButton = acroForm.GetButtonFormField("Submit");
    PdfButtonWidgetFacade buttonWidget = pushButton.Widgets[0];

    // Specify a button icon and set its options:
    buttonWidget.SetNormalIcon("Documents//submit_3802014.png");
    buttonWidget.IconOptions.FitToAnnotationBounds = true;
    buttonWidget.IconOptions.ScaleCondition = PdfIconScalingCircumstances.BiggerThanAnnotationRectangle;
    buttonWidget.TextPosition = PdfWidgetAnnotationTextPosition.NoCaption;

    PdfRadioGroupFormFieldFacade genderField = acroForm.GetRadioGroupFormField("Gender");

    // Change marker style for all radio buttons:
    foreach (PdfRadioButtonWidgetFacade widget in genderField.Widgets)
    {
        widget.ButtonStyle = PdfAcroFormButtonStyle.Square;
    }
    pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");

}

Obtain Form Field Location

Read Tutorial: How to: Replace a Form Field with an Image

The PdfWidgetFacade.Rectangle property allows you to obtain the widget margins, and the PageNumber property gets the page number where the widget is located.

The code sample below retrieves all fields and filters them by location on the page:

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");
    PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
    PdfAcroFormFacade acroForm = documentFacade.AcroForm;

    double halfPage = pdfDocumentProcessor.Document.Pages[0].CropBox.Top / 2;

    // Obtain all form fields:
    var fields = acroForm.GetFields();
    List<PdfFormFieldFacade> bottomFields = new List<PdfFormFieldFacade>();

    foreach (PdfFormFieldFacade field in fields)
    {
        // Check each form field widget
        foreach (PdfWidgetFacade widget in field)
        {
            // Add a field to another list
            // if it is located in the bottom half of the page:
            if (widget.PageNumber == 1 && widget.Rectangle.Top <= halfPage)
            {
                bottomFields.Add(field);
            }
        }
    }
}

Fill Interactive Form Fields

Interactive form fields can have the following values:

  • Text field - string;
  • Radio group and check box - name of the checked/unchecked item;
  • Combo box - a string array;
  • Complex field (field group)- a PdfFormData object.

You can use the PdfDocumentFacade or PdfFormData class to specify form field values.

Use PdfDocumentFacade

Each FormFieldFacade class has the Value (Values for a list box) property that allows you to specify a form field value. Use the PdfChoiceFormFieldFacade.Items property to obtain a list of choice form field (combo box, list box, radio group) values.

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");

    PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
    PdfAcroFormFacade acroForm = documentFacade.AcroForm;
    FillFormFields(acroForm);
    pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");

}
private static void FillFormFields(PdfAcroFormFacade acroForm)
{
    PdfTextFormFieldFacade visaField = acroForm.GetTextFormField("VisaNo");
    visaField.Value = "73203393";

    PdfTextFormFieldFacade addressField = acroForm.GetTextFormField("Address");
    addressField.Value = "98033, 722 Moss Bay Blvd., Kirkland, WA, USA";

    PdfRadioGroupFormFieldFacade genderField = acroForm.GetRadioGroupFormField("Gender");
    genderField.Value = genderField.Field.Items[2].Value;


    PdfComboBoxFormFieldFacade nationalityField = acroForm.GetComboBoxFormField("Nationality");
    nationalityField.Value = nationalityField.Items[68].Value;
}

Use PdfFormData

Utilize the PdfDocumentProcessor.GetFormData method to retrieve the PdfFormData object that contains interactive form data. You can call the PdfDocumentProcessor.GetFormFieldNames method to retrieve a list of field names and iterate through the returned string collection.

Note

Obtain a new PdfFormData instance after one of the following operations: add new interactive form fields, flatten interactive form, merge documents with interactive forms, or delete pages with interactive form fields.

The code sample below uses PdfFormData to set form field values:

// Load a document with an interactive form.
using (PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor()) {
    documentProcessor.LoadDocument(filePath + fileName + ".pdf");

    // Obtain interactive form data from a document.
    PdfFormData formData = documentProcessor.GetFormData();

    // Specify the value for FirstName and LastName text boxes.
    formData["FirstName"].Value = "Janet";
    formData["LastName"].Value = "Leverling";

    // Specify the value for the Gender radio group.
    formData["Gender"].Value = "Female";

    // Specify the check box checked appearance name.
    formData["Check"].Value = "Yes";

    // Specify values for the Category list box.
    formData["Category"].Value = new string[] { "Entertainment", "Meals", "Morale" };

    // Obtain data from the Address form field and specify values for Address child form fields.
    PdfFormData address = formData["Address"];

    // Specify the value for the Country combo box. 
    address["Country"].Value = "United States";

    // Specify the value for City and Address text boxes. 
    address["City"].Value = "California";
    address["Address"].Value = "20 Maple Avenue";

    // Apply data to the interactive form. 
    documentProcessor.ApplyFormData(formData);

    // Save the modified document.
    documentProcessor.SaveDocument(filePath + fileName + "_new.pdf");
}

Fill an Interactive Form from a Data File

You can fill the PdfFormData object from a file with interactive form data (FDF, XML, XFDF or TXT). Pass the data file name and format as the PdfFormData constructor parameter. PdfDocumentProcessor automatically detects the file type.

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    processor.LoadDocument(pathForPdf);
    PdfFormData data = new PdfFormData(pathForData);
    processor.ApplyFormData(data);
    processor.SaveDocument(pathForPdf);
}

Flatten an Interactive Form

The flattening process removes form field interactive features, so the form field value is converted to regular content (text, images, shapes, and so on). The flattening process cannot be undone, so we recommend that you save the flattened document under a different name.

You can flatten an entire form or a specific form field.

Flatten a Form

Call the PdfDocumentProcessor.FlattenForm method to flatten an entire form. This method returns false if the document does not contain an interactive form to be flattened.

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
     processor.LoadDocument("FormDemo.pdf");
     if (processor.FlattenForm())
          processor.SaveDocument("Result.pdf");
}

Flatten a Form Field

Utilize the PdfDocumentProcessor.FlattenFormField method to flatten a specific field. This method returns false if the form field was not found in the document.

The code sample below flattens the VisaNo form field:

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");
    if (pdfDocumentProcessor.Document.AcroForm != null)
    {
        pdfDocumentProcessor.FlattenFormField("VisaNo");
    }
    pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");
}

If you use form field facade API, call the PdfFormFieldFacade.Flatten() method to flatten a form field:

The code sample below flattens all text form fields:

using (PdfDocumentProcessor pdfDocumentProcessor = new PdfDocumentProcessor())
{
    pdfDocumentProcessor.LoadDocument("Documents//FormDemo.pdf");

    PdfDocumentFacade documentFacade = pdfDocumentProcessor.DocumentFacade;
    PdfAcroFormFacade acroForm = documentFacade.AcroForm;

    // Flatten all text form fields:
    var fields = acroForm.GetFields();
    foreach (PdfFormFieldFacade field in fields)
    {
        if (field.Type == PdfFormFieldType.Text) { field.Flatten(); }
    }
    pdfDocumentProcessor.SaveDocument("FormDemo_new.pdf");

}

Import and Export Interactive Form Data

You can import and export AcroForm data to the following formats: FDF, XFDF, XML, and TXT.

Import Interactive Form Data

Call the PdfDocumentProcessor.Import method to import interactive form data. The previous interactive form data is automatically removed from the document after the import.

The example below demonstrates how to import interactive form data from an XML file:

using DevExpress.Pdf;


using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a PDF document with AcroForm data.
    processor.LoadDocument("..\\..\\EmptyForm.pdf");

    // Import AcroForm data from an XML file.
    processor.Import("..\\..\\InteractiveForm.xml");

    // Save the imported document.
    processor.SaveDocument("..\\..\\InteractiveForm.pdf");
}

Export Interactive Form Data

Utilize one of the following methods to export interactive form field data:

Before interactive form data export, make sure that the interactive form contains fields with filled values.

using DevExpress.Pdf;

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
    // Load a PDF document with AcroForm data.
    processor.LoadDocument("..\\..\\InteractiveForm.pdf");

    // Export AcroForm data to XML format.
    processor.Export("..\\..\\InteractiveForm.xml", PdfFormDataFormat.Xml);

    PdfFormData data = processor.GetFormData();
    data.Save(pathForExportedData, PdfFormDataFormat.Fdf);
}

Remove Form Fields

The code sample below removes an interactive form field:

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{

    // Load a document with an interactive form.
    processor.LoadDocument("..\\..\\InteractiveForm.pdf");

    // Remove a form field:
    if (processor.RemoveFormField("FirstName"))

        // Save the document.
        processor.SaveDocument("..\\..\\Result.pdf");
    else
        // Show a message if the form field is not found in a document.
        Console.WriteLine("The form field was not removed. Make sure that the form field name is correct.");
}

The code sample below removes an entire AcroForm:

using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{

    // Load a document with an interactive form:
    processor.LoadDocument("..\\..\\InteractiveForm.pdf");

    // Remove the AcroForm:
    if (processor.RemoveForm())

        // Save the document:
        processor.SaveDocument("..\\..\\Result.pdf");
    else
        // Show a message if the interactive form is not found:
        Console.WriteLine("The interactive form was not removed. Make sure the interactive form exists.");
}