EasyExcel重复多次写入,合并单元格功能详细实现

❤ 作者主页:李奕赫揍小邰的博客

❀ 个人介绍:大家好,我是李奕赫!( ̄▽ ̄)~*

🍊 记得点赞、收藏、评论⭐️⭐️⭐️

📣 认真学习!!!🎉🎉

文章目录

在公司中领导让给查询统计做出一个导出为excel的功能,第一时间想到了easyexcel,为什么?因为他真的很简单,也很容易写,EasyExcel 适用于简单数据的导入导出,因此不是很复杂的导出,都可以考虑使用easyexcel进行实现。但公司的查询统计让我在easyexcel官网中都没有找到合适的样例,因此接下来,我将介绍几种在easyexcel官网中没有记载的使用方式。

EasyExcel

easyexel官网:https://easyexcel.opensource.alibaba.com/

接下来,就默认大家都已经知道easyexcel基本的导出功能了。

如何重复多次将相同的对象写入(写到单个Sheet),并且将列表数据中的某个属性数据排除在外

要导出的页面如下

上述效果需要两个List才能实现,一个是各个业态的数量统计,一个是总数的统计,所以需要将这两个List导入到同一个sheet之中。

java 复制代码
@RequestMapping(value = "/export",method = RequestMethod.GET)
public void exportData(HttpServletResponse response){
    List<ComprehensiveLicenseSummary> summarysheet=comprehensiveLicenseService.getSummarySheet();
    List<ComprehensiveLicenseSummary> summaryTotal = comprehensiveLicenseService.getSummarySheetTotal();
    
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    try {
        String fileName = URLEncoder.encode("汇总表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        //将列表数据中的某个属性数据排除在外不及进行统计,或者也可以直接在实体类中排除的属性数据上方加上@ExcelIgnore即可
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        excludeColumnFiledNames.add("permitArea");
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), ComprehensiveLicenseSummary.class).excludeColumnFiledNames(excludeColumnFiledNames).build();
        WriteSheet sheet1 = EasyExcel.writerSheet("汇总表").build();
        excelWriter.write(summarysheet,sheet1);
        excelWriter.write(summaryTotal,sheet1);
        excelWriter.finish();
    }catch (Exception e){
        log.error("汇总表excel文件导出失败:"+e);
    }
}

如何重复多次将不同对象写入到同一个sheet中,且共用一个标题头

效果图同上,但区别是两个List中的对象不同,因此实体类属性不一样的情况下,如何在导出后位置能够匹配上,共用同一个标题头。

