当前位置: 首页 > news >正文

EasyExcel中自定义拦截器的运用

在EasyExcel中自定义拦截器不仅可以帮助我们不止步于数据的填充,而且可以对样式、单元格合并等带来便捷的功能。下面直接开始

我们定义一个MergeWriteHandler的类继承AbstractMergeStrategy实现CellWriteHandler

public class MergeLastWriteHandler extends AbstractMergeStrategy implements CellWriteHandler 

当中我们重写merge方法

@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {}

我们可以在重写的方法中得到形参中的Cel,那我们可以通过调用cell.getStringCellValue()得到当前单元格的内容,判断当前单元格的内容是否是目标单元格,例如下面代码

if (cell.getStringCellValue().equals("说明")) {cell.setCellValue("说明:这是一条说明");//获取表格最后一行int lastRowNum = sheet.getLastRowNum();CellRangeAddress region = new CellRangeAddress(lastRowNum, lastRowNum, 0, 5);sheet.addMergedRegionUnsafe(region);}

并且这里我们通过sheet中的 getLastRowNum()获取最后一行,最终通过CellRangeAddress来进行单元格合并,从下面源码我们可以了解到合并的规则是什么(通过int firstRow, int lastRow, int firstCol, int lastCol)

/*** Creates new cell range. Indexes are zero-based.** @param firstRow Index of first row* @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow}* @param firstCol Index of first column* @param lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}*/public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {super(firstRow, lastRow, firstCol, lastCol);if (lastRow < firstRow || lastCol < firstCol) {throw new IllegalArgumentException("Invalid cell range, having lastRow < firstRow || lastCol < firstCol, " +"had rows " + lastRow + " >= " + firstRow + " or cells " + lastCol + " >= " + firstCol);}}

这样就可以实现合并单元格,不过这里可能会出现一个问题

java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cellat org.apache.poi.xssf.streaming.SXSSFCell.typeMismatch(SXSSFCell.java:943)at org.apache.poi.xssf.streaming.SXSSFCell.getStringCellValue(SXSSFCell.java:460)

因为会访问所有的单元格,有可能会出现是不是字符串类型的单元格,所以我们最好在开始的时候对其进行处理一次

if (cell.getCellType().equals(CellType.NUMERIC)){double numericCellValue = cell.getNumericCellValue();String s = Double.toString(numericCellValue);String substring = s.substring(0, s.indexOf("."));cell.setCellValue(substring);}

但这里可能我们还需要一个操作,例如如果我们全局配置了表框线条,但是不想当前的单元格有线条,如何处理呢,定义CustomCellWriteHandler拦截器继承AbstractCellWriteHandler

public class CustomCellWriteHandler extends AbstractCellWriteHandler{}

重写当中的afterCellDispose方法,得到

 @Overridepublic void afterCellDispose(CellWriteHandlerContext context) {super.afterCellDispose(context);}

现在我们对其进行操作

  Cell cell = context.getCell();if(BooleanUtils.isNotTrue(context.getHead())){if(cell.getStringCellValue().contains("说明"))){Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();CellStyle cellStyle = workbook.createCellStyle();cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setAlignment(HorizontalAlignment.LEFT);cell.setCellStyle(cellStyle);context.getFirstCellData().setWriteCellStyle(null); //关键代码,不设置不生效}
}

最后只需要在写入的时候,把拦截器放进去就可以了,看完整代码

public class CustomCellWriteHandler extends AbstractCellWriteHandler {@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {short height = 600;row.setHeight(height);}@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {Cell cell = context.getCell();if(BooleanUtils.isNotTrue(context.getHead())){if(cell.getStringCellValue().contains("说明"))){Workbook workbook = context.getWriteWorkbookHolder().getWorkbook();CellStyle cellStyle = workbook.createCellStyle();cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setAlignment(HorizontalAlignment.LEFT);cell.setCellStyle(cellStyle);context.getFirstCellData().setWriteCellStyle(null);}}super.afterCellDispose(context);}
}

合并单元格的拦截器

