当前位置: 首页 > news >正文

如何使用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示例

作者&#xff1a;Funky_oaNiu 一、&#xff08;需求&#xff09;生成的表格效果&#xff1a;二、搞一个模板文件三、建立对应的表格实体类四、开始填充五、Vue3前端发起请求下载六、官方文档及AI问答 一、&#xff08;需求&#xff09;生成的表格效果&#xff1a; 其中只有顶部…...

【MySQL】MySQL在Centos环境安装

&#x1f525;个人主页&#xff1a; Forcible Bug Maker &#x1f525;专栏&#xff1a; MySQL 目录 &#x1f308;前言&#x1f525;卸载不要的环境&#x1f525;检查系统安装包&#x1f525;卸载这些默认安装包&#x1f525;获取mysql官方yum源&#x1f525;安装mysql yum源…...

JDBC-Mysql 时区问题详解

目录 一、前置准备 1.1 版本号列表 1.2 Sql脚本 1.3 application.yaml配置 1.4 数据库时区设置 二、java Date类型与&#xff08;jdbcType&#xff09;TIMESTAMP类型的转换 2.1 jdbc对serverTimeZone的处理 2.2 java Date转&#xff08;jdbcType&#xff09;TIMESTAMP …...

前端页面一些小点

案例一&#xff1a; <!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请求之间存在依赖关系 依赖&#xff1a;一个http请求的响应结果中的数据&#xff0c;被另一个请求使用 登…...

redis和mongodb等对比分析

Redis 和 MongoDB 都是非常流行的 NoSQL 数据库,它们在数据存储模型、性能、扩展性等方面有很大的差异。下面是 Redis 和 MongoDB 的对比分析: 1. 数据模型 Redis: 键值存储:Redis 是一个内存数据结构存储,它支持多种数据类型,如字符串、哈希、列表、集合、有序集合等。…...

如何在 WordPress 中轻松强制所有用户退出登录

作为一名长期管理 WordPress 网站的站长&#xff0c;我深知维护网站安全性的重要性。尤其是在面对会员网站或付费内容平台时&#xff0c;确保所有用户的登录状态是最新的&#xff0c;是维持网站正常运营的关键之一。今天&#xff0c;我就分享一下如何通过简单的步骤&#xff0c…...

移除元素(leetcode 27)

给定一个数组&#xff0c;在数组中删除等于这个目标值的元素&#xff0c;然后返回新数组的大小 数组理论&#xff1a; 数组是一个连续的类型相近的元素的一个集合&#xff0c;数组上的删除是覆盖&#xff0c;只能由后面的元素进行覆盖&#xff0c;而不能进行真正意义上的地理位…...

html5表单属性的用法

文章目录 HTML5表单详解与代码案例一、表单的基本结构二、表单元素及其属性三、表单的高级应用与验证四、表单布局与样式 HTML5表单详解与代码案例 HTML5表单是网页中用于收集用户输入并提交到服务器的重要元素&#xff0c;广泛应用于登录页面、客户留言、搜索产品等场景。本文…...

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan

使用 Ant Design Vue 自定渲染函数customRender实现单元格合并功能rowSpan 背景 在使用Ant Design Vue 开发数据表格时&#xff0c;我们常常会遇到需要合并单元格的需求。 比如&#xff0c;某些字段的值可能会在多行中重复出现&#xff0c;而我们希望将这些重复的单元格合并为…...

相机光学(四十四)——ALL-PD和PDAF

1.PDAF&#xff08;Phase Detection Auto Focus&#xff09; PDAF是相位检测自动对焦技术的缩写&#xff0c;它是一种在数码相机和智能手机摄像头中使用的自动对焦技术。   PDAF的原理是根据CIS&#xff08;CMOS图像传感器&#xff09;不同像素的相位差信息&#xff0c;判断出…...

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 注册

应朋友要求做了个简单的测试&#xff0c;花费时间不过半小时&#xff0c;记录如下&#xff1a; OpenSIPS IP 地址&#xff1a;192.168.31.213 FreeSWITCH IP 地址&#xff1a;192.168.31.166 加载 uac_registrant 模块&#xff08;这个模块依赖 uac_auth 模块&#xff0c;得…...

【C++】深入理解 C++ 优先级队列、容器适配器与 deque:实现与应用解析

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 前言&#x1f4cc; 1. 优先级队列、容器适配器和 deque 概述✨1.1 什么是优…...

Android 开发与救砖工具介绍

Android 开发与救砖工具介绍 在 Android 开发和设备维护中&#xff0c;fastboot、adb 和 9008 模式是三个非常重要的工具和模式。它们各自有不同的用途和操作方式&#xff0c;对于开发者和技术支持人员来说&#xff0c;了解它们的功能和使用方法是必不可少的。 1. Fastboot …...

vue2和vue3:diff算法的区别?

Vue 2 和 Vue 3 在 diff 算法方面的主要区别是&#xff1a; Vue 2 使用普通的 diff 算法&#xff0c;它会遍历所有的节点进行比对。 Vue 3 引入了 patch flag 的概念&#xff0c;并且对 diff 算法进行了优化&#xff0c;比如在相同层级的节点间不会去递归比对已经被移除的节点…...

后端返回大数问题

