Java Excel 多级菜单联动原理与实现(可扩展)

Java Excel级联菜单实现(可扩展)

为什么要写这篇文章呢,因为看到了有人在提问如何用Java做Excel的级联菜单效果。帖子详情:http://spring4all.com/forum-post/575
我之前也遇到过同样的场景,当时查了很多文档才搞定,为了让更多人可以直接使用代码,节省时间,所以决定写这篇文章。

实现效果

先上效果图,这里演示我做了三级下拉菜单的联动,不过我实现的版本可以支持任意级菜单的联动
在这里插入图片描述

实现原理介绍

名称管理器

Excel中有名称管理器的概念,什么意思呢。可以简单理解为,一个名称对应一组数据序列,举个例子,一个省会对映多个市,省名则是名称管理器的名字,对应的数据序列则是相关的市级城市名。

在创建下拉关系对映规则时,需要先根据数据的对映关系,创建所有名称管理器,然后再用数据有效性绑定名称管理器的名字就行了。
在这里插入图片描述
可以在公式->名称管理器内查看我这边创建的名称管理器和对映关系。

数据有效性

名称管理器创建好了,怎么使用呢?这就要用到Excel的数据有效性了。
你可以任意选中一个单元格,在菜单栏上点击数据->有效性
在这里插入图片描述
在数据有效性内设置如下
在这里插入图片描述
来源参数说明
=INDIRECT() :Excel内置函数,可以返回单元格的值引用
dataSheet:数据页的名称
$A$1:数据页的单元格位置
$A$1 是什么值呢,其实就是province
在这里插入图片描述
还记得名称管理器的province对应的数据序列吗,会被引用到这个单元格上,于是效果如下
在这里插入图片描述
好了,基本原理就是这样,接下来我们看下怎么使用代码生成

设计与约定

易使用

只需要用到两个注解,分别是ExcelFile、ExcelValidation
ExcelFile代表需要生成文件
目前Excel是在本地创建的,不过可以根据我的源码修改成上传到服务器,如果你需要帮助,可以给我留言
ExcelValidation是打在字段上的,用来标注字段是否需要生成校验。
目前获取数据源的的方式比较单一,只支持静态无参方法,如果你的项目整合了Spring,也可以改从Bean方法内获取数据,如果你需要帮助,可以给我留言

低入侵

你可以选择copy源码或者打jar包的方式来使用,只需要在Excel实体对象上标注注解即可

约定

  1. 如果数据集返回的是List,代表是单独的、无依赖的列
  2. 如果数据集返回的是Map,key是依赖列的名称,value是key所对应的数据

小试牛刀

