Contents

DOCX4J简介

1. 概述

在本文中,我们将专注于创建一个 . 使用docx4j 库的docx文档。

Docx4j 是一个用于创建和操作 Office OpenXML文件的 Java 库——这意味着它只能使用*.docx文件类型,而旧版本的 Microsoft Word 使用.doc*扩展名(二进制文件)。

请注意,Microsoft Office 从 2007 版本开始支持OpenXML格式。

2. Maven 设置

要开始使用 docx4j,我们需要将所需的依赖项添加到我们的pom.xml中:

<dependency>
    <groupId>org.docx4j</groupId>
    <artifactId>docx4j</artifactId>
    <version>3.3.5</version>
</dependency>
<dependency> 
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.1</version>
</dependency>

请注意,我们始终可以在Maven 中央存储库 中查找最新的依赖项版本。

需要JAXB依赖项,因为 docx4j 在后台使用此库来编组/解组 docx 文件中的XML部分。

3. 创建一个Docx文件文档

3.1. 文本元素和样式

让我们首先看看如何创建一个简单的docx文件——带有一个文本段落:

WordprocessingMLPackage wordPackage = WordprocessingMLPackage.createPackage();
MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
mainDocumentPart.addStyledParagraphOfText("Title", "Hello World!");
mainDocumentPart.addParagraphOfText("Welcome To Blogdemo");
File exportFile = new File("welcome.docx");
wordPackage.save(exportFile);

这是生成的welcome.docx文件:

/uploads/docx4j/1.png

要创建新文档,我们必须使用WordprocessingMLPackage,它表示OpenXML格式的docx文件,而MainDocumentPart类包含主document.xml部分的表示。

为了清楚起见,让我们解压缩welcome.docx文件,然后打开word/document.xml文件以查看XML 表示形式:

<w:body>
    <w:p>
        <w:pPr>
            <w:pStyle w:val="Title"/>
        </w:pPr>
        <w:r>
            <w:t>Hello World!</w:t>
        </w:r>
    </w:p>
    <w:p>
        <w:r>
            <w:t>Welcome To Blogdemo!</w:t>
        </w:r>
    </w:p>
</w:body>

正如我们所看到的,每个句子都由*段落 ( p )中的文本 ( t )的运行 ( r ) 表示,这就是*addParagraphOfText()方法的用途。

*addStyledParagraphOfText()*做的远不止这些;它创建一个段落属性(pPr),其中包含要应用于段落的样式。

简单地说,段落声明了单独的运行,每个运行包含一些文本元素: /uploads/docx4j/3.png

要创建一个漂亮的文档,我们需要完全控制这些元素(paragraphruntext)。

所以,让我们来看看如何使用runProperties ( RPr ) 对象来风格化我们的内容:

ObjectFactory factory = Context.getWmlObjectFactory();
P p = factory.createP();
R r = factory.createR();
Text t = factory.createText();
t.setValue("Welcome To Blogdemo");
r.getContent().add(t);
p.getContent().add(r);
RPr rpr = factory.createRPr();       
BooleanDefaultTrue b = new BooleanDefaultTrue();
rpr.setB(b);
rpr.setI(b);
rpr.setCaps(b);
Color green = factory.createColor();
green.setVal("green");
rpr.setColor(green);
r.setRPr(rpr);
mainDocumentPart.getContent().add(p);
File exportFile = new File("welcome.docx");
wordPackage.save(exportFile);

结果如下:

/uploads/docx4j/5.png

在我们分别使用createP()createR()createText()创建了一个段落、一个 run 和一个文本元素之后,我们声明了一个新的runProperties对象 ( RPr ) 来为文本元素添加一些样式。

rpr对象用于设置格式属性,粗体 ( B )、斜体 ( I ) 和大写 ( Caps ),这些属性使用*setRPr()*方法应用于文本运行。

3.2. 处理图像

Docx4j 提供了一种将图像添加到我们的 Word 文档的简单方法:

File image = new File("image.jpg" );
byte[] fileContent = Files.readAllBytes(image.toPath());
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage
  .createImagePart(wordPackage, fileContent);
Inline inline = imagePart.createImageInline(
  "Blogdemo Image (filename hint)", "Alt Text", 1, 2, false);
P Imageparagraph = addImageToParagraph(inline);
mainDocumentPart.getContent().add(Imageparagraph);

*addImageToParagraph()*方法的实现如下所示:

private static P addImageToParagraph(Inline inline) {
    ObjectFactory factory = new ObjectFactory();
    P p = factory.createP();
    R r = factory.createR();
    p.getContent().add(r);
    Drawing drawing = factory.createDrawing();
    r.getContent().add(drawing);
    drawing.getAnchorOrInline().add(inline);
    return p;
}

首先,我们创建了包含要添加到主文档部分的图像的文件,然后,我们将表示图像的字节数组与wordMLPackage对象链接起来。

创建图像部分后,我们需要使用createImageInline() 方法创建一个*Inline *对象。

addImageToParagraph()方法将Inline对象嵌入到Drawing 中,以便可以将其添加到run中。

最后,与文本段落一样,包含图像的段落被添加到mainDocumentPart中。

这是生成的文件:

/uploads/docx4j/7.png

3.3. 创建表

Docx4j 还使得操作表 (Tbl)、行 (Tr) 和列 (Tc) 变得非常容易。

让我们看看如何创建一个 3×3 的表格并向其中添加一些内容:

int writableWidthTwips = wordPackage.getDocumentModel()
  .getSections().get(0).getPageDimensions().getWritableWidthTwips();
int columnNumber = 3;
Tbl tbl = TblFactory.createTable(3, 3, writableWidthTwips/columnNumber);     
List<Object> rows = tbl.getContent();
for (Object row : rows) {
    Tr tr = (Tr) row;
    List<Object> cells = tr.getContent();
    for(Object cell : cells) {
        Tc td = (Tc) cell;
        td.getContent().add(p);
    }
}

给定一些行和列,createTable()方法创建一个新的Tbl对象,第三个参数是指以缇为单位的列宽(这是距离测量值 - 1/1440 英寸)。

创建后,我们可以遍历tbl对象的内容,并将Paragraph对象添加到每个单元格中。

让我们看看最终结果是什么样子的:

/uploads/docx4j/9.png

4. 阅读 Docx 文件文档

现在我们已经了解了如何使用 docx4j 创建文档,让我们看看如何读取现有的 docx 文件并打印其内容:

File doc = new File("helloWorld.docx");
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
  .load(doc);
MainDocumentPart mainDocumentPart = wordMLPackage
  .getMainDocumentPart();
String textNodesXPath = "//w:t";
List<Object> textNodes= mainDocumentPart
  .getJAXBNodesViaXPath(textNodesXPath, true);
for (Object obj : textNodes) {
    Text text = (Text) ((JAXBElement) obj).getValue();
    String textValue = text.getValue();
    System.out.println(textValue);
}

在此示例中,我们使用load()方法基于现有的helloWorld.docx文件创建了一个WordprocessingMLPackage对象。

之后,我们使用XPath表达式 ( //w:t ) 从主文档部分获取所有文本节点。

getJAXBNodesViaXPath()方法返回JAXBElement对象的列表。

因此,mainDocumentPart对象内的所有文本元素都将打印在控制台中。

请注意,我们始终可以解压缩 docx 文件以更好地理解 XML 结构,这有助于分析问题,并更好地了解如何解决问题。