如何使用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…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
