日安!请帮我找到解决问题的方法:我需要在文档中添加一个新的QR页面,并将其保存在新目录中的新表单中。我设法做到了,除了一个细微差别。源文档有一个标题,在添加新页面时会自动添加,因为它是默认的。问题是,我不需要在添加了QR的页面中添加此标题,但我需要将其保存在所有其他页面中。我需要有一个没有标题的最后一页。如果我使用这个
XWPFHeaderFooterPolicy policy = document.getHeaderFooterPolicy();
policy.getHeader(XWPFHeaderFooterPolicy.DEFAULT).clearHeaderFooter();
这将删除所有页面上的标题,这是预期的。如果我使用这个:
XWPFParagraph paragraph0 = document.createParagraph();
XWPFParagraph paragraph1 = document.createParagraph();
// Working with paragraphs
XWPFHeaderFooterPolicy policy = document.getHeaderFooterPolicy();
XWPFParagraph[] pars = new XWPFParagraph[2];
pars[0] = paragraph0;
pars[0] = paragraph1;
XWPFHeader header = policy.createHeader(XWPFHeaderFooterPolicy.DEFAULT, pars);
header.clearHeaderFooter();
这发生了完全相同的事情,即从所有页面中删除标头。
请帮我添加一个没有标题的段落的新页面,保留原始文档所有页面的标题。非常感谢!
Microsoft Word中没有仅针对最后一页的页眉/页脚。
在XWPF中POI页脚在最后一页不同,我已经展示了如何设置页脚在最后一页不同。页眉也是如此。
我在链接答案中的代码尽可能短,以显示原理。和这里答案中的所有代码一样,它不被认为可以作为每次复制/粘贴的有效代码使用。它被认为可以用于测试和理解。用于有效使用的代码当然必须包含更多的检查,以考虑真正的Word文档可能使用的所有可能的不同选项。但是这样的代码通常过于宽泛,无法理解原则。
根据您的问题(和评论),要求如下:
打开包含信息和两种类型标题的现有文档(FIRST
所以原理是一样的。我们需要:
下面的完整示例再次展示了这一点。它使用当前apache poi 5.2.2
和WordDocumentSource. docx
进行了测试并工作,其中包含多个具有默认内容的页面以及第一页和默认页面的页眉/页脚。
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;
public class WordAddLastPageWithoutHeader {
private static void addLastPageInSeparateSection(XWPFDocument document) {
XWPFParagraph paragraph;
XWPFRun run;
XWPFHeader header;
//Adding a header for even pages, which gets the default header for page in last section later.
header = document.createHeader(HeaderFooterType.EVEN);
paragraph = header.createParagraph();
run = paragraph.createRun();
run.setText("Header EVEN = DEFAULT in last section"); // don't set text here if you wants the header of the page in last section empty.
//Adding a paragraph with section settings for section 1 above and section break.
paragraph = document.createParagraph();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrSect1 = paragraph.getCTP().addNewPPr().addNewSectPr(); //we need ctSectPrSect1 later to set headers/footes
//Adding the content for new section 2.
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Last page. Page in last section ...");
//ToDo: further content of last page in separate section
//Getting the old section settings for last section in document which contains the old header/footer settings too.
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1 ctDocument = document.getDocument();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody ctBody = ctDocument.getBody();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrLastSect = ctBody.getSectPr(); //there must be a SectPr already because of the header/footer settings
//Moving the first and default headers and all footers from last section to new section 1.
java.util.List<org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef> ctHdrFtrRefList = new java.util.ArrayList<org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef>();
for (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef ctHdrFtrRef : ctSectPrLastSect.getHeaderReferenceList()) {
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.FIRST)
ctHdrFtrRefList.add(ctHdrFtrRef);
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.DEFAULT)
ctHdrFtrRefList.add(ctHdrFtrRef);
}
if (ctHdrFtrRefList.size() > 0) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef[] ctHdrFtrRefs = ctHdrFtrRefList.toArray(new org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef[0]);
ctSectPrSect1.setHeaderReferenceArray(ctHdrFtrRefs);
}
ctSectPrSect1.setFooterReferenceArray(ctSectPrLastSect.getFooterReferenceArray());
//Moving the page settings from last section to new section 1.
if (ctSectPrLastSect.isSetPgSz()) ctSectPrSect1.setPgSz(ctSectPrLastSect.getPgSz());
if (ctSectPrLastSect.isSetPgMar()) ctSectPrSect1.setPgMar(ctSectPrLastSect.getPgMar());
if (ctSectPrLastSect.isSetPgNumType()) ctSectPrSect1.setPgNumType(ctSectPrLastSect.getPgNumType());
if (ctSectPrLastSect.isSetCols()) ctSectPrSect1.setCols(ctSectPrLastSect.getCols());
if (ctSectPrLastSect.isSetDocGrid()) ctSectPrSect1.setDocGrid(ctSectPrLastSect.getDocGrid());
//Setting "there is a title page" for section 1 to make first header work.
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff ctOnOff = org.openxmlformats.schemas.wordprocessingml.x2006.main.CTOnOff.Factory.newInstance();
ctOnOff.setVal(true);
ctSectPrSect1.setTitlePg(ctOnOff);
//Removing first and old default header references from last section (now section 2)
//and setting header reference of even header to be the default header reference for this last section.
for (int i = ctSectPrLastSect.getHeaderReferenceArray().length-1; i >= 0; i--) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef ctHdrFtrRef = ctSectPrLastSect.getHeaderReferenceArray(i);
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.FIRST) {
ctSectPrLastSect.removeHeaderReference(i);
continue;
}
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.DEFAULT) {
ctSectPrLastSect.removeHeaderReference(i);
continue;
}
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.EVEN) {
ctHdrFtrRef.setType(org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.DEFAULT); //change this from STHdrFtr.EVEN to STHdrFtr.DEFAULT
}
}
//Unsetting "there is a title page" for the last section.
if (ctSectPrLastSect.isSetTitlePg()) ctSectPrLastSect.unsetTitlePg();
//Unsetting page numbering type for the last section. So it continues the previous.
if (ctSectPrLastSect.isSetPgNumType()) ctSectPrLastSect.unsetPgNumType();
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("./WordDocumentSource.docx"));
addLastPageInSeparateSection(document);
FileOutputStream out = new FileOutputStream("./WordDocumentResult.docx");
document.write(out);
out.close();
document.close();
}
}
如果它不适合您,我需要能够在某处下载您使用的源Word文档。然后我可以得到代码无法使用该文档工作的确切原因。
也许将整个部分属性从下面的部分复制到新插入的部分会更好,而不是复制所有单个部分属性。此外,代码可以更多地划分为单个方法。这在下面的代码示例中完成。为了完整起见,我将保留旧示例。
import java.io.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;
public class WordAddLastPageWithoutHeader {
static org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr getDocumentBodySectPr(XWPFDocument document) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1 ctDocument = document.getDocument();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody ctBody = ctDocument.getBody();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrDocumentBody = ctBody.getSectPr();
return ctSectPrDocumentBody;
}
static org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr getNextSectPr(XWPFParagraph paragraph) {
// get the section settings of next section in document
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrNextSect = null;
// maybe next section settings are in a paragraph
XWPFDocument document = paragraph.getDocument();
int pos = document.getPosOfParagraph(paragraph);
for (int p = pos; p < document.getParagraphs().size(); p++) {
paragraph = document.getParagraphArray(p);
if (paragraph.getCTP().getPPr() != null) {
ctSectPrNextSect = paragraph.getCTP().getPPr().getSectPr();
}
if (ctSectPrNextSect != null) break;
}
// if not in a paragraph next section settings are in documetn body
if (ctSectPrNextSect == null) {
ctSectPrNextSect = getDocumentBodySectPr(document);
}
return ctSectPrNextSect;
}
static XWPFParagraph addSectionbreak(XWPFDocument document) {
XWPFParagraph paragraph = null;;
// add a paragraph for section settings for new section above and section break.
paragraph = document.createParagraph();
// get next section properties, which were section properties for previous section above
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrNextSect = getNextSectPr(paragraph);
// set a copy of section properties for previous section above as section properties for new section
if (ctSectPrNextSect != null) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrNewSect = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr)ctSectPrNextSect.copy();
paragraph.getCTP().addNewPPr().setSectPr(ctSectPrNewSect);
return paragraph;
}
return null;
}
private static void addLastPageInSeparateSection(XWPFDocument document) {
XWPFParagraph paragraph;
XWPFRun run;
XWPFHeader header;
// add a header for even pages, which gets the default header for page in last section later
header = document.createHeader(HeaderFooterType.EVEN);
for (int p = header.getParagraphs().size()-1; p >=0; p--) {
paragraph = header.getParagraphArray(p);
header.removeParagraph(paragraph);
}
paragraph = header.createParagraph();
run = paragraph.createRun();
run.setText("Header EVEN = DEFAULT in last section"); // don't set text here if you wants the header of the page in last section empty.
paragraph = addSectionbreak(document);
if (paragraph != null) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrNewSect = paragraph.getCTP().getPPr().getSectPr();
// remove even header and footer from new section
for (int i = ctSectPrNewSect.getHeaderReferenceArray().length-1; i >= 0; i--) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef ctHdrFtrRef = ctSectPrNewSect.getHeaderReferenceArray(i);
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.EVEN) {
ctSectPrNewSect.removeHeaderReference(i);
continue;
}
}
for (int i = ctSectPrNewSect.getFooterReferenceArray().length-1; i >= 0; i--) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef ctHdrFtrRef = ctSectPrNewSect.getFooterReferenceArray(i);
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.EVEN) {
ctSectPrNewSect.removeFooterReference(i);
continue;
}
}
// remove first and default header references from last section (now section below the new section)
// and set header reference of even header to be the default header reference for this last section
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr ctSectPrDocumentBody = getDocumentBodySectPr(document);
if (ctSectPrDocumentBody != null) {
for (int i = ctSectPrDocumentBody.getHeaderReferenceArray().length-1; i >= 0; i--) {
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef ctHdrFtrRef = ctSectPrDocumentBody.getHeaderReferenceArray(i);
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.FIRST) {
ctSectPrDocumentBody.removeHeaderReference(i);
continue;
}
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.DEFAULT) {
ctSectPrDocumentBody.removeHeaderReference(i);
continue;
}
if (ctHdrFtrRef.getType() == org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.EVEN) {
ctHdrFtrRef.setType(org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.DEFAULT); //change this from STHdrFtr.EVEN to STHdrFtr.DEFAULT
}
}
// unset "there is a title page" for the last section.
if (ctSectPrDocumentBody.isSetTitlePg()) ctSectPrDocumentBody.unsetTitlePg();
// unset page numbering type for the last section. So it continues the previous.
if (ctSectPrDocumentBody.isSetPgNumType()) ctSectPrDocumentBody.unsetPgNumType();
}
try {
// unset evenAndOddHeaders in settings.xml
java.lang.reflect.Field _settings = XWPFDocument.class.getDeclaredField("settings");
_settings.setAccessible(true);
XWPFSettings xwpfsettings = (XWPFSettings)_settings.get(document);
java.lang.reflect.Field _ctSettings = XWPFSettings.class.getDeclaredField("ctSettings");
_ctSettings.setAccessible(true);
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSettings ctsettings =
(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSettings)_ctSettings.get(xwpfsettings);
if (ctsettings.isSetEvenAndOddHeaders()) ctsettings.unsetEvenAndOddHeaders();
} catch(Exception ex) {
ex.printStackTrace();
}
}
// content for the last section
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Last page. Page in last section ...");
//ToDo: further content of last page in separate section
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("./WordDocumentSource.docx"));
addLastPageInSeparateSection(document);
FileOutputStream out = new FileOutputStream("./WordDocumentResult.docx");
document.write(out);
out.close();
document.close();
}
}