通过自定义拦截器优雅的导出Excel并标红的重复数据

     平时我们导入导出Excel的时候如果用poi导出,会发现光设置格式都要很多代码,看起来非常的不优雅。后来业务中遇到了需要导入非常巨大的Excel的需求。如果继续用poi的方式,因为poi把所有excel数据都缓存到内存中,服务器资源又是有限的,所以就有可能导致内存溢出,为了解决这个问题,我发现阿里的EasyExcel导出可以完美的解决这个问题,并且实现方式更加优雅。

     如果业务中需要标红重复的数据,先列一下大致代码。

 /**
     * 导出重复的数据
     *
     * @param planId
     * @param stream
     * @param tenaId
     * @param fileId
     * @param response
     * @throws IOException
     */
    public void screeningExport(Long planId, InputStream stream, Long tenaId, Long fileId, HttpServletResponse response) throws IOException {

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("重复项", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), ScreeningEasyExcelVo.class)
                .registerWriteHandler(new CustomCellWriteHandle())
                .sheet("模板" + Constant.fileIdSeparator + fileId).doWrite(data(stream, planId, tenaId, fileId));


    }

 大致的来说,就是我们传入excel文件流,和对应的业务字段就可以导出了。

 

但是如果想标红某一单元格的数据,那我们就需要自己定义拦截器,同时我们需要知道到底是哪行是重复的,具体校验重复行就不在这里写了,

得到重复行之后,我们把行数存入redis,并且在拦截器中和excel中的行数做对比,如果验证为同一行,那我们就可以对这一行做标红处理,

具体的代码如下

 

package com.guantong.seeing.screening.common;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.guantong.seeing.screening.util.SpringContextHelper;
import org.apache.poi.ss.usermodel.*;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.stream.Stream;

/**
 * @author cuixinxin
 * @desc easyExcel 自定义拦截器
 */
public class CustomCellWriteHandle implements CellWriteHandler {


    public CustomCellWriteHandle() {
    }


    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {
    }


    /**
     * 重写单元格格式--》通过修改每一个单元格格式达到整列标红的效果
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param list
     * @param cell
     * @param head
     * @param integer
     * @param aBoolean
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
        CellStyle cellStyle = cellStyle(workbook);
        //根据校验结果设置单元格文字颜色
        String sheetName = writeSheetHolder.getSheet().getSheetName();
        Long fileId = Long.valueOf(sheetName.substring(sheetName.indexOf(Constant.fileIdSeparator) + 8));
        writeSheetHolder.setSheetName(sheetName.substring(0, sheetName.indexOf(Constant.fileIdSeparator)));
        int rowIndex = cell.getRowIndex();
        if (isExistRepeatData(rowIndex, fileId)) {
            //设置单元格背景色
            Font font = workbook.createFont();
            font.setColor(IndexedColors.RED.getIndex());
            cellStyle.setFont(font);
        }

        cell.setCellStyle(cellStyle);
    }

    private boolean isExistRepeatData(Integer rowNow, Long fileId) {
        StringRedisTemplate stringRedisTemplate = SpringContextHelper.getBean(StringRedisTemplate.class);
        String value = stringRedisTemplate.opsForValue().get(fileId.toString());
        if (StringUtils.isEmpty(value)) {
            return false;
        }
        return Stream.of(value.split(","))
                .anyMatch(k -> k.equals(rowNow.toString()));

    }

    /**
     * 通用样式
     *
     * @param workbook
     * @return
     */
    public static CellStyle cellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        //居中
        cellStyle.setAlignment(HorizontalAlignment.LEFT);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        //设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        return cellStyle;

    }
}

 

整体来看,代码逻辑分工更加清晰,只有标红的拦截器和获取数据以及导出三部分,更加优雅

 

 

  

posted @ 2020-05-28 11:42  山岳之巅  阅读(2144)  评论(2编辑  收藏  举报