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…...
影视大数据分析新范式:亮数据动态代理驱动的实时数据采集方案
一、项目背景与挑战 在数据驱动决策的时代,影视数据分析对内容平台至关重要。但豆瓣等平台设有: 高频请求IP封禁机制User-Agent指纹检测请求频率阈值控制验证码验证系统 传统爬虫方案面临: 单一IP存活时间<5分钟采集成功率<30%数据更新…...
免费体验,在阿里云平台零门槛调用满血版DeepSeek-R1模型
一、引言 随着人工智能技术的飞速发展,各类AI模型层出不穷。其中,DeepSeek作为一款新兴的推理模型,凭借其强大的技术实力和广泛的应用场景,逐渐在市场中崭露头角。本文将基于阿里云提供的零门槛解决方案,对DeepSeek模…...
ok113i平台——多媒体播放器适配
1. 视频播放支持 1.1 在Linux平台交叉编译ffmpeg动态库,详情查看《ok113i平台——交叉编译音视频动态库》 提取如下动态库: libavcodec.so.58.134.100 libavdevice.so.58.13.100 libavfilter.so.7.110.100 libavformat.so.58.76.100 libavutil.so.56.…...
使用Python中的`gensim`库构建LDA(Latent Dirichlet Allocation)模型来分析收集到的评论
下面为你详细介绍如何使用Python中的gensim库构建LDA(Latent Dirichlet Allocation)模型来分析收集到的评论。LDA是一种主题模型,它可以将文档集合中的文本按照主题进行分类。 步骤概述 数据预处理:对收集到的评论进行清洗、分词…...
23种设计模式 - 策略模式
模式定义 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列可互换的算法,并将每个算法封装成独立类,使得算法可以独立于客户端变化。该模式的核心思想是解耦算法的定义与使用,适用于需要动…...
Cursor 与团队协作:提升团队开发效率
引言 在团队开发中,代码质量参差不齐、重复错误频发、代码审查耗时过长是制约效率的三大痛点。据 GitHub 调查,开发者平均每周花费 4.3 小时修复他人代码问题,而 60% 的合并请求(PR)因风格或低级错误被驳回。Cursor 作…...
QT qbytearray转qString
qbytearray转qString 在Qt框架中,QByteArray和QString是常用的数据类型,它们用于处理不同类型的字符串数据。QByteArray用于存储原始字节数据,而QString用于存储Unicode字符串。在某些情况下,你可能需要将QByteArray转换为QStrin…...
激光工控机在自动化生产线中有什么关键作用?
激光工控机作为自动化生产线的核心设备,通过高精度控制、快速响应和智能化集成,在提升效率、保障质量、实现柔性制造等方面发挥着不可替代的作用。以下是其关键作用的具体分析: 一、实现高效连续生产: 1.高速加工能力࿱…...
深度解析应用层协议-----HTTP与MQTT(涵盖Paho库)
HTTP协议概述 1.1 HTTP的基本概念 HTTP是一种应用层协议,使用TCP作为传输层协议,默认端口是80,基于请求和响应的方式,即客户端发起请求,服务器响应请求并返回数据(HTML,JSON)。在H…...
Kubernetes的Ingress和Service有什么区别?
在Kubernetes中,Ingress和Service是两个不同的概念,它们在功能、作用范围、应用场景等方面存在明显区别,具体如下: 功能 Ingress:主要用于管理集群外部到内部服务的HTTP和HTTPS流量路由。它可以根据域名、路径等规则…...
WordPress“更新失败,响应不是有效的JSON响应”问题的修复
在使用WordPress搭建网站时,许多人在编辑或更新文章时,可能会遇到一个提示框,显示“更新失败,响应不是有效的JSON响应”。这个提示信息对于不了解技术细节的用户来说,太难懂。其实,这个问题并不复杂&#x…...
【回溯算法2】
力扣17.电话号码的字母组合 链接: link 思路 这道题容易想到用嵌套的for循环实现,但是如果输入的数字变多,嵌套的for循环也会变长,所以暴力破解的方法不合适。 可以定义一个map将数字和字母对应,这样就可以获得数字字母的映射了…...
【RabbitMQ业务幂等设计】RabbitMQ消息是幂等的吗?
在分布式系统中,RabbitMQ 自身不直接提供消息幂等性保障机制,但可通过业务逻辑设计和技术组合实现消息处理的幂等性。以下是 8 种核心实现方案及最佳实践: 一、消息唯一标识符 (Message Deduplication) 原理 每条消息携带全局唯一IDÿ…...
layui 远程搜索下拉选择组件(多选)
模板使用(lay-module/searchSelect),依赖于 jquery、layui.dist 中的 dropdown 模块实现(所以data 格式请参照 layui文档) <link rel"stylesheet" href"layui-v2.5.6/dist/css/layui.css" /&g…...
【开源】思维导图:思绪思维导图 (Simple Mind Map)
目录 1. 思绪思维导图 2. 本地使用 3. 在线网页 1. 思绪思维导图 思绪思维导图,英文名称为Simple mind map,简称为SSM。 开源、免费 GitHub网址 支持多平台:Windows,Mac和Linux 支持在线和离线使用 2. 本地使用 安装包下载地址…...
国产编辑器EverEdit -告别东找西找!一键打开当前文件所在目录!
1 文件操作 2 应用场景 在文件编辑过程中,有时需要对文件进行一些操作,比如:在命令窗口输入文件路径、文件名,进入到文件目录,对文件进行压缩等,如果没有直达命令,用户需要通过文件管理器找到目…...
STM32MP157A单片机移植Linux驱动
在stm32mp157a单片机移植Linux操作系统,并移植内核驱动,在应用程序中使用3个线程,分别实现控制单片机上3个led流水灯的功能、蜂鸣器控制的功能、风扇控制的功能。 需求整理: 1.驱动程序-->led1.c,led2.cÿ…...
UE引擎游戏加固方案解析
据VGinsights的报告,近年来UE引擎在过去几年中市场占比显著增长,其中亚洲市场增幅达到了30%,随着UE5的推出和技术的不断进步,UE引擎在独立开发者和移动游戏开发中的应用也在逐步增加。 UE引擎的优势在于强大的画面表现与视觉特效…...
[kubelet-check] It seems like the kubelet isn‘t running or healthy.
执行k8s时报错: [kubelet-check] It seems like the kubelet isn’t running or healthy. [kubelet-check] The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz’ failed with error: Get "http://localhost:10248/heal ** 解决办法如下&a…...
C# 背景 透明 抗锯齿 (效果完美)
主要是通过 P/Invoke 技术调用 Windows API 函数 gdi32.dll/user32.dll,同时定义了一些结构体来配合这些 API 函数的使用,常用于处理图形绘制、窗口显示等操作。 运行查看效果 局部放大,抗锯齿效果很不错,尾巴毛毛清晰可见。 using System; u…...
关于uniApp的面试题及其答案解析
我的血液里流淌着战意!力量与智慧指引着我! 文章目录 1. 什么是uniApp?2. uniApp与原生小程序开发有什么区别?3. 如何使用uniApp实现条件编译?4. uniApp支持哪些平台,各有什么特点?5. 在uniApp中…...
Ubuntu编译ZLMediaKit
下载 git clone https://gitee.com/xia-chu/ZLMediaKit cd ZLMediaKit git submodule update --init安装工具 sudo apt install -y build-essential sudo apt install -y gcc g sudo apt install -y cmakesudo apt install -y build-essential cmake git libssl-dev libsdl1.…...
【Java场景题】MySQL死锁排查
大家好,今天XiXi给大家分享一个MySQL死锁排查的实验,文章主要有: 通过show engine innodb status,查看最近一次死锁信息开启innodb_print_all_deadlocks,在错误日志中能够记录所有死锁信息通过解析binlog日志定位死锁…...
Nginx解决前端跨域问题
1. 理解 CORS 和同源策略 1.1 同源策略 同源策略是一种浏览器安全机制,用于阻止不同源(不同域名、协议或端口)的 Web 应用相互访问数据。它确保了 Web 应用的隔离性,防止恶意网站访问用户数据或执行不安全的操作。 同源策略下&…...
Bootstrap Blazor UI 中 <Table> 组件 <TableColumn> 使用备忘01:EF Core 外码处理
应用场景:将外码转换为对应的文本进行显示、编辑。 例如,有一个【用户】表,其中有一个【用户类型ID】字段;另有一个【用户类型】表,包含【ID】、【名称】等字段。现在要求在 <Table> 组件显示列表中,…...
LabVIEW心音信号采集与分析系统
基于LabVIEW软件的心音信号采集与分析系统能够实现心音的采集、去噪和分析。系统利用LabVIEW的强大功能和灵活性,通过模块化设计,实现了心音信号的高效处理和分析,具备深度学习和身份识别的实验能力,适用于医学和生物工程领域的研…...
python:多重继承、MRO(方法解析顺序)
在 Python 中,当类存在多重继承时,方法的调用顺序由 方法解析顺序(Method Resolution Order, MRO) 决定。 Python 使用 C3线性化算法 来确定类的继承顺序(MRO),其核心规则是: 子类优…...
vue 父组件和子组件中v-model和props的使用和区别
一、v-model 1、v-model 可以在组件上使用以实现双向绑定。即父组件的值可以传递给子组件,子组件的值修改后,父组件的值会同步更新。 从 Vue 3.4 开始,推荐的实现方式是使用 defineModel() 宏; 2、示例:最常用的使用…...
【Scrapy】Scrapy教程7——存储数据
上一节我们对爬虫程序的默认回调函数parse做了改写,提取的数据可以在Scrapy的日志中打印出来了,光打印肯定是不行的,还需要把数据存储,数据可以存到文件,也可以存到数据库,我们一一来看。 存储数据到文件 首先我们看看如何将数据存储到文件,在讲[[【Scrapy】Scrapy教程…...
