Hi Luigi,
Unfortunately, GemBox.Document currently doesn’t support exporting interactive form fields to PDF.
However, note that we do have plans to support this and I have added your report to our backlog ticket in which we keep track of this feature’s priority.
But at this moment I cannot tell you exactly when it will be implemented. Please note that we prioritize feature request implementations by the number of users requesting them and currently we are working on some other features that have greater priority (more user requests).
Nevertheless, for now as a workaround perhaps you could try the following:
- Replace the
Field
elements in theDocumentModel
with thePicture
elements of specific metadata. - Save the
DocumentModel
to a PDF file and then load it into aPdfDocument
using GemBox.Pdf. - Find the
PdfImageContent
elements of specific metadata and replace them with one of thePdfInteractiveForm
types of elements.
Something like this:
var document = DocumentModel.Load("Input.docx");
var imageOptions = new GemBox.Document.ImageSaveOptions(GemBox.Document.ImageSaveFormat.Png);
var fieldsMapping = new Dictionary<string, FormFieldData>();
foreach (var fieldData in document.Content.FormFieldsData)
{
var field = fieldData.Field;
// Create a TextBox that will contain only a copy of the current Field element,
// its size will be auto-fitted.
var tempTextBox = new TextBox(document, Layout.Inline(new Size(0, 0)));
tempTextBox.TextBoxFormat.InternalMargin = new Padding(0);
tempTextBox.TextBoxFormat.WrapText = false;
tempTextBox.TextBoxFormat.AutoFit = TextAutoFit.ResizeShapeToFitText;
var tempParagraph = new Paragraph(document, field.Clone(true));
tempParagraph.ParagraphFormat.LineSpacing = 1;
tempParagraph.ParagraphFormat.LineSpacingRule = LineSpacingRule.AtLeast;
tempParagraph.ParagraphFormat.SpaceAfter = 0;
tempParagraph.ParagraphFormat.SpaceBefore = 0;
tempTextBox.Blocks.Add(tempParagraph);
// Save a TextBox as an image.
var imageStream = new MemoryStream();
tempTextBox.FormatDrawing().Save(imageStream, imageOptions);
// Replace the current Field element with its image representation.
var picture = new Picture(document, imageStream);
string guid = Guid.NewGuid().ToString();
picture.Metadata.Title = guid;
field.Content.Start.InsertRange(picture.Content);
field.Content.Delete();
// Map the GUID value with the original Field element,
// I'll use the Picture.Metadata.Title information to identify these images in the output PDF.
fieldsMapping.Add(guid, fieldData);
}
document.Save("Temp.pdf");
using (var pdf = PdfDocument.Load("Temp.pdf"))
{
foreach (var page in pdf.Pages)
{
var imagesMapping = new Dictionary<string, (PdfImageContent Image, PdfQuad Bounds)>();
// Iterate through PdfPage elements and find the PdfImageContent elements
// that are the image representations of the Field elements.
var enumerator = page.Content.Elements.All(page.Transform).GetEnumerator();
while (enumerator.MoveNext())
{
var element = enumerator.Current;
if (element.ElementType != PdfContentElementType.Image)
continue;
var imageElement = (PdfImageContent)element;
string metadata = imageElement.Image.Metadata?.Value;
if (metadata == null)
continue;
var xml = new XmlDocument();
xml.LoadXml(metadata);
var xmlManager = new XmlNamespaceManager(xml.NameTable);
xmlManager.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
var xmlNode = xml.SelectSingleNode("//dc:title", xmlManager);
string guid = xmlNode?.InnerText;
if (guid != null && fieldsMapping.ContainsKey(guid))
{
var bounds = imageElement.Bounds;
enumerator.Transform.Transform(ref bounds);
// Map the GUID value with the image elements.
imagesMapping.Add(guid, (imageElement, bounds));
}
}
// Replace image elements with form fields.
var pdfFields = pdf.Form.Fields;
foreach (var item in imagesMapping)
{
var imageData = item.Value;
var fieldData = fieldsMapping[item.Key];
switch (fieldData.Field.FieldType)
{
case FieldType.FormText:
var textFieldData = (FormTextData)fieldData;
var pdfTextField = pdfFields.AddText(page,
imageData.Bounds.Left,
imageData.Bounds.Bottom,
imageData.Bounds.Right - imageData.Bounds.Left,
imageData.Bounds.Top - imageData.Bounds.Bottom);
pdfTextField.Name = textFieldData.Name;
pdfTextField.Value = textFieldData.ValueOrDefault?.ToString();
// Perhaps set the "pdfTextField.Appearance" as well...
break;
case FieldType.FormCheckBox:
var checkBoxFieldData = (FormCheckBoxData)fieldData;
var pdfCheckBoxField = pdfFields.AddCheckBox(page,
imageData.Bounds.Left,
imageData.Bounds.Bottom,
imageData.Bounds.Right - imageData.Bounds.Left,
imageData.Bounds.Top - imageData.Bounds.Bottom);
pdfCheckBoxField.Name = checkBoxFieldData.Name;
pdfCheckBoxField.Checked = checkBoxFieldData.ValueOrDefault;
// Perhaps set the "pdfCheckBoxField.Appearance" as well...
break;
case FieldType.FormDropDown:
// TODO
break;
}
imageData.Image.Collection.Remove(imageData.Image);
}
}
pdf.Save("Output.pdf");
}
I hope this works for you.
Regards,
Mario