平时我们导入导出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; }
}

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

通过自定义拦截器优雅的导出Excel并标红的重复数据的更多相关文章

  1. Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解)

    不多说,直接上干货! 一.自定义拦截器类型必须是:类全名$内部类名,其实就是内部类名称 如:zhouls.bigdata.MySearchAndReplaceInterceptor$Builder 二 ...

  2. Mybatis自定义拦截器与插件开发

    在Spring中我们经常会使用到拦截器,在登录验证.日志记录.性能监控等场景中,通过使用拦截器允许我们在不改动业务代码的情况下,执行拦截器的方法来增强现有的逻辑.在mybatis中,同样也有这样的业务 ...

  3. spring mvc <mvc:annotation-driven/> 自定义拦截器不走

    <mvc:annotation-driven/> 这个便签会注册2个自定义拦截器,所以导致请求过来就会自己去走注册的这2个拦截器和定义的一堆bean 但是这个便签是必须得定义的 直接贴代码 ...

  4. 12.Struts2自定义拦截器

    12.自定义拦截器        拦截器是Struts2的一个重要特性.因为Struts2的大多数核心功能都是通过拦截器实现的. 拦截器之所以称之为“拦截器”,是因为它可以拦截Action方法的执行, ...

  5. 【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】

    一.struts2文件上传 1.上传文件的时候要求必须使得表单的enctype属性设置为multipart/form-data,把它的method属性设置为post 2.上传单个文件的时候需要在Act ...

  6. SpringMVC——自定义拦截器、异常处理以及父子容器配置

    自定义拦截器: 一.若想实现自定义拦截器,需要实现 org.springframework.web.servlet.HandlerInterceptor 接口. 二.HandlerIntercepto ...

  7. Struts2 自定义拦截器

    自定义拦截器(权限管理),包含了对ajax和表单请求的拦截 package com.interceptor; import java.io.IOException; import java.io.Pr ...

  8. Struts2自定义拦截器

    1. 需求 自定义拦截器实现,用户登录的访问控制. 2. 定义拦截器类 public class LoginInterceptor extends AbstractInterceptor { @Ove ...

  9. SpringMvc自定义拦截器

    SpringMvc也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HandlerInterceptor接口 -preHandle():这个方法在业务处理器 ...

随机推荐

  1. 20200726_java爬虫_使用HttpClient模拟浏览器发送请求

    浏览器获取数据: 打开浏览器 ==> 输入网址 ==> 回车查询 ==> 返回结果 ==> 浏览器显示结果数据 HttpClient获取数据: 创建HttpClient ==& ...

  2. ERROR: No matching distribution found for cv2

    ImportError: No module named cv2和No matching distribution found for cv2的问题 原因 这个是由于没有导入opencv库导致的 解决 ...

  3. FloodFill算法详解及应用

    啥是 FloodFill 算法呢,最直接的一个应用就是「颜色填充」,就是 Windows 绘画本中那个小油漆桶的标志,可以把一块被圈起来的区域全部染色. 这种算法思想还在许多其他地方有应用.比如说扫雷 ...

  4. 老大说新项目的结构和 xxx 项目一样就可以了,我 ……(使用 Maven Archetype 快速创建项目)

    前言 又要开发新项目了,还是创建新项目,怎么办?老大说按照 xxx 项目的结构创建一个新项目就可以了. 公众号:liuzhihangs,记录工作学习中的技术.开发及源码笔记:时不时分享一些生活中的见闻 ...

  5. Flink的sink实战之一:初探

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. Ros中创建msg和srv遇到的问题

    在创建msg和srv文件之后,使用srv和msg文件时候需要对xml文件进行修改,如下: <build_depend>message_generation</build_depend ...

  7. js 元素添加多个监听

    function addListener(element,e,fn){     if(element.addEventListener){         element.addEventListen ...

  8. 测试php

    /** * 测试guzzle * * @return void */ public function index() { $client = new GuzzleHttp\Client(); //12 ...

  9. php xml转数组

    <?php libxml_disable_entity_loader(true); $notify_values = json_decode(json_encode(simplexml_load ...

  10. python_for_else_return

    def login(): # 登录 # 登录 输入用户名密码 # 和self.user_list作比对 while True: username = input('用户名 :') # password ...