如何使用EasyExcel生成多列表组合填充的复杂Excel示例
作者:Funky_oaNiu
- 一、(需求)生成的表格效果:
- 二、搞一个模板文件
- 三、建立对应的表格实体类
- 四、开始填充
- 五、Vue3前端发起请求下载
- 六、官方文档及AI问答
一、(需求)生成的表格效果:
其中只有顶部日期、中间表格数据、底部总计数据,是通过模板填充的
表头、绿色区域、列名、背景颜色、四个表格的结构是模板中定义好的
本文主要可学习如何填充数据

二、搞一个模板文件
这模板文件是自己编写的,占位符使用{xx}的形式,注意观察一下表格和外部的站位符区别,表格是{data1.xxx}这种形式,用来标识不同表格

三、建立对应的表格实体类
@Data
public class FillData {private String name;private double number;private Date date;
}
四、开始填充
这里是SpringBoot项目,写在Controller里的,仔细看代码注释,这里就不过多描述了
@Operation(summary = "导出excel")
@GetMapping("/export-excel")
public void exportExcel(PsbLoc psbLoc, HttpServletResponse response) throws IOException {// 读取资源文件(这样打成jar模板文件也在里面,防止模板文件被修改导致功能不可用,文件是在src/main/resources/excelTemplates下的)ClassPathResource resource = new ClassPathResource("excelTemplates"+File.separator+"productReceiveSendTemplate.xlsx");// 组织并填充模板数据ByteArrayOutputStream byteArrayOutputStream = compositeFill(resource.getInputStream());// 这里文件名不起作用是因为前端是写死的String fileName = "多列表" + System.currentTimeMillis() + ".xlsx";// 设置响应头,告诉浏览器这是一个下载的文件,这里文件名response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");// 将文件内容写入响应输出流,浏览器可以直接触发下载response.getOutputStream().write(byteArrayOutputStream.toByteArray());response.getOutputStream().flush();
}private ByteArrayOutputStream compositeFill(InputStream templateInputStream) throws IOException {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 使用EasyExcel的模板填充功能,在这里指定合并单元格,这里应该是easyExcel的bug,第一列无法合并,其他列都可以,所以第一列单独用原生poi进行合并try (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream).withTemplate(templateInputStream)// 这里的参数就是圈了个合并区域,在这个正方形内的单元格都会合并,要注意索引是从0开始的,并且区域内不能存在已经合并的单元格否则报错.registerWriteHandler(new OnceAbsoluteMergeStrategy(2, 14, 9, 9)).registerWriteHandler(new OnceAbsoluteMergeStrategy(15, 27, 9, 9)).build()) {WriteSheet writeSheet = EasyExcel.writerSheet().build();// 防止上面两个表格覆盖下面两个表格,每一行都采用新增一行的方式FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();// 使用模板填充,必须使用FillWrapper,这是官方要求,并且每行两个表格只能有一个表格设置增行,否则会存在一个表格有空行,这里是造的测试数据excelWriter.fill(new FillWrapper("data1", makeTestData(1)), fillConfig, writeSheet);excelWriter.fill(new FillWrapper("data2", makeTestData(2)), writeSheet);excelWriter.fill(new FillWrapper("data3", makeTestData(3)), fillConfig, writeSheet);excelWriter.fill(new FillWrapper("data4", makeTestData(4)), writeSheet);// 设置表格外的填充数据,例如总计、日期等数据HashMap<String, Object> map = new HashMap<>();map.put("date", "2024年11月15日");map.put("allInStaockQty", 1);map.put("allOutStockQty", 2);map.put("allConvertStockQty", 3);map.put("allStockQty", 4);map.put("convertCenterStockQty", 5);map.put("mixOutStockQty", 6);map.put("endItem1", 7);map.put("endItem2", 8);map.put("endItem3", 9);map.put("endItem4", 10);map.put("endItem5", 11);excelWriter.fill(map, writeSheet);}// 合并单元格,由于easyExcel自带的OnceAbsoluteMergeStrategy合并策略bug,这里需要用poi合并一下return mergeCells(byteArrayOutputStream);
}public ByteArrayOutputStream mergeCells(ByteArrayOutputStream inputStream) {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(inputStream.toByteArray());Workbook workbook = new XSSFWorkbook(byteArrayInputStream)) {// 获取第一个工作表Sheet sheet = workbook.getSheetAt(0);// 合并第1列第3行到第15行,注意行索引从0开始CellRangeAddress range1 = new CellRangeAddress(2, 14, 0,0);sheet.addMergedRegion(range1);// 合并第1列第16行到第28行,注意行索引从0开始CellRangeAddress range2 = new CellRangeAddress(15, 27, 0, 0);sheet.addMergedRegion(range2);// 设置合并单元格的样式CellStyle style = workbook.createCellStyle();style.setAlignment(HorizontalAlignment.CENTER);style.setVerticalAlignment(VerticalAlignment.CENTER);// 将修改后的内容写入 ByteArrayOutputStreamworkbook.write(outputStream);// 刷新一下,确保数据完全写入outputStream.flush();} catch (IOException e) {e.printStackTrace();}return outputStream;
}private List<FillData> makeTestData(Integer listIndx) {List<FillData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {FillData fillData = new FillData();list.add(fillData);fillData.setName("张三"+listIndx);fillData.setNumber(5.2);fillData.setDate(new Date());}return list;}
五、Vue3前端发起请求下载
const handleExport = async () => {try {// 这里的确认框、loading框代码就省略了// 发起导出const data = await ReportTestApi.testReport(queryParams)download.excel(data, '测试模板填充.xlsx')} catch {} finally {exportLoading.value = false}
}const download = {// 下载 Excel 方法excel: (data: Blob, fileName: string) => {download0(data, fileName, 'application/vnd.ms-excel')},// 下载 Word 方法word: (data: Blob, fileName: string) => {download0(data, fileName, 'application/msword')},// 下载 Zip 方法zip: (data: Blob, fileName: string) => {download0(data, fileName, 'application/zip')},// 下载 Html 方法html: (data: Blob, fileName: string) => {download0(data, fileName, 'text/html')},// 下载 Markdown 方法markdown: (data: Blob, fileName: string) => {download0(data, fileName, 'text/markdown')}
}const download0 = (data: Blob, fileName: string, mineType: string) => {// 创建 blobconst blob = new Blob([data], { type: mineType })// 创建 href 超链接,点击进行下载window.URL = window.URL || window.webkitURLconst href = URL.createObjectURL(blob)const downA = document.createElement('a')downA.href = hrefdownA.download = fileNamedownA.click()// 销毁超连接window.URL.revokeObjectURL(href)
}
六、官方文档及AI问答
直接拉到下面,看“多列表组合填充”
https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill#%E6%A8%A1%E6%9D%BF-2
easyExcel官方问答AI,对比了一下,其他AI都没有它答的好
无疑: https://answer.opensource.alibaba.com/docs/intro
客官点个赞再走呗
相关文章:
如何使用EasyExcel生成多列表组合填充的复杂Excel示例
作者:Funky_oaNiu 一、(需求)生成的表格效果:二、搞一个模板文件三、建立对应的表格实体类四、开始填充五、Vue3前端发起请求下载六、官方文档及AI问答 一、(需求)生成的表格效果: 其中只有顶部…...
【MySQL】MySQL在Centos环境安装
🔥个人主页: Forcible Bug Maker 🔥专栏: MySQL 目录 🌈前言🔥卸载不要的环境🔥检查系统安装包🔥卸载这些默认安装包🔥获取mysql官方yum源🔥安装mysql yum源…...
JDBC-Mysql 时区问题详解
目录 一、前置准备 1.1 版本号列表 1.2 Sql脚本 1.3 application.yaml配置 1.4 数据库时区设置 二、java Date类型与(jdbcType)TIMESTAMP类型的转换 2.1 jdbc对serverTimeZone的处理 2.2 java Date转(jdbcType)TIMESTAMP …...
前端页面一些小点
案例一: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>快递单号查询</title><…...
Postman接口测试(断言、关联、参数化、输出测试报告)
基本界面展示 Get、Post请求 Postman断言 使用postman来判断预期结果与实际结果是否一致 响应状态码断言 响应包含字符串 断言判断字符串的格式 关联 用于解决http请求之间存在依赖关系 依赖:一个http请求的响应结果中的数据,被另一个请求使用 登…...
redis和mongodb等对比分析
Redis 和 MongoDB 都是非常流行的 NoSQL 数据库,它们在数据存储模型、性能、扩展性等方面有很大的差异。下面是 Redis 和 MongoDB 的对比分析: 1. 数据模型 Redis: 键值存储:Redis 是一个内存数据结构存储,它支持多种数据类型,如字符串、哈希、列表、集合、有序集合等。…...
如何在 WordPress 中轻松强制所有用户退出登录
作为一名长期管理 WordPress 网站的站长,我深知维护网站安全性的重要性。尤其是在面对会员网站或付费内容平台时,确保所有用户的登录状态是最新的,是维持网站正常运营的关键之一。今天,我就分享一下如何通过简单的步骤,…...
移除元素(leetcode 27)
给定一个数组,在数组中删除等于这个目标值的元素,然后返回新数组的大小 数组理论: 数组是一个连续的类型相近的元素的一个集合,数组上的删除是覆盖,只能由后面的元素进行覆盖,而不能进行真正意义上的地理位…...
html5表单属性的用法
文章目录 HTML5表单详解与代码案例一、表单的基本结构二、表单元素及其属性三、表单的高级应用与验证四、表单布局与样式 HTML5表单详解与代码案例 HTML5表单是网页中用于收集用户输入并提交到服务器的重要元素,广泛应用于登录页面、客户留言、搜索产品等场景。本文…...
使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan
使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan 背景 在使用Ant Design Vue 开发数据表格时,我们常常会遇到需要合并单元格的需求。 比如,某些字段的值可能会在多行中重复出现,而我们希望将这些重复的单元格合并为…...
相机光学(四十四)——ALL-PD和PDAF
1.PDAF(Phase Detection Auto Focus) PDAF是相位检测自动对焦技术的缩写,它是一种在数码相机和智能手机摄像头中使用的自动对焦技术。 PDAF的原理是根据CIS(CMOS图像传感器)不同像素的相位差信息,判断出…...
Opengl光照测试
代码 #include "Model.h" #include "shader_m.h" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" //以上是放在同目录的头文件#include <glad/glad.h> #include <GLFW/glfw3.…...
OpenSIP2.4.11 向 FreeSWITCH 注册
应朋友要求做了个简单的测试,花费时间不过半小时,记录如下: OpenSIPS IP 地址:192.168.31.213 FreeSWITCH IP 地址:192.168.31.166 加载 uac_registrant 模块(这个模块依赖 uac_auth 模块,得…...
【C++】深入理解 C++ 优先级队列、容器适配器与 deque:实现与应用解析
个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 📘 基础数据结构【C语言】 💻 C语言编程技巧【C】 🚀 进阶C【OJ题解】 📝 题解精讲 目录 前言📌 1. 优先级队列、容器适配器和 deque 概述✨1.1 什么是优…...
Android 开发与救砖工具介绍
Android 开发与救砖工具介绍 在 Android 开发和设备维护中,fastboot、adb 和 9008 模式是三个非常重要的工具和模式。它们各自有不同的用途和操作方式,对于开发者和技术支持人员来说,了解它们的功能和使用方法是必不可少的。 1. Fastboot …...
vue2和vue3:diff算法的区别?
Vue 2 和 Vue 3 在 diff 算法方面的主要区别是: Vue 2 使用普通的 diff 算法,它会遍历所有的节点进行比对。 Vue 3 引入了 patch flag 的概念,并且对 diff 算法进行了优化,比如在相同层级的节点间不会去递归比对已经被移除的节点…...
后端返回大数问题
这个问题并不难,但是在开发的时候没有注意到 后端返回了一个列表数据,包含id,这个id是一个大数,列表进入详情,需要将id传入到详情页面详情页面内部通过id获取数据一直404,id不正确找问题,从路由传参到请求数据发现id没有问题,然后和后端进行联调,发现后端返回的id和我获取的id…...
vue3: ref, reactive, readonly, shallowReactive
vue3: ref, reactive, readonly, shallowReactive 原文地址:https://mp.weixin.qq.com/s/S3jPZKEMBP8nQQObF5d2VA <template><!-- <ul><li v-for"item in list.arr">{{item}}</li></ul><button click.prevent"add"…...
5G与4G互通的桥梁:N26接口
5G的商用部署进程将是一个基于4G系统进行的长期的替换、升级、迭代的过程,4G系统是在过渡到5G全覆盖过程中,作为保障用户业务连续性体验这一目的的最好补充。 因此4G/5G融合组网,以及互操作技术将是各大运营商在网络演进中需要重点考虑的问题…...
29-Elasticsearch 集群监控
Elasticsearch Stats 相关的 API ● Elasticsearch 提供了多个监控相关的 API ○ Node Stats: _nodes/stats ○ Cluster Stats: _cluster/stats ○ Index Stats: index_name/_stats Elasticsearch Task API ● 查看 Task 相关的 API ○ Pending Cluster Tasks…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
