-
Notifications
You must be signed in to change notification settings - Fork 242
Forms (AcroForms)
davebrokit edited this page Jun 25, 2024
·
1 revision
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.
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 };
}