[github-310] Allow XWPF sections to have distinct headers and footers. Thanks to Joaquín Perez Valera. This close #310

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1898653 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
PJ Fanning 2022-03-06 13:27:16 +00:00
parent c3cf4e5403
commit ea2cc9e54c
2 changed files with 220 additions and 3 deletions

View File

@ -74,6 +74,8 @@ public class XWPFHeaderFooterPolicy {
private XWPFHeader defaultHeader;
private XWPFFooter defaultFooter;
//This variable allows to have a reference for each section, and having different headers in each of them.
private CTSectPr sectPr;
/**
* Figures out the policy for the given document,
@ -101,6 +103,8 @@ public class XWPFHeaderFooterPolicy {
: ctBody.addNewSectPr();
}
this.doc = doc;
this.sectPr = sectPr;
for (int i = 0; i < sectPr.sizeOfHeaderReferenceArray(); i++) {
// Get the header
CTHdrFtrRef ref = sectPr.getHeaderReferenceArray(i);
@ -293,14 +297,14 @@ public class XWPFHeaderFooterPolicy {
private void setFooterReference(Enum type, XWPFHeaderFooter wrapper) {
CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewFooterReference();
CTHdrFtrRef ref = this.sectPr.addNewFooterReference();
ref.setType(type);
ref.setId(doc.getRelationId(wrapper));
}
private void setHeaderReference(Enum type, XWPFHeaderFooter wrapper) {
CTHdrFtrRef ref = doc.getDocument().getBody().getSectPr().addNewHeaderReference();
CTHdrFtrRef ref = this.sectPr.addNewHeaderReference();
ref.setType(type);
ref.setId(doc.getRelationId(wrapper));
}
@ -494,4 +498,4 @@ public class XWPFHeaderFooterPolicy {
// end watermark paragraph
return new XWPFParagraph(p, doc);
}
}
}

View File

@ -0,0 +1,213 @@
/* ====================================================================
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.model;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.junit.jupiter.api.Test;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class TestMultiSectionHeaders {
@Test
void testAddHeadersForTwoDistinctSections() throws IOException {
String header1Text = "Header 1 Text";
String header2Text = "Header 2 Text";
XWPFDocument doc = new XWPFDocument();
// Add first body/section paragraph
XWPFParagraph par1 = doc.createParagraph();
CTP ctp1 = par1.getCTP();
ctp1.addNewR().addNewT().setStringValue("Text for first body paragraph");
CTPPr ppr1 = null;
if (!ctp1.isSetPPr()) {
ctp1.addNewPPr();
}
ppr1 = ctp1.getPPr();
CTSectPr sec1 = null;
if (!ppr1.isSetSectPr()) {
ppr1.addNewSectPr();
}
sec1 = ppr1.getSectPr();
// Create paragraph of the first header
CTP parCTP = CTP.Factory.newInstance();
parCTP.addNewR().addNewT().setStringValue(header1Text);
XWPFParagraph headerPar1 = new XWPFParagraph(parCTP, doc);
XWPFParagraph[] headerPars1 = { headerPar1 };
XWPFHeaderFooterPolicy pol1 = new XWPFHeaderFooterPolicy(doc, sec1);
XWPFHeader header1 = pol1.createHeader(STHdrFtr.DEFAULT, headerPars1);
// Add second body/section paragraph
XWPFParagraph par2 = doc.createParagraph();
CTP ctp2 = par2.getCTP();
ctp2.addNewR().addNewT().setStringValue("Text for second body paragraph");
CTPPr ppr2 = null;
if (!ctp2.isSetPPr()) {
ctp2.addNewPPr();
}
ppr2 = ctp2.getPPr();
CTSectPr sec2 = null;
if (!ppr2.isSetSectPr()) {
ppr2.addNewSectPr();
}
sec2 = ppr2.getSectPr();
// Create paragraph of the second header
CTP parCTP2 = CTP.Factory.newInstance();
parCTP2.addNewR().addNewT().setStringValue(header2Text);
XWPFParagraph headerPar2 = new XWPFParagraph(parCTP2, doc);
XWPFParagraph[] headerPars2 = { headerPar2 };
XWPFHeaderFooterPolicy pol2 = new XWPFHeaderFooterPolicy(doc, sec2);
XWPFHeader header2 = pol2.createHeader(STHdrFtr.DEFAULT, headerPars2);
// Validate the headers are not null
assertNotNull(header1.getListParagraph().get(0));
assertNotNull(header2.getListParagraph().get(0));
// Validate the headers are not equal
assertNotEquals(header1, header2);
String textFromHeader1 = header1.getListParagraph().get(0).getCTP().getRArray()[0].getTArray()[0]
.getStringValue();
// Validate the text is equal to the text we assigned
assertEquals(header1Text, textFromHeader1);
String textFromHeader2 = header2.getListParagraph().get(0).getCTP().getRArray()[0].getTArray()[0]
.getStringValue();
// Validate the text is equal to the text we assigned
assertEquals(header2Text, textFromHeader2);
// Validate the headers text are not equal
assertNotEquals(header1Text, header2Text);
}
@Test
void testAddFootersForTwoDistinctSections() throws IOException {
String footer1Text = "Footer 1 Text";
String footer2Text = "Footer 2 Text";
XWPFDocument doc = new XWPFDocument();
// Add first body/section paragraph
XWPFParagraph par1 = doc.createParagraph();
CTP ctp1 = par1.getCTP();
ctp1.addNewR().addNewT().setStringValue("Text for first body paragraph");
CTPPr ppr1 = null;
if (!ctp1.isSetPPr()) {
ctp1.addNewPPr();
}
ppr1 = ctp1.getPPr();
CTSectPr sec1 = null;
if (!ppr1.isSetSectPr()) {
ppr1.addNewSectPr();
}
sec1 = ppr1.getSectPr();
// Create paragraph of the first footer
CTP parCTP = CTP.Factory.newInstance();
parCTP.addNewR().addNewT().setStringValue(footer1Text);
XWPFParagraph footerPar1 = new XWPFParagraph(parCTP, doc);
XWPFParagraph[] footerPars1 = { footerPar1 };
XWPFHeaderFooterPolicy pol1 = new XWPFHeaderFooterPolicy(doc, sec1);
XWPFFooter footer1 = pol1.createFooter(STHdrFtr.DEFAULT, footerPars1);
// Add second body/section paragraph
XWPFParagraph par2 = doc.createParagraph();
CTP ctp2 = par2.getCTP();
ctp2.addNewR().addNewT().setStringValue("Text for second body paragraph");
CTPPr ppr2 = null;
if (!ctp2.isSetPPr()) {
ctp2.addNewPPr();
}
ppr2 = ctp2.getPPr();
CTSectPr sec2 = null;
if (!ppr2.isSetSectPr()) {
ppr2.addNewSectPr();
}
sec2 = ppr2.getSectPr();
// Create paragraph of the second footer
CTP parCTP2 = CTP.Factory.newInstance();
parCTP2.addNewR().addNewT().setStringValue(footer2Text);
XWPFParagraph footerPar2 = new XWPFParagraph(parCTP2, doc);
XWPFParagraph[] footerPars2 = { footerPar2 };
XWPFHeaderFooterPolicy pol2 = new XWPFHeaderFooterPolicy(doc, sec2);
XWPFFooter footer2 = pol2.createFooter(STHdrFtr.DEFAULT, footerPars2);
// Validate the footers are not null
assertNotNull(footer1.getListParagraph().get(0));
assertNotNull(footer2.getListParagraph().get(0));
// Validate the footers are not equal, as objects
assertNotEquals(footer1, footer2);
String textFromHeader1 = footer1.getListParagraph().get(0).getCTP().getRArray()[0].getTArray()[0]
.getStringValue();
// Validate the text is equal to the text we assigned
assertEquals(footer1Text, textFromHeader1);
String textFromHeader2 = footer2.getListParagraph().get(0).getCTP().getRArray()[0].getTArray()[0]
.getStringValue();
// Validate the text is equal to the text we assigned
assertEquals(footer2Text, textFromHeader2);
// Validate the footers text are not equal
assertNotEquals(footer1Text, footer2Text);
}
}