EasyExcel导出模板实现下拉选(解决下拉超过50个限制)

news2024/11/28 10:51:46
  • 学习地址:https://d9bp4nr5ye.feishu.cn/wiki/O3obweIbgi2Rk1ksXJncpClTnAf
  • B站视频:https://www.bilibili.com/video/BV1H34y1T7Lm

先来看看最终实现效果,如果效果是你想要的,再看看实现逻辑。

在这里插入图片描述



EasyExcel本身是支持设置下拉校验的,但有个问题,一旦下拉数据超过50个左右的时候就无法正常展示,当然,现在这个问题得到了解决。


来看整体的项目目录

在这里插入图片描述

如果你之前使用过EasyExcel那上面主流程代码你将会很熟悉,下拉选相较于之前的导出只是多注册了一个 Handler。


一、主流程代码

@RestController
@RequestMapping("/one")
public class OneController {

    // 测试数据构建
    private static List<String> countryList = Arrays.asList("中国","美国","俄罗斯","德国","日本");
    private static List<String> cityList = Arrays.asList("深圳","广州","上海","北京","纽约","莫斯科","东京");
    private static Map<String, List> dropDownData = new HashMap<>(2);
    private static List<SheetOneVO> cityEntityList = new ArrayList<>(cityList.size());
    static {
        dropDownData.put("country", countryList);
        dropDownData.put("city", cityList);

        for (String item : cityList) {
            cityEntityList.add(new SheetOneVO(item));
        }
    }



    @GetMapping("/kk-one")
    public void one(HttpServletResponse response) throws Exception {

        // 通用内容设置
        String fileName = URLEncoder.encode("templateOne.xlsx",CharEncoding.UTF_8);
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding(CharEncoding.UTF_8);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);

        // 构建模板数据
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        WriteSheet writeSheet = EasyExcel
                .writerSheet(0, "one")
                .registerWriteHandler(new XdxCellWriteHandler(dropDownData))
                .head(TemplateOneVO.class)
                .build();

        WriteSheet citySheet = EasyExcel
                .writerSheet(1, "city")
                .head(SheetOneVO.class)
                .needHead(false)
                .build();

        excelWriter.write(Arrays.asList(new TemplateOneVO("张三","美国", "胡佛")), writeSheet)
                .write(cityEntityList, citySheet).
                finish();
    }
}

二、处理器代码


  1. 这个handler重写了单元格拦截器,在遍历表头的时候,设置下拉选。
  2. 正常是超过50个下拉才会出问题,这里懒得造那么多数据所以设置了一个LIMIT,超过它就会换成联动sheet方式,从而就解决了个数限制的问题。
public class XdxCellWriteHandler implements CellWriteHandler {

    /**
     * 超过 LIMIT 的大小就使用 sheet关联下拉,否则直接设置下拉
     */
    private static final Integer LIMIT = 6;

    private Map<String, List> dropDownData;

    public XdxCellWriteHandler(Map<String, List> dropDownData) {
        this.dropDownData = dropDownData;
    }

    /**
     * 设置下拉框数据
     * @param writeSheetHolder
     * @param key 当前列名
     * @param rowIndex 行号
     * @param columnIndex 列号
     */
    private void setSelectDataList(WriteSheetHolder writeSheetHolder, String key, int rowIndex, int columnIndex) {
        if (dropDownData.get(key) == null) {
            return;
        }

        Sheet sheet = writeSheetHolder.getSheet();
        DataValidationHelper helper = sheet.getDataValidationHelper();

        // 设置下拉列表的行: 首行,末行,首列,末列
        CellRangeAddressList rangeList = new CellRangeAddressList(rowIndex, 50000, columnIndex, columnIndex);
        // 设置下拉列表的值
        DataValidationConstraint constraint;
        if (dropDownData.get(key).size() < LIMIT) {
            // 直接设置下拉选
            constraint = helper.createExplicitListConstraint((String[]) dropDownData.get(key).toArray(new String[0]));
        } else {
            // 联动到另外一个 sheet
            constraint = helper.createFormulaListConstraint(key+ "!$A$1:$A$" + dropDownData.get(key).size());
        }

        // 设置约束
        DataValidation validation = helper.createValidation(constraint, rangeList);
        // 阻止输入非下拉选项的值
        validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
        validation.setShowErrorBox(true);
        validation.setSuppressDropDownArrow(true);
        validation.createErrorBox("提示", "请输入下拉选项中的内容");
        sheet.addValidationData(validation);
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<WriteCellData<?>> cellDataList, Cell cell, Head head,
                                 Integer relativeRowIndex, Boolean isHead) {
                                 
        // 设置隐藏 sheet
        WriteSheet writeSheet = writeSheetHolder.getWriteSheet();
        if (writeSheet.getSheetNo() > 0) {
            Workbook workbook = writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook();
            workbook.setSheetHidden(writeSheet.getSheetNo(), true);
            return;
        }                         
                                 
        if (!isHead) {
            //设置value下拉框
            setSelectDataList(writeSheetHolder, head.getFieldName(), cell.getRowIndex(), cell.getColumnIndex());
        }
    }
}

