Java使用EasyExcel生成动态表头和多Sheet数据的Excel实例

 更新时间:2025年04月23日 09:22:23   作者:echola_mendes  
这篇文章主要介绍了Java使用EasyExcel生成动态表头和多Sheet数据的Excel实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Java使用EasyExcel生成动态表头和多Sheet数据的Excel

由于业务需求,Excel的表头需要固定表头+动态表头,不同Sheet使用不同的动态表头进行Excel导出,这里还是使用EasyExcel进行数据导出,对关键部分代码会进行释义:

1、动态表头+数据Excel

 String fileName = "设备台账" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
    //根据模版id进行分组,不同模板下的数据,导出为不同Sheet的数据
    Map<Long, DeviceLedgerTemplateEntity> templateMap = deviceTemplateList.stream().collect(Collectors.toMap(DeviceLedgerTemplateEntity::getLedgerTemplateId, v -> v));
    int i = 0;
    response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    fileName = URLEncoder.encode(fileName, "UTF-8");
    response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
    ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
    for (Map.Entry<Long, List<DeviceLedgerImportVO>> deviceMap : deviceTemplateMap.entrySet()) {
       Long templateId = deviceMap.getKey();
       List<List<String>> headList = new ArrayList<>();
       List<List<String>> dataList = new ArrayList<>();
       if (templateMap.containsKey(templateId)) {
          DeviceLedgerTemplateEntity templateEntity = templateMap.get(templateId);
          List<FormDTO> formList = JSONArray.parseArray(templateEntity.getFormItems(), FormDTO.class);
          //动态生成多个Sheet的表头
          getHeadList(headList, formList);
          List<DeviceLedgerImportVO> deviceList = deviceTemplateMap.get(templateId);
          //动态填充多个Sheet的数据
          getDataList(dataList, deviceList);
          //循环输出sheet和表头以及表格内容
          WriteSheet sheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(headList).build();
          excelWriter.write(dataList, sheet);
      }
      i++;
   }
   excelWriter.finish();
  • getHeadList 动态生成表头
  private void getHeadList(List<List<String>> headList, List<FormDTO> formList) {
        //生成Excel中表头
        //固定表头
        Field[] fields = DeviceLedgerImportVO.class.getDeclaredFields();
        for (Field field : fields) {
            boolean bool = field.isAnnotationPresent(ExcelProperty.class);
            if (bool) {
                String value = Arrays.stream(field.getAnnotation(ExcelProperty.class).value()).findFirst().get();
                List<String> filedList = new ArrayList<>();
                filedList.add(value);
                headList.add(filedList);
            }
        }
        //动态表头
        formList.stream().forEach(form -> {
            List<String> filedList = new ArrayList<>();
            filedList.add(form.getLabel());
            headList.add(filedList);
        });
    }
  • getDataList 动态生出数据
   private void getDataList(List<List<String>> dataList, List<DeviceLedgerImportVO> deviceList) {
        //生成Excel中值
        deviceList.stream().forEach(device -> {
            //固定表头下的数据
            List<String> valueList = new ArrayList<>();
            valueList.add(device.getDeviceSn());
            valueList.add(device.getDeviceName());
            valueList.add(device.getDeviceTypeName());
            valueList.add(device.getLocation());
            valueList.add(device.getStatus());
            //动态表头下的数据
            List<FormDTO> formList = JSONArray.parseArray(device.getFormItems(), FormDTO.class);
            if (CollectionUtil.isNotEmpty(formList)) {
                formList.stream().forEach(form -> valueList.add(form.getValue()));
            }
            dataList.add(valueList);
        });
   }
  • Sheet1数据:

  • Shee2数据:

也可以将Excel导出那部分写到工具类,懒的抽出来了,也懒得写Demo了,大概逻辑差不多,需要修改headList和dataList也根据索引导出每个Sheet的数据,在此,提供工具类:

注意:需要修改headList和dataList,不可直接使用上面的headList和dataList方法

  public static void writeDynamicBatchExcel(HttpServletResponse response, String fileName, String sheetName, List<List<String>> headList, List<List<Object>> dataList) throws Exception {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        //循环输出sheet和表头以及表格内容
        for (int i = 0; i < dataList.size(); i++) {
            WriteSheet sheet = EasyExcel.writerSheet(i, "Sheet" + (i + 1)).head(Collections.singletonList(headList.get(i))).build();
            excelWriter.write(dataList.get(i), sheet);
        }
        excelWriter.finish();
    }

