Docx4J简介

Introduction To Docx4J

1.概述

在本文中,我们将重点介绍使用docx4j库创建.docx文档。

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

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

2. Maven安装

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

1
2
3
4
5
6
7
8
9
10
<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文件-带有文本段落:

1
2
3
4
5
6
WordprocessingMLPackage wordPackage = WordprocessingMLPackage.createPackage();
MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
mainDocumentPart.addStyledParagraphOfText("Title","Hello World!");
mainDocumentPart.addParagraphOfText("Welcome To Baeldung");
File exportFile = new File("welcome.docx");
wordPackage.save(exportFile);

这是生成的welcome.docx文件:

 width=

要创建一个新文档,我们必须使用WordprocessingMLPackage,它代表OpenXML格式的docx文件,而MainDocumentPart类保留了main.xml部分的表示。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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 Baeldung!</w:t>
        </w:r>
    </w:p>
</w:body>

如我们所见,每个句子都由段落(p)内的文本(t)的一行(r)表示,这就是addParagraphOfText()方法的作用。

addStyledParagraphOfText()的作用远不止于此。 它创建了一个段落属性(pPr),该属性具有适用于该段落的样式。

简而言之,段落声明了单独的运行,每个运行包含一些文本元素:

 width=

要创建一个漂亮的文档,我们需要完全控制这些元素(段落,运行和文本)。

因此,让我们发现如何使用runProperties(RPr)对象来样式化我们的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ObjectFactory factory = Context.getWmlObjectFactory();
P p = factory.createP();
R r = factory.createR();
Text t = factory.createText();
t.setValue("Welcome To Baeldung");
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);

结果如下所示:

 width=

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

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

3.2。 处理图像

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

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

这是addImageToParagraph()方法的实现的样子:

1
2
3
4
5
6
7
8
9
10
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中,以便可以将其添加到运行中。

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

这是生成的文档:

 width=

3.3。 建立表格

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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对象添加到每个单元格中。

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

 width=

4.读取Docx文件文档

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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结构,这有助于分析问题,并提供有关如何解决问题的更好见解。

5.结论

在本文中,我们发现docx4j如何使在MSWord文档上执行复杂的操作变得更加容易,例如创建段落,表格,文档部分以及添加图像。

可以在GitHub上一如既往地找到代码段。