java 复制代码
@RequestMapping(value = "/exportFine",method = RequestMethod.GET)
    public void exportFine(HttpServletResponse response){
        List<BusinessDistrict> businessDistricts = summarySheetService.getFineProof();
        List<BusinessCountByDistrict> businessCountByDistricts = summarySheetService.getBusinessCountByDistrictLicense();
        
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        ExcelWriter excelWriter = null;
        try {
            String fileName = URLEncoder.encode("明细表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            //不同的对象导出到同一个sheet中
            excelWriter = EasyExcel.write(response.getOutputStream()).build();
            WriteSheet sheet1 = EasyExcel.writerSheet("明细表").needHead(Boolean.FALSE).build();
            WriteTable writeTable0 = EasyExcel.writerTable(0).head(BusinessDistrict.class).needHead(Boolean.TRUE).build();
             //这是两个对象,两个标题头的写法.若是需要区分两个对象数据,可以这样尝试。下面再多写两行excelWriter。write()即可
            //WriteTable writeTable1 = EasyExcel.writerTable(1).head(BusinessCountByDistrict.class).needHead(Boolean.TRUE).build();
            excelWriter.write(businessDistricts,sheet1,writeTable0);
            excelWriter.write(businessCountByDistricts,sheet1);
        }catch (Exception e){
            log.error("汇总表excel文件导出失败:"+e);
        }finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

如何合并单列重复数据

接下来是最复杂的一种,导出数据后合并单列重复数据。,怎么能够将第一列重复数据合并成一个,展示成如下的格式呢?

这次数据仅仅只有一个List,但却需要我们多写一个自定义easyExcel处理器,处理单列数据相同合并单元格。在每个单元格完全创建完之后执行合并的功能。可以在处理器里面规定好要合并哪一列。代码编写如下,注解很多应该可以看懂。

java 复制代码
@RequestMapping(value = "/exportProofByBusiness", method = RequestMethod.GET)
public void exportProofByBusinessHandle(HttpServletResponse response) {
    List<BusinessHandleDetail> licenseList = summarySheetService.getDetailProofByBusiness();
    
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.setCharacterEncoding("utf-8");
    ExcelWriter excelWriter = null;
    try {
        String fileName = URLEncoder.encode("明细表", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        // 自定义easyExcel处理器 ,处理单列数据相同合并单元格
        excelWriter = EasyExcel.write(response.getOutputStream(),BusinessHandleDetail.class)
                               .registerWriteHandler(new SimpleExcelMergeUtil()).build();
        WriteSheet sheet = EasyExcel.writerSheet("办理明细表").build();
        excelWriter.write(licenseList,sheet);
    } catch (Exception e) {
        log.error("明细表excel文件导出失败:" + e);
    } finally {
        if (excelWriter != null) {
            excelWriter.finish();
        }
    }
}


//自定义easyExcel处理器,处理单列数据相同合并单元格
public class SimpleExcelMergeUtil implements CellWriteHandler {

    public SimpleExcelMergeUtil() {
    }
    /**
     * 创建每个单元格之前执行
     */
    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }
    /**
     * 创建每个单元格之后执行
     */
    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }
    /**
     * 每个单元格数据内容渲染之后执行
     */
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }
    /**
     * 每个单元格完全创建完之后执行
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        // 当前行
        int curRowIndex = cell.getRowIndex();
        // 当前列
        int curColIndex = cell.getColumnIndex();

        if (!isHead) {
            if (curRowIndex > 1 && curColIndex == 0) {
                // 从第二行数据行开始,获取当前行第一列数据
                Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
                // 获取上一行第一列数据
                Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
                Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
                if (curData.equals(preData)) {
                    Sheet sheet = writeSheetHolder.getSheet();
                    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
                    boolean isMerged = false;
                    for (int i = 0; i < mergedRegions.size() && !isMerged; i++) {
                        CellRangeAddress cellRangeAddr = mergedRegions.get(i);
                        // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                        if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                            sheet.removeMergedRegion(i);
                            cellRangeAddr.setLastRow(curRowIndex);
                            sheet.addMergedRegion(cellRangeAddr);
                            isMerged = true;
                        }
                    }
                    // 若上一个单元格未被合并,则新增合并单元
                    if (!isMerged) {
                        CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                        sheet.addMergedRegion(cellRangeAddress);
                    }
                }
            }
        }
    }
}

总结:

上述只是我在实现导出为excel遇到的问题,因为官网没有具体实例,所以我记录了下来,其他正常的导入导出官方文档都有记载,大家可以多看看官方文档

相关推荐
忒可君2 分钟前
C# winform 报错:类型“System.Int32”的对象无法转换为类型“System.Int16”。
java·开发语言
斌斌_____17 分钟前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@26 分钟前
Spring如何处理循环依赖
java·后端·spring
一个不秃头的 程序员1 小时前
代码加入SFTP JAVA ---(小白篇3)
java·python·github
丁总学Java1 小时前
--spring.profiles.active=prod
java·spring
上等猿1 小时前
集合stream
java
java1234_小锋1 小时前
MyBatis如何处理延迟加载?
java·开发语言
菠萝咕噜肉i1 小时前
MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
java·mybatis·框架·半自动
林的快手1 小时前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
向阳12182 小时前
mybatis 缓存
java·缓存·mybatis