TX Text Control .NET for Windows Forms

Exporting Interactive and Flattened Forms

Topic

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 formFlattened form
In the PDFAcroForm fields with names and valuesText, check box characters and dates at the places of the fields
Users canFill in and change the values in a PDF readerRead and print the document
Your code canRead the values with Forms.GetAcroFormFieldsOnly extract text, as Text Extraction describes
Typical useForms sent out to be filled inConfirmations, contracts and archived forms

A flattened form field is removed from the document, and the text it showed stays in its place:

Form fieldText that remains
TextFormFieldThe entered text
SelectionFormFieldThe text of the selected item
DateFormFieldThe date as the field displays it, formatted with its DateFormat
CheckFormFieldThe 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:

A PDF form in Adobe Acrobat Reader with highlighted form fields: text fields, a check box and drop-down lists.

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:

The same form, flattened, shows its values as plain text:

The same PDF form in Adobe Acrobat Reader after flattening: the values and check box characters are plain text without form fields.

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.AdobePDFA is 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