0

I have example document.docx Example: Example docx

Task: to detect a text field, analyze the text and replace it if necessary. Thanks to other answers on stackoverflow, I managed to find the text, but I have no idea how to replace it. Can someone help me?

public class POITest {

    public static void main(String[] args) throws Exception {

        final var directory = Paths.get("test");
        final var input = directory.resolve("new_debug_input.docx");
        final var output = directory.resolve("new_debug_output.docx");

        try (var open = OPCPackage.open(Files.newInputStream(input))) {
            try (var document = new XWPFDocument(open)) {

                for (XWPFParagraph paragraph : document.getParagraphs()) {
                    printContentsOfTextBox(paragraph, builder);
                }

                document.write(Files.newOutputStream(output,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.TRUNCATE_EXISTING));
            }
        }

    }

    private static void printContentsOfTextBox(XWPFParagraph paragraph, StringBuilder builder) {

        XmlObject[] objects = paragraph.getCTP().selectPath(
                "declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'" +
                        "declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape'" +
                        "declare namespace v='urn:schemas-microsoft-com:vml'" +
                        ".//*/wps:txbx/w:txbxContent | .//*/v:textbox/w:txbxContent"
        );

        {
            System.out.println("objects.length = " + objects.length);
            for (XmlObject object : objects) {
                try {
                    XmlObject[] children = object.selectChildren(
                            new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p")
                    );
                    System.out.println("children.length = " + children.length);
                    for (final XmlObject child : children) {
                        final var childParagraph = new XWPFParagraph(CTP.Factory.parse(child.xmlText()), paragraph.getBody());
                        final var text = childParagraph.getText();
                        if (!text.isEmpty()) {
                            System.out.println(text);
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

output:

objects.length = 2
children.length = 2
TEXT IN TEXT BOX
TEXT IN TEXT BOX
children.length = 2
TEXT IN TEXT BOX
TEXT IN TEXT BOX

Why duplicated ?

UPD #1:

As I understand it, to get the existing text, we parse an xml object, creating a new paragraph based on it, from which we then get the text, but if we replace the text in it, it will have no effect on the document.

UPD #2:

Not work:

changeText(paragraph, "REPLACED TEXt");

Result:

enter image description here

  • you just need to change the text of your XWPFParagraph, to do that here is an answer that's working : https://stackoverflow.com/questions/3213547/updating-the-text-of-a-xwpfparagraph-using-apache-poi – DEV May 18 '23 at 14:44
  • @DEV i am updated question with y answer – The Prototype May 18 '23 at 14:47
  • @AxelRichter I also tried this option, there is still a problem with setting the value in the text field, it is not clear how to do it – The Prototype May 18 '23 at 15:12
  • 1
    https://stackoverflow.com/questions/46802369/replace-text-in-text-box-of-docx-by-using-apache-poi/46894499#46894499 – Axel Richter May 18 '23 at 15:12
  • @AxelRichter thanks, it solved my problem! I don't understand how I didn't find this answer on my own – The Prototype May 19 '23 at 09:29

0 Answers0