views:

124

answers:

3

I am using Apache POI to generate docx files from a template. There doesn't seem to be an obvious way to replace all text in a paragraph and the documentation is pretty scarce. Right now I am able to read a document by looping through its paragraphs, then looping through each paragraph's runs, then looping through each run's text... This works pretty well and I can replace the contents of a text in a run, but my template placeholders (example: <>) may be split into several runs, which makes it really complicated to match and replace. Is there a way to set the contents of a XWPFParagraph? Or at least a way to zap all runs in a paragraph and create my own runs?

Here is what I have so far:

    public static void main(String[] args) {

    InputStream fs = null;
    try {
        fs = new FileInputStream("C:\\sample1.docx");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    XWPFDocument doc = null;
    try {
        doc = new XWPFDocument(fs);
    } catch (IOException e) {
        e.printStackTrace();
    }

    for (int i = 0; i < doc.getParagraphs().length; i++) {
        XWPFParagraph paragraph = doc.getParagraphs()[i];
        paragraph.getCTP().getRArray().

        // This will output the paragraph's contents.
        System.out.println(paragraph.getParagraphText());

        for (int j = 0; j < paragraph.getCTP().getRArray().length; j++) {
            CTR run = paragraph.getCTP().getRArray()[j];

            for (int k = 0; k < run.getTArray().length; k++) {
                CTText text = run.getTArray()[k];

                // This will output the text contents
                System.out.println(text.getStringValue());

                // And this will set its contents
                text.setStringValue("Success!");
            }
        }
    }

    try {
        doc.write(new FileOutputStream("C:\\output.docx"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
A: 

I have the same problem. Any luck getting it working?

Here is my version:

for (XWPFRun currentRun : xWPFParagraph.getRuns()) {
  if ((currentRun.getText(0) != null) && (currentRun.getText(0).contains("_My_Placeholder_"))
          ) {
    currentRun.setText("_My_New_Text_ ");
  }
}

But this adds extra text to the currently existing one, rather than replace the whole text of the run to the new string.

LeoInSea
I got it working with 3.7-beta2. There is now a setParagraph() method that will do the trick... almost - I found what I think is a bug, but seems to be unrelated and is only exhibited with more complex documents. I think it might have to do with version tracking, but haven't had much time to investigate. I have a couple of examples of writing Word documents with POI on my blog - tkgospodinov.com. Hope that helps.
TK Gospodinov
A: 

Awesome and very helpful, Thanks!

kubasz
A: 

I got it working with 3.7-beta2. The solution is not ideal and is a little convoluted, but it worked for my use case. There is now a XWPFDocument#setParagraph method that will do the trick... I have a couple of examples of writing Word documents with POI on my blog - tkgospodinov.com:

http://tkgospodinov.com/writing-microsoft-word-documents-in-java-with-apache-poi/

Hope that helps.

TK Gospodinov