2、动态表头Excel

如果只生成动态表头模版,不需要数据的话,getHeadList()不变,仅供参考

   public void downloadDeviceLedger(DeviceLedgerSearchDTO param, HttpServletResponse response) throws IOException {
        //查询模版
        DeviceLedgerTemplateEntity templateEntity = deviceLedgerTemplateService.queryDeviceLedgerTemplate(param.getLedgerTemplateId());
        List<FormDTO> formList = JSONArray.parseArray(templateEntity.getFormItems(), FormDTO.class);
        String fileName = "设备台账" + DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
        List<List<String>> resultList = new ArrayList<>();
        getHeadList(resultList, formList);
        EasyExcelUtils.writeDynamicExcel(response, fileName, "设备台账", resultList, Collections.EMPTY_LIST);
    }

EasyExcelUtils.writeDynamicExcel工具类:

  public static void writeDynamicExcel(HttpServletResponse response, String fileName, String sheetName, List<List<String>> headList, List<List<Object>> dataList) throws IOException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream())
                // 设置动态头
                .head(headList)
                .sheet(sheetName)
                .doWrite(dataList);
    }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决HttpServletResponse和HttpServletRequest取值的2个坑

    解决HttpServletResponse和HttpServletRequest取值的2个坑

    这篇文章主要介绍了解决HttpServletResponse和HttpServletRequest取值的2个坑问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • Mybatis映射文件详解之mapper.xml文件

    Mybatis映射文件详解之mapper.xml文件

    本文详细介绍了Mybatis映射文件的结构、标签和使用方法,包括mapper元素、标签的主要属性如id、parameterType、resultType以及动态SQL和结果映射的使用,通过映射文件,可以将数据库表与Java对象映射,支持查询、插入、更新、删除等操作,提高了SQL语句的灵活性和可重用性
    2024-09-09
  • SpringCloud Feign客户端使用流程

    SpringCloud Feign客户端使用流程

    在springcloud中,openfeign是取代了feign作为负载均衡组件的,feign最早是netflix提供的,他是一个轻量级的支持RESTful的http服务调用框架,内置了ribbon,而ribbon可以提供负载均衡机制,因此feign可以作为一个负载均衡的远程服务调用框架使用
    2023-01-01
  • 通过图例了解IDEA引入JQuery实现步骤

    通过图例了解IDEA引入JQuery实现步骤

    这篇文章主要介绍了IDEA引入JQuery实现步骤图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Okhttp在SpringBoot中的应用实战记录(太强了)

    Okhttp在SpringBoot中的应用实战记录(太强了)

    这篇文章主要给大家介绍了关于Okhttp在SpringBoot中应用实战的相关资料,在Spring Boot中使用OkHttp主要是为了发送HTTP请求和处理响应,OkHttp是一个高效、易用的HTTP客户端库,它具有简洁的API和强大的功能,需要的朋友可以参考下
    2023-12-12
  • Java 超详细讲解类的定义方式和对象的实例化

    Java 超详细讲解类的定义方式和对象的实例化

    Java是一门纯面向对象的语言(Object Oriented Program,继承OOP),在面对对象的世界里面,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情
    2022-03-03
  • Java中的ThreadLocalMap源码解读

    Java中的ThreadLocalMap源码解读

    这篇文章主要介绍了Java中的ThreadLocalMap源码解读,ThreadLocalMap是ThreadLocal的内部类,是一个key-value数据形式结构,也是ThreadLocal的核心,需要的朋友可以参考下
    2023-09-09
  • 使用maven实现版本覆盖的案例分享

    使用maven实现版本覆盖的案例分享

    这篇文章主要介绍了使用maven实现版本覆盖的案例分享,文中通过图文结合的方式给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-10-10
  • java 中的volatile关键字

    java 中的volatile关键字

    这篇文章主要介绍了java 中的volatile关键字,volatile在多处理器开发中保证共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另一个一个线程立马可以读到这个修改的值。下面我们来看看文章的具体介绍内容吧

    2021-12-12
  • IDEA 2020 本土化,真的是全中文了(真香)

    IDEA 2020 本土化,真的是全中文了(真香)

    去年,JetBrains 网站进行了本地化,提供了 8 种不同的语言版本,而现在,团队正在对基于 IntelliJ 的 IDE 进行本地化
    2020-12-12

最新评论