zoukankan      html  css  js  c++  java
  • 通过自定义拦截器优雅的导出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;
    
        }
    }

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

      

  • 相关阅读:
    SCU 3133(博弈)
    SCU 3132(博弈)
    hdu 5183(hash)
    hdu3329(2次dfs)
    hdu5179(数位dp)
    zoj2314(有上下界的网络流)
    CF 519E(树上倍增求lca)
    hdu1251(Trie树)
    SCU 2009(数位dp)
    【Leetcode】Letter Combinations of a Phone Number
  • 原文地址:https://www.cnblogs.com/blogsofmy/p/12979591.html
Copyright © 2011-2022 走看看