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

EasyExcel日常使用总结

文章目录

    • 概要
    • 引入依赖
    • 常用操作方法
      • 折叠或隐藏列
      • 折叠或隐藏行
      • 单元格样式
      • 单行表头设置
      • 多行表头设置
      • 多个sheet写入
      • 自动列宽

概要

EasyExcel日常使用总结。

引入依赖

引入依赖

		<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version></dependency>

常用操作方法

折叠或隐藏列

  1. 新建对象用于存储隐藏列数据,后续直接根据此数据进行折叠隐藏。
@Data
public class ExcelHiddenCellVo {// 分组坐标起始private int startHidden;// 分组坐标结束private int endHidden;// 是否折叠private Boolean ifCollapse;// 是否隐藏private Boolean ifHidden;
}
  1. 计算折叠隐藏列数据(逻辑可根据数据自定义,折叠隐藏的,可以是固定的也可以是动态的)
    private List<ExcelHiddenCellVo> calculateHiddenColumn() {List<ExcelHiddenCellVo> excelHiddenCellVos = new ArrayList<>();ExcelHiddenCellVo excelHiddenCellVo = new ExcelHiddenCellVo();excelHiddenCellVo.setStartHidden(monthValue + 1);excelHiddenCellVo.setEndHidden(12);excelHiddenCellVo.setIfHidden(false);excelHiddenCellVo.setIfCollapse(true);excelHiddenCellVos.add(excelHiddenCellVo);return excelHiddenCellVos;}
  1. 定义RowWriteHandler类方法,在写入每一行数据之前或之后执行自定义操作