这个问题并不难,但是在开发的时候没有注意到 后端返回了一个列表数据,包含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系统进行的长期的替换、升级、迭代的过程&#xff0c;4G系统是在过渡到5G全覆盖过程中&#xff0c;作为保障用户业务连续性体验这一目的的最好补充。 因此4G/5G融合组网&#xff0c;以及互操作技术将是各大运营商在网络演进中需要重点考虑的问题…...

29-Elasticsearch 集群监控

Elasticsearch Stats 相关的 API ● Elasticsearch 提供了多个监控相关的 API ○ Node Stats&#xff1a; _nodes/stats ○ Cluster Stats: _cluster/stats ○ Index Stats: index_name/_stats Elasticsearch Task API ● 查看 Task 相关的 API ○ Pending Cluster Tasks…...

线激光手眼标定里,欧拉角和四元数到底怎么选?一个案例讲清机器人姿态的‘坑’

线激光手眼标定中欧拉角与四元数的抉择&#xff1a;从理论误区到工程实践 在机器人视觉系统中&#xff0c;手眼标定是连接感知与执行的关键桥梁。当激光传感器安装在机械臂末端时&#xff0c;如何准确描述传感器坐标系与机器人坐标系之间的姿态关系&#xff0c;直接决定了后续视…...

5分钟解锁网盘直链下载:告别限速,拥抱满速自由

5分钟解锁网盘直链下载&#xff1a;告别限速&#xff0c;拥抱满速自由 【免费下载链接】baiduyun 油猴脚本 - 一个免费开源的网盘下载助手 项目地址: https://gitcode.com/gh_mirrors/ba/baiduyun 还在为网盘下载速度而烦恼吗&#xff1f;你是否经历过下载一个几GB的文件…...

**AI仿真人剧机构推荐,2025年引领娱乐新潮流**随着科技的飞速发展,AI技术已经渗透到我们生活的方方面面。在娱乐领域,AI仿真人剧机构如同一颗璀璨的新星,正在引领着新一轮的潮流。那么,在众多

随着科技的飞速发展&#xff0c;AI技术已经渗透到我们生活的方方面面。在娱乐领域&#xff0c;AI仿真人剧机构如同一颗璀璨的新星&#xff0c;正在引领着新一轮的潮流。那么&#xff0c;在众多的AI仿真人剧机构中&#xff0c;如何选择一家优质的机构呢&#xff1f;本文将为您揭…...

foobar2000 DUI界面深度解析:foobox-cn技术架构与实战配置完整指南

foobar2000 DUI界面深度解析&#xff1a;foobox-cn技术架构与实战配置完整指南 【免费下载链接】foobox-cn DUI 配置 for foobar2000 项目地址: https://gitcode.com/GitHub_Trending/fo/foobox-cn foobox-cn是针对foobar2000播放器开发的现代化DUI&#xff08;默认用户…...

从零开始玩转Arduino:手把手教你用MOS管和继电器控制大电流设备(附电路图)

从零开始玩转Arduino&#xff1a;手把手教你用MOS管和继电器控制大电流设备&#xff08;附电路图&#xff09; 当你第一次尝试用Arduino控制大功率设备时&#xff0c;可能会遇到一个常见问题&#xff1a;小小的开发板输出引脚根本无法直接驱动电机、灯带或加热管。这时候&#…...

保姆级教程:在绿联NAS上用Docker Compose一键部署PaddleOCR,打造本地私有化OCR服务

绿联NASDocker Compose极简部署PaddleOCR&#xff1a;零命令行打造私有文字识别服务 家里堆积如山的合同发票需要电子化&#xff1f;团队内部敏感文档不敢用云端OCR&#xff1f;绿联NAS用户现在可以抛开复杂命令&#xff0c;用Docker Compose三分钟搭建企业级文字识别服务。本文…...

ASCII码表深度解析:从基础到扩展的全面指南

1. ASCII码的前世今生&#xff1a;计算机世界的通用语言 第一次接触ASCII码是在大学计算机基础课上&#xff0c;教授用"65A"这个简单公式瞬间点燃了我的好奇心。这个看似简单的编码系统&#xff0c;实际上是现代数字通信的基石。ASCII&#xff08;American Standard …...

25619+ASMR资源一键获取:让音频收藏效率提升10倍的智能下载工具

25619ASMR资源一键获取&#xff1a;让音频收藏效率提升10倍的智能下载工具 【免费下载链接】asmr-downloader A tool for download asmr media from asmr.one(Thanks for the asmr.one) 项目地址: https://gitcode.com/gh_mirrors/as/asmr-downloader 在数字音频时代&am…...

数学建模竞赛避坑指南:E题‘AI体测’数据预处理与特征工程实战解析

数学建模竞赛E题深度解析&#xff1a;从数据清洗到特征工程的实战避坑指南 数学建模竞赛中&#xff0c;数据处理环节往往决定了模型的成败。面对E题"AI体测"这类涉及多源异构数据的题目&#xff0c;许多参赛队伍在数据预处理阶段就埋下了隐患。本文将结合实战经验&am…...

STM32F103红外循迹避障小车实战:从Proteus仿真到实物调试全解析

1. STM32F103与红外循迹避障小车入门指南 第一次接触STM32F103做红外循迹避障小车时&#xff0c;我和很多初学者一样&#xff0c;以为照着网上的例程就能轻松搞定。但真正动手后发现&#xff0c;从仿真到实物调试的每个环节都可能遇到意想不到的问题。这个小车看似简单&#xf…...