使用 easypoi 导出 excel 实现动态列,完美解决!

点击上方“Java基基”,选择“设为星标”

做积极的人,而不是积极废人!

每天 14:00 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:blog.csdn.net/a656678879/

article/details/88050789/

10b826e76b7f693f69814690484961df.png


说明

  • 使用的是easypoi进行导出

  • 行头是动态生成

  • 依据key进行列匹配,进行数据填充

  • 第一列进行纵向动态合并

自己的一个使用,记录一下

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能。

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

工具依赖

<dependency>
    <groupId>cn.afterturn</groupId>
   <artifactId>easypoi-base</artifactId>
   <version>3.2.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
   <artifactId>easypoi-annotation</artifactId>
   <version>3.2.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
   <artifactId>easypoi-web</artifactId>
   <version>3.2.0</version>
</dependency>

基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。

项目地址:https://github.com/YunaiV/onemall

实现效果

变更前样式

c11ed6103d9c734eaf847501eff71520.png

变更后样式

b01e5928dec90f7423348b37716d97c1.png

代码解析

动态生成列头
private List<ExcelExportEntity> dynamicNewAddExcel(Map<String, PlatformStatisParamRespData> paramInfo) {
   //表头的集合,用于添加表头
    List<ExcelExportEntity> entityList = new ArrayList<>();

 //ExcelExportEntity构造参数【第一个是列名头的统计字段,第二个是需要指定的一个key在填充数据的时候是需要根据这个key进行填充值,第三个参数是列宽】
    ExcelExportEntity platformXh = new ExcelExportEntity("统计字段1", "statisKey1", 30);
    //列的合并(纵向列的同名称会进行合并,效果见上图的平台名称的变化)
    platformXh.setMergeVertical(true);
    entityList.add(platformXh);

    ExcelExportEntity statisDateXh = new ExcelExportEntity("统计字段2", "statisKey2", 30);
    entityList.add(statisDateXh);

    //参数信息--[用于动态拼接列头]
    final Iterator<String> iterator = paramInfo.keySet().iterator();
    while (iterator.hasNext()) {
      final String paramKeyStr = iterator.next();
      final String paramNameStr = paramInfo.get(paramKeyStr).getDataName();
      //列头由参数汉字名称,参数key为列key
      entityList.add(new ExcelExportEntity(paramNameStr, paramKeyStr, 30));
    }
    return entityList;
  }
动态填充数据
private List<Map<String, Object>> dynamicListDataByKey(List<PlatformIncomeRespDTO> statisData) {
    //参数类型
    final Set<String> statisParamKey = statisData.get(0).getParamInfo().keySet();
    final List<String> statisDate = statisData.get(0).getStatisDate();
    final int platformNum = statisData.size();

    //最终的数据
    List<Map<String, Object>> datas = new ArrayList<>();
    for (int i = 0; i < platformNum; i++) {
      for (int j = 0; j < statisDate.size(); j++) {
        Map<String, Object> hashMap = new LinkedHashMap<>(10);
        //这个是依据key进行数据的填充,(根据前面填写的statisKey1进行填充数据)
        hashMap.put("statisKey1", statisData.get(i).getPlatformNickName());
        String statisDateStr = statisDate.get(j);
         //这个是依据key进行数据的填充,(根据前面填写的statisKey2进行填充数据)
        hashMap.put("statisKey2", statisDateStr);
        //参数的验证
        for (String paramKey : statisParamKey) {
          for (BiPlatformStatisRespDTO paramData : statisData.get(i).getStatisData().get(j)) {
            if (paramKey.equals(paramData.getParamKey())) {
              hashMap.put(paramData.getParamKey(), paramData.getValue() + "(" + paramData.getRateValue() + ")");
            }
          }
        }
        datas.add(hashMap);
      }
    }
    return datas;
  }
