2个word内容合并

要在Java中实现将两个Word文档的内容合并,可以使用Apache POI库来操作Word文档。
下面2个word合并包括以下内容的合并和处理:

1、段落、标题合并以及样式处理

2、表格合并以及样式处理

3、单元个内容样式处理

4、带word模板占位符内容处理

步骤:

  1. 使用Apache POI读取两个Word文档。
  2. 将第二个文档的内容追加到第一个文档的末尾。
  3. 保存合并后的Word文档。

依赖配置:

首先,需要在项目中添加Apache POI相关的依赖。如果使用Maven,可以在pom.xml文件中加入以下依赖:

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>

代码实现:

java 复制代码
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());

        // 复制段落中的每个run
        for (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);
        }
    }

}

说明:

  1. XWPFDocument :用于读取和写入Word文档(.docx格式)。我们首先通过FileInputStream读取Word文档。
  2. mergeDocuments:该方法将第二个Word文档的所有段落复制到第一个文档中。我们获取第二个文档的所有段落,并将其逐个添加到第一个文档。
  3. XWPFParagraph :表示Word文档中的一个段落。每个段落包含多个"运行"(XWPFRun),每个"运行"代表文档中的一部分文本。
  4. XWPFRun:表示段落中的一段文本,可以设置文本的样式(如字体、大小、加粗、斜体等)。

注意:

  1. 合并逻辑:本例中只是简单地将第二个文档的所有段落复制到第一个文档。你可以根据需求修改合并的细节(如按页、按段落或按表格等方式进行合并)。
  2. 合并样式:此示例中也将复制了文本的样式(如字体、大小、加粗等)。如果需要更复杂的样式保留,可以根据具体的需求进行调整。
  3. 处理表格、图片等:如果文档中包含表格或图片,你可能需要额外的逻辑来处理这些内容。

结果:

运行以上代码后,你将得到一个新的Word文档,内容包含了两个原始文档的所有内容。

相关推荐
李慕婉学姐4 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆5 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin6 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20056 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉6 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国6 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882486 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈7 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_997 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹7 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理