mirror of https://github.com/apache/poi.git
57366: XWPFTable to Header / Footer
Task-Url: https://bz.apache.org/bugzilla/show_bug.cgi?id=57366 This update contains a breaking change git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1767175 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6e685dad95
commit
1c3d84671e
|
@ -38,14 +38,10 @@ public class BetterHeaderFooterExample {
|
|||
|
||||
// create header/footer functions insert an empty paragraph
|
||||
XWPFHeader head = doc.createHeader(HeaderFooterType.DEFAULT);
|
||||
p = head.getParagraphArray(0);
|
||||
r = p.createRun();
|
||||
r.setText("header");
|
||||
head.createParagraph().createRun().setText("header");
|
||||
|
||||
XWPFFooter foot = doc.createFooter(HeaderFooterType.DEFAULT);
|
||||
p = foot.getParagraphArray(0);
|
||||
r = p.createRun();
|
||||
r.setText("footer");
|
||||
foot.createParagraph().createRun().setText("footer");
|
||||
|
||||
try {
|
||||
OutputStream os = new FileOutputStream(new File("header2.docx"));
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* ====================================================================
|
||||
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.xwpf.usermodel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.apache.poi.wp.usermodel.HeaderFooterType;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGridCol;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType;
|
||||
|
||||
public class HeaderFooterTable {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
XWPFDocument doc = new XWPFDocument();
|
||||
|
||||
// Create a header with a 1 row, 3 column table
|
||||
// changes made for issue 57366 allow a new header or footer
|
||||
// to be created empty. This is a change. You will have to add
|
||||
// either a paragraph or a table to the header or footer for
|
||||
// the document to be considered valid.
|
||||
XWPFHeader hdr = doc.createHeader(HeaderFooterType.DEFAULT);
|
||||
XWPFTable tbl = hdr.createTable(1, 3);
|
||||
|
||||
// Set the padding around text in the cells to 1/10th of an inch
|
||||
int pad = (int) (.1 * 1440);
|
||||
tbl.setCellMargins(pad, pad, pad, pad);
|
||||
|
||||
// Set table width to 6.5 inches in 1440ths of a point
|
||||
tbl.setWidth((int)(6.5 * 1440));
|
||||
// Can not yet set table or cell width properly, tables default to
|
||||
// autofit layout, and this requires fixed layout
|
||||
CTTbl ctTbl = tbl.getCTTbl();
|
||||
CTTblPr ctTblPr = ctTbl.addNewTblPr();
|
||||
CTTblLayoutType layoutType = ctTblPr.addNewTblLayout();
|
||||
layoutType.setType(STTblLayoutType.FIXED);
|
||||
|
||||
// Now set up a grid for the table, cells will fit into the grid
|
||||
// Each cell width is 3120 in 1440ths of an inch, or 1/3rd of 6.5"
|
||||
BigInteger w = new BigInteger("3120");
|
||||
CTTblGrid grid = ctTbl.addNewTblGrid();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
CTTblGridCol gridCol = grid.addNewGridCol();
|
||||
gridCol.setW(w);
|
||||
}
|
||||
|
||||
// Add paragraphs to the cells
|
||||
XWPFTableRow row = tbl.getRow(0);
|
||||
XWPFTableCell cell = row.getCell(0);
|
||||
XWPFParagraph p = cell.getParagraphArray(0);
|
||||
XWPFRun r = p.createRun();
|
||||
r.setText("header left cell");
|
||||
|
||||
cell = row.getCell(1);
|
||||
p = cell.getParagraphArray(0);
|
||||
r = p.createRun();
|
||||
r.setText("header center cell");
|
||||
|
||||
cell = row.getCell(2);
|
||||
p = cell.getParagraphArray(0);
|
||||
r = p.createRun();
|
||||
r.setText("header right cell");
|
||||
|
||||
// Create a footer with a Paragraph
|
||||
XWPFFooter ftr = doc.createFooter(HeaderFooterType.DEFAULT);
|
||||
p = ftr.createParagraph();
|
||||
|
||||
r = p.createRun();
|
||||
r.setText("footer text");
|
||||
|
||||
OutputStream os = new FileOutputStream(new File("headertable.docx"));
|
||||
doc.write(os);
|
||||
doc.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -271,19 +271,19 @@ public class XWPFHeaderFooterPolicy {
|
|||
ftr.setPArray(i, paragraphs[i].getCTP());
|
||||
}
|
||||
} else {
|
||||
CTP p = ftr.addNewP();
|
||||
CTBody body = doc.getDocument().getBody();
|
||||
if (body.sizeOfPArray() > 0) {
|
||||
CTP p0 = body.getPArray(0);
|
||||
if (p0.isSetRsidR()) {
|
||||
byte[] rsidr = p0.getRsidR();
|
||||
byte[] rsidrdefault = p0.getRsidRDefault();
|
||||
p.setRsidP(rsidr);
|
||||
p.setRsidRDefault(rsidrdefault);
|
||||
}
|
||||
}
|
||||
CTPPr pPr = p.addNewPPr();
|
||||
pPr.addNewPStyle().setVal(pStyle);
|
||||
// CTP p = ftr.addNewP();
|
||||
// CTBody body = doc.getDocument().getBody();
|
||||
// if (body.sizeOfPArray() > 0) {
|
||||
// CTP p0 = body.getPArray(0);
|
||||
// if (p0.isSetRsidR()) {
|
||||
// byte[] rsidr = p0.getRsidR();
|
||||
// byte[] rsidrdefault = p0.getRsidRDefault();
|
||||
// p.setRsidP(rsidr);
|
||||
// p.setRsidRDefault(rsidrdefault);
|
||||
// }
|
||||
// }
|
||||
// CTPPr pPr = p.addNewPPr();
|
||||
// pPr.addNewPStyle().setVal(pStyle);
|
||||
}
|
||||
return ftr;
|
||||
}
|
||||
|
|
|
@ -43,10 +43,10 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
|
|||
* Parent of XWPF headers and footers
|
||||
*/
|
||||
public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBody {
|
||||
List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>(1);
|
||||
List<XWPFTable> tables = new ArrayList<XWPFTable>(1);
|
||||
List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
|
||||
List<XWPFTable> tables = new ArrayList<XWPFTable>();
|
||||
List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
|
||||
List<IBodyElement> bodyElements = new ArrayList<IBodyElement>(1);
|
||||
List<IBodyElement> bodyElements = new ArrayList<IBodyElement>();
|
||||
|
||||
CTHdrFtr headerFooter;
|
||||
XWPFDocument document;
|
||||
|
@ -323,13 +323,75 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo
|
|||
|
||||
/**
|
||||
* Adds a new paragraph at the end of the header or footer
|
||||
*
|
||||
* @return new {@link XWPFParagraph} object
|
||||
*/
|
||||
public XWPFParagraph createParagraph() {
|
||||
XWPFParagraph paragraph = new XWPFParagraph(headerFooter.addNewP(), this);
|
||||
paragraphs.add(paragraph);
|
||||
bodyElements.add(paragraph);
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new table at the end of the header or footer
|
||||
*
|
||||
* @param rows - number of rows in the table
|
||||
* @param cols - number of columns in the table
|
||||
* @return new {@link XWPFTable} object
|
||||
*/
|
||||
public XWPFTable createTable(int rows, int cols) {
|
||||
XWPFTable table = new XWPFTable(headerFooter.addNewTbl(), this, rows, cols);
|
||||
tables.add(table);
|
||||
bodyElements.add(table);
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a specific paragraph from this header / footer
|
||||
*
|
||||
* @param paragraph - {@link XWPFParagraph} object to remove
|
||||
*/
|
||||
public void removeParagraph(XWPFParagraph paragraph) {
|
||||
if (paragraphs.contains(paragraph)) {
|
||||
CTP ctP = paragraph.getCTP();
|
||||
XmlCursor c = ctP.newCursor();
|
||||
c.removeXml();
|
||||
c.dispose();
|
||||
paragraphs.remove(paragraph);
|
||||
bodyElements.remove(paragraph);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a specific table from this header / footer
|
||||
*
|
||||
* @param table - {@link XWPFTable} object to remove
|
||||
*/
|
||||
public void removeTable(XWPFTable table) {
|
||||
if (tables.contains(table)) {
|
||||
CTTbl ctTbl = table.getCTTbl();
|
||||
XmlCursor c = ctTbl.newCursor();
|
||||
c.removeXml();
|
||||
c.dispose();
|
||||
tables.remove(table);
|
||||
bodyElements.remove(table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all paragraphs and tables from this header / footer
|
||||
*/
|
||||
public void clearHeaderFooter() {
|
||||
XmlCursor c = headerFooter.newCursor();
|
||||
c.removeXmlContents();
|
||||
c.dispose();
|
||||
paragraphs.clear();
|
||||
tables.clear();
|
||||
bodyElements.clear();
|
||||
CTP ctp = CTP.Factory.newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* add a new paragraph at position of the cursor
|
||||
*
|
||||
|
@ -538,4 +600,25 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo
|
|||
public POIXMLDocumentPart getPart() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareForCommit() {
|
||||
// must contain at least an empty paragraph
|
||||
if (bodyElements.size() == 0) {
|
||||
createParagraph();
|
||||
}
|
||||
|
||||
// Cells must contain at least an empty paragraph
|
||||
for (XWPFTable tbl : tables) {
|
||||
for (XWPFTableRow row : tbl.tableRows) {
|
||||
for (XWPFTableCell cell : row.getTableCells()) {
|
||||
if (cell.getBodyElements().size() == 0) {
|
||||
cell.addParagraph();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
super.prepareForCommit();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,16 +17,22 @@
|
|||
|
||||
package org.apache.poi.xwpf.usermodel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
||||
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
|
||||
import org.junit.Test;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTText;
|
||||
|
||||
public final class TestXWPFHeader extends TestCase {
|
||||
public final class TestXWPFHeader {
|
||||
|
||||
@Test
|
||||
public void testSimpleHeader() throws IOException {
|
||||
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("headerFooter.docx");
|
||||
|
||||
|
@ -38,6 +44,7 @@ public final class TestXWPFHeader extends TestCase {
|
|||
assertNotNull(footer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImageInHeader() throws IOException {
|
||||
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("headerPic.docx");
|
||||
|
||||
|
@ -49,6 +56,7 @@ public final class TestXWPFHeader extends TestCase {
|
|||
assertEquals(1, header.getRelations().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeader() throws IOException {
|
||||
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx");
|
||||
// no header is set (yet)
|
||||
|
@ -56,6 +64,7 @@ public final class TestXWPFHeader extends TestCase {
|
|||
assertNull(policy.getDefaultHeader());
|
||||
assertNull(policy.getFirstPageHeader());
|
||||
assertNull(policy.getDefaultFooter());
|
||||
assertNull(policy.getFirstPageFooter());
|
||||
|
||||
CTP ctP1 = CTP.Factory.newInstance();
|
||||
CTR ctR1 = ctP1.addNewR();
|
||||
|
@ -95,29 +104,31 @@ public final class TestXWPFHeader extends TestCase {
|
|||
XWPFHeader headerD = policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, pars);
|
||||
XWPFHeader headerF = policy.createHeader(XWPFHeaderFooterPolicy.FIRST);
|
||||
// Set a default footer and capture the returned XWPFFooter object.
|
||||
XWPFFooter footer = policy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, pars2);
|
||||
XWPFFooter footerD = policy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, pars2);
|
||||
XWPFFooter footerF = policy.createFooter(XWPFHeaderFooterPolicy.FIRST);
|
||||
|
||||
// Ensure the headers and footer were set correctly....
|
||||
assertNotNull(policy.getDefaultHeader());
|
||||
assertNotNull(policy.getFirstPageHeader());
|
||||
assertNotNull(policy.getDefaultFooter());
|
||||
assertNotNull(policy.getFirstPageFooter());
|
||||
// ....and that the footer object captured above contains two
|
||||
// paragraphs of text.
|
||||
assertEquals(2, footer.getParagraphs().size());
|
||||
assertEquals(2, footerD.getParagraphs().size());
|
||||
assertEquals(0, footerF.getParagraphs().size());
|
||||
|
||||
// Check the header created with the paragraph got them, and the one
|
||||
// created without got an empty one
|
||||
// created without got none
|
||||
assertEquals(1, headerD.getParagraphs().size());
|
||||
assertEquals(1, headerF.getParagraphs().size());
|
||||
|
||||
assertEquals(tText, headerD.getParagraphs().get(0).getText());
|
||||
assertEquals("", headerF.getParagraphs().get(0).getText());
|
||||
|
||||
assertEquals(0, headerF.getParagraphs().size());
|
||||
|
||||
// As an additional check, recover the defauls footer and
|
||||
// make sure that it contains two paragraphs of text and that
|
||||
// both do hold what is expected.
|
||||
footer = policy.getDefaultFooter();
|
||||
XWPFParagraph[] paras = footer.getParagraphs().toArray(new XWPFParagraph[0]);
|
||||
footerD = policy.getDefaultFooter();
|
||||
XWPFParagraph[] paras = footerD.getParagraphs().toArray(new XWPFParagraph[0]);
|
||||
|
||||
assertEquals(2, paras.length);
|
||||
assertEquals("First paragraph for the footer", paras[0].getText());
|
||||
|
@ -126,12 +137,15 @@ public final class TestXWPFHeader extends TestCase {
|
|||
|
||||
// Add some text to the empty header
|
||||
String fText1 = "New Text!";
|
||||
headerF.getParagraphs().get(0).insertNewRun(0).setText(fText1);
|
||||
// TODO Add another paragraph and check
|
||||
|
||||
String fText2 = "More Text!";
|
||||
headerF.createParagraph().insertNewRun(0).setText(fText1);
|
||||
headerF.createParagraph().insertNewRun(0).setText(fText2);
|
||||
// headerF.getParagraphs().get(0).insertNewRun(0).setText(fText1);
|
||||
|
||||
// Check it
|
||||
assertEquals(tText, headerD.getParagraphs().get(0).getText());
|
||||
assertEquals(fText1, headerF.getParagraphs().get(0).getText());
|
||||
assertEquals(fText2, headerF.getParagraphs().get(1).getText());
|
||||
|
||||
|
||||
// Save, re-open, ensure it's all still there
|
||||
|
@ -141,7 +155,7 @@ public final class TestXWPFHeader extends TestCase {
|
|||
assertNotNull(policy.getFirstPageHeader());
|
||||
assertNull(policy.getEvenPageHeader());
|
||||
assertNotNull(policy.getDefaultFooter());
|
||||
assertNull(policy.getFirstPageFooter());
|
||||
assertNotNull(policy.getFirstPageFooter());
|
||||
assertNull(policy.getEvenPageFooter());
|
||||
|
||||
// Check the new headers still have their text
|
||||
|
@ -149,16 +163,20 @@ public final class TestXWPFHeader extends TestCase {
|
|||
headerF = policy.getFirstPageHeader();
|
||||
assertEquals(tText, headerD.getParagraphs().get(0).getText());
|
||||
assertEquals(fText1, headerF.getParagraphs().get(0).getText());
|
||||
assertEquals(fText2, headerF.getParagraphs().get(1).getText());
|
||||
|
||||
// Check the new footers have their new text too
|
||||
footer = policy.getDefaultFooter();
|
||||
paras = footer.getParagraphs().toArray(new XWPFParagraph[0]);
|
||||
footerD = policy.getDefaultFooter();
|
||||
paras = footerD.getParagraphs().toArray(new XWPFParagraph[0]);
|
||||
footerF = policy.getFirstPageFooter();
|
||||
|
||||
assertEquals(2, paras.length);
|
||||
assertEquals("First paragraph for the footer", paras[0].getText());
|
||||
assertEquals("Second paragraph for the footer", paras[1].getText());
|
||||
assertEquals(1, footerF.getParagraphs().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetWatermark() throws IOException {
|
||||
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("SampleDoc.docx");
|
||||
|
||||
|
@ -183,18 +201,22 @@ public final class TestXWPFHeader extends TestCase {
|
|||
assertNotNull(policy.getEvenPageHeader());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddPictureData() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllPictures() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllPackagePictures() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPictureDataById() {
|
||||
// TODO
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ public class TestXWPFPictureData extends TestCase {
|
|||
// Add a default header
|
||||
policy = doc.createHeaderFooterPolicy();
|
||||
XWPFHeader header = policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT);
|
||||
header.getParagraphs().get(0).createRun().setText("Hello, Header World!");
|
||||
header.createParagraph().createRun().setText("Hello, Header World!");
|
||||
header.createParagraph().createRun().setText("Paragraph 2");
|
||||
assertEquals(0, header.getAllPictures().size());
|
||||
assertEquals(2, header.getParagraphs().size());
|
||||
|
|
Loading…
Reference in New Issue