Java后端使用XWPFDocument生成word文档,踩坑

以下都是借鉴网上内容:
环境 纯后端, java, spring项目 maven管理.

maven内容:

		<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.16</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.3</version></dependency>

运行时候如果报错: XmlOptions.setEntityExpansionLimit ( ) 方法找不到,那就是xmlbeans版本太低 升级以下:
就可以解决找不到方法:问题 如果没报错 ( 就把改依赖忽略),

 	<dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><version>3.1.0</version></dependency>

代码如下 工具类一 :

package com.bsoft.hesp.utils.word;import java.util.*;import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;public class WordExportUtil {private WordExportUtil() {}/*** 替换文档中段落文本** @param document docx解析对象* @param textMap  需要替换的信息集合*/public static void changeParagraphText(XWPFDocument document, Map<String, String> textMap) {//获取段落集合List<XWPFParagraph> paragraphs = document.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {//判断此段落是否需要进行替换String text = paragraph.getText();if (checkText(text)) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {//替换模板原来位置String textValue = changeValue(run.toString(), textMap);if (run.toString().toLowerCase().indexOf("checkbox_") != -1) {// 复选框填充值run.setFontFamily("SimSun");String[] tArr = textValue.split("@@@");for (int i = 0; i < tArr.length; i++) {if (i == 0) {run.setText(tArr[i], 0);} else {run.setText(tArr[i]);}if (i != tArr.length - 1) {run.addBreak();//换行}}} else {run.setText(textValue, 0);}}}}}/*** 复制表头 插入行数据,这里样式和表头一样** @param document    docx解析对象* @param tableList   需要插入数据集合*                    tableIndex表格索引,在word表格对象集合中是第几个表格,从0开始* @param headerIndex 表头的行索引,从0开始*/public static void copyHeaderInsertText(XWPFDocument document, List<Map<String, String>> tableList, String[] fields, int tableindex, int headerIndex) {if (null == tableList || null == fields) {return;}//获取表格对象集合List<XWPFTable> tables = document.getTables();XWPFTableRow copyRow = tables.get(tableindex).getRow(headerIndex);List<XWPFTableCell> cellList = copyRow.getTableCells();if (null == cellList) {return;}//遍历要添加的数据的listfor (int i = 0; i < tableList.size(); i++) {//插入一行XWPFTableRow targetRow = tables.get(tableindex).insertNewTableRow(headerIndex + i);//复制行属性targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());Map<String, String> map = tableList.get(i);// 字段匹配后,插入单元格并赋值for (String field : fields) {int idx = 0;for (Map.Entry<String, String> entry : map.entrySet()) {if (!field.equals(entry.getKey())) continue;XWPFTableCell sourceCell = cellList.get(idx);//插入一个单元格XWPFTableCell targetCell = targetRow.addNewTableCell();//复制列属性targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());//targetCell.setText(entry.getValue());/** XWPFTableCell 无法直接设置字体样式,故换一种方式 **///获取 XWPFTableCell 的CTTcCTTc ctTc = targetCell.getCTTc();//获取 CTPCTP ctP = (ctTc.sizeOfPArray() == 0) ? ctTc.addNewP() : ctTc.getPArray(0);//getParagraph(ctP) 获取 XWPFParagraphXWPFParagraph par = targetCell.getParagraph(ctP);//XWPFRun   设置格式XWPFRun run = par.createRun();String textValue = entry.getValue();// 复选框填充值if (field.toLowerCase().indexOf("checkbox_") != -1) {run.setFontFamily("SimSun");String[] tArr = textValue.split("@@@");for (int j = 0; j < tArr.length; j++) {if (j == 0) {run.setText(tArr[j], 0);} else {run.setText(tArr[j]);}if (j != tArr.length - 1) {run.addBreak();//换行}}} else {run.setText(textValue, 0);}idx++;};}}if (tableList.size() > 0) {List<XWPFTableRow> rows = tables.get(tableindex).getRows();int rowLength = rows.size();deleteTable(tables.get(tableindex), tableList.size() + headerIndex, rowLength);}}/*** 删除表格行** @param table     表格对象* @param fromIndex 从第几行,从0开始* @param toIndex   到第几行,从0开始*/public static void deleteTable(XWPFTable table, int fromIndex, int toIndex) {for (int i = fromIndex; i < toIndex; i++) {table.removeRow(fromIndex);}}/*** 替换表格对象方法** @param document docx解析对象* @param textMap  需要替换的信息集合*/public static void changeTableText(XWPFDocument document, Map<String, String> textMap) {//获取表格对象集合List<XWPFTable> tables = document.getTables();for (int i = 0; i < tables.size(); i++) {//只处理行数大于等于2的表格XWPFTable table = tables.get(i);/*if (table.getRows().size() > 1) {//判断表格是需要替换还是需要插入,判断逻辑有$为替换if (checkText(table.getText())) {List<XWPFTableRow> rows = table.getRows();//遍历表格,并替换模板eachTable(rows, textMap);}}*///判断表格是需要替换还是需要插入,判断逻辑有$为替换if (checkText(table.getText())) {List<XWPFTableRow> rows = table.getRows();//遍历表格,并替换模板eachTable(rows, textMap);}}}/*** 遍历表格,并替换模板** @param rows    表格行对象* @param textMap 需要替换的信息集合*/public static void eachTable(List<XWPFTableRow> rows, Map<String, String> textMap) {for (XWPFTableRow row : rows) {List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {//判断单元格是否需要替换if (checkText(cell.getText())) {List<XWPFParagraph> paragraphs = cell.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {fillCheckBox(run, textMap);}}}}}}public static void fillCheckBox(XWPFRun run, Map<String, String> textMap) {String textValue = changeValue(run.toString(), textMap);if (run.toString().toLowerCase().indexOf("checkbox_") != -1) {// 复选框填充值run.setFontFamily("SimSun");String[] tArr = textValue.split("@@@");for (int i = 0; i < tArr.length; i++) {if (i == 0) {run.setText(tArr[i], 0);} else {run.setText(tArr[i]);}/*if (i != tArr.length - 1) {run.addBreak();//换行}*/}} else {run.setText(textValue, 0);}}/*** 匹配传入信息集合与模板** @param value   模板需要替换的区域* @param textMap 传入信息集合* @return 模板需要替换区域信息集合对应值*/public static String changeValue(String value, Map<String, String> textMap) {Set<Map.Entry<String, String>> textSets = textMap.entrySet();for (Map.Entry<String, String> textSet : textSets) {//匹配模板与替换值 格式${key}String key = "${" + textSet.getKey() + "}";if (value.indexOf(key) != -1) {value = textSet.getValue();}}//模板未匹配到区域替换为空if (checkText(value)) {value = "";}return value;}/*** 判断文本中是否包含$** @param text 文本* @return 包含返回true, 不包含返回false*/public static boolean checkText(String text) {boolean check = false;if (text.indexOf("$") != -1) {check = true;}return check;}
}
package com.bsoft.hesp.utils.word;import org.apache.http.HttpHeaders;
import org.apache.poi.xwpf.usermodel.XWPFDocument;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;/*** Author: * Date: 2023/11/27 15:05**/
public class WordGenerate {/*** word生成* @throws FileNotFoundException*/public static void generateWord(List<Map<String, String>> list, Map<String, String> fileAddress, HttpServletResponse response) throws FileNotFoundException {XWPFDocument document = null;try {for (Map<String, String> tableMap : list) {String classpath = WordGenerate.class.getResource("").getPath();File f = new File(classpath+"/模板20231124.docx");FileInputStream fileInputStream = new FileInputStream(new File(f.getPath()));FileOutputStream fileOutStream = new FileOutputStream("E:\\" + tableMap.get("fileName") + ".docx");try {/**解析docx模板并获取document对象**/document = new XWPFDocument(fileInputStream);/**替换docx table中文本字段**/WordExportUtil.changeTableText(document, tableMap);document.write(fileOutStream);} catch (IOException e) {e.printStackTrace();} finally {if (document != null) {try {document.close();} catch (IOException e) {e.printStackTrace();}}if (null != fileInputStream) {try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}if (null != fileOutStream) {try {fileOutStream.close();} catch (IOException e) {e.printStackTrace();}}}}} catch (Exception e) {e.printStackTrace();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/180187.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Centos查看运行内存大小

在CentOS上&#xff0c;你可以使用以下几种方法来查看内存占用情况&#xff1a; 使用 free 命令&#xff1a; free -h这个命令会显示系统的物理内存和交换空间使用情况&#xff0c;以人类可读的方式显示。 使用 top 命令&#xff1a; top在top命令的输出中&#xff0c;第一…

Django:通过user-agent判断请求是来自移动端还是PC端(电脑端)

第一种思路&#xff1a; 根据博文 Djano的request.META是什么&#xff1f;的研究成果&#xff0c;先判断有无键HTTP_SEC_CH_UA_MOBILE&#xff0c;如果没有&#xff0c;再去按博文 网站如何判断请求是来自手机-移动端还是PC-电脑端&#xff1f;如何让网站能适应不同的客户端&am…

Flink流批一体计算(21):Flink SQL之Flink DDL

目录 执行 CREATE 语句 Python脚本 Java代码 SQL语句 列定义 物理/常规列 元数据列 计算列 WATERMARK PRIMARY KEY PARTITIONED BY AS select_statement Flink SQL是为了简化计算模型、降低您使用Flink门槛而设计的一套符合标准SQL语义的开发语言。 执行 CREATE 语…

freerots启动过程分析(qemu仿真RISC-V架构为例)

1、前言 本文是基于qemu上virt板子适配的freertos系统源码进行讲解qemu安装可参考博客&#xff1a;《qemu源码下载和安装》&#xff1b;freertos移植到qemu上运行可参考博客&#xff1a;《移植freertos到qemu上运行》&#xff1b; 2、汇编代码部分 汇编文件&#xff1a;FreeR…

集成学习的两种常见策略:bagging VS. boosting

chatGPT回答&#xff0c;记在这里。 集成学习是一种通过组合多个弱学习器来构建一个更强大的学习器的方法。其中&#xff0c;bagging和boosting是两种常见的集成学习策略。 一、bagging & boosting 简介 Bagging&#xff08;自助聚集法&#xff09;&#xff1a; Bagging…

Web框架与Django路由层

Web框架 一 web框架 Web框架&#xff08;Web framework&#xff09;是一种开发框架&#xff0c;用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式&#xff0c;也为web行为提供了一套通用的方法。web框架已经实现了很多功能&…

golang面试题:reflect(反射包)如何获取字段tag​?为什么json包不能导出私有变量的tag?

问题 json包里使用的时候&#xff0c;会结构体里的字段边上加tag&#xff0c;有没有什么办法可以获取到这个tag的内容呢&#xff1f; 举例 tag信息可以通过反射&#xff08;reflect包&#xff09;内的方法获取&#xff0c;通过一个例子加深理解。 package mainimport ("…

基于单片机的智能饮水机控制系统(论文+源码)

1. 系统设计 本次智能饮水机控制系统的设计研究一款以STC89C52单片机为核心的智能饮水机控制系统&#xff0c;其主要功能设计如下&#xff1a; 1.该饮水机利用DS18B20数字温度传感器实时采集饮水机内水的温度&#xff0c;其检测温度范围为0-100℃&#xff0c;精度0.1℃&#…

拆解按摩器:有意思的按键与LED控制电路,学习借鉴一下!

拆解 外观和配色个人感觉还行,比较青春 拉开拉链&#xff0c;拆开外面的布面&#xff0c;里面还有一层纱面 按键部分使用魔术贴固定 拆开纱面后&#xff0c;看到里面的结构&#xff0c;整体是一个海绵 可以看到如下&#xff0c;电池&#xff0c;按键板&#xff0c;充电线的三条…

Java 设计模式——建造者模式

目录 1.概述2.结构3.实例3.1.产品类3.2.抽象建造者类3.3.具体建造者类3.4.指挥者类3.5.测试 4.优缺点5.使用场景6.模式扩展7.创建者模式对比 1.概述 建造者模式 (Builder Pattern) 是一种创建型设计模式&#xff0c;用于创建复杂对象。它将对象的构建过程分离成独立的部分&…

单片机开发常见问题集合

文章目录 发送串口数据偶尔丢失字节 发送串口数据偶尔丢失字节 场景&#xff1a; 在STM32单片机中进行串口数据发送&#xff0c;在Linux/Windows上进行串口数据接收&#xff0c;会偶发出现接收到的数据有某些字节丢失。 分析&#xff1a; 在STM32中可以使用printf用于发送串口…

前端 | iframe框架标签应用

文章目录 &#x1f4da;嵌入方式&#x1f4da;图表加载显示&#x1f4da;100%嵌入及滑动条问题&#x1f4da;加载动画保留 前情提要&#xff1a; 计划用iframe把画好的home1.html&#xff08;echarts各种图表组成的html数据大屏&#xff09;嵌入整合到index.html&#xff08;搭…

快速筛出EXCEL行中的重复项

比如A列是一些恶意IP需要导入防火墙&#xff0c;但包括一些重复项&#xff0c;为不产生错误&#xff0c;需要把重复项筛出来&#xff1a; 1、给A列排序&#xff0c;让重复项的内容排在相邻的行 2、在B列中写一个条件函数&#xff1a;IF(A1A2,1,0)&#xff0c;然后下拉至行尾完成…

java设计模式 开闭原则

开闭原则&#xff08;Open-Closed Principle&#xff0c;OCP&#xff09;是面向对象设计中的一个重要原则&#xff0c;它指导着我们如何设计和组织代码&#xff0c;以便使系统在扩展性和可维护性方面更加优秀。 开闭原则的定义是&#xff1a;软件实体&#xff08;类、模块、函数…

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 概述 前述博客讲解了 Web 编程的基本知识&#xff0c;包括 HTML、CSS、JavaScript 三个部分&#xff0c;从这节开始&#xff0c;我们进入实战部分&#xff0c;在实际项目中进一步学习 ESP32-Web 编程。 GPIO &#xff08…

WebGL笔记:图形旋转的原理和实现

旋转 1 &#xff09;旋转的概念 三维物体的旋转要比位移复杂一点&#xff0c;三维物体的旋转需要满足以下条件&#xff1a; 旋转轴旋转方向旋转角度 场景举例 模型站在旋转轴的起点进行旋转模型要往左转还是往右转&#xff0c;就是旋转的方向模型旋转的大小就是旋转角度 2 &…

人工智能_AI服务器安装清华开源_CHATGLM大语言模型_GLM-6B安装部署_人工智能工作笔记0092

看到的这个开源的大模型,很牛,~关键让我们自己也可以部署体验一把了,虽然不知道具体内部怎么构造的但是,也可以自己使用也挺好. 可以部署在自己的机器上也可以部署在云服务器上. 安装以后,是可以使用python代码进行提问,然后返回结果的,这样就可以实现我们自己的chat应用了, …

仿美团外卖源码/在线外卖平台源码PHP/支持多商户+多样化配送费+本土外卖+支持第三方配送

源码简介&#xff1a; 进云仿美团外卖源码&#xff0c;作为外卖平台源码&#xff0c;它不仅支持多商户、多样化配送费、本土外卖&#xff0c;还支持第三方配送。 进云仿美团外卖源码是一个进云源生插件&#xff0c;支持多商户多样化配送费模式本土外卖平台支持第三方配送&…

excel表格在线编辑(开源版)

文章目录 前言一、Luckysheetvue3vite 例子如有启发&#xff0c;可点赞收藏哟~ 前言 本文记录好用的开源在线表格 具体如图显示 另外记录下更名后的univer~&#xff0c;如下图&#xff08;有兴趣可自行详细了解&#xff09; univer 在线思维导图 一、Luckysheet 参考git…

Java Web基础教程

Java Web基础教程 1. Servlet基础 1.1 什么是Servlet Servlet是JavaEE中的标准组件之一&#xff0c;专门用于处理客户端的HTTP请求。并且它必须依赖于Servlet容器&#xff08;Tomcat就是一个标准的Servlet容器&#xff09;才能运行。因为Servlet实例的创建和销毁都是由容器负…