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

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

目录

说明

场景说明:对数据库或者其他数据源读取获取到数据,需要写入到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");
            // 设置返回文件信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        }


        //获取模板文件,模板文件需放在 resource下
        String templateExcelFileName = "upload.xlsx";
        InputStream templateExcelInputStream = this.getClass().getClassLoader().getResourceAsStream(templateExcelFileName);
        if (null == templateExcelInputStream) {
            log.error("模板文件不存在!");
        }

        ByteArrayOutputStream outputStream = null;
        ByteArrayOutputStream bos = cloneInputStream(templateExcelInputStream);

        //动态sheet1 Excel表头
        List<String> heads = Arrays.asList("name", "age");
        List<List<String>> excelHeaders = heads.stream().map(Collections::singletonList).collect(Collectors.toList());

        //动态sheet1 Excel数据
        List<List<String>> excelDatas = excelDatas(heads, maps);

        try {
            InputStream copyInputStream = new ByteArrayInputStream(bos.toByteArray());
            outputStream = new ByteArrayOutputStream();
            excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(copyInputStream).excelType(ExcelTypeEnum.XLSX).build();

            WriteSheet writeSheet = EasyExcel.writerSheet(0, "学校信息").build();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("schoolName", "新民小学");
            map.put("className", "四(二)班");
            map.put("count", maps.size());
            map.put("uploadDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(System.currentTimeMillis()));
            excelWriter.fill(map, writeSheet);

            //动态填充表头和内容
            WriteSheet attrSheet = EasyExcel.writerSheet(1, "班级学生信息").build();
            attrSheet.setHead(excelHeaders);
            excelWriter.write(excelDatas, attrSheet);

            excelWriter.finish();
            outputStream.flush();
            outputStream.close();

            copyInputStream.close();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (null != outputStream) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    log.error("导出 excel 时关闭 outputStream 出现异常", e);
                }
            }
        }
    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

