要在Java中实现将两个Word文档的内容合并,可以使用Apache POI库来操作Word文档。
下面2个word合并包括以下内容的合并和处理:
1、段落、标题合并以及样式处理
2、表格合并以及样式处理
3、单元个内容样式处理
4、带word模板占位符内容处理
步骤:
- 使用Apache POI读取两个Word文档。
- 将第二个文档的内容追加到第一个文档的末尾。
- 保存合并后的Word文档。
依赖配置:
首先,需要在项目中添加Apache POI相关的依赖。如果使用Maven,可以在pom.xml
文件中加入以下依赖:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.21</version></dependency><!-- Apache POI for Excel --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency><!-- Apache POI for Word --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId><version>4.1.2</version></dependency><!-- Apache POI dependencies --><dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><version>3.1.0</version></dependency>
代码实现:
package com.meritdata.ddc.common.util;import org.apache.poi.xwpf.usermodel.*;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;/*** @author dongxiajun* @since 2024-11-14 15:15*/
public class WordMerger {/*** 合并两个Word文档,将第二个文件合并到第一个文件中** @param firstFile 第一个文件* @param secondStream 上传的文件* @param outputFile 输出文件* @throws IOException IOException*/public static void mergeWordDocuments(String firstFile, InputStream secondStream, String outputFile) throws IOException {// 使用 try-with-resources 自动关闭资源try (FileInputStream fis1 = new FileInputStream(firstFile);FileOutputStream out = new FileOutputStream(outputFile)) {// 加载第一个文档XWPFDocument doc1 = new XWPFDocument(fis1);// 加载第二个文档XWPFDocument doc2 = new XWPFDocument(secondStream);// 合并文档appendDocument(doc1, doc2);// 保存合并后的文档doc1.write(out);}}/*** 合并两个Word文档,将第二个文件合并到第一个文件中** @param firstFile 第一个文件* @param secondFile 第二个文件* @param outputFile 输出文件* @throws IOException IOException*/public static void mergeWordDocuments(String firstFile, String secondFile, String outputFile) throws IOException {// 使用 try-with-resources 自动关闭资源try (FileInputStream fis1 = new FileInputStream(firstFile);FileInputStream fis2 = new FileInputStream(secondFile);FileOutputStream out = new FileOutputStream(outputFile)) {// 加载第一个文档XWPFDocument doc1 = new XWPFDocument(fis1);// 加载第二个文档XWPFDocument doc2 = new XWPFDocument(fis2);// 合并文档appendDocument(doc1, doc2);// 保存合并后的文档doc1.write(out);}}public static void appendDocument(XWPFDocument doc1, XWPFDocument doc2) {// 获取第二个文档的所有部分,保持顺序合并for (IBodyElement element : doc2.getBodyElements()) {// 根据元素的类型进行不同的处理if (element instanceof XWPFParagraph) {XWPFParagraph paragraph = (XWPFParagraph) element;XWPFParagraph newParagraph = doc1.createParagraph();copyParagraph(paragraph, newParagraph);} else if (element instanceof XWPFTable) {XWPFTable table = (XWPFTable) element;XWPFTable newTable = doc1.createTable();copyTable(table, newTable);}}}private static void copyParagraph(XWPFParagraph source, XWPFParagraph target) {// 只复制段落的布局属性(例如对齐、缩进、行距等),但不包括段落样式(避免改变标题级别)target.getCTP().setPPr(source.getCTP().getPPr());// 复制对齐方式、缩进、行间距等样式target.setAlignment(source.getAlignment());target.setVerticalAlignment(source.getVerticalAlignment());target.setIndentationLeft(source.getIndentationLeft());target.setIndentationRight(source.getIndentationRight());target.setIndentationFirstLine(source.getIndentationFirstLine());target.setSpacingBefore(source.getSpacingBefore());target.setSpacingAfter(source.getSpacingAfter());target.setSpacingBetween(source.getSpacingBetween());// 复制段落中的每个runfor (XWPFRun run : source.getRuns()) {XWPFRun newRun = target.createRun();newRun.setText(run.text());// 复制格式newRun.setBold(run.isBold());newRun.setItalic(run.isItalic());newRun.setUnderline(run.getUnderline());newRun.setColor(run.getColor());newRun.setFontSize(run.getFontSize());newRun.setFontFamily(run.getFontFamily());}if (source.getStyle() != null) {target.setStyle(source.getStyle());}}// 复制源表格到目标表格,包括其行和单元格的样式和内容private static void copyTable(XWPFTable source, XWPFTable target) {// 删除目标表格中的默认创建的第一行,确保从空状态开始复制target.removeRow(0);// 遍历源表格的每一行for (XWPFTableRow sourceRow : source.getRows()) {// 在目标表格中创建新行XWPFTableRow newTableRow = target.createRow();// 复制源行的样式和内容到目标新行copyTableRow(sourceRow, newTableRow);}}// 将源表格行的样式和内容复制到目标表格行private static void copyTableRow(XWPFTableRow source, XWPFTableRow target) {// 复制行的样式属性target.getCtRow().setTrPr(source.getCtRow().getTrPr());// 遍历源行的每一个单元格for (int i = 0; i < source.getTableCells().size(); i++) {XWPFTableCell sourceCell = source.getCell(i);XWPFTableCell targetCell;// 如果目标行的单元格还不够,则创建新单元格if (i < target.getTableCells().size()) {targetCell = target.getCell(i);} else {targetCell = target.addNewTableCell();}String text = source.getCell(0).getText();if (text.contains("{{$fe")) {// 复制单元格的样式属性targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());targetCell.setText(sourceCell.getText());} else {// 复制单元格的样式和内容copyTableCell(sourceCell, targetCell);}}}// 将源单元格的样式和内容复制到目标单元格private static void copyTableCell(XWPFTableCell source, XWPFTableCell target) {// 复制单元格的样式属性target.getCTTc().setTcPr(source.getCTTc().getTcPr());// 清除目标单元格的段落target.getParagraphs().clear();// 复制每个段落for (XWPFParagraph sourceParagraph : source.getParagraphs()) {XWPFParagraph targetParagraph = target.addParagraph();copyParagraph(sourceParagraph, targetParagraph);}}}
说明:
XWPFDocument
:用于读取和写入Word文档(.docx格式)。我们首先通过FileInputStream
读取Word文档。mergeDocuments
:该方法将第二个Word文档的所有段落复制到第一个文档中。我们获取第二个文档的所有段落,并将其逐个添加到第一个文档。XWPFParagraph
:表示Word文档中的一个段落。每个段落包含多个“运行”(XWPFRun
),每个“运行”代表文档中的一部分文本。XWPFRun
:表示段落中的一段文本,可以设置文本的样式(如字体、大小、加粗、斜体等)。
注意:
- 合并逻辑:本例中只是简单地将第二个文档的所有段落复制到第一个文档。你可以根据需求修改合并的细节(如按页、按段落或按表格等方式进行合并)。
- 合并样式:此示例中也将复制了文本的样式(如字体、大小、加粗等)。如果需要更复杂的样式保留,可以根据具体的需求进行调整。
- 处理表格、图片等:如果文档中包含表格或图片,你可能需要额外的逻辑来处理这些内容。
结果:
运行以上代码后,你将得到一个新的Word文档,内容包含了两个原始文档的所有内容。