使用EasyExcel实现导出excel文件时生成多级下拉选

news/2024/10/23 10:26:35/文章来源:https://www.cnblogs.com/lcy2020/p/18494495

前言

公司有个需求本来只涉及到两个下拉选项,后面就想能不能实现多个下拉选,当然我这里说的多个下拉选是联动的,比如我省、地市、区县这种。

实现步骤

1、添加EasyExcel的Maven依赖

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

2、一个具有多级关联的数据项


/*** excel下拉框数据项* @author lcy*/
@Data
public class SelectItem {public SelectItem(Integer columnIndex) {this.columnIndex = columnIndex;}/*** 下拉框所在列的索引,从0开始*/private Integer columnIndex;/*** 下拉框的值列表*/private List<DataItem> dataItems;/*** 子级对应的下拉框数据*/private SelectItem subSelect;public  void addDataItem(String mappingKey,List<String> values){if (this.dataItems == null){this.dataItems = new ArrayList<>();}this.dataItems.add(new DataItem(mappingKey,values));}public  void addDataItem(List<String> values){this.addDataItem("_"+UUID.randomUUID().toString().replaceAll("-",""),values);}@Datapublic static class DataItem{/*** 关联上级的key*/private String mappingKey;/*** 当前下拉框的值*/private List<String> values;/*** 当前下拉框的引用,隐藏页单元格地址*/private String hiddenFormulaRef;public DataItem(String mappingKey, List<String> values) {Assert.notBlank(mappingKey,"mappingKey is not blank");Assert.notEmpty(values,"values is not empty");this.mappingKey = mappingKey;this.values = values;}}

3、定义一个SheetWriteHandler,这是EasyExcel提供的一个组件,允许我们在sheet页生成前后做一些干预动作。


/*** @author lcy*/
public class SelectWriteHandler implements SheetWriteHandler , CellWriteHandler {private static final int ROW_SIZE = 10000;private final  WriteFont redFont;private final  List<SelectItem> selectItems;private final String HIDDEN_SHEET_NAME = "hidden_sheet";private final Set<Integer> selectColumns = new HashSet<>();private boolean isLoadSelectColumns = false;private int rowIndex = 0;public SelectWriteHandler(List<SelectItem> selectItems) {Assert.notEmpty(selectItems, "selectItems can not be empty");this.selectItems = selectItems;redFont = getRedFont();}@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {Workbook workbook = writeWorkbookHolder.getWorkbook();Sheet hiddenSheet = workbook.getSheet(HIDDEN_SHEET_NAME);if (hiddenSheet != null){return ;}hiddenSheet = workbook.createSheet(HIDDEN_SHEET_NAME);workbook.setSheetHidden(workbook.getSheetIndex(hiddenSheet),true);Sheet sheet = writeSheetHolder.getSheet();for (SelectItem selectItem : selectItems) {buildHiddenSheetSelectRef(workbook,sheet,hiddenSheet,selectItem,null);}if (!isLoadSelectColumns){isLoadSelectColumns = true;}}private void buildHiddenSheetSelectRef(Workbook workbook,Sheet sheet,Sheet hiddenSheet, SelectItem selectItem,String formulaRef ) {if (!isLoadSelectColumns){selectColumns.add(selectItem.getColumnIndex());}List<SelectItem.DataItem> dataItems = selectItem.getDataItems();for (SelectItem.DataItem dataItem : dataItems) {setDataAndName(workbook, hiddenSheet, dataItem);}// 单元格地址引用if (formulaRef == null || formulaRef.isEmpty()){formulaRef = dataItems.get(0).getHiddenFormulaRef();}// 创建检验器DataValidation dataValidation = getDataValidation(sheet, selectItem, formulaRef);sheet.addValidationData(dataValidation);SelectItem subSelect = selectItem.getSubSelect();if (subSelect != null){buildHiddenSheetSelectRef(workbook,sheet,hiddenSheet,subSelect,getInDirectFormulaRef(selectItem.getColumnIndex()));}}private  DataValidation getDataValidation(Sheet sheet, SelectItem selectItem, String formulaRef) {DataValidationHelper helper = sheet.getDataValidationHelper();DataValidationConstraint constraint = helper.createFormulaListConstraint(formulaRef);CellRangeAddressList rangeAddressList = new CellRangeAddressList(1,ROW_SIZE, selectItem.getColumnIndex(), selectItem.getColumnIndex());DataValidation dataValidation = helper.createValidation(constraint, rangeAddressList);dataValidation.setShowErrorBox(true);return dataValidation;}private void setDataAndName(Workbook workbook, Sheet hiddenSheet, SelectItem.DataItem dataItem) {// 构建隐藏数据Row row = hiddenSheet.createRow(rowIndex);List<String> values = dataItem.getValues();for (int i = 0; i < values.size(); i++) {row.createCell(i).setCellValue(values.get(i));}// 创建名称命名器Name name = workbook.createName();name.setNameName(dataItem.getMappingKey());name.setRefersToFormula(getFormulaRef(row));dataItem.setHiddenFormulaRef(name.getRefersToFormula());rowIndex++;}private String getInDirectFormulaRef(Integer columnIndex){CellReference slectCellReference = new CellReference(1, columnIndex);return  "INDIRECT("+joinFormulaRef(slectCellReference, false)+")";}@Overridepublic void afterCellDispose(CellWriteHandlerContext context) {if (!context.getHead()){Integer columnIndex = context.getColumnIndex();if (selectColumns.contains(columnIndex)){// 设置红色字体context.getFirstCellData().getOrCreateStyle().setWriteFont(redFont);}}CellWriteHandler.super.afterCellDispose(context);}private   String getFormulaRef(Row prvRow) {Cell startCell = prvRow.getCell(prvRow.getFirstCellNum());Cell endCell = prvRow.getCell(prvRow.getLastCellNum() - 1);return HIDDEN_SHEET_NAME + "!" + joinFormulaRef(new CellReference(startCell),true) + ":" + joinFormulaRef(new CellReference(endCell),true);}public  String joinFormulaRef(CellReference cellReference,boolean isAbsolute){StringBuilder sb = new StringBuilder();String[] refs = cellReference.getCellRefParts();for (int i = refs.length -1 ; i >= 1; i--) {if (isAbsolute){sb.append("$");}sb.append(refs[i]);}return sb.toString();}/*** 返回一个红色字体* @return*/private WriteFont getRedFont() {WriteFont redFont =  new WriteFont();redFont.setColor(IndexedColors.RED.getIndex());return redFont;}
}

4、准备数据

