如何在POI中使用预定义格式的DOCX?

15

我正在使用POI创建一个docx生成器,并希望使用预定义格式。

Word包括多种格式,如标题、一级标题..十级标题等。这些格式在您使用Word创建的每个DOCX中都是预定义的。

我想在我的docx生成器中使用它们。我尝试了以下方法,但未应用该格式:

paragraph = document.createParagraph();
lastParagraph.setStyle("Heading1");
我还尝试了“heading 1”,“heading1”和“Heading1”作为样式,但它们都没有起作用。
API文档没有显示任何细节。
我分析了一个使用Word 2007创建的docx文件,并发现“Heading1”是正确的样式。不幸的是,该样式未在docx中定义。我需要手动创建此样式吗?
有人能指出正确的解决方案吗?
4个回答

20

非常简单:使用一个“模板”docx文件。

  1. 使用Word 2007创建一个空的docx文件。
  2. 将此文件用作XWPFDocument的模板。
  3. 使用样式添加段落。

这是代码:

XWPFDocument document = new XWPFDocument(new FileInputStream("template.docx");
paragraph = document.createParagraph();
paragraph.setStyle("Heading1");

这个模板包含所有的样式,因此可以通过 setStyle("Heading1"); 引用它们。


5
这个很好用!但有一点需要注意......它似乎会从模板文档中舍弃未使用的样式。因此你需要在文档中已经使用这些样式,或者以某种方式使用一个模板... - Jonathan S. Fisher
1
@exabrial 你说得对,除非我们在模板中添加样式,否则无法获取样式。谢谢。这帮了我很多,也节省了很多时间。 - MaheshVarma
@guerda 我可能不是完全了解,但这里的 lastParagraph 是什么意思? - pulse
哇,6年前的代码,竟然没有人注意到错误!当然我是指“段落”。感谢提示! - guerda

9

如果你想创建一个被识别为一级标题的样式(例如用于MS Word生成的目录),并且可以在Word格式栏中访问,可以按照以下步骤操作:

private static File writeSimpleDocxFile(String content) throws IOException {
    XWPFDocument docxDocument = new XWPFDocument();

    String strStyleId = "ownstyle1";

    addCustomHeadingStyle(docxDocument, strStyleId, 1);

    XWPFParagraph paragraph = docxDocument.createParagraph();
    XWPFRun run = paragraph.createRun();
    run.setText(content);

    paragraph.setStyle(strStyleId);
}

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

}

是的,这种样式将会显示在styles.xml中。
(我知道:这不是对你问题的直接回答,但是由于我没有在互联网上找到可用的信息形式,我会在此发布)

我怎样可以在这个自定义风格中设置字体? - Rob Audenaerde
虽然我目前无法在软件中查找此信息,但我进行了快速搜索。遗憾的是,POI javadocs没有提到CT样式(https://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDocument.html),但是office开放网站有一些指针:https://wiki.openoffice.org/wiki/Cell_Style_in_Xls_module - RobertG
看起来你可以在XWPFStyles上设置字体:https://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFStyles.html#setDefaultFonts(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts) - RobertG

9
您可以创建一个Word模板(只需使用Word中的“另存为”功能)。

第一种选择

现在,模板包含了一些额外的XML文件在\word文件夹中: - styles.xml - stylesWithEffects.xml - webSettings.xml - fontTable.xml 还有一个 - \theme文件夹

如果您将这些文件复制到原始POI生成的文件中,那么您可以引用styles.xml文件中给定的样式。

您可以像操作ZIP文件一样操作您的原始文件,这不应该需要太多的工作。

第二种选择

从模板中将样式复制到您的文档中的代码中:

XWPFDocument template = new XWPFDocument(new FileInputStream(new File("Template.dotx")));       

XWPFDocument doc = new XWPFDocument();      
// let's copy styles from template to new doc
XWPFStyles newStyles = doc.createStyles();
newStyles.setStyles(template.getStyle());


XWPFParagraph para = doc.createParagraph();
para.setStyle("Heading1");

XWPFRun run = para.createRun();
run.setText("Heading 1");

return doc;

优点是您可以直接使用 Word 单独操纵样式,并将其保存回模板文件。


2
是的,你应该手动完成。Docx规范说明包含样式信息的styles.xml是可选的。所以,我几乎可以确定如果你不明确要求,POI根本不会创建它。你可以检查一下:只需解压缩docx文件并查看是否存在此文件(yourfile.docx/word/styles.xml)。
因此,在docx术语中,你应该做以下工作(我不知道POI如何实现):
1)创建styles.xml并添加必要的样式;
2)创建连接document.xml和styles.xml的关系(我认为POI应该自动完成);
3)在document.xml中使用样式ID将具体文本部分(docx术语中的Run)与具体样式连接起来。

谢谢你的回答!你的解决方案需要大量手动复制样式。 - guerda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接