我的项目结构
excel-example是例子,准备的一些数据
excel-extend是具体的实现
![在这里插入图片描述](https://img-blog.csdnimg.cn/0ecd87d063cb4fe8b16fac7e253776cd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAeGltdV9zdW5ueQ==,size_20,color_FFFFFF,t_70,g_se,x_16

首先我在com.excel.service.ExcelExampleService准备了数据列表
queryProvinceList,获取省列表
queryMunicipalityList,获取市列表,Map的Key是所属的省
queryDistrictList,获取区列表,Map的Key是所属的市

public class ExcelExampleService {
   

    public static List<String> queryProvinceList() {
   
        return Arrays.asList("浙江省", "湖南省", "贵州省");
    }

    public static Map<String, List<String>> queryMunicipalityList() {
   
        Map<String, List<String>> map = new HashMap<>(4);
        map.put("浙江省", Arrays.asList("杭州市", "温州市", "宁波市"));
        map.put("湖南省", Arrays.asList("长沙市", "邵阳市", "常德市"));
        map.put("贵州省", Arrays.asList("贵阳市", "遵义市", "安顺市"));
        return map;
    }

    public static Map<String, List<String>> queryDistrictList() {
   
        Map<String, List<String>> map = new HashMap<>(8);
        map.put("杭州市", Arrays.asList("上城区", "下城区", "萧山区"));
        map.put("温州市", Arrays.asList("鹿城区", "龙湾区", "瓯海区", "洞头区"));
        map.put("长沙市", Arrays.asList("芙蓉区", "天心区", "岳麓区"));
        map.put("邵阳市", Arrays.asList("双清区", "大祥区", "北塔区"));
        map.put("贵阳市", Arrays.asList("南明区", "云岩区", "花溪区"));
        return map;
    }

}

然后配置DTO

import com.excel.annotation.ExcelFile;
import com.excel.annotation.ExcelValidation;
import lombok.Data;

/**
 * @author ximu
 * @date 2022/4/6
 * @description
 */
@ExcelFile(fileHeadTemplate = "province|municipality|district", fileMappingTemplate = "province=所属省|municipality=所属市|district=所属区",
        datasheetHidden = false, enableDataValidation = true)
@Data
public class ExcelExportDTO {
   

    /**
     * 所属省
     */
    @ExcelValidation(datasourceMethod = "com.excel.service.ExcelExampleService.queryProvinceList")
    private String province;

    /**
     * 所属市
     */
    @ExcelValidation(datasourceMethod = "com.excel.service.ExcelExampleService.queryMunicipalityList", beforeFieldName = "province")
    private String municipality;

    /**
     * 所属区
     */
    @ExcelValidation(datasourceMethod = "com.excel.service.ExcelExampleService.queryDistrictList", beforeFieldName = "municipality")
    private String district;

}

启动项目,创建Excel

public class T_Main {
   

    public static void main(String[] args) throws IOException {
   
        ExcelExportDTO excelExportDTO = new ExcelExportDTO();
        String excel = ExcelUtil.createExcel(Arrays.asList(excelExportDTO));
        System.out.println(excel);
    }

}

创建成功后,sheet1可以正常的选择下拉菜单
你会发现还有一页数据页,可以隐藏起来
使用 ExcelFile 注解属性 datasheetHidden 配置
默认是 true 隐藏的
在这里插入图片描述
如果用户随意输入值的话,是可以强制校验的
在这里插入图片描述
通过 ExcelFile 注解 showErrorBox 属性控制

实现代码

注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author ximu
 * @date 2021/8/29
 * @descripti
### Java Excel 实现多级菜单联动 为了实现Java中操作Excel并创建多级菜单联动的功能,可以采用Apache POI库来处理Excel文件。此过程涉及几个主要方面: #### 使用Apache POI创建隐藏单元格存储下拉数据 通过创建特定的工作表用于保存作为下拉选项的数据源,并将其设为隐藏状态以保持最终用户的界面整洁。 ```java // 创建新的工作簿和工作表 Workbook workbook = new XSSFWorkbook(); Sheet hiddenDataSheet = workbook.createSheet("HiddenData"); hiddenDataSheet.protectSheet("password"); // 可选保护措施 workbook.setSheetHidden(workbook.getSheetIndex(hiddenDataSheet), true); // 隐藏该工作表 ``` #### 定义名称管理器条目关联到隐藏单元格区域 定义名称以便于后续在INDIRECT函数中引用这些命名范围内的值,从而动态更新下拉列表的内容。 ```java Name namedRange = workbook.createName(); namedRange.setNameName("PrimaryOptions"); namedRange.setRefersToFormula("'HiddenData'!$A$1:$A$5"); // 调整至实际数据位置 ``` #### 设置数据验证规则应用间接引用表达式 利用`DataValidationHelper`接口及其子类提供的方法,在目标列上建立基于公式的约束条件,确保仅允许选择来自指定范围的有效输入项。 ```java CellRangeAddressList addressList = new CellRangeAddressList( 1, 100, 0, 0); // 行号区间及起始结束列索引 DVConstraint constraint = DVConstraint.createFormulaListConstraint("INDIRECT(PrimaryOptions)"); DataValidation validation = helper.createValidation(constraint, addressList); sheet.addValidationData(validation); ``` 上述代码片段展示了如何借助Apache POI API构建具有基本结构的Excel文档,并为其添加必要的配置以支持多级菜单的选择逻辑[^2]。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值