Let's go

POI 替换word中的表格excel内容

方法一、

注意:1.替换文本的占位符为 ${xxx} ,在word中填写的时候,需要一次性输入,最好是在text编辑器中写好,然后复制过去。否则可能会被识别为 ${,xxx,}  ,就无法替换了。 

复制代码
package org.jeecg.modules.utils;
 
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
@Slf4j
public class WordExportUtil {
 
    /**
     * @param inputStream 模板文件流
     * @param textMap     待写入字符map
     * @return 新文件流
     */
    public static InputStream changWord(InputStream inputStream, Map<String, String> textMap) {
        try {
            //读取模板信息,替换指定位置字符
            XWPFDocument document = new XWPFDocument(inputStream);
            if (!WordExportUtil.changeText(document, textMap)) {
                return null;
            }
            //新文件(XWPFDocument)转成文件流
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            document.write(byteArrayOutputStream);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            return byteArrayInputStream;
        } catch (Exception e) {
            log.warn("word写入数据异常: "+ JSONUtil.toJsonStr(textMap));
            log.warn(e.getMessage());
        }
        return null;
    }
    /**
     * 替换文本     *
     * @param document docx解析对象
     * @param valueMap  待写入字符map
     */
    public static Boolean changeText(XWPFDocument document, Map<String, String> valueMap) {
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        if (CollectionUtil.isEmpty(paragraphs)) {
            return false;
        }
        for (XWPFParagraph paragraph : paragraphs) {
            String text = paragraph.getText();
            if (StringUtils.isBlank(text)) {
                continue;
            }
            if (text.indexOf("$") == -1) {
                continue;
            }
            List<XWPFRun> runs = paragraph.getRuns();
            for (XWPFRun run : runs) {
                String value = setWordValue(run.toString(), valueMap);
                run.setText(value, 0);
            }
        }
        List<XWPFTable> tables = document.getTables();
        if (CollectionUtil.isEmpty(tables)) {
            return false;
        }
        for (XWPFTable table : tables) {
            String text = table.getText();
            if (StringUtils.isBlank(text)) {
                continue;
            }
            if (text.indexOf("$") == -1) {
                continue;
            }
            //String value = setWordValue(table.getText(), valueMap);
            changeTableMessage(valueMap,table,false,null);
        }
        return true;
    }
    /**
     * word中的表格文字替换
     */
    public static void changeTableMessage(Map<String, String> params, XWPFTable table, boolean isBold, Integer fontSize) {
        int count = table.getNumberOfRows();//获取table的行数
        for (int i = 0; i < count; i++) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {//遍历每行的值并进行替换
                System.out.println(cell.getText());
                for (Map.Entry<String, String> e : params.entrySet()) {
                    if (cell.getText().equals("${" + e.getKey() + "}")) {
                        XWPFParagraph newPara = new XWPFParagraph(cell.getCTTc().addNewP(), cell);
                        XWPFRun r1 = newPara.createRun();
                        r1.setBold(isBold);
                        if (fontSize != null) {
                            r1.setFontSize(fontSize);
                        }
                        r1.setText(e.getValue());
                        cell.removeParagraph(0);
                        cell.setParagraph(newPara);
                    }
                }
            }
        }
    }
    /**
     * 匹配传入信息集合与模板
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String setWordValue(String value, Map<String, String> textMap) {
        Set<Map.Entry<String, String>> textSets = textMap.entrySet();
        for (Map.Entry<String, String> textSet : textSets) {
            String key = "${" + textSet.getKey() + "}";
            if (value.indexOf(key) != -1) {
                value = textSet.getValue();
            }
        }
        return value;
    }
}
复制代码

方法二、

保持原有的样式

注意:1.表格内部参数,尽量不要一个格子有多个变量,尽可能的拆分。同时单元格中尽量不要主动回车换行。

复制代码
   public static void changeTableMessage(Map<String, String> valueMap, XWPFTable table) {
        int count = table.getNumberOfRows();//获取table的行数
        for (int i = 0; i < count; i++) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {//遍历每行的值并进行替换
                    if (cell.getText().indexOf("$") == -1) {
                        continue;
                    }
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        String text = paragraph.getText();
                        if (StringUtils.isBlank(text)) {
                            continue;
                        }
                        if (text.indexOf("$") == -1) {
                            continue;
                        }
                        List<XWPFRun> runs = paragraph.getRuns();
                        for (XWPFRun run : runs) {
                            String value = setWordValue(run.toString(), valueMap);
                            run.setText(value, 0);
                        }
                    }
            }
        }
    }
    /**
     * 匹配传入信息集合与模板
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String setWordValue(String value, Map<String, String> textMap) {
        Set<Map.Entry<String, String>> textSets = textMap.entrySet();
        for (Map.Entry<String, String> textSet : textSets) {
            String key = "${" + textSet.getKey() + "}";
            if (value.indexOf(key) != -1) {
                value = value.replace(key,textSet.getValue());
            }
        }
        return value;
    }
复制代码

 

方法三、

复制代码
        Map<String, String> map =new HashMap<>();//map的key的为模板中替换的对象,value为替换的值
        map.put("aaa","122");
        InputStream is =this.getClass().getResourceAsStream("/demo.docx");
        XWPFDocument document =new XWPFDocument(is);
        Set<String> set = map.keySet();
        Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();//获取word段落
        while(itPara.hasNext()){
            XWPFParagraph paragraph = itPara.next();//获取段落
            Iterator<String> iterator = set.iterator();
            while(iterator.hasNext()){

                String key = iterator.next();////获取key
                List<XWPFRun> run = paragraph.getRuns();//获取⾏
                for(int i =0; i < run.size(); i++){
                    //如果key等于word中的值,就替换
                    if(run.get(i).getText(run.get(i).getTextPosition())!=null&&
                            run.get(i).getText(run.get(i).getTextPosition()).equals(key)){
                        run.get(i).setText(map.get(key),0);//0 指从第⼀个字符开始替换
                    }
                }
            }
        }
        //导出⽂件存在本地

        ByteArrayOutputStream byteArrayOutputStream =new ByteArrayOutputStream();
        document.write((OutputStream) byteArrayOutputStream);
        String filePath ="D://uploads/demo/";//存储⽬的地
        String fileName ="demo";//⽂件名称
        File file =new File(filePath + fileName +".docx");
        //如果不存在⽂件夹则创建
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        FileOutputStream outputStream =new FileOutputStream(filePath + fileName +".docx");
        outputStream.write(byteArrayOutputStream.toByteArray());
        outputStream.flush();
        outputStream.close();

        //2.表格
        Map<String, String> map =new HashMap<>();

        map.put("aaa","122");//map的 key为模板中替换的对象,value为替换的值
        InputStream is =this.getClass().getResourceAsStream("/demo.docx");
        WPFDocument document =new XWPFDocument(is);
        List<XWPFTable> tables = document.getTables();//获取表格
        Set<String> set = map.keySet();
        for(XWPFTable table : tables){
            List<XWPFTableRow> rows = table.getRows();//获取⾏
            for(XWPFTableRow row : rows){
                List<XWPFTableCell> cells = row.getTableCells();//获取单元格
                for(XWPFTableCell cell : cells){
                    for(String s : set){
                        if(cell.getText().contains(s)){
                            String replace ="";
                            replace = cell.getText().replace(s, map.get(s));
                            cell.removeParagraph(0);
                            XWPFParagraph para = cell.addParagraph();
                            para.setSpacingBetween(1);
                            cell.setText(replace);
                        }
                    }
                }
            }
        }
        ByteArrayOutputStream byteArrayOutputStream =new ByteArrayOutputStream();
        document.write((OutputStream) byteArrayOutputStream);
        String filePath ="D://uploads/demo/";//
        String fileName ="demo";//
        File file =new File(filePath + fileName +".docx");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        FileOutputStream outputStream =new FileOutputStream(filePath + fileName +".docx");
        outputStream.write(byteArrayOutputStream.toByteArray());
        outputStream.flush();
        outputStream.close();

        //3.表格中的段落(可通⽤普通表格),精髓在这,其他与上同
        for(XWPFTable table : tables){
            List<XWPFTableRow> rows = table.getRows();//
            for(XWPFTableRow row : rows){
                List<XWPFTableCell> cells = row.getTableCells();//
                for(XWPFTableCell cell : cells){
                    int a =0;
                    String replace = cell.getText();
                    for(String s : set){
                        if(cell.getText().contains(s)){
                            a =1;
                            replace = replace.replace(s, map.get(s));
                        }
                    if(a ==1){
                        int size = cell.getParagraphs().size();
                        for(int i =0; i < size; i++){
                            cell.removeParagraph(0);
                        }
                        String[] jdcl = replace.split("\\|");
                        for(int i =0; i < jdcl.length; i++){
                            XWPFParagraph xwpfParagraph = cell.addParagraph();//
                            XWPFRun run = xwpfParagraph.createRun();//
                            run.setText(jdcl[i]);
                        }
                    }
                }
            }
        }
    }

    //4.页眉页脚
    //页眉与页脚的处理⽅式其实与上述内容都是类似的,只是获取word不同位置的内容⽽已
    //页眉
    Map<String, String> map =new HashMap<>();
    map.put("${a}","123");
    InputStream is =this.getClass().getResourceAsStream("/demo.docx");
    XWPFDocument document =new XWPFDocument(is);
    List<XWPFHeader> headerList = document.getHeaderList();
    for(XWPFHeader xwpfHeader : headerList){
        List<XWPFParagraph> paragraphs = xwpfHeader.getParagraphs();
        for(XWPFParagraph paragraph : paragraphs){
            List<XWPFRun> runs = paragraph.getRuns();
            for(int i =0; i < runs.size(); i++){
                for(String s : set){
                    if(runs.get(i).getText(runs.get(i).getTextPosition())!=null&&
                            runs.get(i).getText(runs.get(i).getTextPosition()).contains(s)){
                        String replace = runs.get(i).getText(runs.get(i).getTextPosition()).replace(s, map.get(s));
                        runs.get(i).setText(replace,0);
                    }
                }
            }
        }
    }

    //页脚
    Map<String, String> map =new HashMap<>();
       map.put("${a}","123");
    InputStream is =this.getClass().getResourceAsStream("/demo.docx");
    XWPFDocument document =new XWPFDocument(is);
    List<XWPFFooter> footerList = document.getFooterList();
    for(XWPFFooter xwpfFooter : footerList){
        List<XWPFParagraph> paragraphs = xwpfFooter.getParagraphs();
        for(XWPFParagraph paragraph : paragraphs){
            List<XWPFRun> runs = paragraph.getRuns();
            for(int i =0; i < runs.size(); i++){
                for(String s : set){
                    if(runs.get(i).getText(runs.get(i).getTextPosition())!=null&&
                            runs.get(i).getText(runs.get(i).getTextPosition()).contains(s)){
                        String replace = runs.get(i).getText(runs.get(i).getTextPosition()).replace(s, map.get(s));
                        runs.get(i).setText(replace,0);
                    }
                }
            }
        }
    }
复制代码

 

 

 

借鉴博客:https://blog.csdn.net/yyfjm1994/article/details/118547570?spm=1001.2014.3001.5502

https://wenku.baidu.com/view/d192a52b7fd184254b35eefdc8d376eeaeaa17fa.html

 

posted @   chenze  阅读(1402)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
有事您Q我
点击右上角即可分享
微信分享提示