创建一个目录与页码指示的XWPFDocument创建一个目录与页码指示的XWPFDocument(C

2019-05-12 08:21发布

我其实生成的Word文档与Apache POI,我需要自动生成的内容(TOC)的表引用段落,用自己网页的指示。

这是我使用的代码(I省略前提条件和内部方法体):

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<XWPFRun> 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);
    }
}

Answer 1:

该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风格。



Answer 2:

我已经解决了神秘,不幸的是(具有相同问题的人),有没有好消息。 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,这种方式。 它绝对没有为了得到那个dinamically。

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

因此,对于一个Word文档的页码不能dinamically检索(正如我在其他帖子阅读),甚至是Apache的POI似乎无法做到这一点,可悲。



Answer 3:

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

H开关必须与使用“\”,而不是“/”,因为它只能与正常工作“\”。 :关于使用TOC开关更多细节使用Word的TOC域微调表的内容



文章来源: Creating a Table of Contents for a XWPFDocument with page numbers' indication