easyexcel 2.2.6版本导出excel模板时,标题带下拉框及其下拉值过多不显示问题
需求背景:有一个需求要做下拉框的值有100多条,同时这个excel是一个多sheet的导入模板
直接用easyexcel 导出,会出现下拉框的值过多,导致生成出来的excel模板无法正常展示下拉功能
使用的easyexcel版本:<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.6</version>
</dependency>
自定义处理器package com.manager.utils;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.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import java.util.Map;/*** 解决使用 easyExcel导出模板,下拉框数据超长,导出模板后,下拉框数据不展示问题* @author yjj* @date 2025/02/18 10:16**/
public class EasyExcelCellWriteHandler implements SheetWriteHandler {public static final String SHEET_NAME = "下拉框隐藏表hidden";/*** 设置阈值,避免生成的导入模板下拉值获取不到*/private static final Integer LIMIT_NUMBER = 50;private Map<Integer, String[]> map = null;public EasyExcelCellWriteHandler(Map<Integer, String[]> map) {this.map = map;}@Overridepublic void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 这里可以对cell进行任何操作Sheet sheet = writeSheetHolder.getSheet();DataValidationHelper helper = sheet.getDataValidationHelper();Class<?> headClass = writeSheetHolder.getClazz();// k 为存在下拉数据集的单元格下表 v为下拉数据集map.forEach((k, v) -> {System.out.println("Key = " + k + ", Value = " + v);// 设置下拉单元格的首行 末行 首列 末列CellRangeAddressList rangeList = new CellRangeAddressList(EasyExcelUtils.headRowNumber(headClass), 65536,k,k);// 如果下拉值总数大于50,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到if (v.length > LIMIT_NUMBER) {//定义sheet的名称//1.创建一个隐藏的sheet 名称为 hidden + kString sheetName = SHEET_NAME +sheet.getSheetName() + k;Workbook workbook = writeWorkbookHolder.getWorkbook();Sheet hiddenSheet = workbook.createSheet(sheetName);for (int i = 0, length = v.length; i < length; i++) {// 开始的行数i,列数khiddenSheet.createRow(i).createCell(k).setCellValue(v[i]);}Name category1Name = workbook.createName();category1Name.setNameName(sheetName);String excelLine = getExcelLine(k);// =hidden!$H:$1:$H$50 sheet为hidden的 H1列开始H50行数据获取下拉数组String refers = "=" + sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.length + 1);// 将刚才设置的sheet引用到你的下拉列表中DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);DataValidation dataValidation = helper.createValidation(constraint, rangeList);writeSheetHolder.getSheet().addValidationData(dataValidation);// 设置存储下拉列值得sheet为隐藏int hiddenIndex = workbook.getSheetIndex(sheetName);if (!workbook.isSheetHidden(hiddenIndex)) {workbook.setSheetHidden(hiddenIndex, true);}}// 下拉列表约束数据DataValidationConstraint constraint = helper.createExplicitListConstraint(v);// 设置约束DataValidation validation = helper.createValidation(constraint, rangeList);// 阻止输入非下拉选项的值validation.setErrorStyle(DataValidation.ErrorStyle.STOP);validation.setShowErrorBox(true);validation.setSuppressDropDownArrow(true);validation.createErrorBox("提示", "此值与单元格定义格式不一致");// validation.createPromptBox("填写说明:","填写内容只能为下拉数据集中的单位,其他单位将会导致无法入仓");sheet.addValidationData(validation);});}/*** 返回excel列标A-Z-AA-ZZ** @param num 列数* @return java.lang.String*/private String getExcelLine(int num) {String line = "";int first = num / 26;int second = num % 26;if (first > 0) {line = (char) ('A' + first - 1) + "";}line += (char) ('A' + second) + "";return line;}}
导出工具类/*** 支持超长下拉框展示* 下载导入模板 - 支持多sheet*/public static void writeTemplateBoxTooLong(HttpServletResponse response, ExcelModel excelModel) {ExcelWriter excelWriter = null;try {excelWriter = EasyExcel.write(outputStream(excelModel.getFileName(), response)).registerConverter(new DateConverter()).useDefaultStyle(false).build();List<ExcelModel.Sheet<?>> sheets = excelModel.getSheets();for (int i = 0; i < sheets.size(); i++) {ExcelModel.Sheet<?> sheet = sheets.get(i);WriteSheet writeSheet;if (ExtraOption.class.isAssignableFrom(sheet.getHeadClass())) {writeSheet = EasyExcel.writerSheet(i, sheet.getSheetName()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(HorizontalCellStyleStrategyFactory.optStyleStrategy()).head(sheet.getHeadClass()).sheetName(sheet.getSheetName()).build();} else {Map<Integer, String[]> map = buildExcelDropDownSetField(sheet.getHeadClass());writeSheet = EasyExcel.writerSheet(i, sheet.getSheetName()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).registerWriteHandler(new EasyExcelCellWriteHandler(map)).registerWriteHandler(new ImportTempleRowWriteHandler()).registerWriteHandler(new ImportTempleCellWriteHandler()).head(sheet.getHeadClass()).sheetName(sheet.getSheetName()).relativeHeadRowIndex(RELATIVE_HEAD_ROW_INDEX).includeColumnFiledNames(sheet.getIncludeFiledNames()).build();}excelWriter.write(sheet.getData(), writeSheet);}} catch (Exception e) {Throwable cause = Throwables.getRootCause(e);log.error("下载模板失败:{}", cause.getMessage(), cause);throw new ServiceException("下载模板失败:{0}", cause.getMessage());} finally {if (excelWriter != null) {excelWriter.finish();}}}
/*** 批量导入 - 支持多sheet*/@SuppressWarnings("rawtypes")public static Map<Class<?>, List<?>> readMultiSheet(MultipartFile file, Class<?>... classes) {Map<Class<?>, List<?>> resultMap = Maps.newHashMapWithExpectedSize(classes.length + 1);try {checkExcelFile(file);ByteArrayInputStream inputStream = deleteHiddenSheets(file);ExcelReader excelReader = EasyExcel.read(inputStream).build();for (int i = 0; i < classes.length; i++) {Class clazz = classes[i];SimpleAnalysisEventListener listener = SimpleAnalysisEventListener.factory(true);ReadSheet readSheet = EasyExcel.readSheet(i).head(clazz).registerReadListener(listener).headRowNumber(headRowNumber(clazz)).build();excelReader.read(readSheet);resultMap.put(clazz, listener.getResults());}if (resultMap.values().stream().allMatch(CollectionUtils::isEmpty)) {throw new ServiceException("请至少录入一条数据");}} catch (Exception e) {Throwable cause = Throwables.getRootCause(e);log.error("解析异常:{}", cause.getMessage(), cause);throw new ServiceException("解析异常:{0}", cause.getMessage());}return resultMap;}//删除导出模板时生成的隐藏sheet,避免导入时读取带隐藏sheet报错public static ByteArrayInputStream deleteHiddenSheets(MultipartFile file){try (InputStream inputStream = file.getInputStream();ByteArrayOutputStream outputStream = new ByteArrayOutputStream();){Workbook workbook = new XSSFWorkbook(inputStream);for (int i = 0; i < workbook.getNumberOfSheets(); i++) {Sheet sheet = workbook.getSheetAt(i);if (sheet.getSheetName().contains(EasyExcelCellWriteHandler.SHEET_NAME)) {workbook.removeSheetAt(i);i--; // 因为删除了一个sheet,索引需要调整}}workbook.write(outputStream);workbook.close();return new ByteArrayInputStream(outputStream.toByteArray());} catch (IOException e) {log.error("解析excel失败!",e);throw new ServiceException("解析失败!");}}

原生poi参考这位大佬:解决POI的SXSSFSheet 创建excel下拉框,下拉框内容过多时不显示的问题_java poi 下拉框数据7万行,隐藏sheet方法也看不不全-CSDN博客
相关文章:
easyexcel 2.2.6版本导出excel模板时,标题带下拉框及其下拉值过多不显示问题
需求背景:有一个需求要做下拉框的值有100多条,同时这个excel是一个多sheet的导入模板 直接用easyexcel 导出,会出现下拉框的值过多,导致生成出来的excel模板无法正常展示下拉功能 使用的easyexcel版本:<depende…...
树(数据结构·)
树(数据结构篇) 里面没有结点时,称之为空树 树型结构是一对多的形式 深度优先遍历: 所谓的DFS,也就是说每次都尝试向更深的节点走,也就是一条路走到黑 当一条路走完,走到…...
XUnity.AutoTranslator-deepseek——调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译
XUnity.AutoTranslator-deepseek 本项目通过调用腾讯的DeepSeek V3 API,实现Unity游戏中日文文本的自动翻译。 准备工作 1. 获取API密钥 访问腾讯云API控制台申请DeepSeek的API密钥(限时免费)。也可以使用其他平台提供的DeepSeek API。 …...
谈谈 ES 6.8 到 7.10 的功能变迁(1)- 性能优化篇
前言 ES 7.10 可能是现在比较常见的 ES 版本。但是对于一些相迭代比较慢的早期业务系统来说,ES 6.8 是一个名副其实的“钉子户”。 借着工作内升级调研的任务东风,我整理从 ES 6.8 到 ES 7.10 ELastic 重点列出的新增功能和优化内容。将分为 6 个篇幅给…...
[250222] Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡 | SQLPage v0.33 发布
目录 Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡SQLPage v0.33 发布:使用 SQL 构建自定义 UI 和 API! Kimi Latest 模型发布:尝鲜最新特性与追求稳定性的平衡 Kimi 开放平台推出全新模型 kimi-latest,旨在…...
深入理解设计模式之解释器模式
深入理解设计模式之解释器模式 在软件开发的复杂世界中,我们常常会遇到需要处理特定领域语言的情况。比如在开发一个计算器程序时,需要解析和计算数学表达式;在实现正则表达式功能时,要解析用户输入的正则表达式来匹配文本。这些场景都涉及到对特定语言的解释和执行,而解…...
深入理解设计模式之代理模式
深入理解设计模式之代理模式 在软件开发的复杂体系中,我们常常会遇到这样的情况:需要控制对某个对象的访问,或者在访问对象前后添加一些额外的处理逻辑,又或者希望在不改变原对象代码的基础上扩展其功能。代理模式(Pr…...
Golang | 每日一练 (3)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...
企业数据集成:实现高效调拨出库自动化
调拨出库对接调出单-v:旺店通企业奇门数据集成到用友BIP 在企业信息化管理中,数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例,展示如何通过轻易云数据集成平台,将旺店通企业奇门的数据无缝集成到用…...
提效10倍:基于Paimon+Dolphin湖仓一体新架构在阿里妈妈品牌业务探索实践
1. 业务背景 阿里妈妈品牌广告数据包括投放引擎、下发、曝光、点击等日志,面向运筹调控、算法特征、分析报表、诊断监控等应用场景,进行了品牌数仓能力建设。随着业务发展,基于Lambda架构的数仓开发模式,缺陷日益突出:…...
Deepseek快速做PPT
背景: DeepSeek大纲生成 → Kimi结构化排版 → 数据审查,细节调整 DeepSeek 拥有深度思考能力,擅长逻辑构建与内容生成,它会根据我们的问题进行思考,其深度思考能力当前测试下来,不愧为国内No.1,而且还会把中间的思考过程展示出来,大多时候会给出很多我们意想不到的思…...
论文解读 | AAAI'25 Cobra:多模态扩展的大型语言模型,以实现高效推理
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 点击 阅读原文 观看作者讲解回放! 个人信息 作者:赵晗,浙江大学-西湖大学联合培养博士生 内容简介 近年来,在各个领域应用多模态大语言模型(MLLMs&…...
uniapp修改picker-view样式
解决问题: 1.选中文案样式,比如字体颜色 2.修改分割线颜色 3.多列时,修改两边间距让其平分 展示效果: 代码如下 <template><u-popup :show"showPicker" :safeAreaInsetBottom"false" close&quo…...
HDFS Java 客户端 API
一、基本调用 Configuration 配置对象类,用于加载或设置参数属性 FileSystem 文件系统对象基类。针对不同文件系统有不同具体实现。该类封装了文件系统的相关操作方法。 1. maven依赖pom.xml文件 <dependency><groupId>org.apache.hadoop</groupId&g…...
【华三】STP的角色选举(一文讲透)
【华三】STP的角色选举 一、引言二、STP基础概念扫盲三、根桥选举过程详解四、根端口选举过程详解五、指定端口选举过程详解六、阻塞端口七、总结与配置建议七、附录**1. BPDU字段结构图(文字描述)****2. 华三STP常用命令速查表** 文章总结 一、引言 在…...
【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解
【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解 在 C# 中,多态是面向对象编程的重要特性之一,它允许不同的对象对同一消息做出不同的响应。多态可以分为静态多态和动态多态,下面将详细介绍它们以及各自包含的知识点。 多态概述 多态性使得代码更加灵活、可扩展…...
宇树科技13家核心零部件供应商梳理!
2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…...
Java集合框架全解析:从LinkedHashMap到TreeMap与HashSet面试题实战
一、LinkedHashMap ①LinkedHashMap集合和HashMap集合的用法完全相同。 ②不过LinkedHashMap可以保证插入顺序。 ③LinkedHashMap集合因为可以保证插入顺序,因此效率比HashMap低一些。 ④LinkedHashMap是如何保证插入顺序的? 底层采用了双向链表来记…...
goland无法debug项目
1、其实个原因是因为正在使用的Delve调试器版本太旧,无法兼容当前的Go语言版本1.2。Delve是Go语言的一个调试工具,用于提供源码级别的调试功能。Go语言每隔一段时间会发布新版本,而相应的调试器Delve也可能会更新以提供新的特性或修复已知问题…...
深入探索 DeepSeek 在数据分析与可视化中的应用
在数据驱动的时代,快速且准确地分析和呈现数据对于企业和个人都至关重要。DeepSeek 作为一款先进的人工智能工具,凭借其强大的数据处理和可视化能力,正在革新数据分析的方式。 1. 数据预处理与清洗 在进行数据分析前,数据预处理…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
CppCon 2015 学习:REFLECTION TECHNIQUES IN C++
关于 Reflection(反射) 这个概念,总结一下: Reflection(反射)是什么? 反射是对类型的自我检查能力(Introspection) 可以查看类的成员变量、成员函数等信息。反射允许枚…...
