Easyexcel(4-模板文件)
相关文章链接
- Easyexcel(1-注解使用)
- Easyexcel(2-文件读取)
- Easyexcel(3-文件导出)
- Easyexcel(4-模板文件)
文件导出
获取 resources 目录下的文件,使用 withTemplate 获取文件流导出文件模板
@GetMapping("/download1")
public void download1(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");EasyExcel.write(response.getOutputStream()).withTemplate(in).sheet("sheet1").doWrite(Collections.emptyList());} catch (Exception e) {e.printStackTrace();}
}
注意:获取 resources 目录下的文件需要在 maven 中添加以下配置,过滤对应的文件,防止编译生成后的 class 文件找不到对应的文件信息
<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><configuration><encoding>UTF-8</encoding><nonFilteredFileExtensions><nonFilteredFileExtension>xls</nonFilteredFileExtension><nonFilteredFileExtension>xlsx</nonFilteredFileExtension></nonFilteredFileExtensions></configuration>
</plugin>
对象填充导出
模板文件信息

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "创建时间")private Date createTime;
}
@GetMapping("/download5")
public void download5(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试3.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试3", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");User user = new User(1, "张三", "12345678901", "zhangsan@qq.com", new Date());EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(user);} catch (Exception e) {e.printStackTrace();}
}
注意:填充模板跟写文件使用的方法不一致,模板填充使用的方法是 doFill,而不是 doWrite
导出文件内容

List 填充导出
对象导出
模板文件信息

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "创建时间")private Date createTime;
}
@GetMapping("/download2")
public void download2(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", "12345678901", "zhangsan@qq.com", new Date()));userList.add(new User(2, "李四", "12345678902", "lisi@qq.com", new Date()));EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(userList);} catch (Exception e) {e.printStackTrace();}
}
导出文件内容

对象嵌套对象(默认不支持)
原因排查
模板文件信息

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "学生")private Student stu;@NoArgsConstructor@AllArgsConstructor@Datapublic static class Student {@ExcelProperty("姓名")private String name;@ExcelProperty("年龄")private Integer age;}
}
@GetMapping("/download3")
public void download3(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试2.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试2", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", "12345678901", "zhangsan@qq.com", new User.Student("张三", 12)));userList.add(new User(2, "李四", "12345678902", "lisi@qq.com", new User.Student("李四", 13)));EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(userList);} catch (Exception e) {e.printStackTrace();}
}
导出文件内容
结果:Student 类的内容没有填充到模板文件中

查看 ExcelWriteFillExecutor 源码
可以看到 dataKeySet 集合中的数据只有 stu(没有 stu.name 和 stu.age),在! dataKeySet.contains(variable)方法中判断没有包含该字段信息,所以被过滤掉


修改源码支持
在 com.alibaba.excel.write.executor 包下创建 ExcelWriteFillExecutor 类,跟源码中的类名称一致,尝试修改 analysisCell.getOnlyOneVariable()方法中的逻辑以便支持嵌套对象,修改如下:
根据分隔符.进行划分,循环获取对象中字段的数据,同时在 FieldUtils.getFieldClass 方法中重新设置 map 对象和字段
if (analysisCell.getOnlyOneVariable()) {String variable = analysisCell.getVariableList().get(0);String[] split = variable.split("\\.");Map map = BeanUtil.copyProperties(dataMap, Map.class);Object value = null;if (split.length == 1) {value = map.get(variable);} else {int len = split.length - 1;for (int i = 0; i < len; i++) {Object o = map.get(split[i]);map = BeanMapUtils.create(o);}value = map.get(split[split.length - 1]);}ExcelContentProperty excelContentProperty = ClassUtils.declaredExcelContentProperty(map,writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadClazz(), split[split.length - 1],writeContext.currentWriteHolder());cellWriteHandlerContext.setExcelContentProperty(excelContentProperty);createCell(analysisCell, fillConfig, cellWriteHandlerContext, rowWriteHandlerContext);cellWriteHandlerContext.setOriginalValue(value);cellWriteHandlerContext.setOriginalFieldClass(FieldUtils.getFieldClass(map, split[split.length - 1], value));converterAndSet(cellWriteHandlerContext);WriteCellData<?> cellData = cellWriteHandlerContext.getFirstCellData();// Restyleif (fillConfig.getAutoStyle()) {Optional.ofNullable(collectionFieldStyleCache.get(currentUniqueDataFlag)).map(collectionFieldStyleMap -> collectionFieldStyleMap.get(analysisCell)).ifPresent(cellData::setOriginCellStyle);}
}
导出文件内容
查看导出的文件内容,此时发现嵌套对象的内容可以导出了

