使用 Apache POI + Flying Saucer (推荐)
这是目前最流行、功能最强大的方法之一,它的工作原理是:

- 编写 HTML/CSS: 你创建一个包含样式和内容的 HTML 文件。
- 渲染为 XHTML: Flying Saucer (一个 XHTML 渲染器) 会读取你的 HTML,并将其渲染成一个符合 XHTML 规范的文档模型。
- 转换为 XWPF: Apache POI 的 XWPF (XML Word Processing Format) 组件负责将这个 XHTML 模型中的内容(段落、表格、列表、图片等)写入到
.docx文件的底层 XML 结构中。
优点
- 样式支持强大: 可以使用大部分 CSS 属性来控制 Word 文档的样式,如字体、颜色、边距、背景色、浮动等。
- 功能全面: 支持表格、列表、图片、超链接、页眉页脚等复杂元素。
- 标准技术: Apache POI 是 Java 操作 Office 文档的事实标准,Flying Saucer 是成熟的 XHTML 渲染器,社区活跃,文档丰富。
缺点
- 依赖较多: 需要同时引入
poi-ooxml和flying-saucer等多个库。 - 性能: 对于非常复杂的文档,渲染过程可能会比较耗时。
- CSS 兼容性: 并非所有 CSS 属性都能被完美支持,需要一定的调试。
详细步骤和代码示例
添加 Maven 依赖
在你的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- Apache POI for .docx file creation -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<!-- Flying Saucer for XHTML rendering -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.22</version>
</dependency>
<!-- 如果你只需要生成 Word,可以只用 flying-saucer-core,但 PDF 版本包含了所有核心功能 -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.22</version>
</dependency>
</dependencies>
编写 Java 代码
import org.apache.poi.xwpf.converter.core.XWPFConverterException;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jsoup.Jsoup;
import org.jsoup.helper.W3CDom;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class HtmlToWordWithPoi {
public static void main(String[] args) {
// 1. 准备你的 HTML 内容
// 注意:最好使用完整的 HTML 结构,包括 <html>, <head>, <body>
String htmlContent = "<!DOCTYPE html>"
+ "<html>"
+ "<head>"
+ "<meta charset=\"UTF-8\">"
+ "<style>"
+ " body { font-family: 'Microsoft YaHei', sans-serif; }"
+ " h1 { color: #333; text-align: center; }"
+ " .highlight { background-color: yellow; font-weight: bold; }"
+ " table { border-collapse: collapse; width: 100%; }"
+ " th, td { border: 1px solid #dddddd; text-align: left; padding: 8px; }"
+ " th { background-color: #f2f2f2; }"
+ "</style>"
+ "</head>"
+ "<body>"
+ " <h1>HTML to Word 生成报告</h1>"
+ " <p>这是一个通过 <span class=\"highlight\">Java</span> 从 HTML 生成的 Word 文档。</p>"
+ ""
+ " <h2>员工信息表</h2>"
+ " <table>"
+ " <tr>"
+ " <th>姓名</th>"
+ " <th>职位</th>"
+ " <th>部门</th>"
+ " </tr>"
+ " <tr>"
+ " <td>张三</td>"
+ " <td>软件工程师</td>"
+ " <td>技术部</td>"
+ " </tr>"
+ " <tr>"
+ " <td>李四</td>"
+ " <td>产品经理</td>"
+ " <td>产品部</td>"
+ " </tr>"
+ " </table>"
+ "</body>"
+ "</html>";
// 2. 将 HTML 转换为 XWPFDocument
XWPFDocument document = htmlToXWPFDocument(htmlContent);
// 3. 保存为 .docx 文件
try (OutputStream out = new FileOutputStream("output_from_poi.docx")) {
document.write(out);
System.out.println("Word 文档生成成功: output_from_poi.docx");
} catch (IOException e) {
e.printStackTrace();
} catch (XWPFConverterException e) {
e.printStackTrace();
}
}
/**
* 使用 Flying Saucer 将 HTML 字符串转换为 XWPFDocument 对象
* @param htmlContent HTML 字符串
* @return XWPFDocument 对象
* @throws XWPFConverterException
* @throws IOException
*/
public static XWPFDocument htmlToXWPFDocument(String htmlContent) throws XWPFConverterException, IOException {
// 使用 Jsoup 解析 HTML,使其成为标准的 XHTML
org.jsoup.nodes.Document jsoupDoc = Jsoup.parse(htmlContent);
org.w3c.dom.Document w3cDoc = new W3CDom().fromJsoup(jsoupDoc);
// 创建一个空的 Word 文档
XWPFDocument document = new XWPFDocument();
// 设置转换选项
XHTMLOptions options = XHTMLOptions.create();
// 如果需要处理图片,可以设置图片根目录
// options.setExtractor(new ThreadLocalFSImageExtractor(new File("C:/path/to/images")));
// 执行转换
XHTMLConverter.getInstance().convert(w3cDoc, document, options);
return document;
}
}
使用 docx4j
docx4j 是另一个功能强大的 Java 库,专门用于处理 Office Open XML 格式(即 .docx, .xlsx, .pptx),它也支持从 HTML 转换。
优点
- 专注: 专门为处理 Office 文档设计,API 更贴近 Word 的内部结构。
- 功能强大: 对 Word 的高级特性(如复杂样式、图表、内容控件等)支持非常好。
- 性能: 通常比 POI+Flying Saucer 的组合性能更好。
缺点
- 学习曲线: API 相对复杂,不如 POI+Flying Saucer 的“HTML 黑盒”方式直观。
- 依赖: 需要引入
docx4j的核心库和org.jsoup用于解析 HTML。
详细步骤和代码示例
添加 Maven 依赖
<dependencies>
<!-- docx4j core -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-core</artifactId>
<version>11.4.4</version>
</dependency>
<!-- docx4j - OOXML import/export -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-ooxml</artifactId>
<version>11.4.4</version>
</dependency>
<!-- For HTML parsing -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>
</dependencies>
编写 Java 代码
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.File;
import java.io.FileOutputStream;
public class HtmlToWordWithDocx4j {
public static void main(String[] args) throws Exception {
// 1. 准备 HTML 内容 (与方法一相同)
String htmlContent = "<!DOCTYPE html>"
+ "<html><head><style>"
+ "body { font-family: 'Microsoft YaHei'; }"
+ "h1 { color: blue; }"
+ "p { font-size: 12pt; }"
+ "table { border: 1px solid black; }"
+ "th, td { border: 1px solid black; padding: 5px; }"
+ "</style></head>"
+ "<body>"
+ " <h1>docx4j 生成示例</h1>"
+ " <p>这是一个使用 <b>docx4j</b> 生成的段落。</p>"
+ " <table><tr><th>Header</th><td>Data</td></tr></table>"
+ "</body></html>";
// 2. 创建 Word 包
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
// 3. 获取主文档部分
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
// 4. 使用 Jsoup 解析 HTML
Document doc = Jsoup.parse(htmlContent);
Element body = doc.body();
// 5. 递归地将 HTML 元素转换为 Word 内容
htmlToWord(body, documentPart);
// 6. 保存文件
File output = new File("output_from_docx4j.docx");
wordMLPackage.save(output);
System.out.println("Word 文档生成成功: output_from_docx4j.docx");
}
private static void htmlToWord(Element element, MainDocumentPart documentPart) throws Exception {
// 这里是一个简化的转换逻辑,实际项目中需要更复杂的处理
// docx4j 提供了更高级的转换器,但手动转换可以更好地控制细节
String tagName = element.tagName().toLowerCase();
String text = element.ownText();
if (tagName.equals("p") || tagName.equals("div")) {
// 创建段落
org.docx4j.wml.P p = docx4j.XmlUtils.deepCopy(documentPart.getContents().getBody().getPArray()[0]);
org.docx4j.wml.R run = (org.docx4j.wml.R) p.getContent().get(0);
((org.docx4j.wml.Text) run.getContent().get(0)).setValue(text);
documentPart.getContents().getBody().addObject(p);
} else if (tagName.equals("h1")) {
// 创建标题 (简化处理,实际应创建不同级别的标题)
org.docx4j.wml.P p = docx4j.XmlUtils.deepCopy(documentPart.getContents().getBody().getPArray()[0]);
org.docx4j.wml.R run = (org.docx4j.wml.R) p.getContent().get(0);
((org.docx4j.wml.Text) run.getContent().get(0)).setValue(text);
// 设置标题样式... (需要更复杂的代码)
documentPart.getContents().getBody().addObject(p);
} else if (tagName.equals("table")) {
// 创建表格... (逻辑更复杂)
System.out.println("表格转换逻辑需要进一步实现");
}
// ... 其他标签处理
}
}
注意: 上面的
docx4j示例是一个简化的手动转换过程。docx4j官方也提供了更高级的HtmlImporter,但使用起来可能不如 POI+Flying Saucer 直接,对于复杂需求,建议查阅docx4j的官方文档。
使用 iText (不推荐)
iText 是一个著名的 PDF 库,它也支持操作 Word 文档,但其 Word 支持能力远不如 PDF,它更适合在已有 Word 模板的基础上进行内容填充,而不是从零开始用 HTML 生成。

