Replace FormFields

I am trying to replace FormFields inside a docx using the Java API by Content Controls/ StructuredDocumentTags.

I have the following code:

try (InputStream stream = new ByteArrayInputStream(bytes)) {
    Document doc = new Document(stream);
    DocumentBuilder builder = new DocumentBuilder(doc);
    List<Node> formFields = Arrays.asList(doc.getChildNodes(NodeType.FORM_FIELD, true).toArray());
    for (Node node: formFields)
    {

        FormField formField = (FormField)node;

        log.debug("FormField: {} Text: [{}]", FieldType.getName(formField.getType()), formField.getResult());

        // 70 is 'FIELD_FORM_TEXT_INPUT'
        if (70 == formField.getType())
        {
            StructuredDocumentTag structuredDocumentTag = new StructuredDocumentTag(doc, SdtType.PLAIN_TEXT, MarkupLevel.INLINE);

            String string = formField.getResult();
            if (string.isBlank()) string = placeHolderString;

            structuredDocumentTag.isShowingPlaceholderText(true);
            structuredDocumentTag.setAppearance(SdtAppearance.BOUNDING_BOX);
            structuredDocumentTag.setTitle(string);

            builder.moveTo(formField);
            builder.insertNode(structuredDocumentTag);
            //formField.getParentNode().appendChild(structuredDocumentTag);
            //formField.getParentNode().insertAfter(structuredDocumentTag, formField);
            //formField.getParentNode().getChildNodes().insert(formField.getParentNode().indexOf(formField) + 1, structuredDocumentTag);
            formField.removeField();
        }
    }

    doc.updateFields();
    return doc;
}

I tried different approaches (see commented code) but the structuredDocumentTag is not showing in the new document. Only the formFields are removed.

@kerner Please try using the following code to achieve what you need.

Document doc = new Document("C:\\Temp\\in.docx");
DocumentBuilder builder = new DocumentBuilder(doc);

// Loop through form fields in the document.
for (FormField ff : doc.getRange().getFormFields())
{
    if (ff.getType() == FieldType.FIELD_FORM_TEXT_INPUT)
    {
        StructuredDocumentTag sdt = new StructuredDocumentTag(doc, SdtType.PLAIN_TEXT, MarkupLevel.INLINE);
        sdt.isShowingPlaceholderText(true);
        sdt.setAppearance(SdtAppearance.BOUNDING_BOX);
        sdt.setTitle(ff.getName());

        builder.moveToBookmark(ff.getName(), false, true);
        builder.insertNode(sdt);
    }
}

// Loop through fields in the document and remove text fields.
for (Field f : doc.getRange().getFields())
{
    if (f.getType() == FieldType.FIELD_FORM_TEXT_INPUT)
        f.remove();
}

doc.save("C:\\Temp\\out.docx");

If the problem still persist, please attach your input and output documents here for our reference.

1 Like

Thank you, that works very well (for most cases)!

Unfortunately, in some cases, the builder cannot move to the FormField Bookmark, as it is not found:

boolean found = builder.moveToBookmark(ff.getName(), false, true);
if(found) builder.insertNode(sdt);
else log.warn("Failed to insert element");

How can I fix the case where the bookmark is not found?

@kerner Could you please attach the problematic document here for testing? We will check the issue and provide you more information. Normally, form field is associated with bookmark in the document and the appropriate field.

Thank you!
Brief Terminbestätigung_EN.docx (1.1 MB)

@kerner Thank you for additional information. You are right there is a buggy form field without a bookmark in your document. You can try using the following code:

Document doc = new Document("C:\\Temp\\in.docx");
DocumentBuilder builder = new DocumentBuilder(doc);

// Loop through fields in the document and replace text fields with SDT.
for (Field f : doc.getRange().getFields())
{
    if (f.getType() == FieldType.FIELD_FORM_TEXT_INPUT)
    {

        // Get Form field wrapped with the field.
        FormField ff = null;
        Node currentNode = f.getStart();
        while (currentNode != null && currentNode != f.getEnd())
        {
            if (currentNode.getNodeType() == NodeType.FORM_FIELD)
            {
                ff = (FormField)currentNode;
                break;
            }
            currentNode = currentNode.getNextSibling();
        }

        // put SDT after the field.
        if (ff != null)
        {
            StructuredDocumentTag sdt = new StructuredDocumentTag(doc, SdtType.PLAIN_TEXT, MarkupLevel.INLINE);
            sdt.isShowingPlaceholderText(true);
            sdt.setAppearance(SdtAppearance.BOUNDING_BOX);
            sdt.setTitle(ff.getName());

            builder.moveToField(f, true);
            builder.insertNode(sdt);
        }
        f.remove();
    }
}

doc.save("C:\\Temp\\out.docx");
1 Like

thank you :pray: :muscle:

1 Like