Spring Boot + Easy Excel 自定义复杂样式导入导出

tips:能用模板就用模板,当模板不适用的情况下,再选择自定义生成 Excel。

官网:https://easyexcel.opensource.alibaba.com

安装

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

一、处理自定义导出复杂场景

1、列不固定,动态列
2、动态下拉
3、自定义锁定行/列,添加密码
4、合并单元格
5、导入自定义统一注解统一校验
6、样式处理(字体,颜色,底色,富文本,列宽,行宽等)
7、冻结窗格
8、多Sheet处理

1、列不固定,动态列

  • 首先定义一个公共实体,处理公共字段和动态列字段,具体实体则继承该类即可。
package com.example.springbootexcel.excel.base.model;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;import java.util.List;
import java.util.Map;@Data
public class BaseExcel {@ExcelProperty( value = "序号")private String num;/*** 动态字段处理*/private List<Map<String, Object>> dynamicList;}

2、动态下拉

封装一个公共类,构造入参Map,key为表头,value为下拉字符串数组。
.registerWriteHandler(new DropDownHandler(dropDownMap));

package com.example.springbootexcel.excel.base.style;import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddressList;import java.util.Map;/*** 添加下拉选单** @author jason*/
public class DropDownHandler implements SheetWriteHandler {private final Map<Integer, String[]> dropDownMap;  // key:列号(从0开始), value:下拉数据public DropDownHandler(Map<Integer, String[]> dropDownMap) {this.dropDownMap = dropDownMap;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 不需要实现}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {if (dropDownMap == null || dropDownMap.isEmpty()) {return;}Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();dropDownMap.forEach((columnIndex, dropDownData) -> {// 设置下拉框数据范围 (这里设置从第2行到第10000行)CellRangeAddressList addressList = new CellRangeAddressList(1, 9999, columnIndex, columnIndex);// 创建数据验证约束DataValidationConstraint constraint = helper.createExplicitListConstraint(dropDownData);// 创建数据验证DataValidation validation = helper.createValidation(constraint, addressList);// 阻止输入非下拉选项的值validation.setErrorStyle(DataValidation.ErrorStyle.STOP);validation.setShowErrorBox(true);validation.setSuppressDropDownArrow(true);validation.createErrorBox("提示", "请从下拉选项中选择");// 添加验证到sheetsheet.addValidationData(validation);});}
}

3、自定义锁定行/列,添加密码

