如何通过poi在单词中设置不同部分的页码 [英] how to set page number for different section in word by poi

查看:147
本文介绍了如何通过poi在单词中设置不同部分的页码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的文档分为三个部分:封面,内容和文本.我想为每个部分设置不同的页码.封面不需要页码.内容页码以罗马数字表示,正文中的页面以希腊数字表示.可以用POI来实现吗?

My document has three parts: cover, contents and text. I want to set different page number for each section. The cover does not need page numbers. The contents page numbers are in Rome numerals, and the pages in the main body are in Greek numbers. Can it be realized with POI?

推荐答案

Apache poi是-到目前为止-仅abel创建三种类型的页眉/页脚:

Apache poi is - until now - only abel creating three types of header / footers: HeaderFooterType.DEFAULT, .EVEN and .First.

因此,为了满足您的要求,我们需要使用底层的低层对象.而且我们需要作弊一点才能创建不同的页脚.

So for fulfilling your requirement we need using the underlaying low level objects. And we need cheating a little bit to be able creating different footers.

我们需要两个不同的页脚.一种用于您的第2部分(内容),另一种用于您的第3部分(文本).但是两者都必须为DEFAULT类型.由于到目前为止,使用apache poi都是不可能的,因此我们首先为整个文档创建两个不同类型(FIRSTDEFAULT)的不同页脚.然后,将FIRST页脚更改为DEFAULT,并将其作为第2节的页脚参考.

We need two different footers. One for your section 2 (contents) and one for your section 3 (text). But both must be of type DEFAULT. Since this is not possible using apache poi until now, we are first creating two different footers of different types (FIRST and DEFAULT) for the whole document. Then we change the FIRST footer to DEFAULT and move it to be footer reference for section 2.

示例:

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;

public class CreateWordMultipleSectionPageNumbering {

 public static void main(String[] args) throws Exception {

  XWPFDocument document= new XWPFDocument();

  //create first footer for section 2 - first created as first footer for the document
  XWPFFooter footer = document.createFooter(HeaderFooterType.FIRST); 
  //making it HeaderFooterType.FIRST first to be able creating one more footer later
  //will changing this later to HeaderFooterType.DEFAULT

  XWPFParagraph paragraph = footer.getParagraphArray(0);
  if (paragraph == null) paragraph = footer.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.CENTER);

  XWPFRun run = paragraph.createRun();  
  run.setText("Page ");
  paragraph.getCTP().addNewFldSimple().setInstr("PAGE \\* ROMAN MERGEFORMAT");
  run = paragraph.createRun();  
  run.setText(" of ");
  paragraph.getCTP().addNewFldSimple().setInstr("NUMPAGES \\* ROMAN MERGEFORMAT");

  //create second footer for section 3 == last section in document
  footer = document.createFooter(HeaderFooterType.DEFAULT);

  paragraph = footer.getParagraphArray(0);
  if (paragraph == null) paragraph = footer.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.CENTER);

  run = paragraph.createRun();  
  run.setText("Page ");
  paragraph.getCTP().addNewFldSimple().setInstr("PAGE \\* ARABIC MERGEFORMAT");
  run = paragraph.createRun();  
  run.setText(" of ");
  paragraph.getCTP().addNewFldSimple().setInstr("NUMPAGES \\* ARABIC MERGEFORMAT");

  //create document content.

  //section 1
  paragraph = document.createParagraph();
  run=paragraph.createRun();  
  run.setText("Cover");

  //paragraph with section setting for section above
  paragraph = document.createParagraph();
  CTSectPr ctSectPr = paragraph.getCTP().addNewPPr().addNewSectPr();

  //section 2
  paragraph = document.createParagraph();
  run=paragraph.createRun();  
  run.setText("Contents");

  //paragraph with section setting for section above
  paragraph = document.createParagraph();
  CTSectPr ctSectPrSect2 = paragraph.getCTP().addNewPPr().addNewSectPr(); //we need this later

  //section 3 
  paragraph = document.createParagraph();
  run=paragraph.createRun();
  run.setText("Text");

  //section setting for section above == last section in document
  CTDocument1 ctDocument = document.getDocument();
  CTBody ctBody = ctDocument.getBody();
  CTSectPr ctSectPrLastSect = ctBody.getSectPr(); //there must be a SectPr already because of the footer settings above

  //get footer reference of first footer and move this to be footer reference for section 2
  CTHdrFtrRef ctHdrFtrRef = ctSectPrLastSect.getFooterReferenceArray(0);
  ctHdrFtrRef.setType(STHdrFtr.DEFAULT); //change this from STHdrFtr.FIRST to STHdrFtr.DEFAULT
  CTHdrFtrRef[] ctHdrFtrRefs = new CTHdrFtrRef[]{ctHdrFtrRef};
  ctSectPrSect2.setFooterReferenceArray(ctHdrFtrRefs);
  ctSectPrLastSect.removeFooterReference(0);

  //unset "there is a title page" for the whole document because we have a section for the title (cover)
  ctSectPrLastSect.unsetTitlePg();

  document.write(new FileOutputStream("CreateWordMultipleSectionPageNumbering.docx"));

 }
}

