【EasyExcel实践】导出多个sheet到多个excel文件,并压缩到一个zip文件

文章目录

  • 前言
  • 正文
    • 一、项目依赖
    • 二、封装表格实体和Sheet实体
      • 2.1 表格实体
      • 2.2 Sheet实体
    • 三、核心实现
      • 3.1 核心实现之导出为输出流
      • 3.2 web导出
      • 3.3 导出为字节数组
    • 四、调试
      • 4.1 构建调试用的实体类
      • 4.2 控制器调用
      • 4.3 测试结果
    • 五、注册大数转换器,长度大于15时,转换为字符串
      • 5.1 实现转换器
      • 5.2 使用转换器

前言

工作中遇到一个需求,一次导出多个Excel 文件,并且每个excel中可能存在1到多个sheet页。
好在没有那种单元格合并的要求。

总体的思路是,设计两个实体,一个表示表格,一个表示sheet 数据。并且表格包含一个list 类型的sheet对象。

然后再使用ZipOutputStreamExcelWriterBuilderEasyExcel#writerSheet(...) 等类和方法去组装表格,最终进行压缩。

项目整体使用 java 8 和 阿里的easyexcel工具包。

正文

一、项目依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.0.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.11</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></exclusion></exclusions></dependency></dependencies>

二、封装表格实体和Sheet实体

2.1 表格实体

/*** excel数据*/
@Data
public static class ExcelData {// sheet的列表private final List<ExcelShellData<?>> shellDataList = new ArrayList<>();// 表格文件名private String filename;public void addShellData(ExcelShellData<?> excelShellData) {this.shellDataList.add(excelShellData);}
}

2.2 Sheet实体

/*** sheet数据*/
@Data
@AllArgsConstructor
public static class ExcelShellData<T> {// 数据private List<T> list;// sheet名private String sheetName;// 数据实体类型private Class<T> clazz;
}

三、核心实现

3.1 核心实现之导出为输出流

这一步主要组装表格数据,以及生成sheet。最终将数据放到输出流outputStream中 。

