Reading Form Fields and Values
A PDF form that comes back filled in carries data: a name, a selected country, a check mark. Forms.GetAcroFormFields reads this data from the PDF file or from a byte array, without loading the document into the editor. A Windows Forms application can show the values, store them or put them back into its own form, for example to let a clerk check and correct what a customer entered.
The examples read form-filled.pdf, the form of Create a PDF Form with its fields name, country and newsletter, after a user filled it in and saved it in a PDF reader. How such forms are created is described in Creating AcroForms.
How GetAcroFormFields Reads a Form
Forms.GetAcroFormFields is a static method of the TXTextControl.DocumentServer.PDF namespace, introduced in version 29.0. One overload takes the path of a PDF file, the other the PDF as a byte array. It returns an array of FormField objects of the TXTextControl.DocumentServer.PDF.AcroForms namespace, each of the class that fits its field:
| Class | Field in the PDF | Value |
|---|---|---|
| FormTextField | Text field; also the date form fields of TX Text Control | Value: the text entered |
| FormCheckBox | Check box | IsChecked |
| FormRadioButton | Radio button, derived from FormCheckBox | IsChecked |
| FormChoiceField | The base class of combo boxes and list boxes | Value: the selected item; Options: all items |
| FormComboBox | Combo box or drop-down list, derived from FormChoiceField | Value |
| FormListBox | List box, derived from FormComboBox | Value |
| FormButton | Push button | None |
Every field has these members of the base class:
- FieldName is the name the author of the form gave the field, for TX Text Control forms the
Nameof the form field. - AlternateFieldName is the alternate name, which PDF readers show as the tooltip.
- FieldType is
Txfor a text field,Btnfor a button,Chfor a choice field orSigfor a signature field. - Bounds is the rectangle of the field in the document.
GetAcroFormFields reads forms filled in and saved with Adobe Acrobat Reader or with Google Chrome since version 85. A user of Chrome saves the filled form with the Download button, choosing the version with the changes:

Show the Values of a Filled Form
The following code in Form1.cs collects the values of a PDF form by field name and shows them after the user picked the file:
private Dictionary<string, string> ReadFormValues(string path)
{
Dictionary<string, string> values = new Dictionary<string, string>();
foreach (AcroForms.FormField field in Forms.GetAcroFormFields(path))
{
switch (field)
{
case AcroForms.FormTextField textField:
values[field.FieldName] = textField.Value;
break;
case AcroForms.FormCheckBox checkBox: // check boxes and radio buttons
values[field.FieldName] = checkBox.IsChecked ? "true" : "false";
break;
case AcroForms.FormChoiceField choiceField: // combo boxes and list boxes
values[field.FieldName] = choiceField.Value;
break;
}
}
return values;
}
private void readFormButton_Click(object sender, EventArgs e)
{
using (OpenFileDialog dialog = new OpenFileDialog() { Filter = "PDF forms|*.pdf" })
{
if (dialog.ShowDialog() != DialogResult.OK)
{
return;
}
Dictionary<string, string> values;
try
{
values = ReadFormValues(dialog.FileName);
}
catch (FilterException exception)
{
MessageBox.Show("The form could not be read: " + exception.Reason);
return;
}
if (values.Count == 0)
{
MessageBox.Show("The PDF document has no form fields.");
return;
}
MessageBox.Show(string.Join("\n", values.Select(value => value.Key + ": " + value.Value)));
}
}
Form1.cs needs these using directives:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using TXTextControl;
using TXTextControl.DocumentServer.PDF;
using AcroForms = TXTextControl.DocumentServer.PDF.AcroForms;
The code works as follows:
- The alias
AcroFormsseparates the classes of the PDF from the form fields of the document, because both namespaces have a class namedFormField. - The
switchstatement testsFormCheckBoxfor check boxes and radio buttons and the base classFormChoiceFieldfor combo boxes and list boxes, because the program needs only their values. To tell the derived classes apart, testFormRadioButtonbeforeFormCheckBoxandFormListBoxbeforeFormComboBox. - The indexer of the dictionary keeps the last value when a name occurs more than once in the array, where
ToDictionarywould throw. - A file that isn't a readable PDF throws a FilterException.
GetAcroFormFieldstakes no password, so the fields of a PDF that requires a password to open can't be read.
For the form of Getting Started, the message shows lines such as name: Tim Typer, country: Germany and newsletter: true.
Put the Values Back Into the Form
TX Text Control doesn't write values into an existing PDF. To continue with the values in your application, load your own document of the form, the one the PDF was created from, into textControl1 and transfer the values into its form fields:
private void fillEditorFormButton_Click(object sender, EventArgs e)
{
Dictionary<string, string> values = ReadFormValues("form-filled.pdf");
// The main text, headers, footers and text frames
foreach (IFormattedText textPart in textControl1.TextParts)
{
foreach (FormField formField in textPart.FormFields)
{
if (string.IsNullOrEmpty(formField.Name) ||
!values.TryGetValue(formField.Name, out string value) || value == null)
{
continue;
}
switch (formField)
{
case CheckFormField checkFormField:
checkFormField.Checked = value == "true";
break;
case SelectionFormField selectionFormField:
// -1 selects nothing if the value isn't one of the items
selectionFormField.SelectedIndex = Array.IndexOf(selectionFormField.Items, value);
break;
case TextFormField textFormField:
textFormField.Text = value;
break;
}
}
}
}
The code works as follows:
- TextControl.TextParts contains the main text, the headers and footers and the text frames, each with its own FormFields collection.
- Each form field type takes the value through its own property: Checked for check boxes, SelectedIndex of the Items for selection fields and Text for text form fields.
- Date form fields are left out: their value arrives as the text the form displayed. To set one, parse the text with the culture of the form and assign DateFormField.Date.
Saved again as PDF, the document is a new fillable form with the values; flattened first, it is a document with fixed values, as Exporting Interactive and Flattened Forms shows. Instead of setting each field, you can also merge the values with MailMerge and FormFieldMergeType.Preselect, as Merge Form Fields describes.
Next Steps
- Exporting Interactive and Flattened Forms: save the form with fixed values.
- Creating AcroForms: create the PDF forms you read.
- The blog article Export and Import Adobe PDF XFDF XML Files in .NET C#: store the values of a form as XFDF.