如何通过poi为word中的不同部分设置页码

2024-01-12

我的文档由三部分组成:封面、内容和正文。我想为每个部分设置不同的页码。封面不需要页码。内容页码采用罗马数字,正文页码采用希腊数字。用POI可以实现吗?


Apache poi到目前为止,只有 abel 创建了三种类型的页眉/页脚:页眉页脚类型 http://poi.apache.org/apidocs/org/apache/poi/wp/usermodel/HeaderFooterType.html.DEFAULT, .EVEN and .First.

因此,为了满足您的要求,我们需要使用底层的低级对象。我们需要稍微作弊才能创建不同的页脚。

我们需要两个不同的页脚。一份用于第 2 部分(内容),一份用于第 3 部分(文本)。但两者都必须是类型DEFAULT。由于这是不可能使用apache poi到目前为止,我们首先创建两个不同类型的不同页脚(FIRST and DEFAULT)对于整个文档。然后我们改变FIRST页脚至DEFAULT并将其移至第 2 部分的页脚参考。

Example:

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"));

 }
}

使用的低级对象参考:http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/ http://grepcode.com/snapshot/repo1.maven.org/maven2/org.apache.poi/ooxml-schemas/1.1/.


上面的代码展示了原理。如果需要满足进一步的要求,那么人们应该知道*.docx文件只是一个ZIP存档,人们可以解压并查看它。所以可以使用Word用于创建一个*.docx满足要求的文件,然后解压并查看/word/document.xml.

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

If in Word 创建使用不同页码格式的 Word 文档 https://support.microsoft.com/en-us/help/326536/how-to-create-a-word-document-that-uses-different-page-numbering-forma。然后在/word/document.xml你会发现类似的东西:

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

所以我们需要一个PgNumType中的元素XML为了这。

再次完成示例:

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"));

 }
}

这也使用SECTIONPAGES领域在Word代替NUMPAGES仅对单个部分中的页面而不是整个文档页面进行编号。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过poi为word中的不同部分设置页码 的相关文章

随机推荐

  • 使用wp_insert_post()创建一个新页面

    我在 PHP 函数中有以下代码 当我安装允许您创建帖子或页面的插件时 该函数会被激活 工作完美并制作页面 如果 post type是 post 但如果 post type是 页面 那么它不起作用 不会创建页面 my post array p
  • Pandas 重置系列索引以删除多重索引

    我有一个看起来像这样的系列 1999 03 31 SOLD PRICE NaN 1999 06 30 SOLD PRICE NaN 1999 09 30 SOLD PRICE NaN 1999 12 31 SOLD PRICE 3 00 2
  • JavaFX 选项卡式窗格,每个选项卡上都有一个表格视图?

    我有一个选项卡式窗格 每个选项卡上都有一个表格 我向表中添加了不同的项目 我只希望每个选项卡向我显示该表的相应项目 但什么也没有出现 当我调试时 我可以清楚地看到选项卡窗格 其中包含选项卡 包含表视图 包含正确的项目 为什么这不起作用 Th
  • 如何为 android ndk 安装 libiconv?

    有人可以教我或给我指点如何为 Android 安装 libiconv 的教程吗 我已经用谷歌搜索了三天 但找不到教程或操作方法 获取 libiconv 源代码 并创建 Android mk makefile 看着这个网站 http grou
  • Drools 中类型不安全的对象字段访问

    我正在使用一个系统 其中插入 Drools 引擎的一些数据遵循以下 严重过度简化 格式 public class Item public String getValueType public Object getValue 这些值可能有几种
  • R 快速 XML 解析

    当前在 R 中将 XML 文件转换为数据帧的最快方法是什么 XML 如下所示 注意 并非所有行都包含所有字段
  • ValueError:名称投影仪的重复插件

    Running tensorboard logdir log dir我收到错误 Traceback most recent call last File home user local bin tensorboard line 11 in
  • 如何使用条形图缩放 Seaborn 的 y 轴

    我在用着factorplot kind bar 如何缩放 y 轴 例如使用对数刻度 我尝试修改绘图的轴 但这总是以某种方式弄乱条形图 所以请先尝试您的解决方案以确保它确实有效 考虑到你的问题提到barplot我想我也会为这种类型的情节添加一
  • 异步 MVVM 命令

    我一直在关注 Stephen Cleary 在 MSDN 杂志上发表的相当优秀的系列文章 异步 MVVM 应用程序的模式 https msdn microsoft com en us magazine dn630647 aspx 并一直在使
  • pydicom“数据集”对象没有属性“TransferSyntaxUID”

    我正在使用 pydicom 1 0 0a1 从下载here https github com pydicom pydicom 当我运行以下代码时 ds pydicom read file DR abnormal abc dcm force
  • 一个季度的周数

    我试图根据日期获取给定季度的周数 我目前有这个公式 1 WEEKNUM EDATE Y4 1 WEEKNUM DATE YEAR EDATE Y4 1 LOOKUP MONTH EDATE Y4 1 1 4 7 10 1 But for J
  • 没有名为 urllib3 的模块

    我编写了一个调用 API 的脚本 并于上周成功运行了它 这周 它不会运行 我收到以下错误消息 Traceback most recent call last File user audit py line 2 in
  • 对基于 REST 的 API 到底是什么感到困惑

    我试图了解基于 REST 的 API 到底是什么 据我了解 这只是在 API 中编写函数的约定 所有函数都应该是 GET POST DELETE PUT 形式吗 因此 例如 REST API 中的函数可以是 public string ge
  • 将虚拟地址转换为物理地址

    The following page table is for a system with 16 bit virtual and physical addresses and with 4 096 byte pages The refere
  • endUpdates 后 UITableView 部分页脚视图位置

    在 ios8 上 我使用核心数据表视图控制器 删除行后 我的部分页脚视图突然一直下降到底部UITableView 当我滚动表格视图时 页脚视图返回到其位置 如何解决这个问题以及为什么会发生这种情况 这是代码以防万一 void control
  • Spark 读取镶木地板文件时出现问题

    我有 2 个镶木地板零件文件part 00043 0bfd7e28 6469 4849 8692 e625c25485e2 c000 snappy parquet 是 2017 年 11 月 14 日运行的部分文件 和part 00199
  • Cube、Rollup 和 GroupBy 运算符之间有什么区别?

    我找不到有关差异的任何详细文档 我确实注意到了差异 因为交换时cube and groupBy函数调用 我得到不同的结果 我注意到对于结果使用cube 我在以前使用的表达式上得到了很多空值groupBy 它们的工作方式不同 groupBy简
  • 如何控制鼠标光标? [复制]

    这个问题在这里已经有答案了 我的表单只有几个按钮 我想知道现在光标下有什么按钮 附 也许它是重复的 但我找不到这个问题的答案 看一下GetChildAtPoint http msdn microsoft com en us library
  • 自定义 QStyledItemDelegate 以绘制多种颜色的文本

    我想在一个中显示两列QTableWidget显示两次刺痛之间的差异 通过之前的一些编辑距离算法计算 这些部分存储在每个部分的数据中QTableWidgetItem as a QStringList 第一部分必须显示为黑色 接下来的部分必须显
  • 如何通过poi为word中的不同部分设置页码

    我的文档由三部分组成 封面 内容和正文 我想为每个部分设置不同的页码 封面不需要页码 内容页码采用罗马数字 正文页码采用希腊数字 用POI可以实现吗 Apache poi到目前为止 只有 abel 创建了三种类型的页眉 页脚 页眉页脚类型