替换MicrosoftWord中的字段

最近在开发中遇到一个客户提的需求:Word模板定制,就是说上传一个Word文档,以后就从这个文档进行数据的套打。

逛了一圈发现哪种实现方案都不是太完美。

方案一:

POI 实现Word替换书签_poi 替换word书签-CSDN博客 这个方案实现了使用书签进行替换,但最后格式也被消除了。

方案二:

POI 实现Word替换文本2种情况(正常文本、表格文本)_poi替换word内容-CSDN博客 这个方案实现了使用关键字进行替换,是可行的。但我觉得怪怪的,输入关键字的时候必须保证一次性输入,虽然不是什么难事,但只能习惯了就好。

方案三:

使用Spire.Doc for Java 可以看这篇
Java 替换 Word 书签内容

这个我也验证了是可行的,但是有个缺点就是《收费》白嫖党的大失败。

当然你也可以使用免费版,然后会出现这个

你也可以使用技术手段对生成后的文件进行二次编辑。

哎。。。。都太不好使最后我自己结合GPT还有方案二搓了一个,能实现doc 和 docx文件的关键字替换。

迫不得已方案四:

依赖

<!-- docx & doc 文件处理依赖 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.3</version>
</dependency>
<!--  junit  -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- hutool工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.22</version>
</dependency>
</dependencies>

自己写的工具类:
 

package com.mrzeng.code;

import cn.hutool.core.util.StrUtil;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.CharacterRun;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.*;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Microsoft Word Util
 */
public class MicrosoftWordUtil {

    /**
     * docx 文件替换 ${text}
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void replaceDocxFields(Map<String, String> textMap, XWPFDocument document) {
        for (Map.Entry<String, String> entry : textMap.entrySet()) {
            String placeholder = "${" + entry.getKey() + "}";
            String replacement = entry.getValue();
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                for (XWPFRun run : paragraph.getRuns()) {
                    String text = run.getText(0);
                    if (text != null && text.contains(placeholder)) {
                        text = text.replace(placeholder, replacement);
                        run.setText(text, 0);
                    }
                }
            }
        }
        changeTable(document, textMap);
    }


    /**
     * doc 文件替换 ${text}
     *
     * @param document doc解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void replaceDocFields(Map<String, String> textMap, HWPFDocument document) {
        Range range = document.getRange();

        for (Map.Entry<String, String> entry : textMap.entrySet()) {
            String placeholder = "${" + entry.getKey() + "}";
            String replacement = entry.getValue();

            for (int i = 0; i < range.numParagraphs(); i++) {
                Paragraph paragraph = range.getParagraph(i);
                for (int j = 0; j < paragraph.numCharacterRuns(); j++) {
                    CharacterRun run = paragraph.getCharacterRun(j);
                    String text = run.text();
                    if (text.contains(placeholder)) {
                        text = text.replace(placeholder, replacement);
                        run.replaceText(text, false);
                    }
                }
            }
        }
    }

    /**
     * docx 替换表格对象方法
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    private static void changeTable(XWPFDocument document, Map<String, String> textMap) {
        // 获取表格对象集合
        List<XWPFTable> tables = document.getTables();
        for (XWPFTable table : tables) {
            // 判断表格内容是否可以替换
            String cellText = table.getText();
            if (StrUtil.isNotBlank(cellText) && cellText.contains("${")) {
                List<XWPFTableRow> rows = table.getRows();
                // 遍历表格,并替换模板
                eachTable(rows, textMap);
            }
        }
    }

    /**
     * docx 遍历表格
     *
     * @param rows    表格行对象
     * @param textMap 需要替换的信息集合
     */
    private static void eachTable(List<XWPFTableRow> rows, Map<String, String> textMap) {
        for (XWPFTableRow row : rows) {
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                // 判断单元格内容是否可以替换
                String cellText = cell.getText();
                if (StrUtil.isNotBlank(cellText) && cellText.contains("${")) {
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();
                    for (XWPFParagraph paragraph : paragraphs) {
                        List<XWPFRun> runs = paragraph.getRuns();
                        for (XWPFRun run : runs) {
                            run.setText(changeValue(run.toString(), textMap), 0);
                        }
                    }
                }
            }
        }
    }

    /**
     * docx 匹配传入信息集合与模板
     *
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    private static String changeValue(String value, Map<String, String> textMap) {
        Set<Entry<String, String>> textSets = textMap.entrySet();
        for (Entry<String, String> textSet : textSets) {
            // 匹配模板与替换值 格式${key}
            String key = "${" + textSet.getKey() + "}";
            if (value.contains(key)) {
                value = value.replace(key, textSet.getValue());
            }
        }
        return value;
    }

}

测试用的测试类:

import com.mrzeng.code.MicrosoftWordUtil;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class ReplaceWordTest {


    /**
     * 测试doc
     *
     * @throws IOException
     */
    @Test
    public void DocReplaceWordsTest() throws IOException {
        FileInputStream fileInputStream = new FileInputStream("input.doc");
        HWPFDocument document = new HWPFDocument(fileInputStream);
        Map<String, String> bookTagMap = new HashMap<>();
        bookTagMap.put("school", "清华大学");
        bookTagMap.put("name", "张三");
        MicrosoftWordUtil.replaceDocFields(bookTagMap, document);

        // 保存文档到 output.docx
        FileOutputStream fileOutputStream = new FileOutputStream("output.doc");
        document.write(fileOutputStream);
    }

    /**
     * 测试docx
     *
     * @throws IOException
     */
    @Test
    public void DocxReplaceWordsTest() throws IOException {
        FileInputStream fileInputStream = new FileInputStream("input.docx");
        XWPFDocument document = new XWPFDocument(fileInputStream);
        Map<String, String> bookTagMap = new HashMap<>();
        bookTagMap.put("school", "清华大学");
        bookTagMap.put("name", "张三");
        MicrosoftWordUtil.replaceDocxFields(bookTagMap, document);

        // 保存文档到 output.docx
        FileOutputStream fileOutputStream = new FileOutputStream("output.docx");
        document.write(fileOutputStream);
    }
}

最后测试需要的word文档中的内容可以参考图片:

这个现在也只能这样了,如果哪天有新的想法再说吧。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值