Adding footer to ms word using POI api

2019-01-28 09:49发布

问题:

I searched a lot and getting some results in which some sample code is there but no one is working. All are either getting null pointer exception or if document is generated then at the time of opening file (.docx) giving error and displaying message A text/xml declaration may occur only at the very beginning of innput.

I thought may be I am adding some content and then adding footer is giving some problem so I pasted my footer code at very beginning now this time I am getting

index out of bound exception

Here is my complete code

String fileName ="Book.docx";
String   folderPath=SystemProperties.get(SystemProperties.TMP_DIR)+File.separator+"liferay" + File.separator    + "document_preview";
String filePath=folderPath+File.separator+fileName;
File file=new File(filePath);
XWPFDocument document = new XWPFDocument();  
XWPFParagraph paragraphOne = document.createParagraph();
paragraphOne.setAlignment(ParagraphAlignment.CENTER);
XWPFRun paragraphOneRunOne = paragraphOne.createRun();
paragraphOneRunOne.setText("Training Report");
paragraphOneRunOne.addBreak();
XWPFTable table = document.createTable();
XWPFTableRow tableRowOne = table.getRow(0);
tableRowOne.getCell(0).setText("No");
tableRowOne.createCell().setText("Name");
XWPFHeaderFooterPolicy headerFooterPolicy = document.getHeaderFooterPolicy();
            if (headerFooterPolicy == null) {
                CTBody body = document.getDocument().getBody();
                CTSectPr sectPr = body.getSectPr();
                if (sectPr == null) {
                sectPr = body.addNewSectPr();
                }
                headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr);
                }
            CTP ctP1 = CTP.Factory.newInstance();
            CTR ctR1 = ctP1.addNewR();
            CTText t = ctR1.addNewT();
            t.setStringValue("first footer");
            XWPFParagraph codePara = new XWPFParagraph(ctP1);
            XWPFParagraph[] newparagraphs = new XWPFParagraph[1];
            newparagraphs[0] = codePara;
             XWPFFooter xwpfFooter = null;
    xwpfFooter =  headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);
 FileOutputStream fileoutOfTraining = new FileOutputStream(file);
            document.write(fileoutOfTraining);
            fileoutOfTraining.flush();
            fileoutOfTraining.close();
   downloadOperation(file, fileName, resourceResponse);

code in downloadOperation method

HttpServletResponse httpServletResponse =PortalUtil.getHttpServletResponse(resourceResponse);
BufferedInputStream input = null;
        BufferedOutputStream output = null;
 httpServletResponse.setHeader("Content-Disposition", "attachment;    filename=\""+fileName+"\"; filename*=UTF-8''"+fileName);
int  DEFAULT_BUFFER_SIZE=1024;
        try {
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            resourceResponse.flushBuffer();
            output = new BufferedOutputStream(httpServletResponse.getOutputStream(), DEFAULT_BUFFER_SIZE);
        } catch (IOException e) {
            e.printStackTrace();
        }
byte[] buffer = new byte[2*DEFAULT_BUFFER_SIZE];
        int length;
        try {
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            output.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

Please help me to generate footer, this is my code, if I add footer code after my paragraph and table then no run time error but error in opening generated file, if I placed footer at before the contents that I want to add in documents then I am getting error "index out of bound exception". Please help me if any one having any code snippet or at least some pointers towards the solution. Thanks

回答1:

I faced this issue and the solution is We have to use 3.10 final poi jar. 3.9 having this problem. Please remove jars of previous version and add jars of 3.10 final version in which this bug is fixed. jars requires are 1. poi-3.10-FINAL.jar 2. poi-ooxml-3.10-FINAL.jar 3. poi-ooxml-schemas-3.10-FINAL.jar Easily available in net. http://mvnrepository.com/artifact/org.apache.poi/poi/3.10-FINAL

XWPFDocument document = new XWPFDocument();
CTP ctp = CTP.Factory.newInstance();
CTR ctr = ctp.addNewR();
CTRPr rpr = ctr.addNewRPr();
CTText textt = ctr.addNewT();
textt.setStringValue( " Page 1" );
XWPFParagraph codePara = new XWPFParagraph( ctp, document );
XWPFParagraph[] newparagraphs = new XWPFParagraph[1];
newparagraphs[0] = codePara;
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy headerFooterPolicy = new  XWPFHeaderFooterPolicy( document, sectPr );
headerFooterPolicy.createFooter( STHdrFtr.DEFAULT, newparagraphs );

The above code is working perfectly, please use 3.10 wars those I mentioned above.



回答2:

I don't know if adding image to header from scratch works in new version, but I know for a fact that "templating" works just perfectly. I created the template document in word, adapted the header the way I needed it to be (in my case, logo-image was on the right, paragraph with dummy text on the left, and another image that separates the upper two objects from the content, on the header bottom, and all was repeating on all the pages) and left the rest of the document empty. On the very beginning, I didn't create the XWPFDocument by calling the ...new XWPFDocument() anymore, I created it this way:

XWPFDocument doc = new XWPFDocument(new FileInputStream("pathTo/template.docx"));

Than just fill your document with your content, and if you need to update the header text for different exports like I did, call the update header function, that in my case looks something like this:

public void updateHeader() throws InvalidFormatException, IOException {
        // load the header policy from template and update the paragraph text
        XWPFHeaderFooterPolicy headerFooterPolicy = document
                .getHeaderFooterPolicy();
        XWPFHeader defaultHeader = headerFooterPolicy.getDefaultHeader();
        defaultHeader.getParagraphs().get(0).getRuns().get(0)
                .setText(profileName, 0);
        // this is only to put some space between the content in the header and the real content
        defaultHeader.getParagraphs()
                .get(defaultHeader.getParagraphs().size() - 1)
                .setSpacingAfter(300);
    }

As far as I know, this works since 3.10, and if you stumble upon some java security issues, try the current nightly version where many of these security issues were resolved. For me it even worked on Google App Engine.