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
作者:chenze 出处:https://www.cnblogs.com/chenze-Index/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律