使用页码指示为XWPFDocument创建目录

我实际上是使用Apache POI生成Word文档,我需要自动创建一个引用段落的目录(TOC)及其页面指示。

这是我正在使用的代码(我省略了前置条件和内部方法的主体):

XWPFDocument doc = new XWPFDocument(OPCPackage.openOrCreate(new File(document))); String strStyleId = "Index Style"; addCustomHeadingStyle(doc, strStyleId, 1); XWPFParagraph documentControlHeading = doc.createParagraph(); changeText(documentControlHeading, "First try"); documentControlHeading.setAlignment(ParagraphAlignment.LEFT); documentControlHeading.setPageBreak(true); documentControlHeading.setStyle(strStyleId); XWPFParagraph documentControlHeading1 = doc.createParagraph(); changeText(documentControlHeading1, "Second try"); documentControlHeading1.setAlignment(ParagraphAlignment.LEFT); documentControlHeading1.setPageBreak(true); documentControlHeading1.setStyle(strStyleId); doc.createTOC(); 

当我打开生成的文档时,我得到了这个结果(见蓝色方块):

在此处输入图像描述

在左侧部分,我可以看到生成的TOC。 到现在为止还挺好。 但是,在文档的正文中,我只能看到一个静态文本“目录”,根本没有任何指示(既没有段落也没有页面)。 我甚至无法与它互动。

如果我点击菜单条目“目录”(左上角的红色方块),则会生成我想要的“真实”内容表(当然,请按照箭头…)。

我的问题是: 如何从代码中获得第二个结果(红色TOC)?

非常感谢。

旁注:我甚至试过把doc.enforceUpdateFields();doc.createTOC(); 但是,TOC的每一个参考都会以这种方式消失。

@Sucy,我添加了你要求的方法。 但不知道你是否能发现它们有用:

 /* * Adds a custom style with the given indentation level at the given document. */ private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) { CTStyle ctStyle = CTStyle.Factory.newInstance(); ctStyle.setStyleId(strStyleId); CTString styleName = CTString.Factory.newInstance(); styleName.setVal(strStyleId); ctStyle.setName(styleName); CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance(); indentNumber.setVal(BigInteger.valueOf(headingLevel)); // lower number > style is more prominent in the formats bar ctStyle.setUiPriority(indentNumber); CTOnOff onoffnull = CTOnOff.Factory.newInstance(); ctStyle.setUnhideWhenUsed(onoffnull); // style shows up in the formats bar ctStyle.setQFormat(onoffnull); // style defines a heading of the given level CTPPr ppr = CTPPr.Factory.newInstance(); ppr.setOutlineLvl(indentNumber); ctStyle.setPPr(ppr); XWPFStyle style = new XWPFStyle(ctStyle); // is a null op if already defined XWPFStyles styles = docxDocument.createStyles(); style.setType(STStyleType.PARAGRAPH); styles.addStyle(style); } /* * Changes the text of a given paragraph. */ public static void changeText(XWPFParagraph p, String newText) { if (p != null) { List runs = p.getRuns(); for (int i = runs.size() - 1; i >= 0; i--) { p.removeRun(i); } if (runs.size() == 0) { p.createRun(); } XWPFRun run = runs.get(0); run.setText(newText, 0); } } 

您所看到的XWPF类正在进行中,没有真正的总体架构。 随着时间的推移,这会随着时间的推移而改变,但同时您可以尝试以这种方式向段落添加简单的TOC字段。

 XWPFParagraph p; ... // get or create your paragraph .... CTP ctP = p.getCTP(); CTSimpleField toc = ctP.addNewFldSimple(); toc.setInstr("TOC \\h"); toc.setDirty(STOnOff.TRUE); 

这将创建一个目录,其中包含指向页面的超链接,当Word打开它时应重新计算,目录将基于预定义的HeaderX样式。

我已经解开了这个谜团,不幸的是(对于有同样问题的人),没有好消息。 Apache POI的createTOC()被窃听(说实话,它似乎是一种方法,其实现已经开始但从未以适当的方式完成) (请考虑jmarkmurphy的接受答案)。

文档没有解释有关方法本身的任何内容(它仅报告签名,仅此而已),这是可疑的。

观看XWPFDocument的类代码:

 public void createTOC() { CTSdtBlock block = getDocument().getBody().addNewSdt(); TOC toc = new TOC(block); for (XWPFParagraph par : this.paragraphs) { String parStyle = par.getStyle(); if ((parStyle != null) && (parStyle.startsWith("Heading"))) try { int level = Integer.valueOf(parStyle.substring("Heading".length())).intValue(); toc.addRow(level, par.getText(), 1, "112723803"); } catch (NumberFormatException e) { e.printStackTrace(); } } } 

Apache POI搜索​​具有名为“HeadingX”的样式的段落,其中X是数字。 因此,我的变量strStyleId应该被标准化为Heading1 ,作为示例。 但这并没有解决问题。 实际上, createTOC()总是将1作为页面编号传递给addRow()方法,这样总是将页面设置为1。 它绝对没有任何东西可以获得它的恐怖。

这是最终的,无用的结果(你可以看到,它也是一个“假的”TOC,而不是你可以使用问题中的红色方形按钮通过Microsoft Word创建的那个):

在此处输入图像描述

因此,无法通过dinamically检索Word文档的页码(正如我在其他post中读到的那样),甚至Apache POI似乎无法做到这一点,遗憾的是。

 toc.setInstr("TOC \\h"); 

h开关必须与’\’一起使用,而不是’/’,因为它只能与’\’一起使用。 有关使用TOC开关的更多详细信息: 使用Word的TOC字段来微调您的目录