三、两个VO


TemplateOneVO

@Data
@AllArgsConstructor
public class TemplateOneVO {

    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("国家")
    private String country;

    @ExcelProperty("城市")
    private String city;
}

SheetOneVO

@Data
@AllArgsConstructor
public class SheetOneVO {

    private String key;
}

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

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

相关文章

大学物理 之 安培环路定理

文章目录 前言什么是安培环路定理安培环路定理有什么作用 深入了解深入学习 前言 什么是安培环路定理 安培环路定理的物理意义在于描述了电流和磁场之间的相互作用&#xff0c;以及如何在一个封闭的回路中分析这种相互作用。 简单的来说 , 用环路定理来解决在磁场中B对任意封…

教你如何让iPhone电池更健康,不容错过的10个技巧

iPhone是一款功能强大的设备,但与许多电子产品一样,它需要一些维护才能确保正常工作。就像一艘可以永远航行的船,只要人们愿意维护它,只要你保持电池健康,你的iPhone就会继续工作。 以下是为什么维护iPhone电池至关重要,以及如何做到这一点,让你的设备使用更长时间。 …

数据结构 -作用及基本概念

为什么要使用数据结构 学习数据结构是计算机科学和软件工程领域中非常重要的一门课程。以下是学习数据结构的几个重要原因&#xff1a; 组织和管理数据&#xff1a;数据结构提供了一种组织和管理数据的方式。通过学习不同的数据结构&#xff0c;你可以了解如何有效地存储和操作…

【项目经验】:elementui表格中表头的多选框换成文字

一.项目需求 表格可以多选&#xff0c;表头都是汉字。。。。类似于这种 二.实现功能 用到的方法 Table Attributes 参数说明类型可选值默认值header-cell-class-name表头单元格的 className 的回调方法&#xff0c;也可以使用字符串为所有表头单元格设置一个固定的 className。…

在STS里使用Gradle编译Apache POI5.0.0

1、到官方下面地址下载Gradle最新的版本 Gradle Distributions 2、解压后拷贝到D盘下D:\gradle-8.3-rc-4里 3、配置环境变量 新建系统变量 GRADLE_HOME &#xff0c;值为 路径 4、在 Path 中添加上面目录的 bin 文件路径 &#xff08;可以用 %GRADLE_HOME%\bin&#xff0c…

Web3 solidity编写cancelorder取消订单函数 并梳理讲述逻辑

上文 Web3 solidity订单池操作 中 我们讲述了订单池的基本概念 并手动编写了创建订单的操作 最近的 我们还是先将 ganache 环境起起来 然后 我们打开项目 上文中 我们写了makeOrder创建订单的函数 但是 也带出一个问题 我们创建之后 如果不要了 怎么干掉呀&#xff1f; js中我…

CS420 课程笔记 P2 - 内存编辑和基础的 GameHacking 尝试

文章目录 IntroductionOperating SystemToolsMemory ScanningMemory ScanExamples!Conclusion Introduction 本节将介绍操作系统的基础知识和内存扫描&#xff0c;这可以说是 game hacking 中最重要的技能&#xff0c;我们不会深入讨论操作系统&#xff0c;因为这本身就是一门…

【Linux】Libevent相关小知识总结

Libevent是基于事件的&#xff0c;也就是说&#xff0c;相当于去注册一个事件&#xff0c;当这个事件发生的话&#xff0c;那么就会调用回调函数。

Spark-Core核心算子

