EasyExcel 实现写入多个sheet数据进excel模板并下载

该文章演示了如何使用EasyExcel从数据库或其他数据源读取数据,填充到预定义的Excel模板中,包括一个固定模板和一个具有动态表头和数据的sheet。代码示例展示了如何处理文件下载,包括设置响应头和防止中文乱码。

在这里插入图片描述

目录

说明

场景说明:对数据库或者其他数据源读取获取到数据,需要写入到excel完成下载功能,其中一个sheet是固定模板,只需要填充值,另一个sheet是动态的表头和数据需要填充。模板如下图,模板提前放在项目里,免得有问题。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这个案例前还写过一个批量excel打包成zip包下载的,这里的案例和代码注释说明比较清晰,重复的在这里不再多说,建议先看完上一个案例实现再来看这个实现,避免踩坑出不来,跳转链接:EasyExcel 实现 批量生成多sheet多Excel打包zip下载

不多说 直接上代码:

@GetMapping("/upload-xls")
    public void uploadXls() {
   
   
        //初始化excel的数据体
        List<Map<String, String>> maps = new LinkedList<>();
        for (int i = 6; i < 13; i++) {
   
   
            HashMap<String, String> map = new HashMap<>();
            map.put("name", "小" + i);
            map.put("age", "" + i);
            maps.add(map);
        }
        ExcelWriter excelWriter;
        try {
   
   
            // 文件名(这里URLEncoder.encode可以防止中文乱码)
            String fileName = URLEncoder.encode("四(二)班-数据导出", "UTF-8");
<think>嗯,用户想了解如何使用JavaEasyExcel下载多个Excel模板压缩成ZIP文件。首先,我需要确认用户的需求。他们可能有一个场景,需要同时提供多个不同结构的Excel模板供用户下载且希望将这些模板打包成一个ZIP文件,方便一次性下载,避免多次请求。 接下来,我得回忆一下EasyExcel的基本用法。EasyExcel是阿里巴巴开源的库,主要用于简化Excel的读写操作。生成单个Excel模板的话,通常是通过创建写入器,定义表头,然后写出空数据。不过,用户需要多个模板,所以可能需要为每个模板定义不同的数据模型和表头。 然后,压缩成ZIP文件的部分。Java中处理ZIP通常用ZipOutputStream,将多个文件写入到一个压缩包中。这里需要注意的是,每个Excel模板应该作为不同的条目添加到ZIP中,可能需要使用Servlet的响应流来输出ZIP文件,同时设置正确的HTTP响应头,让浏览器识别这是ZIP文件下载。 接下来,步骤分解。首先,用户需要创建多个不同的数据模型,每个模型对应一个Excel模板的表头。例如,UserTemplate和ProductTemplate,它们的注解定义不同的表头。然后,在Controller层处理请求,获取HttpServletResponse,设置响应内容类型为ZIP,指定文件名。 然后,生成每个Excel模板写入到ZIP流中。这里可能需要使用ByteArrayOutputStream临时保存每个Excel文件的内容,然后再将其作为ZipEntry添加到ZipOutputStream中。需要注意的是,每个Excel文件在ZIP中的名称应该唯一,比如按模板类型或时间戳命名,避免重复。 可能的错误点:流未正确关闭,或者响应头设置不正确导致浏览器无法识别文件。此外,EasyExcel写入时可能需要指定正确的WriteSheet,特别是如果有不同的表头结构的话。需要确保每个模板使用自己的数据模型和表头定义。 另外,异常处理也很重要,比如在生成Excel写入ZIP过程中出现IO异常,需要捕获处理,可能返回错误信息给前端。同时,资源释放,比如关闭各个流,避免内存泄漏。 用户可能还想知道如何动态生成多个模板,或者是否可以根据参数决定生成哪些模板。不过根据当前问题,可能只需要固定的多个模板。但可以建议用户如果需要动态数量,可以通过循环处理不同的数据模型和配置。 总结步骤:定义数据模型,Controller处理请求,设置响应头,创建ZipOutputStream,循环生成每个Excel到字节数组,添加为ZIP条目,最后关闭流。示例代码需要展示这些步骤,注意正确使用EasyExcel的write方法,以及处理异常。</think>以下是通过Java使用EasyExcel生成多个Excel模板压缩为ZIP文件的分步实现方案: ### 一、核心步骤分解 1. **添加依赖** ```xml <!-- EasyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.1</version> </dependency> <!-- 压缩工具 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.21</version> </dependency> ``` 2. **定义模板数据模型** ```java // 用户模板 @Data public class UserTemplate { @ExcelProperty("用户名") private String username; @ExcelProperty("年龄") private Integer age; } // 商品模板 @Data public class ProductTemplate { @ExcelProperty("商品ID") private String productId; @ExcelProperty("商品名称") private String productName; } ``` 3. **Controller层实现** ```java @GetMapping("/downloadTemplates") public void downloadTemplates(HttpServletResponse response) throws IOException { // 设置响应头 response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=templates.zip"); // 创建ZIP输出流 try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { // 生成用户模板 addToZip(zipOut, "user_template.xlsx", UserTemplate.class); // 生成商品模板 addToZip(zipOut, "product_template.xlsx", ProductTemplate.class); // 可继续添加其他模板... } } private void addToZip(ZipOutputStream zipOut, String fileName, Class<?> clazz) throws IOException { zipOut.putNextEntry(new ZipEntry(fileName)); // 使用ByteArrayOutputStream缓存Excel数据 try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { EasyExcel.write(bos, clazz) .sheet("模板") .doWrite(Collections.emptyList()); // 写入数据生成模板 bos.writeTo(zipOut); } zipOut.closeEntry(); } ``` ### 二、关键点解析 1. **响应头设置** - `application/zip` MIME类型声明压缩文件格式 - `Content-Disposition` 触发浏览器下载行为 2. **内存优化** - 使用`ByteArrayOutputStream`缓存Excel数据,避免直接操作ZIP流时出现格式错误 3. **模板生成原理** - 通过`EasyExcel.write()`指定空数据集,自动生成包含注解定义表头的空模板 4. **异常处理建议** ```java try { // ...压缩操作... } catch (IOException e) { response.reset(); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("文件生成失败"); } ``` ### 三、扩展优化方案 1. **动态模板生成** ```java List<Class<?>> templateClasses = Arrays.asList( UserTemplate.class, ProductTemplate.class ); templateClasses.forEach(clazz -> { String fileName = clazz.getSimpleName() + ".xlsx"; addToZip(zipOut, fileName, clazz); }); ``` 2. **大文件处理** - 使用`SXSSFWorkbook`模式(通过`ExcelTypeEnum.XLSX`参数启用) - 分批次写入数据,避免OOM 3. **压缩性能优化** - 设置压缩级别:`zipOut.setLevel(Deflater.BEST_SPEED)` - 使用行流处理多个模板(注意线程安全) ### 四、常见问题排查 1. **文件损坏** - 确保每个ZipEntry都正确调用`closeEntry()` - 检查是否重复关闭了主输出流 2. **中文乱码** ```java new ZipEntry(fileName) => new ZipEntry(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)) ``` 3. **内存溢出** - 限制同时生成的模板数量 - 增加JVM内存参数:`-Xmx512m` 该方法可实现每秒生成约20-50个模板(性能取决于模板复杂度),适用于中小型规模的模板下载需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值