private static void exportZipStream(List<ExcelData> excelDataList, OutputStream outputStream) {try {// 开始存入try (ZipOutputStream zipOut = new ZipOutputStream(outputStream)) {try {for (ExcelData excelData : excelDataList) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();com.alibaba.excel.ExcelWriter excelWriter = null;try {ExcelWriterBuilder builder = EasyExcel.write(byteArrayOutputStream).autoCloseStream(false)// 自动适配.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());excelWriter = builder.build();zipOut.putNextEntry(new ZipEntry(excelData.getFilename()));// 开始写入excelfor (ExcelShellData<?> shellData : excelData.getShellDataList()) {WriteSheet writeSheet = EasyExcel.writerSheet(shellData.getSheetName()).head(shellData.getClazz()).build();excelWriter.write(shellData.getList(), writeSheet);}} catch (Exception e) {throw new RuntimeException("导出Excel异常", e);} finally {if (excelWriter != null) {excelWriter.finish();}}byteArrayOutputStream.writeTo(zipOut);zipOut.closeEntry();}} catch (Exception e) {throw new RuntimeException("导出Excel异常", e);}}} catch (IOException e) {throw new RuntimeException("导出Excel异常", e);}}

3.2 web导出

可以调用本方法,直接在Controller中调用之后,当访问对应url,会直接下载到浏览器。

    /*** 导出多个sheet到多个excel文件,并压缩到一个zip文件*/public static void exportZip(String zipFilename, List<ExcelData> excelDataList, HttpServletResponse response) {try {// 这里URLEncoder.encode可以防止中文乱码zipFilename = URLEncoder.encode(zipFilename, "utf-8");// 指定文件名response.setHeader("Content-disposition", "attachment;filename=" + zipFilename);response.setContentType("application/x-msdownload");response.setCharacterEncoding("utf-8");exportZipStream(excelDataList, response.getOutputStream());} catch (IOException e) {throw new RuntimeException("导出Excel异常", e);}}

3.3 导出为字节数组

当我们需要导出为字节数组时,可以调用本方法。之后随你怎么加工。

    /*** 导出多个sheet到多个excel文件,并压缩到一个zip文件。最终得到一个字节数组。*/public static byte[] exportZip(List<ExcelData> excelDataList) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();exportZipStream(excelDataList, byteArrayOutputStream);return byteArrayOutputStream.toByteArray();}

四、调试

4.1 构建调试用的实体类

指定简单的几个字段作为导出数据。

    @Data@AllArgsConstructorpublic static class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;}

4.2 控制器调用

组装假数据,进行导出。

@Controller
@RequestMapping("/excel")
public class ExcelDemoController {@GetMapping("/exportTransportDetail")public String exportTransportDetail(HttpServletResponse response) throws IOException {// 压缩包文件名String fileName = "结算单运单明细-" + System.currentTimeMillis() + ".zip";List<ExcelData> excelDataList = new ArrayList<>();// 第一个ExcelExcelData excelData1 = new ExcelData();excelData1.setFilename("结算单运单明细-1-" + System.currentTimeMillis() + ".xlsx");List<DemoData> demoData1 = new ArrayList<>();demoData1.add(new DemoData("excel-sheet1", new Date(), 123112.321));demoData1.add(new DemoData("excel-sheet1", new Date(), 34.3));List<DemoData> demoData2 = new ArrayList<>();demoData2.add(new DemoData("excel-sheet2", new Date(), 123112.321));demoData2.add(new DemoData("excel-sheet2", new Date(), 34.3));ExcelShellData<DemoData> shellData1 = new ExcelShellData<>(demoData1, "sheet1", DemoData.class);ExcelShellData<DemoData> shellData2 = new ExcelShellData<>(demoData2, "sheet2", DemoData.class);excelData1.addShellData(shellData1);excelData1.addShellData(shellData2);// 第2个ExcelExcelData excelData2 = new ExcelData();excelData2.setFilename("结算单运单明细-2-" + System.currentTimeMillis() +".xlsx");List<DemoData> demoData21 = new ArrayList<>();demoData21.add(new DemoData("excel-sheet21", new Date(), 123112.321));demoData21.add(new DemoData("excel-sheet22", new Date(), 34.3));List<DemoData> demoData22 = new ArrayList<>();demoData22.add(new DemoData("excel-sheet21", new Date(), 123112.321));demoData22.add(new DemoData("excel-sheet22", new Date(), 34.3));ExcelShellData<DemoData> shellData21 = new ExcelShellData<>(demoData21, "sheet1", DemoData.class);ExcelShellData<DemoData> shellData22 = new ExcelShellData<>(demoData22, "sheet2", DemoData.class);excelData2.addShellData(shellData21);excelData2.addShellData(shellData22);excelDataList.add(excelData1);excelDataList.add(excelData2);// 写法1///// exportZip(fileName, excelDataList , response);// 写法2///byte[] bytes = exportZip(excelDataList);response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.setContentType("application/x-msdownload");response.setCharacterEncoding("utf-8");response.getOutputStream().write(bytes);response.getOutputStream().flush();return "succ";}
}

4.3 测试结果

可以看到压缩包解压后的效果:
在这里插入图片描述
其中一个文件内容如下:
sheet1:
在这里插入图片描述

sheet2:
在这里插入图片描述

五、注册大数转换器,长度大于15时,转换为字符串

5.1 实现转换器

/*** Excel 数值长度大于maxLength的数值转换为字符串*/public static class ExcelBigNumberConvert implements Converter<Long> {private final int maxLength;public ExcelBigNumberConvert() {this(15);}public ExcelBigNumberConvert(Integer maxLength) {this.maxLength = maxLength;}@Overridepublic Class<Long> supportJavaTypeKey() {return Long.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic Long convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {Object data = cellData.getData();if (data == null) {return null;}String s = String.valueOf(data);if (s.matches("^\\d+$")) {return Long.parseLong(s);}return null;}@Overridepublic CellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {if (object != null) {String str = object.toString();if (str.length() > maxLength) {return new CellData<>(str);}}return null;}}

5.2 使用转换器

在构建建造器时,增加注册转换器即可。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/180837.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webGL开发虚拟实验室

开发虚拟实验室是一个具有挑战性但也非常有趣和有价值的任务。通过 WebGL&#xff0c;你可以创建交互式、沉浸式的虚拟实验室&#xff0c;使用户能够进行实验和学习。以下是一些步骤和关键考虑因素&#xff0c;帮助你开始开发虚拟实验室&#xff0c;希望对大家有所帮助。北京木…

Unity 通过代码控制Texture进行缩放

在实际应用开发中&#xff0c;有时候需要通过代码对Texture进行缩放。 有两个方法&#xff0c;一个是通过控制宽高进行缩放&#xff0c;另一个是通过比例值进行等比例缩放。 1、控制宽高的方法&#xff1a; /// <summary>/// 纹理缩放方法一&#xff0c;指定宽高/// &…

游戏开发原画的设计方法

游戏原画设计是游戏开发中至关重要的一环&#xff0c;因为它直接影响到游戏的视觉吸引力和用户体验。以下是一些常见的游戏原画设计方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 理解游戏概念&…

如何在Python中操作Redis数据库

目录 一、安装redis-py库 二、连接Redis数据库 三、执行操作 1、设置和获取键值对 2、删除键值对 3、获取列表数据 四、处理数据 1、使用哈希表&#xff08;Hash&#xff09;处理关联数据 2、使用列表&#xff08;List&#xff09;处理有序数据 3、使用集合&#xff…

XIAO ESP32S3之AI应用

一、XIAO ESP32S3 AI应用示例 包含 ChatGPT语音助手、关键字识别等 英文:https://wiki.seeedstudio.com/xiao_esp32s3_speech2chatgpt/ 中文:SenseCraft 模型助手部署 | Seeed Studio Wiki 二、XIAO开发板TinyML项目展示 各种XIAO开发板基于Tiny ML的演示项目:XIAO 系列教…

链接共享平台LinkStack

什么是 LinkStack &#xff1f; LinkStack 是一个独特的平台&#xff0c;为在线管理和共享链接提供了高效的解决方案。平台提供了一个类似于 Linktree 的网站&#xff0c;它可以让用户克服社交媒体平台上只能添加一个链接的限制。借助 LinkStack&#xff0c;用户可以轻松链接到…

Jetson AGX XAVIER刷机时提示invalid_request - Authorization flow not allowed

我下的版本是sdkmanager_1.9.2-10899_amd64.deb&#xff0c;安装后后直接在terminal输入 sdkmanager&#xff0c;出来后提示登录有问题&#xff0c;跳到浏览器链接 http://localhost:8080/?error_descriptionAuthorizationflownotallowed&statehttp://localhost:41369&a…

shell_exec 和 exec区别

shell_exec 和 exec 都是用于在 PHP 中执行系统命令的函数&#xff0c;但它们之间有一些区别。 返回值类型&#xff1a;shell_exec 函数返回命令的输出结果作为字符串&#xff0c;而 exec 函数将输出结果存储在数组中。 输出结果&#xff1a;shell_exec 函数返回命令的完整输出…

录音模块:WT588FM01高性能录音语音芯片IC,功能丰富,音质卓越,满足多样化需求

在音频市场日益繁荣的今天&#xff0c;用户对于录音模块的需求也日益多样化。唯创知音针对这一市场趋势&#xff0c;推出了高性能录音语音芯片模块WT588FM01。凭借其远距离录音、优质音质以及多样化的功能&#xff0c;它成为了众多电子产品中的首选之一。 WT588FM01是深圳唯创…

8 有损压缩的.jpg图片文件格式详解,解封装拆包

有损压缩的.jpg文件 作者将狼才鲸创建日期2023-11-28 1&#xff09;简述 JPEG文件描述 JPEG协议格式分为JPEG、渐进式JPEG&#xff08;图片先显示一部分再显示全部&#xff09;、JPEG2000&#xff08;压缩品质更好&#xff0c;压缩率更高&#xff09;压缩模式&#xff1a;顺序…

苹果mac屏幕投屏镜像工具AirServer2024

airserver 是什么软件&#xff1f;AirServer 是一款 Airplay Mac屏幕镜像应用&#xff0c;AirServer可以通过 mac 实时接收iPhone、iPad以及Android设备的实时屏幕画面。AirServer 可以将一个简单的大屏幕或投影仪变成一个通用的屏幕镜像接收器。在您的大屏幕上启用 AirServer …

Databend 开源周报第 121 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持追加流 Da…

11月27日,每日信息差

今天是2023年11月27日&#xff0c;以下是为您准备的20条信息差 第一、阿里达摩院AI突破胰腺癌早筛难题。通过平扫CT&#xff0c;在2万多真实世界连续病人群体中发现了31例临床漏诊病变&#xff0c;其中2例早期胰腺癌病患已完成手术治愈 第二、丰田汽车将于11月29日恢复丰田车…

python之pyqt专栏7-信号与槽3

在上一篇文章中python之pyqt专栏6-信号与槽2-CSDN博客中&#xff0c;我们可以了解到对象可以使用内置信号&#xff0c;这些信号来自于类定义或者继承过来的。我们可以对这些信号可以通过connect连接槽函数。 需求 现在有一个需求&#xff0c;有两个UI界面“untitled.ui”和“u…

深度解析异常值在数据分析中的重要性与应对策略

写在前面 在数据分析的过程中&#xff0c;异常值的存在常常是一个需要认真对待的问题。异常值可能影响分析的准确性&#xff0c;导致误导性的结论。本文将深入探讨以下异常值的应对策略&#xff0c;旨在为数据科学家们提供全面、易读、严谨的一些建议。 1.什么是异常值 异常…

Linux 安装 Minio 配置 HTTPS

安装 创建目录 [roott2 local]# mkdir minio [roott2 local]# cd minio [roott2 minio]# mkdir data下载 [roott2 minio]# wget https://dl.min.io/server/minio/release/linux-amd64/minio [roott2 minio]# chmod x minio # 赋权设置账号密码 minio 默认账号密码为 minio…

如何集成一个TypeScript开发环境?

首先要安装个node.js。Node.js (nodejs.org) 然后我们随便建一个文件夹&#xff0c;并且打开它运行到终端 然后再运行命令&#xff1a; npm install typescript -g 成功后 尝试使用 tsc -v 查看版本 接下来再使用命令&#xff1a; tsc --init 我们在.ts文件中尝试输出一些…

.mat格式文件是什么?及将png,jpg,bmp,gif,tiff,psd等格式图片转为.mat格式(附代码)

很多深度学习网络的输入要求为.mat格式&#xff0c;当然也可以直接修改输入数据的代码&#xff0c;比如修改为使用OpenCV读取图片等&#xff0c;但有些网络修改起来比较麻烦&#xff0c;且.mat数据有很多优势&#xff0c;所以部分网络最好还是用默认的.mat格式数据 目录 一、.…

【从零开始学习Linux】一文带你了解yum周边生态及vim常见模式

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;Linux入门 &#x1f52d;【从零开始学习Linux】系列均属于Linux入门&#xff0c;主要包含Linux操作系统下的指令、操作、权限以及开发工具&a…

​无人机摄影测量

无人机摄影测量技术是传统航空摄影测量手段的有力补充&#xff0c;具有机动灵活、高效快速、精细准确、作业成本低、生产周期短、影像获取空间分辨率高、高危地区探测等优势。无人机与航空摄影测量相结合使得“无人机数字低空遥感”成为航空遥感领域的一个崭新发展方向。无人机…