skip to Main Content

I am trying to find and replace a text different sections of header in each page using Apache poi but getting only null data, but Docx has different header sections and footer too

    package com.concretepage;
    import java.io.FileInputStream;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFFooter;
    import org.apache.poi.xwpf.usermodel.XWPFHeader;
    public class ReadDOCXHeaderFooter {
        public static void main(String[] args) {
            try {
                FileInputStream fis = new FileInputStream("D:/docx/read-test.docx");
                XWPFDocument xdoc=new XWPFDocument(OPCPackage.open(fis));
                XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(xdoc);
                //read header
 
                for(int i=0;i<90;i++)
                {
                 XWPFHeader header = policy.getHeader(i);
       List<XWPFRun> runs = header.getRuns();
  if (runs != null) {
         for (XWPFRun r : runs) {
          String text = r.getText(0);
          if (text != null && text.contains("$$key$$")) {
           text = text.replace("$$key$$", "ABCD");//your content
           r.setText(text, 0);
          }
         }
                    System.out.println(header.getText());

                    //read footer
                    XWPFFooter footer = policy.getFooter(i);
                    System.out.println(footer.getText());
                }
            } catch(Exception ex) {
                ex.printStackTrace();
            }
        }
    }

1.Screen shot of Docx header sections.

Docx header sections

2.Screen shot of Docx header another section.

Docx header another section

3.Screen shot of Docx header another section.

Docx header another section

4.Screen Shot

Screen Shot

3

Answers


  1. In a *.docx document, which contains multiple sections, each section starts in a paragraph which has section properties set. To get the headers and footers out of section properties there is public XWPFHeaderFooterPolicy(XWPFDocument doc, org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr sectPr) constructor.

    Only the section properties for the last section are set in document’s body.

    So the following code should get all headers and footers out of all sections in the document.

    import java.io.FileInputStream;
    import org.apache.poi.xwpf.usermodel.*;
    import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
    
    public class ReadWordAllHeaderFooters {
    
     static void getAllHeaderFooterFromPolicy(XWPFHeaderFooterPolicy headerFooterPolicy) {
      XWPFHeader header;
      XWPFFooter footer;
      header = headerFooterPolicy.getDefaultHeader();
      if (header != null) System.out.println("DefaultHeader: " + header.getText());
      header = headerFooterPolicy.getFirstPageHeader();
      if (header != null) System.out.println("FirstPageHeader: " + header.getText());
      header = headerFooterPolicy.getEvenPageHeader();
      if (header != null) System.out.println("EvenPageHeader: " + header.getText());
      header = headerFooterPolicy.getOddPageHeader();
      if (header != null) System.out.println("OddPageHeader: " + header.getText());
    
      footer = headerFooterPolicy.getDefaultFooter();
      if (footer != null) System.out.println("DefaultFooter: " + footer.getText());
      footer = headerFooterPolicy.getFirstPageFooter();
      if (footer != null) System.out.println("FirstPageFooter: " + footer.getText());
      footer = headerFooterPolicy.getEvenPageFooter();
      if (footer != null) System.out.println("EvenPageFooter: " + footer.getText());
      footer = headerFooterPolicy.getOddPageFooter();
      if (footer != null) System.out.println("OddPageFooter: " + footer.getText());
     }
    
     public static void main(String[] args) throws Exception {
      XWPFDocument document = new XWPFDocument(new FileInputStream("MultipleHeaderFooters.docx"));
      XWPFHeaderFooterPolicy headerFooterPolicy;
    
      //are there paragraphs to start sections?
      int section = 1;
      for (XWPFParagraph paragraph : document.getParagraphs()) {
       if (paragraph.getCTP().isSetPPr()) { //paragraph has paragraph properties set
        if (paragraph.getCTP().getPPr().isSetSectPr()) { //paragraph property has section properties set
         //headers and footers in paragraphs section properties:
         headerFooterPolicy = new XWPFHeaderFooterPolicy(document, paragraph.getCTP().getPPr().getSectPr());
         System.out.println("headers and footers in section properties of section " + section++ + ":");
         getAllHeaderFooterFromPolicy(headerFooterPolicy);
        }
       }
      }
    
      //headers and footers in documents body = headers and footers of last section:
      headerFooterPolicy = new XWPFHeaderFooterPolicy(document);
      System.out.println("headers and footers in documents body = headers and footers of last section " + section + ":");
      getAllHeaderFooterFromPolicy(headerFooterPolicy);
    
     }
    }
    
    Login or Signup to reply.
  2. This function should do the job

    static void replaceHeaderText(XWPFDocument document, String searchValue, String replacement)
    {
        List<XWPFHeader> headers = document.getHeaderList();
        for(XWPFHeader h : headers)
        {
            for (XWPFParagraph p : h.getParagraphs()) {
                List<XWPFRun> runs = p.getRuns();
                if (runs != null) {
                    for (XWPFRun r : runs) {
                        String text = r.getText(0);
                        if (text != null && text.contains(searchValue)) {
                            text = text.replace(searchValue, replacement);
                            r.setText(text, 0);
                        }
                    }
                }
            }
            for (XWPFTable tbl : h.getTables()) {
                for (XWPFTableRow row : tbl.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            for (XWPFRun r : p.getRuns()) {
                                String text = r.getText(0);
                                if (text != null && text.contains(searchValue)) {
                                    text = text.replace(searchValue, replacement);
                                    r.setText(text,0);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    Login or Signup to reply.
  3. Here is a code snippet that replaces all the occurrences of a key like ${firstName} with its String value in an XWPFDocument. All the parameters to be replaced will be stored in a Map<String, String>.

    private void replaceParameters(XWPFDocument document, Map<String, String> replacements) {
        for (Map.Entry<String, String> parameter : replacements.entrySet()) {
            // replaces all occurrences in the headers
            replaceHeadersParams(document.getHeaderList(), parameter);
    
            // replaces all occurrences in the document's body
            replaceParagraphsParams(document.getParagraphs(), parameter);
            replaceTablesParams(document.getTables(), parameter);
    
            // replaces all occurrences in the footers
            replaceFootersParams(document.getFooterList(), parameter);
        }
    }
    
    private void replaceHeadersParams(List<XWPFHeader> headers, Map.Entry<String, String> paramToReplace) {
        for (XWPFHeader header : headers) {
            replaceParagraphsParams(header.getParagraphs(), paramToReplace);
            replaceTablesParams(header.getTables(), paramToReplace);
        }
    }
    
    private void replaceFootersParams(List<XWPFFooter> footers, Map.Entry<String, String> parameter) {
        for (XWPFFooter footer : footers) {
            replaceParagraphsParams(footer.getParagraphs(), parameter);
            replaceTablesParams(footer.getTables(), parameter);
        }
    }
    
    private void replaceTablesParams(List<XWPFTable> tables, Map.Entry<String, String> paramToReplace) {
        for (XWPFTable tbl : tables) {
            for (XWPFTableRow row : tbl.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    replaceParagraphsParams(cell.getParagraphs(), paramToReplace);
                }
            }
        }
    }
    

    Replace the startIndex and endIndex with your values $$. Keep in mind that this implementation replaces all the occurrences ignoring the case.

    private void replaceParagraphsParams(List<XWPFParagraph> paragraphs, Map.Entry<String, String> paramToReplace) throws POIXMLException {
        for (XWPFParagraph p : paragraphs) {
            for (XWPFRun r : p.getRuns()) {
                String text = r.getText(0);
                if (text != null && text.toLowerCase().contains(paramToReplace.getKey().toLowerCase())) {
                    int startIndex = text.indexOf("${");
                    int endIndex = text.indexOf("}");
                    String toBeReplaced = text.substring(startIndex, endIndex + 1);
                    text = text.replace(toBeReplaced, paramToReplace.getValue());
                    r.setText(text, 0);
                }
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search