Apache POI目录未更新

时间:2016-05-26 07:29:19

标签: java ms-word apache-poi tableofcontents

我正在使用Apache POI XWPF组件和java,将.xml文件中的数据提取到word文档中。到目前为止这么好,但我正在努力创建一个目录。我必须在方法的开头创建一个目录,然后在最后更新它以获取所有新标头。目前我使用doc.createTOC(),其中doc是从XWPFDocument创建的变量,在开始时创建表,然后我使用doc.enforceUpdateFields()来更新文档末尾的所有内容。但是当我运行程序后打开文档时,目录是空的,但导航面板确实包含了我指定的一些标题。

评论建议我添加一些代码。所以我开始从模板创建文档:

XWPFDocument doc = new XWPFDocument(new FileInputStream("D://Template.docx"));

然后我创建了一个目录:

doc.createTOC();

然后在整个方法中我将标题添加到文档中:

XWPFParagraph documentControlHeading = doc.createParagraph();
documentControlHeading.setPageBreak(true);
documentControlHeading.setAlignment(ParagraphAlignment.LEFT);
documentControlHeading.setStyle("Tier1Header");

添加完所有标题后,我想更新文档,以便所有新标题都出现在目录中。我这样做是使用以下命令购买的:

doc.enforceUpdateFields();

3 个答案:

答案 0 :(得分:0)

嗯...我正在查看import java.util.*; class calc { public static void main(String ar[]) { char choice; Scanner in = new Scanner(System.in); System.out.println("WELCOME TO SHREYDAN'S CALC 1.0"); System.out.println(" "); boolean loop = true; while (loop) { System.out.println("YOU CAN DO THE FOLLOWING:"); System.out.println("+: ADDITION"); System.out.println("-: SUBTRACTION"); System.out.println("*: PRODUCT"); System.out.println("/: QUOTIENT"); System.out.println("#: SQUARE ROOT"); System.out.println("^: POWER"); System.out.println("$: ROUND OFF"); System.out.println("!: FACTORIAL"); System.out.println(" "); System.out.println("ENTER CHOICE"); choice = in.next().charAt(0); switch (choice) { case '+': System.out.println("ENTER 2 NUMBERS, USER"); double a = in.nextDouble(); double b = in.nextDouble(); System.out.println("SUM = " + (a + b)); break; case '-': System.out.println("ENTER 2 NUMBERS, USER"); double c = in.nextDouble(); double d = in.nextDouble(); System.out.println("SUBTRACTING " + d + " FROM " + c + " ... DIFFERENCE = " + (c - d)); break; case '*': System.out.println("ENTER 2 NUMBERS, USER"); double e = in.nextDouble(); double f = in.nextDouble(); System.out.println("PRODUCT = " + (e * f)); break; case '/': System.out.println("ENTER 2 NUMBERS, USER"); double g = in.nextDouble(); double h = in.nextDouble(); System.out.println("DIVIDING " + g + " BY " + h + " = " + (g / h)); break; case '#': System.out.println("ENTER NO. FOR SQAURE ROOT:"); double sqrt = in.nextDouble(); System.out.println("SQUARE ROOT OF " + sqrt + " = " + Math.sqrt(sqrt)); break; case '^': System.out.println("ENTER BASE, USER"); double base = in.nextDouble(); System.out.println("ENTER POWER, USER"); double power = in.nextDouble(); System.out.println(base + " RAISED TO POWER " + power + " = " + Math.pow(base, power)); break; case '$': System.out.println("ENTER DECIMAL VALUES TO ROUND OFF"); double deci = in.nextDouble(); System.out.println("THE NEAREST ROUND OFF = " + Math.round(deci)); break; case '!': System.out.println("ENTER A NO. FOR FACTORIAL:"); int fact = in.nextInt(); int factorial = 1; for (int i = fact; i >= 1; i--) factorial = factorial * i; System.out.println(fact + "! = " + factorial); break; default: System.out.println("WRONG CHOICE USER"); } System.out.println("Want to calculate more?Y/N"); loop = in.next().charAt(0) == 'Y'; } } } 方法代码,看起来它看起来像createTOC()的样式。所以找不到Heading #。首先尝试创建文本,然后使用Tier1Header等样式作为标题。然后使用Heading 1添加TOC。它应该在创建TOC时找到所有标题。我不知道createTOC()是否会影响TOC。

答案 1 :(得分:0)

//您的docx模板应该包含以下或类似的文本//将被搜索并替换为WORD TOC。

// $ {TOC}

public static void main(String[] args) throws IOException, OpenXML4JException {
        XWPFDocument docTemplate = null;
        try {
            File file = new File(PATH_TO_FILE); //"C:\\Reports\\Template.docx";
            FileInputStream fis = new FileInputStream(file);
            docTemplate = new XWPFDocument(fis);
             generateTOC(docTemplate);
            saveDocument(docTemplate);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (docTemplate != null) {
                docTemplate.close();
            }
        }
    }   

private static void saveDocument(XWPFDocument docTemplate) throws FileNotFoundException, IOException {
    FileOutputStream outputFile = null;
    try {
        outputFile = new FileOutputStream(OUTFILENAME);
        docTemplate.write(outputFile);
    } finally {
        if (outputFile != null) {
            outputFile.close();
        }
    }
}


public static void generateTOC(XWPFDocument document) throws InvalidFormatException, FileNotFoundException, IOException {
        String findText = "${TOC}";
        String replaceText = "";
        for (XWPFParagraph p : document.getParagraphs()) {
            for (XWPFRun r : p.getRuns()) {
                int pos = r.getTextPosition();
                String text = r.getText(pos);
                if (text != null && text.contains(findText)) {
                    text = text.replace(findText, replaceText);
                    r.setText(text, 0);
                    addField(p, "TOC \\o \"1-3\" \\h \\z \\u");
                    break;
                }
            }
        }
    }

private static void addField(XWPFParagraph paragraph, String fieldName) {
    CTSimpleField ctSimpleField = paragraph.getCTP().addNewFldSimple();
    // ctSimpleField.setInstr(fieldName + " \\* MERGEFORMAT ");
    ctSimpleField.setInstr(fieldName);
    ctSimpleField.addNewR().addNewT().setStringValue("<<fieldName>>");
}

答案 2 :(得分:0)

这是createTOC()的代码,通过检查XWPFDocument.class

获得
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();
        }
    }
}

正如您所看到的,它将TOC的所有段落添加到名为&#34; HeadingX&#34;的样式中,其中X为数字。但不幸的是,这还不够。事实上,该方法在其实现中存在错误/不完整。

传递给addRow()的网页代码始终为1,甚至没有计算。 因此,最后,您将拥有一个包含所有段落的TOC,并且尾随点会给出正确的缩进,但页面将始终等于&#34; 1&#34;。

修改 ......但是,有一个解决方案here