我可以使用VBA函数将可接受值的(动态)列表返回到Excel的数据验证中吗?

Oll*_*893 5 excel vba excel-vba

对于给定的单元格,我选择数据/验证并将允许设置为"列表".我现在希望像这样设置Source:

= rNames(REGS)

但这不起作用(找不到名字).所以我去插入/名称/定义并通过简单地指定上面的公式创建"REGNAMES"(没有单元格范围).然后我返回数据/验证,当我像这样设置Source时:

= REGNAMES

现在我得到"Source当前评估为错误".不幸的是,即使忽略它,这个错误也不会消失.我可以在表格中创建一个范围公式,如下所示:

{= REGNAMES}

并将其拖到几个单元格的右侧,并忠实地返回rNames函数

选项#1 | 选项#2 | ...

也就是说,该函数返回预期的范围.

我知道我可以使用宏代码来操作VBA中该单元格的List设置.我不太喜欢这些副作用.我更喜欢一个基于函数的干净依赖树.任何想法如何让数据/验证接受从rNames返回的数组值?

谢谢.

PS:rNames将结果范围作为Variant返回,如果有任何影响的话.

jto*_*lle 8

我认为问题是数据验证对话框只接受以下"列表":

  • 直接输入Source字段的实际事物列表

  • 字面范围参考(如$ Q $ 42:$ Q $ 50)

  • 一个命名公式,它本身解析为范围引用

最后一个是关键 - 没有办法让VBA函数只返回一个可用于验证的数组,即使你从一个命名公式中调用它.

但是,您可以编写一个返回范围引用的VBA函数,并从命名公式中调用.这可以用作以下技术的一部分,该技术近似于您实际想要的能力.

首先,在某处调用返回任意数组的VBA UDF的实际范围.说你有这个功能:

Public Function validationList(someArg, someOtherArg)

    'Pretend this got calculated somehow based on the above args...
    validationList = Array("a", "b", "c")
End Function
Run Code Online (Sandbox Code Playgroud)

你用$ Q $ 42:$ Q $ 50作为数组公式称它.您将获得三个单元格,其中包含"a","b"和"c",其余单元格将出现#N/A错误,因为返回的数组小于调用UDF的范围.到现在为止还挺好.

现在,让另一个VBA UDF返回一个范围的"被占用"部分,忽略#N/A错误单元格:

Public Function extractSeq(rng As Range)

    'On Error GoTo EH stuff omitted...

    'Also omitting validation - is range only one row or column, etc.

    Dim posLast As Long
    For posLast = rng.Count To 1 Step -1
        If Not IsError(rng(posLast)) Then
            Exit For
        End If

        If rng(posLast) <> CVErr(xlErrNA) Then
            Exit For
        End If
    Next posLast

    If posLast < 1 Then
        extractSeq = CVErr(xlErrRef)
    Else
        Set extractSeq = Range(rng(1), rng(posLast))
    End If
End Function
Run Code Online (Sandbox Code Playgroud)

然后,您可以从命名公式中调用它,如下所示:

=extractSeq($Q$42:$Q$50)
Run Code Online (Sandbox Code Playgroud)

并且命名公式将返回Excel将接受允许的验证列表的范围引用.笨重但副作用自由!

请注意在上面的代码中使用关键字"Set".你的问题并不清楚,但这可能是整个答案中唯一对你很重要的部分.如果在尝试返回范围引用时未使用"设置",则VBA将返回范围的,该不能用作验证列表.