文章目录 一、数据源获取1、从集合中获取2、从外部存储系统创建3、从其它RDD中创建4、分区规则—load数据时 二、转换算子(Transformation)1、Value类型1.1 map()_1.2 mapPartitions()1.3 mapPartitionsWithIndex(不常用)1.4 filterMap()_扁平化&#xff08;合并流&#xff09;…

MATLAB制图代码【第二版】

MATLAB制图代码【第二版】 文档描述 Code describtion: This code is version 2 used for processing the data from the simulation and experiment. Time : 2023.9.3 Author: PEZHANG 这是在第一版基础上&#xff0c;迭代出的第二版MATLAB制图代码&#xff0c;第二版的特点是…

一探究竟:为什么需要 JVM?它处在什么位置?

小熊学Java全能学习面试指南&#xff1a;https://www.javaxiaobear.cn/ JVM我们并不陌生&#xff0c;现在我们就正式进入 JVM 的学习&#xff0c;如果你是一名软件开发工程师&#xff0c;在日常工作中除了 Java 这个关键词外&#xff0c;还有一个名词也一定经常被提及&#xf…

3、Spring 之IOC 容器 详解

IoC 是 Inversion of Control 的简写&#xff0c;译为“控制反转”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出松耦合、更优良的程序。 Spring 通过 IoC 容器来管理所有 Java 对象的…

【SpringSecurity】十二、集成JWT搭配Redis实现退出登录

文章目录 1、登出的实现思路2、集成Redis3、认证成功处理器4、退出成功处理器5、修改token校验过滤器6、调试 1、登出的实现思路 这是目前的token实现图&#xff1a; 因为JWT的无状态&#xff0c;服务端无法在使用过程中主动废止某个 token&#xff0c;或者更改 token 的权限…

《TCP/IP网络编程》阅读笔记--基于Windows实现Hello Word服务器端和客户端

目录 1--Hello Word服务器端 2--客户端 3--编译运行 3-1--编译服务器端 3-2--编译客户端 3-3--运行 1--Hello Word服务器端 // gcc hello_server_win.c -o hello_server_win -lwsock32 // hello_server_win 9190 #include <stdio.h> #include <stdlib.h> #i…

07-ThreadLocal有哪些使用场景?【Java面试题总结】

ThreadLocal有哪些使用场景&#xff1f; 7.1 多线程场景下共享变量问题 ThreadLocal是线程本地变量&#xff0c;可以存储共享变量副本&#xff0c;每一个独立线程都有与共享变量一模一样的副本。ThreadLocal在当前线程下共享变量是全局共享的&#xff0c;各个线程之间是相互独…

虚拟内存相关笔记

虚拟内存是计算机系统内存管理的一个功能&#xff0c;它允许程序认为它们有比实际物理内存更多的可用内存。它使用硬盘来模拟额外的RAM。当物理内存不足时&#xff0c;操作系统将利用磁盘空间作为虚拟内存来存储数据。这种机制提高了资源的利用率并允许更大、更复杂的应用程序的…

ICCV 2023 | TUM谷歌提出md4all:挑战性条件下的单目深度估计

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【深度估计】交流群 Robust Monocular Depth Estimation under Challenging Conditions 作者列表: Stefano Gasperini, Nils Morbitzer, HyunJun Jung, Nassir Navab, Federi…

【小作文】【信】

【邀请信】【22&#xff0c;1邀请教授参加比赛】 【投诉信】【12,2投诉产品质量问题】

一般不用buildroot来编译uboot和kernel

Buildroot 是一个流行的嵌入式 Linux 系统构建工具&#xff0c;它可以帮助开发者自动化地构建完整的嵌入式 Linux 系统&#xff0c;包括文件系统、内核以及各种用户空间应用程序。虽然 Buildroot 在构建嵌入式系统方面非常强大且易于使用&#xff0c;但一般情况下&#xff0c;它…

STM32WB55开发(1)----套件概述

STM32WB55开发----1.套件概述 所用器件视频教学样品申请优势支持协议系统控制和生态系统访问功能示意图系统框图跳线设置开发板原理图 所用器件 所使用的器件是我们自行设计的开发板&#xff0c;该开发板是基于 STM32WB55 系列微控制器所构建。STM32WBXX_VFQFPN68 不仅是一款评…