List a PDF form’s fields, fill text fields and check boxes in C#, save the filled form, then flatten it so the values become part of the page, with OnePDF.
using OnePdf; using (PdfDocument doc = PdfDocument.Open("of345.pdf", new PdfOpenOptions { AllowEditing = true })) { PdfAcroForm form = doc.Form ?? throw new InvalidOperationException("The file has no form."); Console.WriteLine($"{form.TerminalFields.Count()} fields, XFA: {form.HasXfa}"); // Field names, kinds and allowed values. foreach (PdfFormField field in form.TerminalFields.Take(8)) { string options = field.Options.Count > 0 ? $" options: {string.Join(", ", field.Options.Select(o => o.Export))}" : ""; Console.WriteLine($" {field.FullName} ({field.Kind}) = {field.Value}{options}"); } try { form.SetValue("name", "Ada Lovelace"); form.SetValue("dob", "12/10/1985"); form.SetChecked("xno1", true); form.SetValue("missing", "x"); // no such field } catch (PdfFormValueException e) { Console.WriteLine($"refused: {e.Reason}"); // nothing was changed by the refused call } doc.Save("filled.pdf"); // still a fillable form } // Bake the values into the page and drop the form. using (PdfDocument doc = PdfDocument.Open("filled.pdf", new PdfOpenOptions { AllowEditing = true })) { PdfFlattenResult result = doc.Flatten(); Console.WriteLine($"form removed: {result.FormRemoved}"); doc.Save("flat.pdf"); } using (PdfDocument flat = PdfDocument.Open("flat.pdf")) Console.WriteLine($"form after flattening: {(flat.Form is null ? "none" : "still there")}; text has the name: {flat.Pages[0].ExtractText().Text.Contains("Ada Lovelace")}");
53 fields, XFA: False name (Text) = dob (Text) = title (Text) = homeaddr (Text) = agcy (Text) = xyes1 (CheckBox) = xno1 (CheckBox) = xyes2 (CheckBox) = refused: UnknownField form removed: True form after flattening: none; text has the name: True
The form is OF 345, a US government form. The values set before the refused call are kept: a call that fails changes nothing, but it doesn’t undo earlier calls.
Filling
- Fields are found by fully qualified name (
parent.child).TerminalFieldslists the fields that hold values. SetValuefills text fields, combo boxes and list boxes (by export value or display text) and radio groups (by state name or option text).SetValuesfills a multi-select list box.SetCheckedsets a check box.- A value that can’t be stored throws
PdfFormValueException, whoseReasonsays why:UnknownField,WrongType,ReadOnly,NotInOptions,TooLong,NotMultiSelectorNotTerminal.PdfFillOptionscan override read-only fields or cut text to the field’s maximum length. - OnePDF draws each filled field’s appearance and stores it, so the value shows in every viewer.
- Field scripts never run. Calculated fields aren’t recomputed and format scripts aren’t applied: values are stored exactly as given. XFA form data isn’t filled.
Flattening
Flatten() draws each field’s appearance into the page and removes the fields; when none are left, the form itself goes (FormRemoved). The values are then ordinary page content, so text extraction finds them and nobody can edit them in a viewer.
PdfFlattenOptions.FieldNamesflattens only the named fields.IncludeMarkupalso flattens comments and other markup annotations.- Signed signature fields are kept.
- Flattening works on encrypted documents, and new objects are encrypted like the rest.
Every rule is in Forms, and how appearances are drawn is in Appearance generation.
Longer walk-throughs on real government forms: Fill PDF form fields in C# and Flatten a PDF form in C#.