excel的导出
//statisData就是我们查询出来的数据
public void downloadPlatformIncomeContrast(List<PlatformIncomeRespDTO> statisData, HttpServletResponse response) {
    if (CollectionUtils.isEmpty(statisData)) {
      return;
    }
    //获取参数信息
    final Map<String, PlatformStatisParamRespData> paramInfo = statisData.get(0).getParamInfo();

    //拼装列头
    List<ExcelExportEntity> colList = this.dynamicNewAddExcel(paramInfo);

    //数据拼装
    List<Map<String, Object>> list = this.dynamicListDataByKey(statisData);
    final String xlsFileName = DateHelper.getNowString(FormatUnit.yyyyMMddHHmmss, true) + ".xls";
    final Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), colList, list);

    //动态合并纵列[mergeMap key列索引(从0开始),value依赖的列,没有传空,startRow 开始行(从零开始)]
    //Map<Integer, int[]> mer = new HashMap<>();
    //mer.put(0, new int[]{});
    //PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0), mer, 1);
    EasypoiUtil.downLoadExcel(xlsFileName, response, workbook);
  }

EasypoiUtil工具类

public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
    try {
      response.setCharacterEncoding("UTF-8");
      response.setHeader("content-Type", "application/vnd.ms-excel");
      response.setHeader("Content-Disposition",
          "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
      workbook.write(response.getOutputStream());
    } catch (IOException e) {
      throw new RuntimeException(e.getMessage());
    }
  }

PlatformIncomeRespDTO

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PlatformIncomeRespDTO implements Serializable {

  private static final long serialVersionUID = 1100499105160261425L;


  /**
   * 平台别名
   */
  private String platformNickName;

  /*统计时间*/
  private List<String> statisDate;

  /*查询参数信息--[用户收入来源统计导出使用]*/
  private Map<String, PlatformStatisParamRespData> paramInfo;


  /*统计数据*/
  private List<List<BiPlatformStatisRespDTO>> statisData;
}

PlatformStatisParamRespData

@Data
@NoArgsConstructor
@AllArgsConstructor
public class PlatformStatisParamRespData implements Serializable {

  private static final long serialVersionUID = 4263523446154995471L;

  /**
   * 参数名称
   */
  private String dataName;

  /**
   * 参数key
   */
  private String dateKey;

  /**
   * 参数描述
   */
  private String dateDesc;

}

BiPlatformStatisRespDTO

@Data
@AllArgsConstructor
public class BiPlatformStatisRespDTO implements Serializable {

  private static final long serialVersionUID = 6070471415344415351L;

  @Excel(name = "统计字段", orderNum = "1")
  private String param;

  /**
   * 参数的key
   */
  private String paramKey;

  /**
   * 参数描述
   */
  private String paramDesc;

  private String startDate;

  private String endDate;

  @Excel(name = "统计数据", orderNum = "2")
  private String value;

  private String rateValue;

  private Long id;

  private Integer riseOrFall;

  public BiPlatformStatisRespDTO(String startDate, String paramKey, String value) {
    this.paramKey = paramKey;
    this.startDate = startDate;
    this.value = value;
  }

  public BiPlatformStatisRespDTO() {
  }
}

测试用例

测试特殊说明

导出的结果有个控制,是在拼装的时候没有填充此数据,不影响整体效果

测试结果示例
2adffb9ce04b3eff9b8a0a988b1d4ffa.png
测试数据json示例
[
    {
        "paramInfo": {
            "userCount": {
                "dataName": "用户数", 
                "dateDesc": "用户信息", 
                "dateKey": "userCount"
            }, 
            "friendsCount": {
                "dataName": "好友数", 
                "dateDesc": "好友信息", 
                "dateKey": "friendsCount"
            }
        }, 
        "platformNickName": "aaa", 
        "statisData": [
            [
                {
                    "paramKey": "userCount", 
                    "startDate": "2019-12-26", 
                    "value": "100"
                }, 
                {
                    "paramKey": "friendsCount", 
                    "startDate": "2019-12-26", 
                    "value": "200"
                }
            ], 
            [
                {
                    "paramKey": "userCount", 
                    "startDate": "2019-12-27", 
                    "value": "300"
                }, 
                {
                    "paramKey": "friendsCount", 
                    "startDate": "2019-12-27", 
                    "value": "400"
                }
            ]
        ], 
        "statisDate": [
            "2019-12-26", 
            "2019-12-27"
        ]
    }, 
    {
        "paramInfo": {
            "userCount": {
                "dataName": "用户数", 
                "dateDesc": "用户信息", 
                "dateKey": "userCount"
            }, 
            "friendsCount": {
                "dataName": "好友数", 
                "dateDesc": "好友信息", 
                "dateKey": "friendsCount"
            }
        }, 
        "platformNickName": "bbb", 
        "statisData": [
            [
                {
                    "paramKey": "userCount", 
                    "startDate": "2019-12-26", 
                    "value": "500"
                }, 
                {
                    "paramKey": "friendsCount", 
                    "startDate": "2019-12-26", 
                    "value": "600"
                }
            ], 
            [
                {
                    "paramKey": "userCount", 
                    "startDate": "2019-12-27", 
                    "value": "700"
                }, 
                {
                    "paramKey": "friendsCount", 
                    "startDate": "2019-12-27", 
                    "value": "800"
                }
            ]
        ], 
        "statisDate": [
            "2019-12-26", 
            "2019-12-27"
        ]
    }
]
测试用例代码
public class Simple {

