通過自定義攔截器優雅的導出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;

    }
}

 

整體來看,代碼邏輯分工更加清晰,只有標紅的攔截器和獲取數據以及導出三部分,更加優雅

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM