Exporting Interactive and Flattened Forms
The same form leaves a Windows Forms application in one of two states. Sent to a customer, it stays interactive: the PDF has fields that the customer fills in. Signed, approved or archived, it is flattened: each form field is replaced by the text it shows, so nobody can change the values in a PDF reader. You choose the state when you save, for all fields or only some of them.
The examples use the form of Create a PDF Form, with the form fields name, country and newsletter, in textControl1.
Interactive or Flattened
| Interactive form | Flattened form | |
|---|---|---|
| In the PDF | AcroForm fields with names and values | Text, check box characters and dates at the places of the fields |
| Users can | Fill in and change the values in a PDF reader | Read and print the document |
| Your code can | Read the values with Forms.GetAcroFormFields | Only extract text, as Text Extraction describes |
| Typical use | Forms sent out to be filled in | Confirmations, contracts and archived forms |
A flattened form field is removed from the document, and the text it showed stays in its place:
| Form field | Text that remains |
|---|---|
| TextFormField | The entered text |
| SelectionFormField | The text of the selected item |
| DateFormField | The date as the field displays it, formatted with its DateFormat |
| CheckFormField | The character that shows the state of the check box, set with CheckedCharacter and UncheckedCharacter |
Read the values before you flatten, as Reading Form Fields and Values describes. A SignatureField isn't a form field, so flattening leaves signature fields in place.
Save a Fillable Form
Saved with StreamType.AdobePDF, form fields are always saved as fillable fields. A master password and permissions let readers fill in the form and print it, but not change the rest of the document:
private void saveFillableFormButton_Click(object sender, EventArgs e)
{
SaveSettings saveSettings = new SaveSettings()
{
MasterPassword = "owner1234",
// Fill in the fields and print, nothing else
DocumentAccessPermissions = DocumentAccessPermissions.AllowAuthoringFields |
DocumentAccessPermissions.AllowHighLevelPrinting
};
textControl1.Save("form.pdf", StreamType.AdobePDF, saveSettings);
}
DocumentAccessPermissions AllowAuthoringFields allows filling in existing form fields, and AllowHighLevelPrinting allows printing. The permissions take effect only together with a MasterPassword. Without a user password, everyone can open the form. Passwords and Access Permissions lists all permissions.
In Adobe Acrobat Reader, the fields of an interactive form are highlighted and can be filled in:

Save a Flattened Copy
To send a flattened PDF while the user continues with the form in the editor, flatten a copy in a ServerTextControl:
private void saveFlattenedFormButton_Click(object sender, EventArgs e)
{
// A copy of the form in the editor, which keeps its form fields
byte[] document;
textControl1.Save(out document, BinaryStreamType.InternalUnicodeFormat);
using (ServerTextControl tx = new ServerTextControl())
{
// Initialize the new instance before using it
tx.Create();
tx.Load(document, BinaryStreamType.InternalUnicodeFormat);
// The main text, headers, footers and text frames
foreach (IFormattedText textPart in tx.TextParts)
{
// true: the fields are removed, their text stays
textPart.GetTextFields(TextFieldType.FormFields).Clear(true);
}
tx.Save("form-flattened.pdf", StreamType.AdobePDF);
}
}
The code works as follows:
- ServerTextControl.TextParts contains the main text, the headers and footers and the text frames, so form fields in all of them are flattened.
- IFormattedText.GetTextFields returns the fields of the TextFieldType you pass as a TextFieldCollection.
FormFieldsstands for all form field types, and the values can be combined, for exampleTextFieldType.CheckFormField | TextFieldType.DateFormField. - TextFieldCollection.Clear with
trueremoves the fields and keeps their text. FormFieldCollection.Clear has no such parameter, so useGetTextFieldsfor flattening.
The same form, flattened, shows its values as plain text:

Flatten Some Fields and Keep Others
A form can go out partly filled: the values your application knows are fixed, and the fields the recipient still has to fill in stay interactive. The following handler flattens every form field of textControl1 except newsletter; it needs using System.Collections.Generic;:
private void flattenSomeFieldsButton_Click(object sender, EventArgs e)
{
foreach (IFormattedText textPart in textControl1.TextParts)
{
TextFieldCollection formFields = textPart.GetTextFields(TextFieldType.FormFields);
// Collect first: removing a field changes the collection
List<TextField> flatten = new List<TextField>();
foreach (TextField field in formFields)
{
if (field.Name != "newsletter")
{
flatten.Add(field);
}
}
foreach (TextField field in flatten)
{
formFields.Remove(field, true);
}
}
textControl1.Save("form-partly-flattened.pdf", StreamType.AdobePDF);
}
TextFieldCollection.Remove with true as the second parameter removes a field and keeps its text; without it, the text is deleted as well. Here the fields are flattened in the editor itself, so the user sees the result. Reload the form to get the fields back.
Flatten While Merging Data
When a form is final as soon as data is merged into it, MailMerge.FormFieldMergeType Replace fills and flattens in one step:
private void mergeAndFlattenButton_Click(object sender, EventArgs e)
{
textControl1.Load("form.tx", StreamType.InternalUnicodeFormat);
using (MailMerge mailMerge = new MailMerge()
{
TextComponent = textControl1,
// Fill the form fields and replace them with their values
FormFieldMergeType = FormFieldMergeType.Replace
})
{
mailMerge.MergeJsonData(File.ReadAllText("registration.json"));
}
textControl1.Save("registration-final.pdf", StreamType.AdobePDF);
}
The handler needs using TXTextControl.DocumentServer;. With Replace, the form fields are replaced with the values of the data, and empty form fields are removed according to RemoveEmptyFields. Preselect fills the fields and keeps them interactive. Merge Form Fields compares the merge types.
Flatten Before Signing and Archiving
- Signing. A digital signature covers the document as it is saved. Flatten first, then save with SaveSettings.DigitalSignature, so that the signed PDF contains the final values, as Signing PDF Documents describes.
- Archiving. A flattened form saved with
StreamType.AdobePDFAis a PDF/A document with fixed values, as PDF/A describes.
The blog article Convert MS Word DOCX to PDF with Form Fields in C# .NET: Preserve or Flatten Form Fields converts a Word form both ways.
Next Steps
- Reading Form Fields and Values: read the values before you flatten.
- PDF/A: archive flattened forms.
- Digital Signatures: sign the final document.