How to replace placeholders in header of docx in java using poi 3.8
Asked Answered
T

4

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

Timbale answered 16/10, 2013 at 0:48 Comment(0)
L
16

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);
        }
    }
}
Lifegiving answered 8/5, 2015 at 19:8 Comment(1)
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://mcmap.net/q/1603800/-replacing-a-text-in-apache-poi-xwpf-not-working, it will handle the multiple run case appropriately.Newark
D
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. :)

Diner answered 23/2, 2014 at 12:49 Comment(0)
L
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

Leighannleighland answered 16/10, 2013 at 0:53 Comment(5)
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:Timbale
XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy(); XWPFHeader defaultHeader = headerFooterPolicy.getDefaultHeader(); System.out.println("Header value is : " + defaultHeader.getText()); List<XWPFParagraph> paraList = null; List<XWPFRun> runList = null; XWPFRun run = null; Iterator<XWPFRun> runIter = null; Iterator<XWPFParagraph> paraIter = null; XWPFParagraph para = null; paraList = defaultHeader.getListParagraph(); paraIter = paraList.iterator();Timbale
It looks like you are only getting the default header. Are you sure each page is using the default header?Leighannleighland
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.Timbale
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 DennisTimbale
I
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.

Implacental answered 17/1, 2019 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.