private RowWriteHandler rowWriteHandler(List<ExcelHiddenCellVo> excelHiddenCellVos) {return new RowWriteHandler() {@Overridepublic void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {// 列分组if (isHead && relativeRowIndex == 0) {excelHiddenCellVos.forEach(item -> {Sheet sheet = writeSheetHolder.getSheet();sheet.groupColumn(item.getStartHidden(), item.getEndHidden());sheet.setColumnGroupCollapsed(item.getStartHidden(), item.getIfCollapse());});}}};}
  1. 使用的话直接注册一个写入处理器,把RowWriteHandler操作写入。
EasyExcel.write(outputStream).head(this.emailExcelHead(year, deptName)) // 设置表头.inMemory(true).registerWriteHandler(this.rowWriteHandler(this.calculateHiddenColumn())).doWrite(deptKpiStatisticsExportVos);

折叠或隐藏行

和列是类似的,只是使用的Hanlder不一样

  1. 计算折叠隐藏行数据(逻辑可根据数据自定义,折叠隐藏的,可以是固定的也可以是动态的)
// 计算出需要折叠的行private List<ExcelHiddenCellVo> calculateHiddenRow(List<DeptKpiStatisticsExportVo> vos) {List<ExcelHiddenCellVo> excelHiddenCellVos = new ArrayList<>();......
  1. 定义CellWriteHandler类方法,在单元格创建后触发行折叠
private CellWriteHandler cellStyleHandler(List<ExcelHiddenCellVo> excelHiddenCellVos) {return new CellWriteHandler() {@Overridepublic void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {excelHiddenCellVos.forEach(item -> {Sheet sheet = writeSheetHolder.getSheet();sheet.groupRow(item.getStartHidden(), item.getEndHidden());sheet.setRowGroupCollapsed(item.getStartHidden(), true);});}}
}            
  1. 使用的话直接注册一个写入处理器,把CellWriteHandler操作写入。
EasyExcel.write(outputStream).head(this.emailExcelHead(year, deptName)) // 设置表头.inMemory(true).registerWriteHandler(this.rowWriteHandler(this.calculateHiddenColumn())).registerWriteHandler(this.cellStyleHandler(excelHiddenCellVos)).doWrite(deptKpiStatisticsExportVos);

单元格样式

  1. 我一般使用自定义HorizontalCellStyleStrategy类,作为整体的默认样式
// 整体默认的样式private HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {WriteCellStyle headWriteCellStyle = new WriteCellStyle();WriteFont headWriteFont = new WriteFont();headWriteFont.setFontHeightInPoints((short) 9);headWriteFont.setBold(true);headWriteFont.setFontName("微软雅黑");headWriteCellStyle.setWriteFont(headWriteFont);// 内容的策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();// 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);// 背景绿色contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 9);contentWriteFont.setFontName("微软雅黑");contentWriteCellStyle.setWriteFont(contentWriteFont);contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); // 设置水平居中contentWriteCellStyle.setBorderTop(BorderStyle.THIN); // 设置边框contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);// 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}
  1. 需要自定义样式的,再写一个CellWriteHandler类。
// 创建自定义的单元格样式private CellWriteHandler cellStyleHandler(List<FinanceDeptKpiStatisticsExportVo> financeDeptKpiStatisticsExportVos, List<ExcelHiddenCellVo> excelHiddenCellVos) {return new CellWriteHandler() {@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {Cell cell = context.getCell();WriteCellData<?> cellData = context.getFirstCellData();WriteCellStyle writeCellStyle = cellData.getOrCreateStyle();if (cell.getRowIndex() == 0 || cell.getRowIndex() == 1 || cell.getRowIndex() == 2) {WriteFont writeFont = new WriteFont();writeFont.setBold(true);writeFont.setFontName("微软雅黑");writeFont.setFontHeightInPoints((short) 14);writeCellStyle.setBorderTop(BorderStyle.NONE); // 设置边框writeCellStyle.setBorderBottom(BorderStyle.NONE);writeCellStyle.setBorderLeft(BorderStyle.NONE);writeCellStyle.setBorderRight(BorderStyle.NONE);writeCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);writeCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());writeCellStyle.setWriteFont(writeFont);}}      }
}
  1. 使用同样的注册到registerWriteHandler里面。

单行表头设置

  1. 单行表头可以定义一个类,使用@ExcelProperty注解标识每个字段。
@Data
public class ExportVo {@ExcelProperty(index = 0, value = "工号")private String headAccount;@ExcelProperty(index = 1, value = "姓名")private String headName;
}    
  1. 使用
EasyExcel.write(outputStream).head(ExportVo.class) // 设置表头

多行表头设置

使用List<List>嵌套,List里面元素有多少个,则表示有多少级表头。以下为四级表头。

// 表头设置private List<List<String>> emailExcelHead(String year, String deptName) {String title = deptName + "明细表";String titleYear = "(" + year + "年度)";List<List<String>> list = new ArrayList<>();List<String> head1 = new ArrayList<>();head1.add(title);head1.add(titleYear);head1.add("部门:");head1.add("序号");List<String> head2 = new ArrayList<>();head2.add(title);head2.add(titleYear);head2.add(deptName);head2.add("科目");List<String> head3 = new ArrayList<>();head3.add(title);head3.add(titleYear);head3.add("");head3.add("费用类型");list.add(head1);list.add(head2);list.add(head3);return list;

多个sheet写入

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ExcelWriter excelWriter = EasyExcel.write(outputStream).build();WriteSheet writeSheet = EasyExcel.writerSheet("报表1").head(CompleteWarehousingManHourExportVo.class).registerWriteHandler(new ExcelWidthStyleStrategy(0)) // 自定义列宽策略.registerWriteHandler(WriteExcelUtils.getHorizontalCellStyleStrategy()) // 整体单元格的样式设置.registerWriteHandler(this.CompleteWarehousingStyleHandler()) // 自定义单元格样式.registerWriteHandler(this.rowWriteHandler(this.calculateHiddenColumn())) // 列分组.build();excelWriter.write(warehousingManHourExportVos, writeSheet);WriteSheet writeSheet2 = EasyExcel.writerSheet("报表2").head(CompleteMesManHourExportVo.class).registerWriteHandler(new ExcelWidthStyleStrategy(0)) // 自定义列宽策略.registerWriteHandler(WriteExcelUtils.getHorizontalCellStyleStrategy()) // 整体单元格的样式设置.build();excelWriter.write(completeMesManHourExportVos, writeSheet2);excelWriter.finish();outputStream.flush();outputStream.close();InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

自动列宽

使用同样registerWriteHandler注册

public class ExcelWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {// 单元格的最大宽度private static final int MAX_COLUMN_WIDTH = 8;// 缓存(第一个Map的键是sheet的index, 第二个Map的键是列的index, 值是数据长度)private  Map<Integer, Map<Integer, Integer>> CACHE = new HashMap(8);// 表头 0为第a行,1为第2行 依次类推Integer headRow = 0;public ExcelWidthStyleStrategy(Integer headRow){this.headRow = headRow;}// 重写设置列宽的方法@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder,List<WriteCellData<?>> cellDataList,Cell cell,Head head,Integer relativeRowIndex,Boolean isHead) {boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);// 当时表头或者单元格数据列表有数据时才进行处理if (needSetWidth) {Map<Integer, Integer> maxColumnWidthMap =CACHE.get(writeSheetHolder.getSheetNo());if (maxColumnWidthMap == null) {maxColumnWidthMap = new HashMap(16);CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);}// 获取数据长度Integer columnWidth = this.getLength(cellDataList, cell, cell.getRowIndex());if (columnWidth >= 0) {if (columnWidth > MAX_COLUMN_WIDTH) {columnWidth = MAX_COLUMN_WIDTH;}// 确保一个列的列宽以表头为主,如果表头已经设置了列宽,单元格将会跟随表头的列宽Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {// 控制以哪一行为表头,大于1则以第二行if (cell.getRowIndex() >= headRow)maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);// 如果使用EasyExcel默认表头,那么使用columnWidth * 512// 如果不使用EasyExcel默认表头,那么使用columnWidth * 256// 如果是自己定义的字体大小,可以再去测试这个参数常量writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 512);}}}}/*** 获取当前单元格的数据长度* @param cellDataList* @param cell* @param* @return*/private Integer getLength(List<WriteCellData<?>> cellDataList,Cell cell,Integer rowNum) {if (rowNum == headRow) {return cell.getStringCellValue().getBytes().length;} else {WriteCellData cellData = cellDataList.get(0);CellDataTypeEnum type = cellData.getType();if (type == null) {return -1;} else {switch(type) {case STRING:return cellData.getStringValue().getBytes().length;case BOOLEAN:return cellData.getBooleanValue().toString().getBytes().length;case NUMBER:return cellData.getNumberValue().toString().getBytes().length;default:return -1;}}}}}

相关文章:

EasyExcel日常使用总结

文章目录 概要引入依赖常用操作方法折叠或隐藏列折叠或隐藏行单元格样式单行表头设置多行表头设置多个sheet写入自动列宽 概要 EasyExcel日常使用总结。 引入依赖 引入依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</a…...

人只活一次,活出一道光吧

人只活一次, 你怎么舍得让自己的短暂的一生是丑陋的, 你怎么舍得让自己短暂的一生, 只是在往下坠落, 即便是坠落, 也应该具有落日般的华丽吧, 你会漫漫的活成一束光, 谁若接近你, 就是接近光, 【人人都想向上&#xff0c;人人都想老而不衰&#xff0c;但现实是当你想活成一道光…...

sqli-labs:1~16(sql注入点稳定判断语句、全回显半回显报错回显无回显利用思路、sql注入tips)

怎么验证sql注入的存在呢&#xff1f; 首先&#xff0c;双引号单引号注入&#xff0c;看看有没有报错&#xff0c;或者与正常参数的区别&#xff0c;有报错说明大概率可以注入成功&#xff0c;但是&#xff0c;很可能单引号和双引号测试可能没有报错回显&#xff0c;或者与正常…...

springboot农产品销售信息微信小程序—计算机毕业设计源码35557

摘 要 在信息飞速发展的今天&#xff0c;网络已成为人们重要的信息交流平台。每天都有大量的农产品需要通过网络发布&#xff0c;为此&#xff0c;本人开发了一个基于springboot农产品销售信息微信小程序。 对于本农产品销售信息系统的设计来说&#xff0c;它主要是采用后台采…...

HuggingChat macOS 版现已发布

Hugging Face 的开源聊天应用程序 Hugging Chat&#xff0c;现已推出适用于 macOS 的版本。 主要特点 Hugging Chat macOS 版本具有以下亮点: 强大的模型支持: 用户可以一键访问多个顶尖的开源大语言模型&#xff0c;包括 Qwen 2.5 72B、Command R、Phi 3.5、Mistral 12B 等等&…...

C#:动态为Object对象添加新属性的方法

在C#中&#xff0c;object 类型本身是一个基础类型&#xff0c;它不支持直接添加属性&#xff0c;因为 object 并不具备定义属性的能力&#xff08;它不支持任何接口或基类中的属性&#xff0c;除非通过类型转换&#xff09;。然而&#xff0c;有几种方法可以在运行时模拟给对象…...

我常用的几个Python金融数据接口库,非常好用~

在金融分析和量化投资领域&#xff0c;Python已成为最受欢迎的编程语言之一。这主要归功于其丰富的库和框架&#xff0c;它们提供了处理和分析金融数据所需的工具&#xff0c;而且还有大量免费实时的金融股票数据供你分析研究。 以下是六个最常用的Python金融数据接口库&#x…...

【机器学习】ID3、C4.5、CART 算法

目录 常见的决策树算法 1. ID3 2. C4.5 3. CART 决策树的优缺点 优点&#xff1a; 缺点&#xff1a; 决策树的优化 常见的决策树算法 1. ID3 ID3&#xff08;Iterative Dichotomiser 3&#xff09;算法使用信息增益作为特征选择的标准。它是一种贪心算法&#xff0c;信…...

UE5: Content browser工具编写02

DebugHeader.h 中的全局变量&#xff0c;已经在一个cpp file中被include了&#xff0c;如果在另一个cpp file中再include它&#xff0c;就会有一些conflicts。先全部给加一个static Add static keyword to debug functionsWrap all the functions inside of a namespaceprint …...

【ARM】MDK-当选择AC5时每次点击build都会全编译

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 解决MDK中选择AC5时每次点击build都会全编译 2、 问题场景 在MDK中点击build时&#xff0c;正常会只进行增量编译&#xff0c;但目前每次点击的时候都会全编译。 3、软硬件环境 1 软件版本&#xff1a;Keil MDK 5.…...

使用ESPnet的 setup_anaconda.sh安装脚本一步到位,配置conda虚拟环境

使用ESPnet的 setup_anaconda.sh 安装脚本一步到位&#xff0c;配置conda虚拟环境 前言 ESPnet&#xff08;End-to-End Speech Processing Toolkit&#xff09;是一款用于语音识别、语音合成等任务的开源端到端语音处理工具包。为了在不同系统上快速配置ESPnet开发环境&#…...

9、论文阅读:无监督的感知驱动深水下图像增强

Perception-Driven Deep Underwater Image Enhancement Without Paired Supervision 前言引言相关工作UIE模型基于非物理模型基于物理模型基于深度学习质量度量在图像增强中的应用方法论问题表述PQR模型PDD网络生成器损失函数实验Enhancement Without Paired Supervision) 前言…...

谷歌收录查询工具,使用谷歌收录查询工具查询网站收录情况并优化内容的详细步骤

在数字营销和SEO领域&#xff0c;了解网站在谷歌搜索引擎中的收录情况至关重要。使用谷歌收录查询工具&#xff0c;可以有效地监测网站的索引状态&#xff0c;进而优化内容以提升网站排名和曝光度。以下是如何使用谷歌收录查询工具查询网站收录情况并优化内容的详细步骤&#x…...

代理中长效的长板在哪里

伙伴们&#xff0c;之前咱们讨论过了短效代理的用途&#xff0c;那么今天我们来聊一聊长效代理的多元化用途&#xff0c;大家也可以对比一下它们的区别&#xff0c;根据自身的需求针对性地去选择合适的哦。 在企业的网络安全保卫战中&#xff0c;长效代理像是一座坚不可摧的钢…...

VS code Jupyter notebook 导入文件目录问题

VS code Jupyter notebook 导入文件目录问题 引言正文引言 这几天被 VS code 中 Jupyter Notebook 中的文件导入折磨的死去活来。这里特来说明一下放置于不同文件夹下的模块该如何被导入。 正文 首先,我们需要按下 Ctrl + , 键打开设置,然后搜索 notebook file root。在如…...

【IDEA】将光标移动到您上一次编辑的地方

将光标移动到您上一次编辑的地方 使用 ctl <-- 似乎是回到上一个文件而 ctl shift Backspace 是回到上一次的光标&#xff0c;似乎更有用一些。Backspace 是删除按键&#xff0c;要非常小心。 快捷键快速回退到上一次编辑的位置 在 IntelliJ IDEA 中&#xff0c;您可以…...

设备管理平台-支持快速开发

技术路线&#xff08;同时支持前后端分离 / 前后端一体&#xff0c;可用于网关或者服务器部署&#xff09; 前端&#xff1a;layui-v2.9.17 后端&#xff1a;Net8.0 使用组件 Swagger、Jwt、Freesql、MiniExcel、MemoryCache(存储登录用户信息&#xff0c;代替HttpContext.S…...

Vue项目开发注意事项

事项一&#xff1a;项目代码放在本地怎么运行起来 1、首先确定项目对应的node和npm版本 node下载地址 Index of /dist/https://nodejs.org/dist/ node 与 npm版本对应关系 Node.js — Node.js Releases 2、node卸载的时候&#xff0c;会自动把对应的npm卸载掉 情况1&…...

Vivado时序报告之CDC详解大全

目录 一、前言 二、Report CDC 2.1 Report CDC 2.2 配置界面 2.3 CDC报告 2.3.1 General Information 2.3.2 Summary 2.3.3 CDC Details 2.4 Waiver 2.4.1 设置Waiver 2.4.2 报告查看 2.4.3 去除Waiver设置 三、工程设计 四、参考资料 一、前言 前面已经针对…...

【研赛A题成品论文】24华为杯数学建模研赛A题成品论文+可运行代码丨免费分享

2024华为杯研究生数学建模竞赛A题精品成品论文已出&#xff01; A题 风电场有功功率优化分配 一、问题分析 A题是一道工程建模与优化类问题&#xff0c;其目的是根据题目所给的附件数据资料分析风机主轴及塔架疲劳损伤程度&#xff0c;以及建立优化模型求解最优有功功率分配…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

c++第七天 继承与派生2

这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分&#xff1a;派生类构造函数与析构函数 当创建一个派生类对象时&#xff0c;基类成员是如何初始化的&#xff1f; 1.当派生类对象创建的时候&#xff0c;基类成员的初始化顺序 …...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...