就先说到这 \color{#008B8B}{ 就先说到这} 就先说到这
在下 A p o l l o \color{#008B8B}{在下Apollo} 在下Apollo
一个爱分享 J a v a 、生活的小人物, \color{#008B8B}{一个爱分享Java、生活的小人物,} 一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞! \color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!} 咱们来日方长,有缘江湖再见,告辞!

在这里插入图片描述

<think>好的,我现在需要帮助用户解决使用EasyExcel导出包含61个sheet页的Excel文件的问题。首先,用户提到了参考引用中的代码片段,其中有一个方法exportSystemExcel,但具体实现需要自己编写。我需要先回忆EasyExcel的基本用法,特别是多sheet导出的方法。 EasyExcel通常通过多次调用write方法指定不同的sheet名称来创建多个sheet。每个sheet对应一个数据列表。对于61个sheet,可能需要循环创建,每次循环生成一个sheet写入对应的数据。但是需要注意,大量sheet导出时内存占用可能会比较高,所以需要考虑分批次处理或者使用缓存机制。 接下来,我应该检查用户的需求是否涉及大数据量。用户提到的是“大规模Excel文件”,所以除了sheet数量多,可能每个sheet数据量也较大。这时候需要确保使用EasyExcel写入特性,比如重复利用头信息、使用模板或者分页查询数据,避免一次性加载所有数据到内存中。 然后,想到EasyExcel的文档中关于多次写入sheet的部分,通常示例代码是多次调用write方法,每次传入不同的sheet名称和数据。例如: ```java ExcelWriter excelWriter = EasyExcel.write(fileName).build(); for (int i = 0; i < 61; i++) { WriteSheet writeSheet = EasyExcel.writerSheet(i, "Sheet" + i).head(head).build(); excelWriter.write(dataList.get(i), writeSheet); } excelWriter.finish(); ``` 这样可以循环创建多个sheet。每个sheet数据可以来自不同的数据源,或者分批次查询。但用户需要导出的是大规模数据,可能需要每个sheet数据也是分页查询的,避免内存溢出。 另外,需要考虑性能问题。61个sheet如果每个都包含大量数据,可能会导致导出时间较长或者内存不足。这时候建议使用分批次查询数据在每次写入时及时清空缓存。例如,对于每个sheet,分页读取数据,逐页写入,而不是一次性加载所有数据。 此外,可能还需要设置参数来优化性能,比如设置autoCloseStream为true,使用默认的ExcleType(xlsx格式),以及调整内存参数,如使用SXSSF模式,不过EasyExcel本身已经做了优化,可能不需要额外设置。 用户可能遇到的另一个问题是sheet名称的重复或长度限制,需要确保每个sheet的名称唯一且符合Excel的命名规则,比如长度不超过31字符,不含特殊字符等。 总结步骤应该是: 1. 创建ExcelWriter对象。 2. 循环61次,每次创建一个WriteSheet,指定名称和表头。 3. 每次循环时,获取对应sheet数据,可能分页查询。 4. 将数据写入对应的sheet。 5. 最后关闭ExcelWriter。 同时,需要处理可能的异常,比如IO异常,确保流正确关闭。在导出完成后,要调用finish方法,关闭资源。 可能还需要考虑发问题,但如果是单线程导出的话,可能不需要处理。另外,如果数据量极大,可能需要使用临时文件或者磁盘缓存,但EasyExcel默认已经处理了这些情况。 最后,给出示例代码,提醒用户注意内存管理和性能优化,比如分页查询数据,避免一次性加载所有数据。同时,检查sheet名称的有效性,确保导出成功。</think>使用 EasyExcel 导出包含 61 个工作表的大规模 Excel 文件时,需通过循环创建多个 `WriteSheet` 对象分批次写入数据。以下是实现步骤与示例代码: --- ### **实现步骤** 1. **初始化 ExcelWriter** 使用 `EasyExcel.write()` 创建 `ExcelWriter` 对象,指定输出流或文件路径。 2. **循环创建 Sheet** 通过循环生成 61 个 `WriteSheet` 对象,每个 Sheet 需设置**唯一名称**和**表头结构**。注意:Sheet 名称长度需 ≤31 字符,且不可重复[^1]。 3. **分批次写入数据** 针对每个 Sheet数据,建议通过分页查询(如数据库分页)逐批读取数据,避免一次性加载全部数据到内存。 4. **关闭资源** 最后调用 `excelWriter.finish()` 确保数据刷入文件释放资源。 --- ### **示例代码** ```java public void exportSystemExcel(HttpServletResponse response) throws IOException { // 1. 初始化 ExcelWriter String fileName = "大规模数据导出.xlsx"; ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()) .autoCloseStream(true) // 自动关闭输出流 .build(); // 2. 循环创建 61 个 Sheet for (int sheetIndex = 0; sheetIndex < 61; sheetIndex++) { // 定义表头(根据业务调整) List<List<String>> head = Arrays.asList( Arrays.asList("字段1"), Arrays.asList("字段2") ); // 创建 WriteSheet 对象 WriteSheet writeSheet = EasyExcel.writerSheet(sheetIndex, "Sheet" + sheetIndex) .head(head) .build(); // 3. 分页查询数据写入(示例仅演示单次写入,实际需循环分页) List<YourDataModel> data = fetchDataByPage(sheetIndex, pageSize); // 自定义数据获取方法 excelWriter.write(data, writeSheet); } // 4. 关闭资源 excelWriter.finish(); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); } ``` --- ### **关键优化点** 1. **内存控制** - 每个 Sheet数据通过 `fetchDataByPage()` 分页查询,避免全量加载。 - EasyExcel 默认使用磁盘缓存(SXSSF 模式),无需手动配置。 2. **性能提升** - 使用 `autoCloseStream(true)` 自动关闭输出流。 - 若数据量极大,可对每个 Sheet 单独分页写入: ```java for (int page = 0; ; page++) { List<YourDataModel> chunk = fetchDataByPage(sheetIndex, page, pageSize); if (chunk.isEmpty()) break; excelWriter.write(chunk, writeSheet); } ``` 3. **异常处理** 添加 `try-catch` 块确保 `excelWriter.finish()` 始终执行,防止流未关闭。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值