public class MergeLastWriteHandler extends AbstractMergeStrategy implements CellWriteHandler {public static HorizontalCellStyleStrategy getStyleStrategy() {// 头的策略WriteCellStyle headWriteCellStyle = new WriteCellStyle();// 设置对齐//headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);// 背景色, 设置为绿色,也是默认颜色headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());// 字体//WriteFont headWriteFont = new WriteFont();//headWriteFont.setFontHeightInPoints((short) 12);//headWriteCellStyle.setWriteFont(headWriteFont);// 内容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定// contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 字体策略WriteFont contentWriteFont = new WriteFont();//contentWriteFont.setFontHeightInPoints((short) 12);contentWriteCellStyle.setWriteFont(contentWriteFont);//设置 自动换行contentWriteCellStyle.setWrapped(true);//设置 垂直居中contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置 水平居中contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//设置边框样式contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderTop(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);return horizontalCellStyleStrategy;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {if (cell.getCellType() == CellType.NUMERIC) {double numericCellValue = cell.getNumericCellValue();String s = Double.toString(numericCellValue);String substring = s.substring(0, s.indexOf("."));cell.setCellValue(substring);}if (cell.getStringCellValue().equals("说明")) {cell.setCellValue("说明:这是一条说明");//获取表格最后一行int lastRowNum = sheet.getLastRowNum();CellRangeAddress region = new CellRangeAddress(lastRowNum, lastRowNum, 0, 5);sheet.addMergedRegionUnsafe(region);}}
}

看一下Controller层

@GetMapping("/excelWrapper")public void excelWrapper(HttpServletResponse response) throws IOException {try {List<User> userList =  DataByExcel();  //获取数据的列表List<BudgetForm> budgetForm = BeanUtil.copyToList(userList,BudgetForm.class);String fileName = one.getProjectName() + ".xlsx";response.setContentType("application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName );// 创建ExcelWriter对象WriteSheet writeSheet = EasyExcel.writerSheet("表格sheet").registerWriteHandler(new MergeLastWriteHandler()).registerWriteHandler(new CustomCellWriteHandler()).build();// 向Excel中写入数据ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), BudgetForm.class).build();excelWriter.write(userList , writeSheet);// 关闭流excelWriter.finish();} catch (Exception e) {e.printStackTrace();}}

对表头设置(自己对应表格设置对应字段)

@Data
@ContentRowHeight(47) //内容行高
@HeadRowHeight(35)//表头行高
public class BudgetForm implements Serializable  {@ColumnWidth(6)@ExcelProperty(value ={"表格","序号"} ,index = 0)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)private Integer serialNumber;@ColumnWidth(15)@ExcelProperty(value ={"表格","名称"} ,index = 1)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)private String name;@ColumnWidth(26)@ExcelProperty(value = {"表格","备注"},index = 2)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)private String remark;@ColumnWidth(26)@ExcelProperty(value = {"表格","其他"},index = 3)@ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER)private String budgetary;@ExcelIgnore@ApiModelProperty("合计")private String total;}

相关文章:

EasyExcel中自定义拦截器的运用

在EasyExcel中自定义拦截器不仅可以帮助我们不止步于数据的填充&#xff0c;而且可以对样式、单元格合并等带来便捷的功能。下面直接开始 我们定义一个MergeWriteHandler的类继承AbstractMergeStrategy实现CellWriteHandler public class MergeLastWriteHandler extends Abst…...

shell编程-7

shell学习第7天 sed的学习1.sed是什么2.sed有两个空间pattern hold3.sed的语法4. sed里单引号和双引号的区别:5.sed的查找方式6.sed的命令sed的标签用法sed的a命令:追加sed的i命令:根据行号插入sed的c命令:整行替换sed的r命令sed的s命令:替换sed的d命令:删除sed中的&符号 7…...

工业智能网关储能物联网应用实现能源的高效利用及远程管理

储能电力物联网是指利用物联网技术和储能技术相结合&#xff0c;实现对电力系统中各种储能设备的智能管理和优化控制。随着可再生能源的不断发展和应用&#xff0c;电力系统面临着越来越大的电力调度和储能需求而储能电力物联网的出现可以有效解决这一问题&#xff0c;提高电力…...

虹科数字化与AR部门升级为安宝特AR子公司

致关心虹科AR的朋友们&#xff1a; 感谢您一直以来对虹科数字化与AR的支持和信任&#xff0c;为了更好地满足市场需求和公司发展的需要&#xff0c;虹科数字化与AR部门现已升级为虹科旗下独立子公司&#xff0c;并正式更名为“安宝特AR”。 ”虹科数字化与AR“自成立以来&…...

服务器是什么?(四种服务器类型)

服务器 服务器定义广义: 专门给其他机器提供服务的计算机。狭义:一台高性能的计算机&#xff0c;通过网络提供外部计算机一些业务服务 个人PC内存大概8G&#xff0c;服务器内存128G起步 服务器是什么 服务器指的是 网络中能对其他机器提供某些服务的计算机系统 &#xff0c;相对…...

09-微服务Sentinel整合GateWay

一、概述 在微服务系统中&#xff0c;网关提供了微服务系统的统一入口&#xff0c;所以我们在做限流的时候&#xff0c;肯定是要在网关层面做一个流量的控制&#xff0c;Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。 1.1 总览 Sentinel 1.6.…...

python基础学习-03 安装

python3 可应用于多平台包括 Windows、Linux 和 Mac OS X。 Unix (Solaris, Linux, FreeBSD, AIX, HP/UX, SunOS, IRIX, 等等。)Win 9x/NT/2000Macintosh (Intel, PPC, 68K)OS/2DOS (多个DOS版本)PalmOSNokia 移动手机Windows CEAcorn/RISC OSBeOSAmigaVMS/OpenVMSQNXVxWorksP…...

