1. 概述

Apache POI 是一个 Java 库,用于处理基于 Office Open XML 标准(OOXML)和 Microsoft OLE 2 复合文档格式(OLE2)的各种文件格式。

本教程重点介绍 Apache POI 对最常用的 Office 文件格式——Microsoft Word 的支持。我们将逐步讲解格式化和生成 MS Word 文档所需的步骤,以及如何解析此类文档。

2. Maven 依赖

Apache POI 处理 MS Word 文件只需一个依赖:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.5</version>
</dependency>

最新版本可点击此处查看。

3. 准备工作

我们先了解生成 MS Word 文档所需的核心元素。

3.1 资源文件

我们将收集三个文本文件的内容,写入名为 rest-with-spring.docx 的 MS Word 文档。

此外,使用 logo-leaf.png 文件向新文档插入图片。所有文件均位于类路径下,通过静态变量表示:

public static String logo = "logo-leaf.png";
public static String paragraph1 = "poi-word-para1.txt";
public static String paragraph2 = "poi-word-para2.txt";
public static String paragraph3 = "poi-word-para3.txt";
public static String output = "rest-with-spring.docx";

这些资源文件的内容来自本站课程页面(仓库链接见文末)。

3.2 辅助方法

生成文档的主逻辑会使用以下辅助方法:

public String convertTextFileToString(String fileName) {
    try (Stream<String> stream 
      = Files.lines(Paths.get(ClassLoader.getSystemResource(fileName).toURI()))) {
        
        return stream.collect(Collectors.joining(" "));
    } catch (IOException | URISyntaxException e) {
        return null;
    }
}

此方法提取类路径中指定文本文件的内容,合并所有行后返回字符串。

4. 生成 MS Word 文档

本节介绍如何格式化和生成 Microsoft Word 文档。操作前需先创建 XWPFDocument 实例:

XWPFDocument document = new XWPFDocument();

4.1 格式化标题和副标题

创建标题需先实例化 XWPFParagraph 并设置对齐方式:

XWPFParagraph title = document.createParagraph();
title.setAlignment(ParagraphAlignment.CENTER);

段落内容需包装在 XWPFRun 对象中,可设置文本值和样式:

XWPFRun titleRun = title.createRun();
titleRun.setText("Build Your REST API with Spring");
titleRun.setColor("009933");
titleRun.setBold(true);
titleRun.setFontFamily("Courier");
titleRun.setFontSize(20);

各 set 方法名已明确其用途。

类似地创建副标题段落:

XWPFParagraph subTitle = document.createParagraph();
subTitle.setAlignment(ParagraphAlignment.CENTER);

格式化副标题:

XWPFRun subTitleRun = subTitle.createRun();
subTitleRun.setText("from HTTP fundamentals to API Mastery");
subTitleRun.setColor("00CC44");
subTitleRun.setFontFamily("Courier");
subTitleRun.setFontSize(16);
subTitleRun.setTextPosition(20);
subTitleRun.setUnderline(UnderlinePatterns.DOT_DOT_DASH);

setTextPosition 设置副标题与后续图片的间距,setUnderline 定义下划线样式。

由于标题和副标题内容简短,直接硬编码更高效。

4.2 插入图片

图片也需包装在 XWPFParagraph 中。为使图片水平居中并位于副标题下方,添加以下代码:

XWPFParagraph image = document.createParagraph();
image.setAlignment(ParagraphAlignment.CENTER);

设置图片与下方文本的间距:

XWPFRun imageRun = image.createRun();
imageRun.setTextPosition(20);

从类路径读取图片并插入文档,指定尺寸:

Path imagePath = Paths.get(ClassLoader.getSystemResource(logo).toURI());
imageRun.addPicture(Files.newInputStream(imagePath),
  XWPFDocument.PICTURE_TYPE_PNG, imagePath.getFileName().toString(),
  Units.toEMU(50), Units.toEMU(50));

4.3 格式化段落

使用 poi-word-para1.txt 创建第一个段落:

XWPFParagraph para1 = document.createParagraph();
para1.setAlignment(ParagraphAlignment.BOTH);
String string1 = convertTextFileToString(paragraph1);
XWPFRun para1Run = para1.createRun();
para1Run.setText(string1);

段落创建方式与标题/副标题类似,区别在于使用辅助方法读取内容。

类似地,用 poi-word-para2.txtpoi-word-para3.txt 创建其他段落:

XWPFParagraph para2 = document.createParagraph();
para2.setAlignment(ParagraphAlignment.RIGHT);
String string2 = convertTextFileToString(paragraph2);
XWPFRun para2Run = para2.createRun();
para2Run.setText(string2);
para2Run.setItalic(true);

XWPFParagraph para3 = document.createParagraph();
para3.setAlignment(ParagraphAlignment.LEFT);
String string3 = convertTextFileToString(paragraph3);
XWPFRun para3Run = para3.createRun();
para3Run.setText(string3);

三个段落的创建逻辑基本一致,仅样式(如对齐方式、斜体)不同。

4.4 生成 MS Word 文件

document 对象写入文件:

FileOutputStream out = new FileOutputStream(output);
document.write(out);
out.close();
document.close();

本节所有代码封装在 handleSimpleDoc 方法中。

5. 解析与测试

本节介绍 MS Word 文档的解析及结果验证。

5.1 准备工作

在测试类中声明静态字段:

static WordDocument wordDocument;

该字段用于引用包含第 3、4 节代码的类实例。

解析测试前需初始化变量并生成文档:

@BeforeClass
public static void generateMSWordFile() throws Exception {
    WordTest.wordDocument = new WordDocument();
    wordDocument.handleSimpleDoc();
}

5.2 解析文档与验证

首先从项目目录读取文档内容,存储为 XWPFParagraph 列表:

Path msWordPath = Paths.get(WordDocument.output);
XWPFDocument document = new XWPFDocument(Files.newInputStream(msWordPath));
List<XWPFParagraph> paragraphs = document.getParagraphs();
document.close();

验证标题内容和样式:

XWPFParagraph title = paragraphs.get(0);
XWPFRun titleRun = title.getRuns().get(0);
 
assertEquals("Build Your REST API with Spring", title.getText());
assertEquals("009933", titleRun.getColor());
assertTrue(titleRun.isBold());
assertEquals("Courier", titleRun.getFontFamily());
assertEquals(20, titleRun.getFontSize());

为简化,仅验证其他部分内容(样式验证逻辑类似):

assertEquals("from HTTP fundamentals to API Mastery",
  paragraphs.get(1).getText());
assertEquals("What makes a good API?", paragraphs.get(3).getText());
assertEquals(wordDocument.convertTextFileToString
  (WordDocument.paragraph1), paragraphs.get(4).getText());
assertEquals(wordDocument.convertTextFileToString
  (WordDocument.paragraph2), paragraphs.get(5).getText());
assertEquals(wordDocument.convertTextFileToString
  (WordDocument.paragraph3), paragraphs.get(6).getText());

至此可确认 rest-with-spring.docx 生成成功。

6. 总结

本教程介绍了 Apache POI 对 Microsoft Word 格式的支持,详细讲解了生成文档及验证内容的步骤。

所有示例代码可在 GitHub 项目 中找到。


原始标题:Microsoft Word Processing with Apache POI