@Overridepublic void afterCellCreate(CellWriteHandlerContext context) {WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder();Sheet sheet = writeSheetHolder.getSheet();Workbook workbook = sheet.getWorkbook();Cell cell = context.getCell();int columnIndex = cell.getColumnIndex();Row row = cell.getRow();// 设置工作表保护if (!sheet.getProtect()) {XSSFSheet xssfSheet = (XSSFSheet) sheet;// 启用保护xssfSheet.protectSheet("1234");// 设置保护选项:允许删除未锁定行xssfSheet.lockDeleteRows(false);// 设置保护选项:允许插入未锁定行xssfSheet.lockInsertRows(false);}// 设置工作表的默认单元格样式为不锁定CellStyle defaultStyle = workbook.createCellStyle();defaultStyle.setLocked(false);sheet.setDefaultColumnStyle(columnIndex, defaultStyle);row.setRowStyle(defaultStyle);}

4、合并单元格

sheet.addMergedRegion(new CellRangeAddress(relativeRowIndex, relativeRowIndex, 0, 10));

5、导入自定义统一注解统一校验

package com.example.springbootexcel.excel.base.component;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** tips:非必填校验,填了就校验,不填不校验*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ExcelValidation {/*** 日期校验** @return true表示必须为日期,false表示不限制*/boolean date() default false;/*** 是否必须为数字** @return true表示必须为数字,false表示不限制*/boolean numeric() default false;/*** 是否允许小数,且最多两位小数** @return true表示允许最多两位小数,false表示不允许小数*/boolean decimal() default false;/*** 是否允许斜杠** @return true表示允许斜杠,false表示不允许*/boolean allowSlash() default false;/*** 校验失败时的错误提示信息** @return 错误提示信息*/String message() default "字段校验失败";}

6、样式处理(字体,颜色,底色,富文本,列宽,行宽等)

// 基本样式设置cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setBorderLeft(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);// 设置水平对齐为左对齐cellStyle.setAlignment(HorizontalAlignment.LEFT);// 设置垂直对齐为垂直居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 设置自动换行cellStyle.setWrapText(true);// 创建默认字体Font defaultFont = workbook.createFont();defaultFont.setFontName(DEFAULT_FONT_NAME);defaultFont.setFontHeightInPoints(DEFAULT_FONT_POINTS);defaultFont.setColor(IndexedColors.BLACK.getIndex());defaultFont.setBold(false);// 创建红色字体Font redFont = workbook.createFont();redFont.setFontName(DEFAULT_FONT_NAME);redFont.setFontHeightInPoints(DEFAULT_FONT_POINTS);redFont.setColor(IndexedColors.RED.getIndex());redFont.setBold(true);// 自定义列宽String cellValue = cell.getStringCellValue();Integer columnWidth = COLUMN_WIDTHS.get(cellValue);if (ObjectUtil.isNotNull(columnWidth) && !CollectionUtil.contains(COLUMN_WIDTHS_EXIST, context.getColumnIndex())) {sheet.setColumnWidth(context.getColumnIndex(), columnWidth);COLUMN_WIDTHS_EXIST.add(context.getColumnIndex());}// 设置默认宽度if (!CollectionUtil.contains(COLUMN_WIDTHS_EXIST, context.getColumnIndex())) {sheet.setColumnWidth(context.getColumnIndex(), DEFAULT_COLUMN_WIDTH);}// 提示词if (CollectionUtil.contains(TIPS_LIST, relativeRowIndex)) {defaultFont = redFont;// 合并单元格sheet.addMergedRegion(new CellRangeAddress(relativeRowIndex, relativeRowIndex, 0, 10));}// 表头if (CollectionUtil.contains(HEAD_LIST, relativeRowIndex)) {defaultFont.setBold(true);// 背景色cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);// 动态字段标红if (CollectionUtil.contains(HEAD_READ_COLOR, cell.getColumnIndex())) {defaultFont = redFont;} else {// 星号标红RichTextString richText = cell.getRichStringCellValue();if (StrUtil.startWith(cellValue, "*")) {richText.applyFont(0, 1, redFont);if (cellValue.length() > 1) {richText.applyFont(1, cellValue.length(), defaultFont);}cell.setCellValue(richText);}}}cellStyle.setFont(defaultFont);

7、冻结窗格

.registerWriteHandler(new FreezePaneHandler(2))

package com.example.springbootexcel.excel.base.style;import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.Sheet;/*** 冻结窗格** @author jason*/
public class FreezePaneHandler implements SheetWriteHandler {private final int row;  // 需要冻结的行public FreezePaneHandler(int row) {this.row = row;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Sheet sheet = writeSheetHolder.getSheet();// 冻结首行// sheet.createFreezePane(0, 1, 0, 1);sheet.createFreezePane(0, row, 0, row);}}

8、多Sheet处理

        // 创建 ExcelWriter 对象ExcelWriter excelWriter = EasyExcel.write(filePath).inMemory(true).build();// 写入第1个 SheetWriteSheet sheet1 = EasyExcel.writerSheet("Sheet1").registerWriteHandler(new CommonStyleHandler(MockDataUtil.getHeadReadColor(headList, dynamicList))).registerWriteHandler(new DropDownHandler(dropDownMap)).registerWriteHandler(new FreezePaneHandler(2)).build();excelWriter.write(sheet1DataList, sheet1);// 写入第2个 SheetWriteSheet sheet2 = EasyExcel.writerSheet("Sheet2").head(BrandModelExcel.class).registerWriteHandler(new FreezePaneHandler(1)).build();excelWriter.write(MockDataUtil.brandModelExcelList(), sheet2);// 写入第3个 SheetWriteSheet sheet3 = EasyExcel.writerSheet("Sheet3").head(VehicleNameExcel.class).registerWriteHandler(new FreezePaneHandler(1)).build();excelWriter.write(MockDataUtil.vehicleNameExcelList(), sheet3);// 非常重要:最后一定要关闭 excelWriterexcelWriter.finish();log.info("导出成功:{}", filePath);

源码:https://gitee.com/zhaomingjian/workspace_dora/tree/master/spring-boot-excel

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88041.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spark从入门到实战:安装与使用全攻略

目录一、Spark 简介1.1 Spark 的概念1.2 Spark 的优势1.3 Spark 的应用场景二、安装前准备2.1 硬件要求2.2 软件要求2.3 下载 Spark三、Spark 安装步骤3.1 解压安装包3.2 配置环境变量3.3 配置 spark-env.sh3.4 配置 slaves 文件&#xff08;分布式模式&#xff09;3.5 启动 Sp…

Python 进程间的通信:原理剖析与项目实战

在 Python 编程中,当涉及多进程编程时,进程间的通信(Inter-Process Communication,简称 IPC)是一个重要的课题。多个进程在运行过程中,常常需要交换数据、传递状态或协同工作,这就离不开进程间通信机制。本文将深入讲解 Python 进程间通信的原理,并结合实际项目案例,展…

神经网络之BP算法

一、正向传播正向传播&#xff08;Forward Propagation&#xff09;是神经网络中数据从输入层流向输出层的过程。输入数据通过各层的权重和激活函数逐层计算&#xff0c;最终得到预测输出。数学表示&#xff1a; 对于第 ( l ) 层的神经元&#xff0c;其输出计算如下&#xff1a…

Ubuntu 版本号与别名对照表(部分精选)

Ubuntu 的别名遵循 形容词 动物名 的命名规则&#xff0c;且两个单词首字母相同&#xff0c;按字母表顺序循环使用&#xff08;从 Ubuntu 6.06 开始&#xff09;。 &#x1f4c5; Ubuntu 版本号与别名对照表&#xff08;部分精选&#xff09; 版本号别名 (开发代号)发布时间…

实验03-Spark批处理开发

使用Spark Shell探索RDD 启动并使用Scala Spark Shell 在终端窗口&#xff0c;启动Scala Spark shell&#xff1a; spark-shell --master local查看对象&#xff1a; scala> sc scala> spark输入spark.[TAB]然后可以看到所有可用的方法。 读并显示文本文件 查看文本…

【R语言】Can‘t subset elements that don‘t exist.

Error in select(): ℹ In argument: all_of(label_col). Caused by error in all_of(): ! Cant subset elements that dont exist. ✖ Element Label doesnt exist. Run rlang::last_trace() to see where the error occurred.原文中文解释涉及关键词Error in select()报错发生…

Spring的依赖注入(xml)

引入 首先先明白&#xff0c;依赖注入描述的是在容器中建立bean与bean之间的依赖关系&#xff0c;本质就是将一个类中和别的类解耦的方式&#xff0c;就是把别的类&#xff0c;写在成员变量位置&#xff0c;再对外提供可以给成员变量赋值的方法&#xff0c;外界就直接调用来给…

docker运行的一些常用命令

docker images 显示可以加载的镜像docker ps 显示运行的docker容器 加-a显示所有的容器docker run --name 容器名字 -d 镜像名字docker start 容器名/ID 开启容器docker stop 容器名/ID 关闭容器docker exec -it dock…

Django跨域

步骤 1&#xff1a;安装 django-cors-headerspip install django-cors-headers步骤 2&#xff1a;修改 Django 配置 在 settings.py 中添加&#xff1a;INSTALLED_APPS [...,"corsheaders", # 新增 ]MIDDLEWARE [...,"corsheaders.middleware.CorsMiddleware…

20250706-10-Docker快速入门(下)-Harbor镜像仓库_笔记

一、Harbor镜像仓库搭建与使用1. Harbor概述&#xfeff;&#xfeff;定义: 由VMWare公司开源的容器镜像仓库系统技术基础: 在Docker Registry基础上进行企业级扩展核心特性:提供管理用户界面(GUI)基于角色的访问控制(RBAC)支持&#xfeff;AD/LDAP\mathrm{AD}/\mathrm{LDAP}AD…

JavaScript之数组方法详解

JavaScript之数组方法详解一、数组的创建与基础特性1.1 数组的创建方式1.2 数组的核心特性二、修改原数组的方法2.1 添加/删除元素2.1.1 push()&#xff1a;尾部添加元素2.1.2 pop()&#xff1a;尾部删除元素2.1.3 unshift()&#xff1a;头部添加元素2.1.4 shift()&#xff1a;…

品牌增长困局突围:大模型时代,AI 如何帮我的品牌少走弯路?

AI时代对企业战略的冲击与机遇 在当今瞬息万变的商业环境中&#xff0c;大模型的崛起正以前所未有的力量重塑着各行各业的竞争格局。传统的市场营销、品牌传播模式正在被颠覆&#xff0c;消费者获取信息、认知品牌的方式发生了根本性变化。如果说过去十年是“互联网”的时代&am…

从单体到微服务:Spring Cloud 开篇与微服务设计

一、单体架构的核心痛点与微服务化目标 1. 单体架构的致命缺陷问题表现后果可维护性差百万行代码耦合&#xff0c;修改一处需全量测试迭代周期长&#xff0c;创新停滞扩展性受限无法按模块独立扩缩容&#xff08;如订单模块需扩容时&#xff0c;用户模块被迫一起扩容&#xff0…

篇二 OSI七层模型,TCP/IP四层模型,路由器与交换机原理

一 前言 本章节主要介绍OSI七层模型&#xff0c;TCP/IP四层模型划分&#xff0c;以及日常使用的路由器&#xff0c;交换机的一些基础知识 二 OSI 七层 OSI&#xff08;Open Systems Interconnection Model&#xff09;即开放式系统互联模型&#xff0c;是国际标准化组织提出的&…

【JavaSE面试篇】Java集合部分高频八股汇总

目录 概念 1. 说说Java中的集合&#xff1f; 2. Java中的线程安全的集合有什么&#xff1f; 3. Collections和Collection的区别&#xff1f; 4. 集合遍历的方法有哪些&#xff1f; List 5. 讲一下java里面list的几种实现&#xff0c;几种实现有什么不同&#xff1f; 6.…

利用低空无人机影像进行树种实例分割

在本项先导研究中,我们开发了一个基于低空无人机影像的本地树种机器学习实例分割模型,用于生态调查。该实例分割包括单株树冠的描绘和树种的分类。我们利用无人机影像对20个树种及其对应的学名进行了训练,并收集了这些树种的学名用于机器学习。为了评估该机器学习模型的准确…

二、Flutter基础

目录1. 什么是Widget&#xff1f;Flutter中的Widget分为哪几类&#xff1f;2. StatelessWidget和StatefulWidget的区别3. StatefulWidget生命周期4. 什么是BuildContext&#xff1f;5. 如何优化Widget重建&#xff1f;6. Flutter布局机制7. Row/Column的主轴和交叉轴8. Expande…

设计模式笔记_创建型_建造者模式

1. 建造者模式介绍 建造者模式是一种创建型设计模式&#xff0c;旨在通过将复杂对象的构建过程与其表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。它通常用于构造步骤固定但具体实现可能变化的对象。 1.1 功能&#xff1a; 封装复杂对象的创建过程&#xff1a;适…

【ROS2 自动驾驶学习】03-ROS2常用命令

目录 1. ros2 pkg list 2. ros2 node list 3. ros2 node info 节点名称 4. ros2 topic list 5. ros2 topic info 话题名 6. ros2 topic type 话题名 7. ros2 topic find 消息类型 8. ros2 service list 9. ros2 service type 服务名称 10. ros2 service find 服…

MyBatis-Plus:提升数据库操作效率的利器

在Java开发中&#xff0c;MyBatis是一个非常流行的持久层框架&#xff0c;它简化了数据库操作&#xff0c;提供了灵活的SQL映射功能。然而&#xff0c;随着项目规模的扩大和业务复杂度的增加&#xff0c;开发者需要更高效、更便捷的方式来处理数据库操作。MyBatis-Plus应运而生…