有关使用的低级对象的参考:

Reference for used low level objects: http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/.

上面的代码显示了原理.如果需要满足进一步的要求,则应该知道*.docx文件只是一个ZIP存档,您可以将其解压缩并进行查看.因此,可以使用Word创建满足要求的*.docx文件,然后将其解压缩并查看/word/document.xml.

The above code shows the principle. If the need is to fulfilling further requirements then one should know that a *.docx file is simply a ZIP archive which one can unzip and have a look into it. So one can using Word for creating a *.docx file which fulfils the requirements, then unzipping it and look at /word/document.xml.

例如: 如何设置罗马数字以I II开头,阿拉伯数字又以1,2开头?"

For example: "How to set roman numerals start with I II and arabic numerals start with 1,2 again?"

如果在Word

If in Word create a Word document that uses different page numbering formats . Then in /word/document.xml you will find something like:

...
 <w:sectPr>
  ...
  <w:pgNumType w:start="1"/>
  ...
 </w:sectPr>
...

为此,我们需要在XML中的一个PgNumType元素.

So we need a PgNumType element in the XML for this.

再次完成示例:

import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtrRef;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr;

public class CreateWordMultipleSectionPageNumbering {

 //default section setting for page size and page borders
 //measurement unit = twips (twentieth of an inch point) = 1 inch = 1440 twips
 private static String defaultSectPr = 
   "<w:sectPr xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">"
  +"<w:pgSz w:w=\"12240\" w:h=\"15840\"/>" //A4
  +"<w:pgMar w:top=\"1417\" w:right=\"1417\" w:bottom=\"1134\" w:left=\"1417\""
  +" w:header=\"720\" w:footer=\"720\" w:gutter=\"0\"/>"
  +"<w:cols w:space=\"720\"/>"
  +"</w:sectPr>"; 

 public static void main(String[] args) throws Exception {

  CTSectPr ctSectPrDefault = (CTPPr.Factory.parse(defaultSectPr)).getSectPr();

  XWPFDocument document= new XWPFDocument();

  //set the default section setting for page size and page borders 
  CTDocument1 ctDocument = document.getDocument();
  CTBody ctBody = ctDocument.getBody();
  ctBody.setSectPr(ctSectPrDefault);

  //create first footer for section 2 - first created as first footer for the document
  XWPFFooter footer = document.createFooter(HeaderFooterType.FIRST); 
  //making it HeaderFooterType.FIRST first to be able creating one more footer later
  //will changing this later to HeaderFooterType.DEFAULT

  XWPFParagraph paragraph = footer.getParagraphArray(0);
  if (paragraph == null) paragraph = footer.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.CENTER);

  XWPFRun run = paragraph.createRun();  
  run.setText("Page ");
  paragraph.getCTP().addNewFldSimple().setInstr("PAGE \\* ROMAN MERGEFORMAT");
  run = paragraph.createRun();  
  run.setText(" of ");
  //paragraph.getCTP().addNewFldSimple().setInstr("NUMPAGES \\* ROMAN MERGEFORMAT");
  paragraph.getCTP().addNewFldSimple().setInstr("SECTIONPAGES \\* ROMAN MERGEFORMAT");