对象嵌套 List(默认不支持)
原因排查
模板文件信息

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "创建时间")private Date createTime;@ExcelProperty(value = "id列表")private List<String> idList;
}
@GetMapping("/download4")
public void download4(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试2.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");List<User> userList = new ArrayList<>();userList.add(new User(1, "张三", "12345678901", "zhangsan@qq.com", new Date(), Arrays.asList("234", "465")));userList.add(new User(2, "李四", "12345678902", "lisi@qq.com", new Date(), Arrays.asList("867", "465")));EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(userList);} catch (Exception e) {e.printStackTrace();}
}
执行后会发现报错 Can not find ‘Converter’ support class ArrayList.
EasyExcel 默认不支持对象嵌套 List 的,可以通过自定义转换器的方式修改导出的内容
自定义转换器
public class ListConvert implements Converter<List> {@Overridepublic WriteCellData<?> convertToExcelData(List value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {if (value == null || value.isEmpty()) {return new WriteCellData<>("");}String val = (String) value.stream().collect(Collectors.joining(","));return new WriteCellData<>(val);}@Overridepublic List convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {if (cellData.getStringValue() == null || cellData.getStringValue().isEmpty()) {return new ArrayList<>();}List list = new ArrayList();String[] items = cellData.getStringValue().split(",");Collections.addAll(list, items);return list;}
}
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "创建时间")private Date createTime;@ExcelProperty(value = "id列表", converter = ListConvert.class)private List<String> idList;
}
导出文件内容
可以看到 List 列表的数据导出内容为 String 字符串,显示在一个单元格内

Map 填充导出
简单导出
模板文件信息

注意:map跟对象导出有所区别,最前面没有.
@GetMapping("/download4")
public void download4(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试3.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");Map<String, String> map = new HashMap<>();map.put("userId", "123");map.put("name", "张三");map.put("phone", "12345678901");map.put("email", "zhangsan@qq.com");map.put("createTime", "2021-01-01");EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(map);} catch (Exception e) {e.printStackTrace();}
}
导出文件内容

嵌套方式(不支持)
模板文件信息

@GetMapping("/download4")
public void download4(HttpServletResponse response) {try (InputStream in = new ClassPathResource("测试3.xls").getInputStream()) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");Map<String, String> map = new HashMap<>();map.put("userId", "123");map.put("name", "张三");map.put("phone", "12345678901");map.put("email", "zhangsan@qq.com");map.put("createTime", "2021-01-01");map.put("student.name", "小张");map.put("student.age", "23");EasyExcel.write(response.getOutputStream(), User.class).withTemplate(in).sheet("模板").doFill(map);} catch (Exception e) {e.printStackTrace();}
}
导出文件内容
注意:Easyexcel 不支持嵌套的方式导出数据

