我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用EasyExcel模版导出

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用EasyExcel模版导出

easyexcel官方文档 填充Excel | Easy Excel

官方demo是利用本地模版文件填充并下载到本地

        @Test    public void complexFill() {        // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替        // {} 代表普通变量 {.} 代表是list的变量        String templateFileName =            TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "complex.xlsx";        String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx";        // 方案1        try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {            WriteSheet writeSheet = EasyExcel.writerSheet().build();            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用            // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存            // 如果数据量大 list不是最后一行 参照下一个            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();            excelWriter.fill(data(), fillConfig, writeSheet);            excelWriter.fill(data(), fillConfig, writeSheet);            Map map = MapUtils.newHashMap();            map.put("date", "2019年10月9日13:28:28");            map.put("total", 1000);            excelWriter.fill(map, writeSheet);        }    }

我用的是web项目,将输出改为了输出流 OutputStream

@Overridepublic void exportTask(Long id, HttpServletResponse response) {ExcelWriter excelWriter = null;try {// outputStream:要导出的文件的输出流OutputStream outputStream = response.getOutputStream();// 模版文件ClassPathResource classPathResource = new ClassPathResource("template/taskTemplate.xlsx");// 使用模版文件的两种方式:// 1、文件路径:.withTemplate(templateFileName)// 2、输入流:.withTemplate(inputStream)String templateFileName = classPathResource.getFile().getPath();InputStream inputStream = classPathResource.getInputStream();excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).autoCloseStream(Boolean.FALSE).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();// 获取数据 dataList columnList formDataMap mapDetail = qmsQcTaskDetailService.getDataListByTaskId(id);// 调用微服务获取字典 determine 用来翻译判定结果List determineItem = remoteDictService.getDictByType("determine").getData();// 调用微服务获取字典 product_unit 用来翻译零件单位List unitItem = remoteDictService.getDictByType("product_unit").getData();QmsQcTask formData = (QmsQcTask) mapDetail.get("formData");determineItem.stream().filter(item -> StrUtil.equals(formData.getResult(), item.getItemValue())).findFirst().ifPresent(sysDictItem -> formData.setResult(sysDictItem.getLabel()));unitItem.stream().filter(item -> StrUtil.equals(formData.getMaterialUnit(), item.getItemValue())).findFirst().ifPresent(sysDictItem -> formData.setMaterialUnit(sysDictItem.getLabel()));excelWriter.fill(formData, writeSheet);List> cols = new ArrayList<>();// 查找抽检数是多少,即有几列int num = formData.getSampleNum();for (int i = 1; i <= num; i++) {Map map = new HashMap<>();// 列名map.put("label", "" + i);cols.add(map);}// 横向填充FillConfig fillConfigCols = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();excelWriter.fill(new FillWrapper("cols", cols), fillConfigCols, writeSheet);// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();List> dataList = (List>) mapDetail.get("dataList");for (int i = 0; i < dataList.size(); i++) {Map data = dataList.get(i);// 翻译判定合不合格(因为业务和字典不在一个数据库,所以放在代码里处理)String determine = (String) data.get("determine");determineItem.stream().filter(item -> StrUtil.equals(determine, item.getItemValue())).findFirst().ifPresent(sysDictItem -> data.put("determine", sysDictItem.getLabel()));// 如果没有质检标准,每一个质检值都要转为合不合格if (StrUtil.isBlank((String) data.get("inspection_standard"))){int samplingNum = Optional.ofNullable((Integer) data.get("sampling_num")).orElse(0);for (int j = 1; j <= samplingNum; j++) {String val = (String) data.get(""+j);int finalJ = j;determineItem.stream().filter(item -> StrUtil.equals(val, item.getItemValue())).findFirst().ifPresent(sysDictItem -> data.put(""+ finalJ, sysDictItem.getLabel()));}}// 给数据加上序号data.put("index", i + 1);}excelWriter.fill(new FillWrapper("details", dataList), fillConfig, writeSheet);// 设置输出流格式以及文件名:response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("质检任务", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");} catch (IOException e) {throw new RuntimeException(e);} finally {// 千万别忘记close关闭流if (excelWriter != null) {excelWriter.close();}}}

 模版:

效果:

1、获取输出流

// outputStream:要导出的文件的输出流OutputStream outputStream = response.getOutputStream();

2、获取模版文件

// 模版文件ClassPathResource classPathResource = new ClassPathResource("template/taskTemplate.xlsx");// 方式一:路径String templateFileName = classPathResource.getFile().getPath();// 方式二:输入流InputStream inputStream = classPathResource.getInputStream();

3、创建 ExcelWriterWriteSheet

excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).autoCloseStream(Boolean.FALSE).build();WriteSheet writeSheet = EasyExcel.writerSheet().build();

使用模版文件有两种方式,使用其中一种就可以:
    1.文件路径:.withTemplate(templateFileName)
    2.输入流:.withTemplate(inputStream)

4、获取数据

Map mapDetail = qmsQcTaskDetailService.getDataListByTaskId(id);

我这里直接调用了方法,map包含

dataList主要列表数据 formData 列表外的数据

5、填充数据

1.获取字典数据

// 调用微服务获取字典 determine 用来翻译判定结果List determineItem = remoteDictService.getDictByType("determine").getData();// 调用微服务获取字典 product_unit 用来翻译零件单位List unitItem = remoteDictService.getDictByType("product_unit").getData();

我的业务数据和字典不在同一个数据库内,sql无法翻译,所以需要在代码里翻译

2.填充列表外的数据

QmsQcTask formData = (QmsQcTask) mapDetail.get("formData");determineItem.stream().filter(item -> StrUtil.equals(formData.getResult(), item.getItemValue())).findFirst().ifPresent(sysDictItem -> formData.setResult(sysDictItem.getLabel()));unitItem.stream().filter(item -> StrUtil.equals(formData.getMaterialUnit(), item.getItemValue())).findFirst().ifPresent(sysDictItem -> formData.setMaterialUnit(sysDictItem.getLabel()));excelWriter.fill(formData, writeSheet);

只要对象属性名和模版里写的标记已知就可以了

3.填充缺少的列名

模版:

 效果:

 因为我后半部分列名涉及到行转列,且不固定列数,所以需要横着填充上列名。注意列表的名字“cols”要对应起来。

使用.direction(WriteDirectionEnum.HORIZONTAL) 设置为横向填充。

List> cols = new ArrayList<>();// 查找抽检数是多少,即有几列int num = formData.getSampleNum();for (int i = 1; i <= num; i++) {Map map = new HashMap<>();// 列名map.put("label", "" + i);cols.add(map);}// 横向填充FillConfig fillConfigCols = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();excelWriter.fill(new FillWrapper("cols", cols), fillConfigCols, writeSheet);

4.填充主列表数据

// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();List> dataList = (List>) mapDetail.get("dataList");for (int i = 0; i < dataList.size(); i++) {Map data = dataList.get(i);// 翻译判定合不合格(因为业务和字典不在一个数据库,所以放在代码里处理)String determine = (String) data.get("determine");determineItem.stream().filter(item -> StrUtil.equals(determine, item.getItemValue())).findFirst().ifPresent(sysDictItem -> data.put("determine", sysDictItem.getLabel()));// 如果没有质检标准,每一个质检值都要转为合不合格if (StrUtil.isBlank((String) data.get("inspection_standard"))){int samplingNum = Optional.ofNullable((Integer) data.get("sampling_num")).orElse(0);for (int j = 1; j <= samplingNum; j++) {String val = (String) data.get(""+j);int finalJ = j;determineItem.stream().filter(item -> StrUtil.equals(val, item.getItemValue())).findFirst().ifPresent(sysDictItem -> data.put(""+ finalJ, sysDictItem.getLabel()));}}// 给数据加上序号data.put("index", i + 1);}excelWriter.fill(new FillWrapper("details", dataList), fillConfig, writeSheet);

最重要的三句话:

FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();List> dataList = (List>) mapDetail.get("dataList");excelWriter.fill(new FillWrapper("details", dataList), fillConfig, writeSheet);
这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存

5.设置输出流格式以及文件名

// 设置输出流格式以及文件名:response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("质检任务", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

我的模版使用了动态的列,不确定有几列,所以我就写了一百多个。

还有另外一种设想:

如果先把列表外的数据填充,然后将主列表的列填充完毕,再把主列表的标记写上,这些操作完毕之后把文件输出到另外的输出流上,再将此输出流转为输入流,再把主列表的数据填充,输出到response。

理论上可行,但我没试。

来源地址:https://blog.csdn.net/weixin_45735511/article/details/127762821

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用EasyExcel模版导出

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

java如何使用EasyExcel导入导出excel

这篇文章主要介绍了java如何使用EasyExcel导入导出excel,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、准备工作1、导包
2023-06-15

使用EasyExcel实现Excel的导入导出

文章目录 前言一、EasyExcel是什么?二、使用步骤1.导入依赖2.编写文件上传配置3.配置表头对应实体类4.监听器编写5.控制层6.前端代码 总结 前言 在真实的开发者场景中,经常会使用excel作为数据的载体,进行
2023-08-17

java实现excel的导出之使用easyExcel

前言 在我们的项目需求中,经常会遇到导出的需求,其中excel的导出最为常见。生成Excel比较有名的框架有Apache poi,jxl等,但他们都存在一个严重的问题就是非常的耗内存,如果你的系统并发量不大的话可能还行,但是一旦并发上来后一
2023-08-18

Spring Boot + EasyExcel导入导出,简直太好用了!

本篇文章基于SpringBoot集成EasyExcel的实现展开,为大家讲解了EasyExcel在实践中的具体运用。大家可根据需要,进行变通处理。同时,基于自定义转换器、自定义策略、自定义监听器等形式达到灵活适用于各种场景。希望本篇文章能给

Java使用easyExcel实现导入功能

这篇文章介绍了Java使用easyExcel实现导入功能的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2022-11-13

使用 Spring Boot + EasyExcel 实现百万级数据导入导出功能开发

在实际开发中,大家需要根据具体的业务需求对数据的处理逻辑进行进一步的优化和完善。同时,还需要考虑异常处理、数据校验等方面,以确保系统的稳定性和可靠性。

Java怎么用EasyExcel解析动态表头并导出

本文小编为大家详细介绍“Java怎么用EasyExcel解析动态表头并导出”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java怎么用EasyExcel解析动态表头并导出”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知
2023-07-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录