       // 准备数据SelectItem selectItem = new SelectItem(0);selectItem.addDataItem(List.of("浙江省","河南省"));SelectItem subSelectItem = new SelectItem(1);subSelectItem.addDataItem("浙江省",List.of("杭州市","宁波市"));subSelectItem.addDataItem("河南省",List.of("郑州市","洛阳市","开封市"));selectItem.setSubSelect(subSelectItem);SelectItem selectItem3 = new SelectItem(2);selectItem3.addDataItem("杭州市",List.of("滨江区","西湖区"));selectItem3.addDataItem("宁波市",List.of("宁波市1","宁波市2"));selectItem3.addDataItem("郑州市",List.of("金水区","二七区"));selectItem3.addDataItem("洛阳市",List.of("洛阳市1","洛阳市2"));selectItem3.addDataItem("开封市",List.of("开封市1","开封市2"));subSelectItem.setSubSelect(selectItem3);

5、测试

EasyExcel.write("d:\\5555.xlsx").registerWriteHandler(new SelectWriteHandler(List.of(selectItem))).sheet().doWrite(Collections.emptyList());

完整的测试代码

public class SelectExcelTest {public static void main(String[] args) {// 准备数据SelectItem selectItem = new SelectItem(0);selectItem.addDataItem(List.of("浙江省","河南省"));SelectItem subSelectItem = new SelectItem(1);subSelectItem.addDataItem("浙江省",List.of("杭州市","宁波市"));subSelectItem.addDataItem("河南省",List.of("郑州市","洛阳市","开封市"));selectItem.setSubSelect(subSelectItem);SelectItem selectItem3 = new SelectItem(2);selectItem3.addDataItem("杭州市",List.of("滨江区","西湖区"));selectItem3.addDataItem("宁波市",List.of("宁波市1","宁波市2"));selectItem3.addDataItem("郑州市",List.of("金水区","二七区"));selectItem3.addDataItem("洛阳市",List.of("洛阳市1","洛阳市2"));selectItem3.addDataItem("开封市",List.of("开封市1","开封市2"));subSelectItem.setSubSelect(selectItem3);EasyExcel.write("d:\\5555.xlsx").registerWriteHandler(new SelectWriteHandler(List.of(selectItem))).sheet().doWrite(Collections.emptyList());}}

6、结果



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

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

相关文章

【运维自动化-作业平台】如何快速执行脚本和分发文件

脚本执行和文件分发是作业平台最基本、最核心的两个原子功能,主要分页面快速执行和作业里步骤引用,使用逻辑一样,一起来看看具体如何使用快速执行脚本 核心实现原理就是基于gse的命令管道,把脚本内容以WebPortal的方式透传到目标服务器进行执行,可以页面输入脚本也可以引用…

CMDB平台(进阶篇):企业级CMDB的高阶教程

企业IT架构日益复杂,配置项数量庞大且关系错综复杂。为了有效管理这些配置项,确保IT服务的稳定性和可靠性,配置管理数据库(Configuration Management Database,简称CMDB)系统应运而生。本文将深入探讨企业搭建CMDB系统所需具备的要素,以及实践路径,旨在为企业提供有益的…

U 盘

目录1 USB 大容量存储设备2 设备描述符3 字符串描述符4 配置描述符集合4.1 配置描述符4.2 接口描述符4.3 端点描述符6 类特殊请求6.1 Get Max LUN 请求6.2 Bulk-Only Mass Storage Reset 请求7 Bulk-Only 传输协议的数据流模型7.1 CBW 的结构7.2 CSW 的结构7.3 对批量数据的处理…

manim边做边学--复数平面

所谓复数平面,就是一种二维坐标系统,用于几何表示复数的场景,其中横轴代表实部,纵轴代表虚部。 每个点对应一个唯一的复数,反之亦然,这种表示方法使得复数的加法、乘法等运算可以通过直观的图形变换来理解。 ComplexPlane是Manim库中用于处理复数平面的类。 它不仅提供了…

3185. 构成整天的下标对数目 II

给你一个整数数组 hours,表示以 小时 为单位的时间,返回一个整数,表示满足 i < j 且 hours[i] + hours[j] 构成 整天 的下标对 i, j 的数目。 整天 定义为时间持续时间是 24 小时的 整数倍 。 例如,1 天是 24 小时,2 天是 48 小时,3 天是 72 小时,以此类推。 示例 1:…

使用dbeaver导出数据csv格式要求

1.分隔符改成使用\t, 默认的会导致数字不对2.下面也要修改下,不然会出现列和值对不上情况

通过集成平台实现聚水潭销售出库单与金蝶云星辰V2的无缝对接

PACKAGE-聚水潭销售出库单对接销售出库单-1 在企业信息化系统的集成过程中,数据的高效、准确传输至关重要。本文将分享一个具体的技术案例:如何通过轻易云数据集成平台,将聚水潭奇门的数据无缝对接到金蝶云星辰V2,实现销售出库单的自动化处理。 本次集成方案命名为“PACKAG…

Windows下给Visual Studio添加OpenSSL

一、安装OpenSSL 1.下载OpenSSL Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions可以下载已经编译好的包含 lib 和 include 文件的安装包 有Win32和Win64可选,这里的位数指的是你使用OpenSSL开发出来的软件的位数版本,而不是你计算机的位数。 注意,…

分享一个开源的文件MD5、Hash值等校验的小工具

官方主页 https://github.com/dragonyee/MyHash 软件截图介绍 一款采用并行计算,充分利用多核CPU性能,快速计算文件哈希值的工具。 功能特点: 1、只支持常用的CRC32、MD5、SHA1、SHA256、SHA512算法; 2、支持多核CPU并行计算,大幅提高计算速度; 3、支持多个文件或文件夹拖…

Python 学习记录

前言 简单情况:主要记录学习Python的简单情况,包括代码与结果,以及关键注释 工具与来源: 一下代码与结果都可在JupyterLab上实现,更多情况可看Github使用 NumPy 可视化数学函数 1.可视化 f=x1*e(-x12-x22) import numpy as np import matplotlib.pyplot as pltx1_array=…