通过自定义拦截器优雅的导出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; }
}
整体来看,代码逻辑分工更加清晰,只有标红的拦截器和获取数据以及导出三部分,更加优雅
通过自定义拦截器优雅的导出Excel并标红的重复数据的更多相关文章
- Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解)
不多说,直接上干货! 一.自定义拦截器类型必须是:类全名$内部类名,其实就是内部类名称 如:zhouls.bigdata.MySearchAndReplaceInterceptor$Builder 二 ...
- Mybatis自定义拦截器与插件开发
在Spring中我们经常会使用到拦截器,在登录验证.日志记录.性能监控等场景中,通过使用拦截器允许我们在不改动业务代码的情况下,执行拦截器的方法来增强现有的逻辑.在mybatis中,同样也有这样的业务 ...
- spring mvc <mvc:annotation-driven/> 自定义拦截器不走
<mvc:annotation-driven/> 这个便签会注册2个自定义拦截器,所以导致请求过来就会自己去走注册的这2个拦截器和定义的一堆bean 但是这个便签是必须得定义的 直接贴代码 ...
- 12.Struts2自定义拦截器
12.自定义拦截器 拦截器是Struts2的一个重要特性.因为Struts2的大多数核心功能都是通过拦截器实现的. 拦截器之所以称之为“拦截器”,是因为它可以拦截Action方法的执行, ...
- 【Java EE 学习 35 下】【struts2】【struts2文件上传】【struts2自定义拦截器】【struts2手动验证】
一.struts2文件上传 1.上传文件的时候要求必须使得表单的enctype属性设置为multipart/form-data,把它的method属性设置为post 2.上传单个文件的时候需要在Act ...
- SpringMVC——自定义拦截器、异常处理以及父子容器配置
自定义拦截器: 一.若想实现自定义拦截器,需要实现 org.springframework.web.servlet.HandlerInterceptor 接口. 二.HandlerIntercepto ...
- Struts2 自定义拦截器
自定义拦截器(权限管理),包含了对ajax和表单请求的拦截 package com.interceptor; import java.io.IOException; import java.io.Pr ...
- Struts2自定义拦截器
1. 需求 自定义拦截器实现,用户登录的访问控制. 2. 定义拦截器类 public class LoginInterceptor extends AbstractInterceptor { @Ove ...
- SpringMvc自定义拦截器
SpringMvc也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义拦截器必须实现HandlerInterceptor接口 -preHandle():这个方法在业务处理器 ...
随机推荐
- insert into select 和select into from 备份表
一 insert into select要求表必须存在 INSERTINTO order_record SELECT * FROM order_today FORCEINDEX (idx_pay_su ...
- 【SpringCloud】03.微服务的设计原则
微服务的设计原则: 一.AKF拆分原则 业界对于可扩展的系统架构设计有一个朴素的理念:通过加机器就可以解决容量和可用性问题(如果一台不行就两台). Y轴(功能)--关注应用中功能划分,基于不同的业务拆 ...
- c#集合随机数
List<int> list = new List<int>(10); Random r=new Random(); int num = 0; for (int i = 0; ...
- MobaXterm 连接 VirtualBox 6 虚拟机中的 CentOS 7
1 运行环境 本机系统:Windows 7 虚拟机软件:Oracle VM VirtualBox 6 虚拟机系统:CentOS 7 MobaXterm(安装在本机上) 2 MobaXterm - 远端 ...
- 论文解读 - Relational Pooling for Graph Representations
1 简介 本文着眼于对Weisfeiler-Lehman算法(WL Test)和WL-GNN模型的分析,针对于WL测试以及WL-GNN所不能解决的环形跳跃连接图(circulant skip link ...
- 【笔记】nrf52832广播使用--厂商自定义数据应用
需求: 1)使用蓝牙不停发送ble广播,发送自定义的数据,并每一秒更新自定义数据. 2)设置不同的发射功率.广播间隔.广播名称 1.初始化 使用nordic官方sdk17版本,打开一个ble串口用例. ...
- day89:luffy:使用Celery完成我的订单超时取消&Polyv视频加密播放
目录 1.我的订单超时取消 2.PoliV视频播放 1.我的订单超时取消 使用Celery完成超时取消功能 mycelery/order/tasks.py from mycelery.main imp ...
- 【webSocket】实现原理
服务端文件: import base64 import hashlib import socket # 将请求头格式化成字典 def get_headers(data): ""&q ...
- redis乐观锁
乐观锁(又名乐观并发控制,Optimistic Concurrency Control,缩写"OCC"),是一种并发控制的方法.它假设多用户并发的事务在处理时不会彼此互相影响,各事 ...
- 《GNU_Makefile》第4章——makefile规则
规则明确在什么情况下,使用什么方法,重构文件,该文件称为目标. make的唯一目的是重构终极目标.终极目标默认是第一个目标. 1. 2.规则语法 TARGETS : PREREQUISITES COM ...