  /**
   * @Description: 拼接表头
   * @Param: paramInfo :表头信息
   * @return: java.util.List<cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity>
   * @Author: peikunkun
   * @Date: 2019/12/26 0026 上午 10:42
   */
  private static List<ExcelExportEntity> dynamicNewAddExcel(Map<String, PlatformStatisParamRespData> paramInfo) {
    //表头的集合,用于添加表头
    List<ExcelExportEntity> entityList = new ArrayList<>();

    //ExcelExportEntity构造参数【第一个是列名头的统计字段,第二个是需要指定的一个key在填充数据的时候是需要根据这个key进行填充值,第三个参数是列宽】
    ExcelExportEntity platformXh = new ExcelExportEntity("统计字段1", "statisKey1", 30);
    //列的合并(纵向列的同名称会进行合并,效果见上图的平台名称的变化)
    platformXh.setMergeVertical(true);
    entityList.add(platformXh);

    ExcelExportEntity statisDateXh = new ExcelExportEntity("统计字段2", "statisKey2", 30);
    entityList.add(statisDateXh);

    //参数信息--[用于动态拼接列头]
    final Iterator<String> iterator = paramInfo.keySet().iterator();
    while (iterator.hasNext()) {
      final String paramKeyStr = iterator.next();
      final String paramNameStr = paramInfo.get(paramKeyStr).getDataName();
      //列头由参数汉字名称,参数key为列key
      entityList.add(new ExcelExportEntity(paramNameStr, paramKeyStr, 30));
    }
    return entityList;
  }


  /**
   * @Description: 拼接数据
   * @Param: statisData :拼接数据
   * @Author: peikunkun
   * @Date: 2019/12/26 0026 上午 10:42
   */
  private static List<Map<String, Object>> dynamicListDataByKey(List<PlatformIncomeRespDTO> statisData) {
    //参数类型
    final Set<String> statisParamKey = statisData.get(0).getParamInfo().keySet();
    final List<String> statisDate = statisData.get(0).getStatisDate();
    final int platformNum = statisData.size();

    //最终的数据
    List<Map<String, Object>> datas = new ArrayList<>();
    for (int i = 0; i < platformNum; i++) {
      for (int j = 0; j < statisDate.size(); j++) {
        Map<String, Object> hashMap = new LinkedHashMap<>(10);
        //这个是依据key进行数据的填充,(根据前面填写的statisKey1进行填充数据)
        hashMap.put("statisKey1", statisData.get(i).getPlatformNickName());
        String statisDateStr = statisDate.get(j);
        //这个是依据key进行数据的填充,(根据前面填写的statisKey2进行填充  数据)
        hashMap.put("statisKey2", statisDateStr);
        //参数的验证
        for (String paramKey : statisParamKey) {
          for (BiPlatformStatisRespDTO paramData : statisData.get(i).getStatisData().get(j)) {
            if (paramKey.equals(paramData.getParamKey())) {
              hashMap.put(paramData.getParamKey(), paramData.getValue() + "(" + paramData.getRateValue() + ")");
            }
          }
        }
        datas.add(hashMap);
      }
    }
    return datas;
  }


