Hutool 导出excel并合并单元格

一、Hutool介绍

Hutool:https://www.hutool.cn/

参考文档:https://hutool.cn/docs/#/

API文档:https://apidoc.gitee.com/loolly/hutool/

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。

今天要讲的是excel的导出并合并单元格,其他工具类,可查看参考文档,之后也会陆续的更新一些常用工具类的用法。

二、背景

之前常用的是Apache的POI库,代码复杂、非常耗内存,严重时会导致内存溢出,并发上来,一定会OOM或频繁full gc,后来发现平时使用的Hutool工具类,也有excel的导入导出API,使用起来简单方便。Hutool-poi是针对Apache POI的封装,因此需要用户自行引入POI库,Hutool默认不引入

三、excel普通导出

引入依赖:

推荐引入poi-ooxml,这个包会自动关联引入poi包,且可以很好的支持Office2007+的文档格式

普通导出

/**
     * @Author zmyhow
     * @Description 普通导出excel
     * @Date 11:01 2020/12/16
     * @param response 响应
     * @param fileName excel文件名
     * @param sheetName sheet名称
     * @param headers 表头别名map,有序maplinkHashMap,才能保证表头是有序的
     * @param data 数据集合
     * @return void
     */
    public void exportExcelByHutools(HttpServletResponse response,
                                     String fileName,
                                     String sheetName,
                                     Map<String, String> headers,
                                     List<T> data) {
        //通过工具类创建writer
        try {
            //对于大量数据输出,采用bigwriter,其他方法不变
            // ExcelWriter writer = ExcelUtil.getBigWriter();
            ExcelWriter writer = ExcelUtil.getWriter();
            //设置sheet的名称
            writer.renameSheet(sheetName);
            //设置head的名称, 此时的顺序就是导出的顺序, key就是属性名称, value就是别名
            headers.entrySet().forEach(entry -> {
                //这个添加顺序和导出顺序相同
                writer.addHeaderAlias(entry.getKey(), entry.getValue());
            });
            writer.write(data, true);
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
            writer.flush(response.getOutputStream());
            writer.close();
        } catch (Exception e) {
            //如果导出异常,则生成一个空的文件
            log.info("######导出  excel异常  :{}", e.getMessage());
        }

    }

其他导出方法可参考GitHub:https://github.com/looly/hutool/blob/v5-master/hutool-poi/src/test/java/cn/hutool/poi/excel/ExcelWriteTest.java

四、excel导出并合并单元格

今天重点是合并单元格,最近遇到导出excel需要自定义字段合并单元格,网上查了一些,资料比较少,有些是针对特定项目的逻辑处理,没有一个通用的方法,于是自己就着手写了一个

支持自定义表头别名,合并单元格,创建writer的方法可根据业务需要进行修改。

/**
     * @Author zmyhow
     * @Description hutool导出excel
     * @Date 10:28 2020/12/16
     * @param dataList 数据集合
     * @param fileName excel文件名
     * @param headAliasMap 表头别名
     * @param mergeNameColumnIndexMap 合并单元格的字段名和列角标,角标从0开始
     * @param isMerge 是否需要合并单元格
     * @return void
     */
    public static void hutoolExportExcel(List<?> dataList,
                                         String fileName,
                                         LinkedHashMap<String, String> headAliasMap,
                                         LinkedHashMap<String, Integer> mergeNameColumnIndexMap,
                                         Boolean isMerge) throws Exception {
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(fileName);
        //自定义标题别名
        if (MapUtil.isNotEmpty(headAliasMap)) {
            writer.setHeaderAlias(headAliasMap);
        }
        if (isMerge) {
            //获取需要合并的单元格所对应的行集合
            Map<Integer, List<RowRangeDto>> stringListMap = addMerStrategy(dataList, mergeNameColumnIndexMap);
            //调用merge合并单元格
            layout(writer, stringListMap);
        }
        // 一次性写出内容,使用默认样式,强制输出标题
        writer.write(dataList, true);
        // flush或者close方法后才会真正写出文件;关闭writer,才会释放Workbook对象资源
        writer.close();
    }

addMerStrategy:获取合并单元格对应的行集合map

 /**
     * @Author zmyhow
     * @Description 获取合并单元格对应的行集合
     * @Date 11:16 2020/12/16
     * @param dataList 数据集合
     * @param mergeNameColumnIndexMap 有序map,合并单元格字段和列角标map
     * @return 合并单元格对应的行集合映射
     */
    public static Map<Integer, List<RowRangeDto>> addMerStrategy(List<?> dataList, LinkedHashMap<String, Integer>       mergeNameColumnIndexMap) throws Exception {
        Map<Integer, List<RowRangeDto>> strategyMap = new HashMap<>();
        Object preObj = null;
        int i = 0;
        for (Object currObj : dataList) {
            if (preObj != null) {
                Boolean mergeFlag = false;
                int j = 0;
                for (Map.Entry<String, Integer> entry : mergeNameColumnIndexMap.entrySet()) {
                    //在第一个列合并的情况下,后面的列才需要合并
                    if (mergeFlag || j == 0) {
                        String name = entry.getKey();
                        if (getGetMethod(currObj, name).equals(getGetMethod(preObj, name))) {
                            fillStrategyMap(strategyMap, mergeNameColumnIndexMap.get(name), i);
                            mergeFlag = true;
                        }
                    } else {
                        break;
                    }
                    j++;
                }
            }
            i++;
            preObj = currObj;
        }
        return strategyMap;
    }

getGetMethod:根据方法获取get方法
Hutool 导出excel并合并单元格_第1张图片

fillStrategyMap:获取合并单元格对应的行集合Hutool 导出excel并合并单元格_第2张图片
layout:调用merge,合并单元格Hutool 导出excel并合并单元格_第3张图片

RowRangeDto:起始截止行对象在这里插入图片描述

你可能感兴趣的:(开发工具,excel,java)