  //create second footer for section 3 == last section in document
  footer = document.createFooter(HeaderFooterType.DEFAULT);

  paragraph = footer.getParagraphArray(0);
  if (paragraph == null) paragraph = footer.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.CENTER);

  run = paragraph.createRun();  
  run.setText("Page ");
  paragraph.getCTP().addNewFldSimple().setInstr("PAGE \\* ARABIC MERGEFORMAT");
  run = paragraph.createRun();  
  run.setText(" of ");
  //paragraph.getCTP().addNewFldSimple().setInstr("NUMPAGES \\* ARABIC MERGEFORMAT");
  paragraph.getCTP().addNewFldSimple().setInstr("SECTIONPAGES \\* ARABIC MERGEFORMAT");

  //create document content.

  //section 1
  paragraph = document.createParagraph();
  run=paragraph.createRun();  
  run.setText("Cover");

  //paragraph with section setting for section above
  paragraph = document.createParagraph();
  paragraph.getCTP().addNewPPr().setSectPr(ctSectPrDefault);

  //section 2
  paragraph = document.createParagraph();
  run=paragraph.createRun();  
  run.setText("Contents");
  paragraph = document.createParagraph();
  run = paragraph.createRun();
  run.setText("Lorem ipsum semit dolor ...");
  run.addBreak(BreakType.PAGE); 
  paragraph = document.createParagraph();

  //paragraph with section setting for section above
  paragraph = document.createParagraph();
  paragraph.getCTP().addNewPPr().setSectPr(ctSectPrDefault);  
  CTSectPr ctSectPrSect2 = paragraph.getCTP().getPPr().getSectPr(); //we need this later
  //set this page numbering starting with 1 again
  ctSectPrSect2.addNewPgNumType().setStart(java.math.BigInteger.valueOf(1));

  //section 3 
  paragraph = document.createParagraph();
  run=paragraph.createRun();
  run.setText("Text");
  paragraph = document.createParagraph();
  run = paragraph.createRun();
  run.setText("Lorem ipsum semit dolor ...");
  run.addBreak(BreakType.PAGE); 
  paragraph = document.createParagraph();

  //section setting for section above == last section in document
  CTSectPr ctSectPrLastSect = ctBody.getSectPr(); 
  //there must be a SectPr already because of the default and footer settings above
  //set this page numbering starting with 1 again
  ctSectPrLastSect.addNewPgNumType().setStart(java.math.BigInteger.valueOf(1));

  //get footer reference of first footer and move this to be footer reference for section 2
  CTHdrFtrRef ctHdrFtrRef = ctSectPrLastSect.getFooterReferenceArray(0);
  ctHdrFtrRef.setType(STHdrFtr.DEFAULT); //change this from STHdrFtr.FIRST to STHdrFtr.DEFAULT
  CTHdrFtrRef[] ctHdrFtrRefs = new CTHdrFtrRef[]{ctHdrFtrRef};
  ctSectPrSect2.setFooterReferenceArray(ctHdrFtrRefs);
  ctSectPrLastSect.removeFooterReference(0);

  //unset "there is a title page" for the whole document because we have a section for the title (cover)
  ctSectPrLastSect.unsetTitlePg();

  document.write(new FileOutputStream("CreateWordMultipleSectionPageNumbering.docx"));

 }
}

这也使用NUMPAGESWord指令中的SECTIONPAGES字段来仅对单个部分中的页面进行编号,而不是对整个文档页面进行编号.

This also uses SECTIONPAGES field in Word insteand of NUMPAGES to numbering only the pages in single section istead of the whole document pages.

此外,它还将默认部分设置用于每个部分的页面大小和页面边框.这与可以读取*.docx文件的不同文字处理应用程序更加兼容.

Also it uses default section settings for page size and page borders in each section. This is more compatible with different word processing applications which can read *.docx files.

这篇关于如何通过poi在单词中设置不同部分的页码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