easyexcel合并单元格底色
一、效果图
二、导出接口代码
@PostMapping("selectAllMagicExport")public void selectAllMagicExport(HttpServletRequest request, HttpServletResponse response) throws IOException {ServiceResult<SearchResult<TestMetLineFe2o3Export>> result = success(searcher.search(TestMetLineFe2o3Export.class, MapUtils.flat(request.getParameterMap())));SearchResult<TestMetLineFe2o3Export> searchResult = result.getData();List<TestMetLineFe2o3Export> dataList = searchResult.getDataList();// Excel格式:入厂日期相同日期合并// 设置响应头信息response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename=chatEduExport.xlsx");// 使用EasyExcel进行导出ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), TestMetLineFe2o3Export.class).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(new ExcelFillCellMergeStrategy(1, new int[]{1, 4, 5, 6, 12, 14})).build();WriteSheet writeSheet = EasyExcel.writerSheet("铁红").build();excelWriter.write(dataList, writeSheet);excelWriter.finish();}
三、拦截器
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.ciih.workshop.entity.TestMetLineFe2o3Export;
import com.ciih.workshop.utils.HexToRGB;
import com.ejlchina.searcher.BeanSearcher;
import lombok.Data;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;/*** 合并单元格*/
@Component
@Data
public class ExcelFillCellMergeStrategy implements CellWriteHandler {@Resourceprivate BeanSearcher searcher;// 先声明一个对象private static ExcelFillCellMergeStrategy excelFillCellMergeStrategy;//启动注入@PostConstructpublic void init() {excelFillCellMergeStrategy = this;excelFillCellMergeStrategy.searcher = this.searcher;}/*** 合并字段的下标,如第一到五列new int[]{0,1,2,3,4}*/private int[] mergeColumnIndex;/*** 从第几行开始合并,如果表头占两行,这个数字就是2*/private int mergeRowIndex;public ExcelFillCellMergeStrategy() {}public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {this.mergeRowIndex = mergeRowIndex;this.mergeColumnIndex = mergeColumnIndex;}@Overridepublic void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,Head head, Integer integer, Integer integer1, Boolean aBoolean) {}@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,Head head, Integer integer, Boolean aBoolean) {}@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {// 当前单元格Cell cell = context.getCell();//当前行int curRowIndex = context.getCell().getRowIndex();//当前列int curColIndex = context.getCell().getColumnIndex();if (curRowIndex > mergeRowIndex) {for (int i = 0; i < mergeColumnIndex.length; i++) {if (curColIndex == mergeColumnIndex[i]) {// 合并单元格mergeWithPrevRow(context.getWriteSheetHolder(), context.getCell(), curRowIndex, curColIndex);break;}}}// 设置内容居中WriteCellData<?> cellData = context.getFirstCellData();WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 设置边框writeCellStyle.setBorderBottom(BorderStyle.THIN);writeCellStyle.setBorderLeft(BorderStyle.THIN);writeCellStyle.setBorderRight(BorderStyle.THIN);writeCellStyle.setBorderTop(BorderStyle.THIN);// 忽略表头if (cell.getRowIndex() > 0) {// 底色coloring(context, writeCellStyle, cell, curRowIndex, curColIndex);}}/*** 着色** @param writeCellStyle* @param cell* @param curRowIndex 当前行* @param curColIndex 当前列*/private void coloring(CellWriteHandlerContext context, WriteCellStyle writeCellStyle, Cell cell, int curRowIndex, int curColIndex) {// 设置单元格颜色// 拿到当前行的所有数据Cell curInDateCell = cell.getSheet().getRow(curRowIndex).getCell(0); // 唯一编号double id = curInDateCell.getNumericCellValue();// 完整数据HashMap<String, Object> flat = new HashMap<>();flat.put("id", (long) id);TestMetLineFe2o3Export fe2o3Export = excelFillCellMergeStrategy.searcher.searchFirst(TestMetLineFe2o3Export.class, flat);// 渲染入场批号的颜色if (cell.getColumnIndex() == 4) {coloringAction(fe2o3Export.getTestMetInnumStandardColor(), writeCellStyle);// 加批注noteAction(context, cell, fe2o3Export.getTestMetInnumStandardLevel());}// 氯根着色if (cell.getColumnIndex() == 7) {coloringAction(fe2o3Export.getLgStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getLgStandardLevel());}// 水分着色if (cell.getColumnIndex() == 8) {coloringAction(fe2o3Export.getWaterStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getWaterStandardLevel());}// 粒度着色if (cell.getColumnIndex() == 10) {coloringAction(fe2o3Export.getLdStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getLdStandardLevel());}// Na2O着色if (cell.getColumnIndex() == 17) {coloringAction(fe2o3Export.getNa2oStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getNa2oStandardLevel());}// Al2O3着色if (cell.getColumnIndex() == 19) {coloringAction(fe2o3Export.getAl2o3StandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getAl2o3StandardLevel());}// SiO2着色if (cell.getColumnIndex() == 20) {coloringAction(fe2o3Export.getSio2StandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getSio2StandardLevel());}// CaO着色if (cell.getColumnIndex() == 24) {coloringAction(fe2o3Export.getCaoStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getCaoStandardLevel());}// Cr2O3着色if (cell.getColumnIndex() == 26) {coloringAction(fe2o3Export.getCr2o3StandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getCr2o3StandardLevel());}// MnO着色if (cell.getColumnIndex() == 27) {coloringAction(fe2o3Export.getMnoStandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getMnoStandardLevel());}// Fe2O3着色if (cell.getColumnIndex() == 28) {coloringAction(fe2o3Export.getFe2o3StandardColor(), writeCellStyle);noteAction(context, cell, fe2o3Export.getFe2o3StandardLevel());}}/*** 批注*/private void noteAction(CellWriteHandlerContext context, Cell cell, String content) {if (StrUtil.isBlank(content)) {return;}Sheet sheet = context.getWriteSheetHolder().getSheet();ClientAnchor anchor = new XSSFClientAnchor();//关键修改anchor.setDx1(0);anchor.setDx2(0);anchor.setDy1(0);anchor.setDy2(0);anchor.setCol1(cell.getColumnIndex());anchor.setRow1(cell.getRowIndex());anchor.setCol2(cell.getColumnIndex());anchor.setRow2(cell.getRowIndex());Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();Comment cellComment = drawingPatriarch.createCellComment(anchor);cellComment.setString(new XSSFRichTextString(content));cell.setCellComment(cellComment);}/*** 着色动作*/private void coloringAction(String color, WriteCellStyle writeCellStyle) {if (color == null) {return;}Integer r = null;Integer g = null;Integer b = null;//if (color.startsWith("#")) {int[] ints = HexToRGB.hexToRGB(color);r = ints[0];g = ints[1];b = ints[2];} else {List<String> all01 = ReUtil.findAll("(?<=\\().*?(?=\\))", color, 0);if (all01 != null && all01.size() > 0 && all01.get(0).split(",").length >= 3) {String[] split = all01.get(0).split(",");// RGB颜色转换r = Integer.parseInt(split[0].trim());g = Integer.parseInt(split[1].trim());b = Integer.parseInt(split[2].trim());}}if (r != null && g != null && b != null) {HSSFWorkbook wb = new HSSFWorkbook();HSSFPalette palette = wb.getCustomPalette();HSSFColor hssfColor = palette.findSimilarColor(r, g, b);
// writeCellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());writeCellStyle.setFillForegroundColor(hssfColor.getIndex());writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);}}private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :cell.getNumericCellValue();Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :preCell.getNumericCellValue();// 如果是日期列,即第一列,只要相同就合并if (cell.getColumnIndex() == 1) {if (curData.equals(preData)) {Sheet sheet = writeSheetHolder.getSheet();List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();boolean isMerged = false;for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {CellRangeAddress cellRangeAddr = mergeRegions.get(i);// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {sheet.removeMergedRegion(i);cellRangeAddr.setLastRow(curRowIndex);sheet.addMergedRegion(cellRangeAddr);isMerged = true;}}// 若上一个单元格未被合并,则新增合并单元if (!isMerged) {CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,curColIndex);sheet.addMergedRegion(cellRangeAddress);}}} else {// 如果日期和批号与上一行的日期和批号相同。则进行当前行列的合并// 当前行的日期和批号Cell curInDateCell = cell.getSheet().getRow(curRowIndex).getCell(1);Object curInDate = curInDateCell.getCellTypeEnum() == CellType.STRING ? curInDateCell.getStringCellValue() : curInDateCell.getNumericCellValue();Cell curInNumCell = cell.getSheet().getRow(curRowIndex).getCell(4);Object curInNum = curInNumCell.getCellTypeEnum() == CellType.STRING ? curInNumCell.getStringCellValue() : curInNumCell.getNumericCellValue();// 上一行的日期和批号Cell preInDateCell = cell.getSheet().getRow(curRowIndex - 1).getCell(1);Object preInDate = preInDateCell.getCellTypeEnum() == CellType.STRING ? preInDateCell.getStringCellValue() : preInDateCell.getNumericCellValue();Cell preInNumCell = cell.getSheet().getRow(curRowIndex - 1).getCell(4);Object preInNum = preInNumCell.getCellTypeEnum() == CellType.STRING ? preInNumCell.getStringCellValue() : preInNumCell.getNumericCellValue();if (curInDate.equals(preInDate) && curInNum.equals(preInNum)) {Sheet sheet = writeSheetHolder.getSheet();List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();boolean isMerged = false;for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {CellRangeAddress cellRangeAddr = mergeRegions.get(i);// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {sheet.removeMergedRegion(i);cellRangeAddr.setLastRow(curRowIndex);sheet.addMergedRegion(cellRangeAddr);isMerged = true;}}// 若上一个单元格未被合并,则新增合并单元if (!isMerged) {CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,curColIndex);sheet.addMergedRegion(cellRangeAddress);}}}}
}
相关文章:

easyexcel合并单元格底色
一、效果图 二、导出接口代码 PostMapping("selectAllMagicExport")public void selectAllMagicExport(HttpServletRequest request, HttpServletResponse response) throws IOException {ServiceResult<SearchResult<TestMetLineFe2o3Export>> result …...

OpenCV图片校正
OpenCV图片校正 背景几种校正方法1.傅里叶变换 霍夫变换 直线 角度 旋转3.四点透视 角度 旋转4.检测矩形轮廓 角度 旋转参考 背景 遇到偏的图片想要校正成水平或者垂直的。 几种校正方法 对于倾斜的图片通过矫正可以得到水平的图片。一般有如下几种基于opencv的组合方…...

数字孪生流域共建共享相关政策解读
当前数字孪生技术在水利方面的应用刚起步,2021年水利部首次提出“数字孪生流域”概念,即以物理流域为单元、时空数据为底座、数学模型为核心、水利知识为驱动,对物理流域全要素和水利治理管理活动全过程的数字映射、智能模拟、前瞻预演&#…...

FSC147数据集格式解析
一. 引言 在研究很多深度学习框架的时候,往往需要使用到FSC147格式数据集,若要是想在自己的数据集上验证深度学习框架,就需要自己制作数据集以及相关标签,在论文Learning To Count Everything中,该数据集首次被提出。 …...
el-element中el-tabs案例的使用
el-element中el-tabs的使用 代码呈现 <template><div class"enterprise-audit"><div class"card"><div class"cardTitle"><p>交易查询</p></div><el-tabs v-model"activeName" tab-cl…...
tomcat结构目录有哪些?
bin 启动,关闭和其他脚本。这些 .sh文件(对于Unix系统)是这些.bat文件的功能副本(对于 Windows系统)。由于Win32命令行缺少某些功能,因此此处包含一些其他文件。 比如说:windows下启动tomcat用的…...

生成式AI系列 —— DCGAN生成手写数字
1、模型构建 1.1 构建生成器 # 导入软件包 import torch import torch.nn as nnclass Generator(nn.Module):def __init__(self, z_dim20, image_size256):super(Generator, self).__init__()self.layer1 nn.Sequential(nn.ConvTranspose2d(z_dim, image_size * 32,kernel_s…...
vscode-vue项目格式化+语法检验-草稿
Vue学习笔记7 - 在Vscode中配置Vetur,ESlint,Prettier_vetur规则_Myron.Maoyz的博客-CSDN博客...

【Java从0到1学习】10 Java常用类汇总
1. System类 System类对读者来说并不陌生,因为在之前所学知识中,需要打印结果时,使用的都是“System.out.println();”语句,这句代码中就使用了System类。System类定义了一些与系统相关的属性和方法,它所提供的属性和…...

第三届人工智能与智能制造国际研讨会(AIIM 2023)
第三届人工智能与智能制造国际研讨会(AIIM 2023) The 3rd International Symposium on Artificial Intelligence and Intelligent Manufacturing 第三届人工智能与智能制造国际研讨会(AIIM 2023)将于2023年10月27-29日在成都召开…...

层次分析法
目录 一:问题的引入 二:模型的建立 1.分析系统中各因素之间的关系,建立系统的递阶层次结构。 2.对于同一层次的各元素关于上一层次中某一准则的重要性进行两两比较,构造两两比较矩阵(判断矩阵)。 3.由判…...
Error Handling
有几个特定的异常类允许用户代码对与CAN总线相关的特定场景做出反应: Exception (Python standard library)+-- ...+-- CanError (python-can)+-- CanInterfaceNotImplementedError+-- CanInitializationError...

leetcode:字符串相乘(两种方法)
题目: 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 "2", nu…...

【爬虫练习之glidedsky】爬虫-基础2
题目 链接 爬虫往往不能在一个页面里面获取全部想要的数据,需要访问大量的网页才能够完成任务。 这里有一个网站,还是求所有数字的和,只是这次分了1000页。 思路 找到调用接口 可以看到后面有个参数page来控制页码 代码实现 import reques…...
03.有监督算法——决策树
1.决策树算法 决策树算法可以做分类,也可以做回归 决策树的训练与测试: 训练阶段:从给定的训练集构造出一棵树(从根节点开始选择特征,如何进行特征切分) 测试阶段:根据构造出来的树模型从上…...

网络协议详解之STP
目录 一、STP协议(生成树) 1.1 生成树协议核心知识点: 1.2 生成树协议与导致问题: 生成树含义: 1.3 802.1D 规则: 802.1D 缺点: 1.4 PVST cisco私有 1.5 PVST 1.6 快速生成树 快速的原…...

Eltima USB Network Gate 10.0 Crack
USB Network Gate -通过网络共享USB 设备 USB Network Gate (前身为以太网USB控制器USB) 轻松的通过网络(Internet/LAN/WAN)分享您的一个或者多个连接到您计算机的USB设备。 无论您身处异国还是近在隔壁办公室,您都可以轻松使用远程扫描仪、打印机、摄像头、调制解…...
SpringCloudGateway网关实战(一)
SpringCloudGateway网关实战(一) 目前对cloud的gateway功能还是不太熟悉,因此特意新建了对应的应用来尝试网关功能。 网关模块搭建 首先我们新建一个父模块用于添加对应的springboot依赖和cloud依赖。本模块我们的配置读取使用的是nacos&a…...

django中使用ajax发送请求
1、ajax简单介绍 浏览器向网站发送请求时 是以URL和表单的形式提交的post 或get 请求,特点是:页面刷新 除此之外,也可以基于ajax向后台发送请求(异步) 依赖jQuery 编写ajax代码 $.ajax({url: "发送的地址"…...

C++之std::list<string>::iterator迭代器应用实例(一百七十九)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...