53009: Problem creating header and footer
Task-Url: https://bz.apache.org/bugzilla/show_bug.cgi?id=53009 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1764563 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
83bd292fff
commit
37f9122633
@ -0,0 +1,60 @@
|
||||
package org.apache.poi.xwpf.usermodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFRun;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Richard Ngo
|
||||
*
|
||||
*/
|
||||
public class SimpleDocumentWithHeader {
|
||||
|
||||
private static XWPFParagraph[] pars;
|
||||
|
||||
public static void main(String[] args) {
|
||||
XWPFDocument doc = new XWPFDocument();
|
||||
|
||||
XWPFParagraph p = doc.createParagraph();
|
||||
|
||||
XWPFRun r = p.createRun();
|
||||
r.setText("Some Text");
|
||||
r.setBold(true);
|
||||
r = p.createRun();
|
||||
r.setText("Goodbye");
|
||||
|
||||
CTP ctP = CTP.Factory.newInstance();
|
||||
CTText t = ctP.addNewR().addNewT();
|
||||
t.setStringValue("header");
|
||||
pars = new XWPFParagraph[1];
|
||||
p = new XWPFParagraph(ctP, doc);
|
||||
pars[0] = p;
|
||||
|
||||
XWPFHeaderFooterPolicy hfPolicy = doc.createHeaderFooterPolicy();
|
||||
hfPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, pars);
|
||||
|
||||
ctP = CTP.Factory.newInstance();
|
||||
t = ctP.addNewR().addNewT();
|
||||
t.setStringValue("My Footer");
|
||||
pars[0] = new XWPFParagraph(ctP, doc);
|
||||
hfPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, pars);
|
||||
|
||||
try {
|
||||
OutputStream os = new FileOutputStream(new File("header.docx"));
|
||||
doc.write(os);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
62
src/java/org/apache/poi/wp/usermodel/HeaderFooterType.java
Normal file
62
src/java/org/apache/poi/wp/usermodel/HeaderFooterType.java
Normal file
@ -0,0 +1,62 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.wp.usermodel;
|
||||
|
||||
/**
|
||||
* @since POI v3.16 beta 1
|
||||
*/
|
||||
public enum HeaderFooterType {
|
||||
|
||||
/**
|
||||
* This is the default header or Footer, It is displayed on every page where
|
||||
* a more specific header or footer is not specified. It is always displayed
|
||||
* on ODD pages that are not the first page of the section.
|
||||
*/
|
||||
DEFAULT(2),
|
||||
|
||||
/**
|
||||
* This is an even page header or footer, it is displayed on even pages that
|
||||
* are not the first page of the section.
|
||||
*/
|
||||
EVEN(1),
|
||||
|
||||
/**
|
||||
* This is a first page header or footer It is displayed on the first page
|
||||
* of the section.
|
||||
*/
|
||||
FIRST(3);
|
||||
|
||||
private final int code;
|
||||
|
||||
private HeaderFooterType(int i) {
|
||||
code = i;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public static HeaderFooterType forInt(int i) {
|
||||
for (HeaderFooterType type : values()) {
|
||||
if (type.code == i) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid HeaderFooterType code: " + i);
|
||||
}
|
||||
}
|
@ -18,9 +18,6 @@ package org.apache.poi.xwpf.model;
|
||||
|
||||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.poi.POIXMLDocumentPart.RelationPart;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
@ -90,7 +87,7 @@ public class XWPFHeaderFooterPolicy {
|
||||
* as required.
|
||||
*/
|
||||
public XWPFHeaderFooterPolicy(XWPFDocument doc) {
|
||||
this(doc, doc.getDocument().getBody().getSectPr());
|
||||
this(doc, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,6 +100,12 @@ public class XWPFHeaderFooterPolicy {
|
||||
// For now, we don't care about different ranges, as it
|
||||
// doesn't seem that .docx properly supports that
|
||||
// feature of the file format yet
|
||||
if (sectPr == null) {
|
||||
CTBody ctBody = doc.getDocument().getBody();
|
||||
sectPr = ctBody.isSetSectPr()
|
||||
? ctBody.getSectPr()
|
||||
: ctBody.addNewSectPr();
|
||||
}
|
||||
this.doc = doc;
|
||||
for (int i = 0; i < sectPr.sizeOfHeaderReferenceArray(); i++) {
|
||||
// Get the header
|
||||
@ -154,7 +157,7 @@ public class XWPFHeaderFooterPolicy {
|
||||
* Creates an empty header of the specified type, containing a single
|
||||
* empty paragraph, to which you can then set text, add more paragraphs etc.
|
||||
*/
|
||||
public XWPFHeader createHeader(Enum type) throws IOException {
|
||||
public XWPFHeader createHeader(Enum type) {
|
||||
return createHeader(type, null);
|
||||
}
|
||||
|
||||
@ -163,33 +166,35 @@ public class XWPFHeaderFooterPolicy {
|
||||
* supplied (and previously unattached!) paragraphs are
|
||||
* added to.
|
||||
*/
|
||||
public XWPFHeader createHeader(Enum type, XWPFParagraph[] pars) throws IOException {
|
||||
XWPFRelation relation = XWPFRelation.HEADER;
|
||||
String pStyle = "Header";
|
||||
int i = getRelationIndex(relation);
|
||||
HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
|
||||
|
||||
XWPFHeader wrapper = (XWPFHeader) doc.createRelationship(relation, XWPFFactory.getInstance(), i);
|
||||
wrapper.setXWPFDocument(doc);
|
||||
public XWPFHeader createHeader(Enum type, XWPFParagraph[] pars) {
|
||||
XWPFHeader header = getHeader(type);
|
||||
|
||||
CTHdrFtr hdr = buildHdr(type, pStyle, wrapper, pars);
|
||||
wrapper.setHeaderFooter(hdr);
|
||||
if (header == null) {
|
||||
HdrDocument hdrDoc = HdrDocument.Factory.newInstance();
|
||||
|
||||
OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
|
||||
hdrDoc.setHdr(hdr);
|
||||
XWPFRelation relation = XWPFRelation.HEADER;
|
||||
int i = getRelationIndex(relation);
|
||||
|
||||
assignHeader(wrapper, type);
|
||||
hdrDoc.save(outputStream, DEFAULT_XML_OPTIONS);
|
||||
outputStream.close();
|
||||
|
||||
return wrapper;
|
||||
XWPFHeader wrapper = (XWPFHeader) doc.createRelationship(relation,
|
||||
XWPFFactory.getInstance(), i);
|
||||
wrapper.setXWPFDocument(doc);
|
||||
|
||||
String pStyle = "Header";
|
||||
CTHdrFtr hdr = buildHdr(type, pStyle, wrapper, pars);
|
||||
wrapper.setHeaderFooter(hdr);
|
||||
hdrDoc.setHdr(hdr);
|
||||
assignHeader(wrapper, type);
|
||||
header = wrapper;
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty footer of the specified type, containing a single
|
||||
* empty paragraph, to which you can then set text, add more paragraphs etc.
|
||||
*/
|
||||
public XWPFFooter createFooter(Enum type) throws IOException {
|
||||
public XWPFFooter createFooter(Enum type) {
|
||||
return createFooter(type, null);
|
||||
}
|
||||
|
||||
@ -198,25 +203,28 @@ public class XWPFHeaderFooterPolicy {
|
||||
* supplied (and previously unattached!) paragraphs are
|
||||
* added to.
|
||||
*/
|
||||
public XWPFFooter createFooter(Enum type, XWPFParagraph[] pars) throws IOException {
|
||||
XWPFRelation relation = XWPFRelation.FOOTER;
|
||||
String pStyle = "Footer";
|
||||
int i = getRelationIndex(relation);
|
||||
FtrDocument ftrDoc = FtrDocument.Factory.newInstance();
|
||||
|
||||
XWPFFooter wrapper = (XWPFFooter) doc.createRelationship(relation, XWPFFactory.getInstance(), i);
|
||||
wrapper.setXWPFDocument(doc);
|
||||
public XWPFFooter createFooter(Enum type, XWPFParagraph[] pars) {
|
||||
XWPFFooter footer = getFooter(type);
|
||||
|
||||
CTHdrFtr ftr = buildFtr(type, pStyle, wrapper, pars);
|
||||
wrapper.setHeaderFooter(ftr);
|
||||
if (footer == null) {
|
||||
FtrDocument ftrDoc = FtrDocument.Factory.newInstance();
|
||||
|
||||
OutputStream outputStream = wrapper.getPackagePart().getOutputStream();
|
||||
ftrDoc.setFtr(ftr);
|
||||
XWPFRelation relation = XWPFRelation.FOOTER;
|
||||
int i = getRelationIndex(relation);
|
||||
|
||||
assignFooter(wrapper, type);
|
||||
ftrDoc.save(outputStream, DEFAULT_XML_OPTIONS);
|
||||
outputStream.close();
|
||||
return wrapper;
|
||||
XWPFFooter wrapper = (XWPFFooter) doc.createRelationship(relation,
|
||||
XWPFFactory.getInstance(), i);
|
||||
wrapper.setXWPFDocument(doc);
|
||||
|
||||
String pStyle = "Footer";
|
||||
CTHdrFtr ftr = buildFtr(type, pStyle, wrapper, pars);
|
||||
wrapper.setHeaderFooter(ftr);
|
||||
ftrDoc.setFtr(ftr);
|
||||
assignFooter(wrapper, type);
|
||||
footer = wrapper;
|
||||
}
|
||||
|
||||
return footer;
|
||||
}
|
||||
|
||||
private int getRelationIndex(XWPFRelation relation) {
|
||||
@ -349,6 +357,21 @@ public class XWPFHeaderFooterPolicy {
|
||||
}
|
||||
return defaultHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this section header for the given type
|
||||
*
|
||||
* @param type of header to return
|
||||
* @return {@link XWPFHeader} object
|
||||
*/
|
||||
public XWPFHeader getHeader(Enum type) {
|
||||
if (type == STHdrFtr.EVEN) {
|
||||
return evenPageHeader;
|
||||
} else if (type == STHdrFtr.FIRST) {
|
||||
return firstPageHeader;
|
||||
}
|
||||
return defaultHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the footer that applies to the given
|
||||
@ -365,19 +388,31 @@ public class XWPFHeaderFooterPolicy {
|
||||
}
|
||||
return defaultFooter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this section footer for the given type
|
||||
*
|
||||
* @param type of footer to return
|
||||
* @return {@link XWPFFooter} object
|
||||
*/
|
||||
public XWPFFooter getFooter(Enum type) {
|
||||
if (type == STHdrFtr.EVEN) {
|
||||
return evenPageFooter;
|
||||
} else if (type == STHdrFtr.FIRST) {
|
||||
return firstPageFooter;
|
||||
}
|
||||
return defaultFooter;
|
||||
}
|
||||
|
||||
|
||||
public void createWatermark(String text) {
|
||||
XWPFParagraph[] pars = new XWPFParagraph[1];
|
||||
try {
|
||||
pars[0] = getWatermarkParagraph(text, 1);
|
||||
createHeader(DEFAULT, pars);
|
||||
pars[0] = getWatermarkParagraph(text, 2);
|
||||
createHeader(FIRST, pars);
|
||||
pars[0] = getWatermarkParagraph(text, 3);
|
||||
createHeader(EVEN, pars);
|
||||
} catch (IOException e) {
|
||||
LOG.log(POILogger.ERROR, "error while creating watermark", e);
|
||||
}
|
||||
pars[0] = getWatermarkParagraph(text, 1);
|
||||
createHeader(DEFAULT, pars);
|
||||
pars[0] = getWatermarkParagraph(text, 2);
|
||||
createHeader(FIRST, pars);
|
||||
pars[0] = getWatermarkParagraph(text, 3);
|
||||
createHeader(EVEN, pars);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
@ -14,6 +15,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xwpf.usermodel;
|
||||
|
||||
import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
|
||||
@ -55,27 +57,13 @@ import org.apache.poi.util.Internal;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.util.PackageHelper;
|
||||
import org.apache.poi.wp.usermodel.HeaderFooterType;
|
||||
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
||||
import org.apache.xmlbeans.XmlCursor;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtBlock;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CommentsDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.DocumentDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.EndnotesDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.NumberingDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STDocProtect;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.StylesDocument;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
|
||||
|
||||
/**
|
||||
* <p>High(ish) level class for working with .docx files.</p>
|
||||
@ -438,13 +426,69 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
||||
}
|
||||
public XWPFHeaderFooterPolicy createHeaderFooterPolicy() {
|
||||
if (headerFooterPolicy == null) {
|
||||
if (! ctDocument.getBody().isSetSectPr()) {
|
||||
ctDocument.getBody().addNewSectPr();
|
||||
}
|
||||
// if (! ctDocument.getBody().isSetSectPr()) {
|
||||
// ctDocument.getBody().addNewSectPr();
|
||||
// }
|
||||
headerFooterPolicy = new XWPFHeaderFooterPolicy(this);
|
||||
}
|
||||
return headerFooterPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a header of the given type
|
||||
*
|
||||
* @param type {@link HeaderFooterType} enum
|
||||
* @return object of type {@link XWPFHeader}
|
||||
*/
|
||||
public XWPFHeader createHeader(HeaderFooterType type) {
|
||||
XWPFHeaderFooterPolicy hfPolicy = createHeaderFooterPolicy();
|
||||
// TODO this needs to be migrated out into section code
|
||||
if (type == HeaderFooterType.FIRST) {
|
||||
CTSectPr ctSectPr = getSection();
|
||||
if (ctSectPr.isSetTitlePg() == false) {
|
||||
CTOnOff titlePg = ctSectPr.addNewTitlePg();
|
||||
titlePg.setVal(STOnOff.ON);
|
||||
}
|
||||
} else if (type == HeaderFooterType.EVEN) {
|
||||
// TODO Add support for Even/Odd headings and footers
|
||||
}
|
||||
return hfPolicy.createHeader(STHdrFtr.Enum.forInt(type.toInt()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a footer of the given type
|
||||
*
|
||||
* @param type {@link HeaderFooterType} enum
|
||||
* @return object of type {@link XWPFFooter}
|
||||
*/
|
||||
public XWPFFooter createFooter(HeaderFooterType type) {
|
||||
XWPFHeaderFooterPolicy hfPolicy = createHeaderFooterPolicy();
|
||||
// TODO this needs to be migrated out into section code
|
||||
if (type == HeaderFooterType.FIRST) {
|
||||
CTSectPr ctSectPr = getSection();
|
||||
if (ctSectPr.isSetTitlePg() == false) {
|
||||
CTOnOff titlePg = ctSectPr.addNewTitlePg();
|
||||
titlePg.setVal(STOnOff.ON);
|
||||
}
|
||||
} else if (type == HeaderFooterType.EVEN) {
|
||||
// TODO Add support for Even/Odd headings and footers
|
||||
}
|
||||
return hfPolicy.createFooter(STHdrFtr.Enum.forInt(type.toInt()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link CTSectPr} object that corresponds with the
|
||||
* last section in this document.
|
||||
*
|
||||
* @return {@link CTSectPr} object
|
||||
*/
|
||||
private CTSectPr getSection() {
|
||||
CTBody ctBody = getDocument().getBody();
|
||||
return (ctBody.isSetSectPr() ?
|
||||
ctBody.getSectPr() :
|
||||
ctBody.addNewSectPr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the styles object used
|
||||
|
Loading…
Reference in New Issue
Block a user