HTML — 区块元素

HTML 通过各种标签将元素组合起来。 一. 区块元素 大多数 HTML 元素被定义为块级元素或内联元素。块级元素在浏览器显示时&#xff0c;通常会以新的行开始。例如&#xff1a;<div>、<h1>、<p>、<ul>等。 它们在使用时会独自占据一行&#xff0c;称为块…...

《PCI Express体系结构导读》随记 —— 第I篇 第3章 PCI总线的数据交换(4)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第I篇 第3章 PCI总线的数据交换&#xff08;3&#xff09; 3.2 PCI设备的数据传递 PCI设备的数据传递使用地址译码方式&#xff0c;当一个存储器读写总线事务到达PCI总线时&#xff0c;在这条总线上的所有PCI设…...

力扣0083——删除排序链表中的重复元素

删除排序链表中的重复元素 难度&#xff1a;简单 题目描述 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例1 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2]示例2 输入&#xff1a…...

MySQL数据库的一些缩写含义

DDL Data Definition Language&#xff0c;数据定义语言&#xff0c;用来定义数据库对象(数据库&#xff0c;表&#xff0c;字段) DML DML英文全称是Data Manipulation Language(数据操作语言)&#xff0c;用来对数据库中表的数据记录进 行增、删、改操作。 添加数据&#x…...

解决 ssh: connect to host github.com port 22: Connection timed out

问题 今天使用git克隆github上的代码时&#xff0c;一直报错 原以为是公钥过期了&#xff0c;就尝试修改配置公钥&#xff0c;但是尝试了几次都不行&#xff0c;最终在博客上找到了解决方案&#xff0c;在次记录一下&#xff0c;以备不时之需 解决ssh-connect-to-host-github…...

【iOS ARKit】同时开启前后摄像头BlendShapes

在上一节中已经了解了 iOS ARkit 进行BlendShapes的基本操作&#xff0c;这一小节继续实践同时开启前后摄像头进行人脸捕捉和世界追踪。 iOS设备配备了前后两个摄像头&#xff0c;在运行AR 应用时&#xff0c;需要选择使用哪个摄像头作为图像输人。最常见的AR 体验使用设备后置…...

Vue3动态插入组件

一、使用<component>is实现动态组件插入 <component>&#xff1a;一个用于渲染动态组件或元素的“元组件”。 :is : 要渲染的实际组件&#xff0c;当 is 是字符串&#xff0c;它既可以是 HTML 标签名也可以是组件的注册名。 <script> import Foo from ./F…...

介绍一下OpenCV中常用的图像处理函数

OpenCV中常用的图像处理函数有很多&#xff0c;以下是其中一些函数的介绍&#xff1a; - cvLoadImage()&#xff1a;读入图像函数。 - imshow()&#xff1a;显示图像函数。 - imwrite()&#xff1a;保存图像函数。 - Mat srcImage imread()&#xff1a;读入图像函数。 - …...

vscode vim 快捷键汇总

需满足操作&#xff1a; 上下移动按照 word 移动选中增删改查找字符/变量移动、增加、复制、删除 行选中多个相同的变量/字符屏幕移动增加多个光标快速注释 上下左右移动 CommandDescription&#x1f522; hleft (also: CTRL-H, BS, or Left key)&#x1f522; lright (also…...

npm官方注册表和淘宝镜像切换

1.切换到淘宝镜像 加快npm包的下载速度&#xff0c; //已失效 //npm config set registry https://registry.npm.taobao.org/ npm config set registry https://registry.npmmirror.com这会将npm的注册表设置为淘宝镜像 查看&#xff1a; npm config get registry如果返回的…...

LFU算法

LFU算法 Least Frequently Used&#xff08;最不频繁使用&#xff09; Leetcode有原题&#xff0c;之前手写过LRU&#xff0c;数据结构还是习惯于用java实现&#xff0c;实现是copy的评论题解。 题解注释写的很清楚 大致就是说LFUCache类维护一个存放node的map&#xff0c;同…...

JVM系列-7内存调优

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…...

[UI5 常用控件] 01.Text

文章目录 前言1. 普通文本2. 长文本&#xff1a;3. 设置最大显示行数 ( maxLines3 )4. 单行显示 ( wrappingfalse )5. 显示空白符 ( renderWhitespacetrue )6. 使用 - 连接单词:只适用于英文 ( wrappingTypeHyphenated )7. 空白时使用 - 代替 ( emptyIndicatorModeOn )8. JSON数…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

虚拟电厂发展三大趋势:市场化、技术主导、车网互联

市场化&#xff1a;从政策驱动到多元盈利 政策全面赋能 2025年4月&#xff0c;国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》&#xff0c;首次明确虚拟电厂为“独立市场主体”&#xff0c;提出硬性目标&#xff1a;2027年全国调节能力≥2000万千瓦&#xff0…...