相关文章:
Easyexcel(4-模板文件)
相关文章链接 Easyexcel(1-注解使用)Easyexcel(2-文件读取)Easyexcel(3-文件导出)Easyexcel(4-模板文件) 文件导出 获取 resources 目录下的文件,使用 withTemplate 获…...
国产linux系统(银河麒麟,统信uos)使用 PageOffice 动态生成word文件
PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)、龙芯(LoogArch)芯片架构。 数据区域填充文本 数…...
Window11+annie 视频下载器安装
一、ffmpeg环境的配置 下载annie之前需要先配置ffmpeg视频解码器。 网址下载地址 https://ffmpeg.org/download.html1、在网址中选择window版本 2、点击后选择该版本 3、下载完成后对压缩包进行解压,后进行环境的配置 (1)压缩包解压&#…...
SAP GR(Group Reporting)配置篇(七)
1.7、合并处理的配置 1.7.1 定义方法 菜单路径 组报表的SAP S4HANA >合并处理的配置>定义方法 事务代码 SPI4...
共建智能软件开发联合实验室,怿星科技助力东风柳汽加速智能化技术创新
11月14日,以“奋进70载,智创新纪元”为主题的2024东风柳汽第二届科技周在柳州盛大开幕,吸引了来自全国的汽车行业嘉宾、技术专家齐聚一堂,共襄盛举,一同探寻如何凭借 “新技术、新实力” 这一关键契机,为新…...
优化表单交互:在 el-select 组件中嵌入表格显示选项
介绍了一种通过 el-select 插槽实现表格样式数据展示的方案,可更直观地辅助用户选择。支持列配置、行数据绑定及自定义搜索,简洁高效,适用于复杂选择场景。完整代码见GitHub 仓库。 背景 在进行业务开发选择订单时,如果单纯的根…...
每日一题 LCR 079. 子集
LCR 079. 子集 主要应该考虑遍历的顺序 class Solution { public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>> ans;vector<int> temp;dfs(nums,0,temp,ans);return ans;}void dfs(vector<int> &…...
cocos creator 3.8 Node学习 3
//在Ts、js中 this指向当前的这个组件实例 //this下的一个数据成员node,指向组件实例化的这个节点 //同样也可以根据节点找到挂载的所有组件 //this.node 指向当前脚本挂载的节点//子节点与父节点的关系 // Node.parent是一个Node,Node.children是一个Node[] // th…...
微信小程序底部button,小米手机偶现布局错误的bug
预期结果:某button fixed 到页面底部,进入该页面时,正常显示button 实际结果:小米13pro,首次进入页面,button不显示。再次进入时,则正常展示 左侧为小米手机第一次进入。 遇到bug的解决思路&am…...
【计组】复习题
冯诺依曼型计算机的主要设计思想是什么?它包括哪些主要组成部分? 主要设计思想: ①采用二进制表示数据和指令,指令由操作码和地址码组成。 ②存储程序,程序控制:将程序和数据存放在存储器中,计算…...
Apache Maven 标准文件目录布局
Apache Maven 采用了一套标准的目录布局来组织项目文件。这种布局提供了一种结构化和一致的方式来管理项目资源,使得开发者更容易导航和维护项目。理解和使用标准目录布局对于有效的Maven项目管理至关重要。本文将探讨Maven标准目录布局的关键组成部分,并…...
Android 功耗分析(底层篇)
最近在网上发现关于功耗分析系列的文章很少,介绍详细的更少,于是便想记录总结一下功耗分析的相关知识,有不对的地方希望大家多指出,互相学习。本系列分为底层篇和上层篇。 大概从基础知识,测试手法,以及案例…...
【Xbim+C#】创建圆盘扫掠IfcSweptDiskSolid
基础回顾 https://blog.csdn.net/liqian_ken/article/details/143867404 https://blog.csdn.net/liqian_ken/article/details/114851319 效果图 代码示例 在前文基础上,增加一个工具方法: public static IfcProductDefinitionShape CreateDiskSolidSha…...
IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发
对于新手学习SpringBoot开发,可能最急迫的事情就是尽快掌握数据库的开发。目前数据库开发主要流行使用Mybatis和Mybatis Plus,不过这2个框架对于新手而言需要一定的时间掌握,如果快速上手数据库开发,可以先按照本文介绍的方式使用JdbcTemplat…...
利用oss进行数据库和网站图片备份
1.背景 由于网站迁移到香港云 服务器,虽然便宜,但是宿主服务器时不时重启,为了预防不可控的因素导致网站资料丢失,所以想到用OSS 备份网站数据,bucket选择在香港地区创建,这样和你服务器传输会更快。 oss…...
Excel - VLOOKUP函数将指定列替换为字典值
背景:在根据各种复杂的口径导出报表数据时,因为关联的表较多、数据量较大,一行数据往往会存在三个以上的字典数据。 为了保证导出数据的效率,博主选择了导出字典code值后,在Excel中处理匹配字典值。在查询百度之后&am…...
实验室管理平台:Spring Boot技术构建
3系统分析 3.1可行性分析 通过对本实验室管理系统实行的目的初步调查和分析,提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本实验室管理系统采用SSM框架,JAVA作为开发语言&a…...
操作系统进程和线程——针对实习面试
目录 操作系统进程和线程什么是进程和线程?进程和线程的区别?进程有哪些状态?什么是线程安全?如何实现线程安全?什么是线程安全?如何实现线程安全? 进程间的通信有哪几种方式?什么是…...
使用 cnpm 安装 Electron,才是正确快速的方法
当然,下面是总结的几种安装 Electron 的方法,包括使用 npm 和 cnpm,以及一些常见的问题解决技巧。 ### 1. 使用 npm 安装 Electron #### 步骤 1: 初始化项目 在你的项目目录中初始化一个新的 Node.js 项目: bash npm init -y …...
【人工智能】PyTorch、TensorFlow 和 Keras 全面解析与对比:深度学习框架的终极指南
文章目录 PyTorch 全面解析2.1 PyTorch 的发展历程2.2 PyTorch 的核心特点2.3 PyTorch 的应用场景 TensorFlow 全面解析3.1 TensorFlow 的发展历程3.2 TensorFlow 的核心特点3.3 TensorFlow 的应用场景 Keras 全面解析4.1 Keras 的发展历程4.2 Keras 的核心特点4.3 Keras 的应用…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
