Skip to content
davebrokit edited this page Jun 25, 2024 · 1 revision

Intro

Form fields for interactive forms (AcroForms) can be retrieved using:

bool hasForm = document.TryGetForm(out AcroForm form);

This will return false if the document does not contain a form.

The fields can be accessed using the AcroForm's Fields property. Since the form is defined at the document level this will return fields from all pages in the document. Fields are of the types defined by the enum AcroFieldType, for example PushButton, Checkbox, Text, etc.

Please note the forms are readonly and values cannot be changed or added using PdfPig.

Example

using UglyToad.PdfPig;
using UglyToad.PdfPig.AcroForms;
using UglyToad.PdfPig.AcroForms.Fields;
using UglyToad.PdfPig.Core;
using UglyToad.PdfPig.Fonts.Standard14Fonts;
using UglyToad.PdfPig.Geometry;
using UglyToad.PdfPig.Writer;


var sourcePdfPath = @"C:\Users\David\Downloads\Aviva.pdf";
var outputPath = @"C:\Users\David\Downloads\Aviva.out.pdf";
var pageNumber = 1;
using (var document = PdfDocument.Open(sourcePdfPath))
{
    var builder = new PdfDocumentBuilder { };
    var boundingBlocks = new List<PdfRectangle>();
    PdfDocumentBuilder.AddedFont font = builder.AddStandard14Font(Standard14Font.Helvetica);
    var pageBuilder = builder.AddPage(document, pageNumber);
    pageBuilder.SetStrokeColor(0, 255, 0);
    var page = document.GetPage(pageNumber);

    // 1. Check if has form fields
    bool hasForm = document.TryGetForm(out AcroForm form);

    // 2. Get fields for page
    var fieldsForPage = form.GetFieldsForPage(pageNumber);

    // 3. Iterate through each field pulling out information want/need
    foreach (var field in fieldsForPage)
    {
        if (field is AcroTextField text)
        {
            // Text box. Can be single or multi line        
            Console.WriteLine($"TextField Value: {text.Value ?? ""}. Multiline: {text.IsMultiline}");
            boundingBlocks.Add(field.Bounds.Value);
        }
        else if (field is AcroCheckboxField checkbox)
        {
            // Check box
            Console.WriteLine($"Checkbox Value: {checkbox.CurrentValue.Data}");
            boundingBlocks.Add(field.Bounds.Value);
        }
        else if (field is AcroComboBoxField comboBox)
        {
            // Combo box
            Console.WriteLine($"Selected Options: {string.Join(",", comboBox.SelectedOptions)}");
            boundingBlocks.Add(field.Bounds.Value);
        }
        else if (field is AcroNonTerminalField container)
        {
            // Checkbox or radio buttons. We need to recreate a bounding box containing all of them
            var points = container.Children.Select(x => x.Bounds).SelectMany(ToPoints);
            var containingBox = GeometryExtensions.MinimumAreaRectangle(points);
            boundingBlocks.Add(containingBox);
        }
        else if (field is AcroSignatureField signatureField)
        {
            // ...
        }
        else if (field is AcroListBoxField listbox)
        {
            // ...
        }
        else if (field is AcroPushButtonField)
        {
            // ...
        }
    }

    // 4. Add debug info - Bounding boxes
    foreach (var bbox in boundingBlocks)
    {
        pageBuilder.DrawRectangle(bbox.BottomLeft, bbox.Width, bbox.Height);
    }

    // 5. Write result to a file
    byte[] fileBytes = builder.Build();
    File.WriteAllBytes(outputPath, fileBytes); // save to file
}


IEnumerable<PdfPoint> ToPoints(PdfRectangle? rectangle)
{
    if (rectangle == null)
        return Enumerable.Empty<PdfPoint>();

    var pdfRectangle = rectangle.Value;
    return new[] { pdfRectangle.BottomLeft, pdfRectangle.TopLeft, pdfRectangle.TopRight, pdfRectangle.BottomRight };
}
Clone this wiki locally