6

I'm tying to replace tokens in the header of docx file.I have handled the token replacement in paragraphs and tables but its not picking the header data. Im using apache poi 3.8 and coding in java using eclipse ID. Thanx

Liquidpie
  • 1,589
  • 2
  • 22
  • 32
NKB
  • 71
  • 1
  • 3

4 Answers4

15

This methods will replace all selected text, in tables, headers and paragraph, in the entire document.

public XWPFDocument replacePOI(XWPFDocument doc, String placeHolder, String replaceText){
    // REPLACE ALL HEADERS
    for (XWPFHeader header : doc.getHeaderList()) 
        replaceAllBodyElements(header.getBodyElements(), placeHolder, replaceText);
    // REPLACE BODY
    replaceAllBodyElements(doc.getBodyElements(), placeHolder, replaceText);
    return doc;
}

private void replaceAllBodyElements(List<IBodyElement> bodyElements, String placeHolder, String replaceText){
    for (IBodyElement bodyElement : bodyElements) {
        if (bodyElement.getElementType().compareTo(BodyElementType.PARAGRAPH) == 0)
            replaceParagraph((XWPFParagraph) bodyElement, placeHolder, replaceText);
        if (bodyElement.getElementType().compareTo(BodyElementType.TABLE) == 0)
            replaceTable((XWPFTable) bodyElement, placeHolder, replaceText);
    }
}

private void replaceTable(XWPFTable table, String placeHolder, String replaceText) {
    for (XWPFTableRow row : table.getRows()) {
        for (XWPFTableCell cell : row.getTableCells()) {
            for (IBodyElement bodyElement : cell.getBodyElements()) {
                if (bodyElement.getElementType().compareTo(BodyElementType.PARAGRAPH) == 0) {
                    replaceParagraph((XWPFParagraph) bodyElement, placeHolder, replaceText);
                }
                if (bodyElement.getElementType().compareTo(BodyElementType.TABLE) == 0) {
                    replaceTable((XWPFTable) bodyElement, placeHolder, replaceText);
                }
            }
        }
    }  
}

private void replaceParagraph(XWPFParagraph paragraph, String placeHolder, String replaceText) {
    for (XWPFRun r : paragraph.getRuns()) {
        String text = r.getText(r.getTextPosition());
        if (text != null && text.contains(placeHolder)) {
            text = text.replace(placeHolder, replaceText);
            r.setText(text, 0);
        }
    }
}
Julio Villane
  • 994
  • 16
  • 28
Deyvid Martinez
  • 430
  • 3
  • 8
  • 4
    This one covers a bunch of use cases, great job! Only downside is that it doesn't cover the case of words and sentences that span multiple runs. But, if we replace the implementation for "replaceParagraph" with the implementation from https://stackoverflow.com/a/28740659/4411975, it will handle the multiple run case appropriately. – Ray W Sep 18 '18 at 18:18
4

I don't know if you have got the solution for this question. But, I've tried to replace tokens in document header and it worked for me.

public XWPFDocument setHeader(XWPFDocument document, String token, String textToReplace){
    XWPFHeaderFooterPolicy policy= document.getHeaderFooterPolicy();
    XWPFHeader header = policy.getHeader(0);
    replaceInParagraphs(header.getParagraphs(), token, textToReplace);
    return document;
}

private void replaceInParagraphs(List<XWPFParagraph> paragraphs, String placeHolder, String replaceText){
    for (XWPFParagraph xwpfParagraph : paragraphs) {
        List<XWPFRun> runs = xwpfParagraph.getRuns();
        for (XWPFRun run : runs) {
            String runText = run.getText(run.getTextPosition());

            if(placeHolder !="" && !placeHolder.isEmpty()){
                if(runText != null &&
                        Pattern.compile(placeHolder, Pattern.CASE_INSENSITIVE).matcher(runText).find()){
                    runText = replaceText;
                }
            }
            run.setText(runText, 0);
        }
    }
}

Hope this helps. :)

Liquidpie
  • 1,589
  • 2
  • 22
  • 32
0

You can leverage "content controls" in MS Word. Then you can access the content controls using the openxml library. Content controls act as placeholders/input sections in Word documents. I'm not a Java guy, but just letting you know this is another method

Dennis Flagg
  • 664
  • 6
  • 12
  • Im using xml Library, since after posting my question I experimented some more and able to get header data but its only giving second page header data which line is in the centre. Im using the following code: – NKB Oct 16 '13 at 04:00
  • XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy(); XWPFHeader defaultHeader = headerFooterPolicy.getDefaultHeader(); System.out.println("Header value is : " + defaultHeader.getText()); List paraList = null; List runList = null; XWPFRun run = null; Iterator runIter = null; Iterator paraIter = null; XWPFParagraph para = null; paraList = defaultHeader.getListParagraph(); paraIter = paraList.iterator(); – NKB Oct 16 '13 at 04:02
  • It looks like you are only getting the default header. Are you sure each page is using the default header? – Dennis Flagg Oct 16 '13 at 04:07
  • No, its also returning data which i put in the header at that place.If I Implement XWPFHeader defaultHeader =document.getHeaderList().get(1); It gives me only first page data. – NKB Oct 16 '13 at 04:16
  • It's handled in paragraph. I didn't notice that in my user given template there was a table in the header. Code isn't replacing the table values but its replacing otherwise. and secondly the page header has label like First header and header.So im handling it using two different functions. Thank you Dennis – NKB Oct 16 '13 at 05:57
0

Code referred by (edited Sep 30 '16 at 1:19, Julio Villane) works for only headers across the document. Thanks for the code. To Replace in Footer, Same code has to called inside iteration of FooterList. To Replace across the document other than Header and Footer, You have to call the replaceParagraph(), replaceTable() again,to replace text across the document, other than Header and Footer.