You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@poi.apache.org by Stephan Aßmus <su...@gmx.de> on 2012/12/19 17:16:53 UTC

XWPF header and footer

Hi,

thank you for this great framework!

I am generating .docx files from scratch using POI. I have so far 
understood that I can compensate for missing features by directly 
manipulating the XML layer. For example, I've added support for 
generating tab stops which is so far not accessible by the XWPFParagraph 
API.

Now I am trying to turn on page numbering by adding a header to the 
document, but the generated XML is incomplete and I don't understand why 
exactly. My immediate goal is to properly generate the word/header1.xml 
file. Google doesn't help me. This is the code I am using so far:


protected void initializeDocument(PageModel pageModel,
     String title, OutputStreamProvider streamProvider) {

     fWordDocument = new XWPFDocument();

     // Create the CTSectPr element which stores page size and margins.
     CTSectPr sectPr
         = fWordDocument.getDocument().getBody().addNewSectPr();

     CTPageSz pageSz = sectPr.addNewPgSz();
     pageSz.setW(BigInteger.valueOf(
         lengthInPointsToUnit(pageModel.getPageWidth(), 20)));
     pageSz.setH(BigInteger.valueOf(
         lengthInPointsToUnit(pageModel.getPageHeight(), 20)));

     PageMargins margins = pageModel.getPageMargins(0);

     CTPageMar pageMar = sectPr.addNewPgMar();
     pageMar.setLeft(BigInteger.valueOf(
         lengthInPointsToUnit(margins.getLeftMargin(), 20)));
     pageMar.setTop(BigInteger.valueOf(
         lengthInPointsToUnit(margins.getTopMargin(), 20)));
     pageMar.setRight(BigInteger.valueOf(
         lengthInPointsToUnit(margins.getRightMargin(), 20)));
     pageMar.setBottom(BigInteger.valueOf(
         lengthInPointsToUnit(margins.getBottomMargin(), 20)));

     try {
         XmlOptions xmlOptions = createHeaderOptions();

         CTHdrFtr headerFooter
             = CTHdrFtr.Factory.newInstance(xmlOptions);
         CTP p = headerFooter.addNewP();
         CTPPr pr = p.addNewPPr();

         CTJc jc = pr.isSetJc() ? pr.getJc() : pr.addNewJc();
         jc.setVal(STJc.RIGHT);

         CTR r = p.addNewR();
         r.addNewRPr();
         CTFldChar fldChar = r.addNewFldChar();
         fldChar.setFldCharType(STFldCharType.BEGIN);

         r = p.addNewR();
         CTText instruction = r.addNewInstrText();
         instruction.setStringValue(" PAGE ");

         r = p.addNewR();
         fldChar = r.addNewFldChar();
         fldChar.setFldCharType(STFldCharType.SEPARATE);

         r = p.addNewR();
         CTText dummy = r.addNewT();
         dummy.setStringValue("0");

         r = p.addNewR();
         fldChar = r.addNewFldChar();
         fldChar.setFldCharType(STFldCharType.END);

         r = p.addNewR();
         r.addNewRPr();
         CTText textAfter = r.addNewT();
         textAfter.setStringValue(".");

         XWPFHeader header
             = (XWPFHeader)fWordDocument.createRelationship(
                 XWPFRelation.HEADER, XWPFFactory.getInstance(), 1);
         header.setHeaderFooter(headerFooter);

     } catch (Exception e) {
         Logger.getLogger(OOXMLExporter.class).debug(
             "Failed to create header", e);
     }
}

private XmlOptions createHeaderOptions() {
     XmlOptions xmlOptions = new XmlOptions(
         XWPFHeaderFooter.DEFAULT_XML_OPTIONS);
     Map<String, String> map = new HashMap<String, String>();
 
map.put("http://schemas.openxmlformats.org/officeDocument/2006/math", "m");
 
map.put("http://schemas.openxmlformats.org/markup-compatibility/2006", 
"ve");
     map.put("http://schemas.microsoft.com/office/word/2006/wordml", "wne");
     // The following ones are used by LibreOffice when storing the header
     // document
     map.put("urn:schemas-microsoft-com:office:office", "o");
 
map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", 
"r");
     map.put("urn:schemas-microsoft-com:vml", "v");
 
map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", 
"w");
     map.put("urn:schemas-microsoft-com:office:word", "w10");
 
map.put("http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", 
"wp");
     xmlOptions.setSaveSuggestedPrefixes(map);
     return xmlOptions;
}


This is the output:

<?xml version="1.0" encoding="UTF-8"?>
<w:hdr 
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
     <w:p>
         <w:pPr>
             <w:jc w:val="right"/>
         </w:pPr>
         <w:r>
             <w:rPr/>
             <w:fldChar w:fldCharType="begin"/>
         </w:r>
         <w:r>
             <w:instrText> PAGE </w:instrText>
         </w:r>
         <w:r>
             <w:fldChar w:fldCharType="separate"/>
         </w:r>
         <w:r>
             <w:t>0</w:t>
         </w:r>
         <w:r>
             <w:fldChar w:fldCharType="end"/>
         </w:r>
         <w:r>
             <w:rPr/>
             <w:t>.</w:t>
         </w:r>
     </w:p>
</w:hdr>


And this is what it would need to look like:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:hdr
     xmlns:o="urn:schemas-microsoft-com:office:office"
 
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
     xmlns:v="urn:schemas-microsoft-com:vml"
     xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
     xmlns:w10="urn:schemas-microsoft-com:office:word"
 
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">
     <w:p>
         <w:pPr>
             <w:pStyle w:val="style20"/>
             <w:jc w:val="right"/>
         </w:pPr>
         <w:r>
             <w:rPr></w:rPr>
             <w:fldChar w:fldCharType="begin"></w:fldChar>
         </w:r>
         <w:r>
             <w:instrText> PAGE </w:instrText>
         </w:r>
         <w:r>
             <w:fldChar w:fldCharType="separate"/>
         </w:r>
         <w:r>
             <w:t>2</w:t>
         </w:r>
         <w:r>
             <w:fldChar w:fldCharType="end"/>
         </w:r>
         <w:r>
             <w:rPr></w:rPr>
             <w:t>.</w:t>
         </w:r>
     </w:p>
</w:hdr>

I have no clue why the other xmlns: stuff isn't stored.

My second question would be if I am doing it right in principle, and if 
the relation setup will work like intended. In my "reference" document 
(created by LibreOffice), I see this entry in the <w:sectPr> tag:

     <w:headerReference w:type="default" r:id="rId2"/>

In the document I generate, I don't see that header reference.

Best regards,
-Stephan

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@poi.apache.org
For additional commands, e-mail: user-help@poi.apache.org