Excel·VBA多级联动的数据有效性

76 篇文章 28 订阅
Function val_lv(arr, Optional lv& = 1)
    '数据有效性级别函数,arr为数据有效性的数组,lv为级别,返回第lv级的规则数据;arr建议从表格读取
    '第lv级的内容为便于定义,允许在一个单元格内有多个数据,使用分隔符,默认为","(半角)
    '代码简易,每级避免出现归属不同上级的同名字符串,会出错
    Dim dict As Object, delimiter$, i&, j&, temp, high_lv, result
    delimiter = ","    '分隔符,最好为数据中不存在的字符,如Chr(28)或|
    If LBound(arr) = 0 Then  '转为从1开始计数
        arr = WorksheetFunction.Transpose(WorksheetFunction.Transpose(arr))
    End If
    If UBound(arr, 2) < lv Then Debug.Print "级别不能大于数组列数": val_lv = "": Exit Function
    Set dict = CreateObject("scripting.dictionary")
    If lv = 1 Then
        For i = 1 To UBound(arr)
            temp = Split(arr(i, lv), delimiter)
            For Each t In temp
                dict(t) = ""
            Next
        Next
        result = Array(Join(dict.keys, ","), "")
        val_lv = WorksheetFunction.Transpose(result)  'lv=1时,则ubound(val_lv,2)=1
    ElseIf lv > 1 Then
        For i = 1 To UBound(arr)
            high_lv = arr(i, lv - 1)  '第lv级的上一级,字典嵌套
            If Not dict.Exists(high_lv) Then Set dict(high_lv) = CreateObject("scripting.dictionary")
            temp = Split(arr(i, lv), delimiter)
            For Each t In temp
                dict(high_lv)(t) = ""
            Next
        Next
        ReDim result(1 To dict.Count, 1 To 2)  '从1开始计数,返回第lv级的上一级和本级
        For Each k In dict.keys
            j = j + 1: result(j, 1) = k: result(j, 2) = Join(dict(k).keys, ",")
        Next
        val_lv = result  'lv>1时,则ubound(val_lv,2)=2
    End If
End Function

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    '适用单个单元格选中,多级联动的数据有效性,但上级修改下级不会自动修改
    Dim arr, brr, args_dict As Object, a&, b$, c&
    Set args_dict = CreateObject("scripting.dictionary")  '参数字典
'--------------------参数填写:字典(列号)=级别,列号、级别都为数字
    args_dict(1) = 1: args_dict(2) = 2: args_dict(3) = 3
    arr = Worksheets("数据有效性").[a2:c7].Value: a = Target.Column
    If Not args_dict.Exists(a) Then Debug.Print "范围外": Exit Sub
    For Each k In args_dict.keys
        If args_dict(k) = args_dict(a) - 1 Then c = k - a  '当前选中的上级列号的偏移量
    Next
    If args_dict(a) = 1 Then  '第1级
        brr = val_lv(arr, 1)
        With Target.Validation
            .Delete
            .Add xlValidateList, xlValidAlertStop, xlEqual, Formula1:=brr(1, 1)
        End With
    ElseIf args_dict(a) > 1 And Target.Offset(0, c) <> "" Then
        brr = val_lv(arr, args_dict(a))
        For i = 1 To UBound(brr)
            If brr(i, 1) = Target.Offset(0, c).Text Then b = brr(i, 2): Exit For
        Next
        With Target.Validation
            .Delete
            .Add xlValidateList, xlValidAlertStop, xlEqual, Formula1:=b
        End With
    End If
End Sub

使用了工作表事件Worksheet_SelectionChange,单元格选中变化时代码自动运行
可以实现多级联动的数据有效性,但要注意上级修改后下级不会自动修改/清空
仅需定义数据规则,传参给sub过程,再定义参数字典,即可自动运行

数据
在这里插入图片描述
数据有效性
在这里插入图片描述
仅举例三级联动的数据有效性,实际使用可以更多级数

参考资料
官方文档:《Validation 对象 (Excel)》
其他技术博客,一级数据有效性:《L罗乐-Excel技术 | 数据有效性11:认识Validation对象》
其他技术博客,可以存在归属不同上级的同名数据有效性《excelhome蓝桥玄霜-3级动态数据有效性设置》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔_51

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值