为什么不推荐?
- 功能有限: 对 Word 文档的样式和布局支持非常弱,很多 HTML/CSS 特性无法实现。
- 易用性差: API 设计不友好,操作复杂。
- 已过时: iText 5 的 Word 支持基于旧的
.doc格式,非常陈旧,iText 7 的 Word 支持有所改善,但仍不是首选。
除非你有非常特殊的需求(比如在 PDF 和 Word 之间共享大量底层代码),否则强烈不推荐使用 iText 来生成 Word。
总结与选择建议
| 特性 | Apache POI + Flying Saucer | docx4j | iText |
|---|---|---|---|
| 易用性 | 高 (HTML 黑盒,简单直接) | 中 (需要理解 Word 结构) | 低 |
| 样式支持 | 强 (CSS 支持) | 强 (更接近 Word 原生样式) | 弱 |
| 功能全面性 | 强 (表格、列表、图片等) | 非常强 (支持高级 Word 特性) | 弱 |
| 性能 | 中等 | 好 | 中等 |
| 适用场景 | 绝大多数从 HTML 生成 Word 的场景,特别是对样式有要求的报表、合同等。 | 需要精细控制 Word 文档结构,或利用其高级功能的场景。 | 不推荐,除非已有其他项目依赖且需求简单。 |
最终建议:
- 首选方案: 如果你只是想把一个设计好的 HTML 页面转换成 Word,并且希望样式能最大限度地保留,请使用 Apache POI + Flying Saucer,这是最平衡、最省心的选择。
- 高级方案: 如果你需要对 Word 文档进行像素级的控制,或者需要生成包含复杂内容控件、引用等高级特性的文档,可以考虑 docx4j,但需要投入更多学习成本。
- 避免方案: 尽量避免使用 iText 来处理 Word 文档生成。