  @Test
  public void Administrator_84_20191226095523() throws IOException {
    System.out.println("欢迎使用单元测试方法【Administrator_84()_20191226095523】");
    System.out.println("此方法测试描述:【】");
    //拼装第一个数据---------------------------------------------------------------------
    final PlatformIncomeRespDTO platformIncomeRespDTO1 = new PlatformIncomeRespDTO();
    platformIncomeRespDTO1.setPlatformNickName("aaa");
    //拼装时间维度
    platformIncomeRespDTO1.setStatisDate(Lists.newArrayList("2019-12-26","2019-12-27"));
    //拼装头信息
    Map<String, PlatformStatisParamRespData> paramInfo1=new HashMap<>();
    paramInfo1.put("userCount", new PlatformStatisParamRespData("用户数","userCount","用户信息"));
    paramInfo1.put("friendsCount", new PlatformStatisParamRespData("好友数","friendsCount","好友信息"));
    platformIncomeRespDTO1.setParamInfo(paramInfo1);
    //拼装数据
    final ArrayList<List<BiPlatformStatisRespDTO>> data1 = Lists.newArrayList();
    data1.add(Lists.newArrayList(new BiPlatformStatisRespDTO("2019-12-26","userCount","100"),new BiPlatformStatisRespDTO("2019-12-26","friendsCount","200")));
    data1.add(Lists.newArrayList(new BiPlatformStatisRespDTO("2019-12-27","userCount","300"),new BiPlatformStatisRespDTO("2019-12-27","friendsCount","400")));
    platformIncomeRespDTO1.setStatisData(data1);


    //拼装第二个数据---------------------------------------------------------------------
    final PlatformIncomeRespDTO platformIncomeRespDTO2 = new PlatformIncomeRespDTO();
    platformIncomeRespDTO2.setPlatformNickName("bbb");
    //拼装时间维度
    platformIncomeRespDTO2.setStatisDate(Lists.newArrayList("2019-12-26","2019-12-27"));
    //拼装头信息
    Map<String, PlatformStatisParamRespData> paramInfo2=new HashMap<>();
    paramInfo2.put("userCount", new PlatformStatisParamRespData("用户数","userCount","用户信息"));
    paramInfo2.put("friendsCount", new PlatformStatisParamRespData("好友数","friendsCount","好友信息"));
    platformIncomeRespDTO2.setParamInfo(paramInfo2);

    //拼装数据
    final ArrayList<List<BiPlatformStatisRespDTO>> data2 = Lists.newArrayList();
    data2.add(Lists.newArrayList(new BiPlatformStatisRespDTO("2019-12-26","userCount","500"),new BiPlatformStatisRespDTO("2019-12-26","friendsCount","600")));
    data2.add(Lists.newArrayList(new BiPlatformStatisRespDTO("2019-12-27","userCount","700"),new BiPlatformStatisRespDTO("2019-12-27","friendsCount","800")));
    platformIncomeRespDTO2.setStatisData(data2);

    final ArrayList<PlatformIncomeRespDTO> platformIncomeRespDTOS = Lists.newArrayList(platformIncomeRespDTO1, platformIncomeRespDTO2);
    System.out.println(JSONObject.toJSONString(platformIncomeRespDTOS));

    //拼装列头
    List<ExcelExportEntity> colList = dynamicNewAddExcel(paramInfo2);

    //数据拼装
    List<Map<String, Object>> list = dynamicListDataByKey(platformIncomeRespDTOS);

    //文件名称
    final Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), colList, list);

    //此功能与【拼装列头】中的 platformXh.setMergeVertical(true);功能效果一样,可直接使用 platformXh.setMergeVertical(true);进行纵向合并
    //动态合并纵列[mergeMap key列索引(从0开始),value依赖的列,没有传空,startRow 开始行(从零开始)]
    //Map<Integer, int[]> mer = new HashMap<>();
    //mer.put(0, new int[]{});
    //PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0), mer, 1);

    final FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\1.xls");
    //导出excel
    downLoadExcel(null, fileOutputStream, workbook);
  }




  /**
   * @Description: 下载文件
   * @Param: fileName
   * @Param outputStream
   * @Param workbook
   * @return: void
   * @Author: peikunkun
   * @Date: 2019/12/26 0026 上午 10:44
   */
  public static void downLoadExcel(String fileName, FileOutputStream outputStream, Workbook workbook)
      throws IOException {
    try {
      workbook.write(outputStream);
    } catch (IOException e) {
      throw new RuntimeException(e.getMessage());
    } finally {
      outputStream.close();
    }
  }
}


欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

ed9e2d8113c5ec7d91019fdd244e2445.png

已在知识星球更新源码解析如下:

56923f281343dab551dcd7f3b4dde382.png

3726115e23c9f3ad71150f2ed7388fc9.png

475f5f3ff8a9c192a4ab59a11f90fd48.png

7ba074486c270132f76459f99b1aab5c.png

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值