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

对于给定的单元格,我selectData / Validation并将Allow设置为“List”。 我现在希望像这样设置Source:

= rNames(REGS)

但不起作用(名称未find)。 所以我去插入/名称/定义和创build“REGNAMES”通过简单地分配上面的公式(没有细胞范围)。 然后我回到数据/validation,当我设置源如此:

= REGNAMES

现在我得到“源目前评估错误”。 不幸的是,即使我忽略了这个错误也不会消失。 我可以在工作表中创build一个范围公式,如下所示:

{= REGNAMES}

并通过一对单元格将其拖到右侧,并且rNames函数会忠实地返回

选项#1 | 选项#2 | …

也就是说,该函数按预期返回一个范围。

我知道我可以使用macros代码来处理VBA中该单元格的List设置。 我不喜欢这些副作用。 我宁愿build立在函数上的干净的依赖关系树。 任何想法如何获得数据/validation接受从rNames返回的数组值?

谢谢。

PS:rNames返回结果范围作为Variant,如果有任何方位。

我认为问题是数据validation对话框只接受以下“列表”:

  • 直接inputSource字段的实际列表

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

  • 一个命名的公式本身parsing为一个范围引用

最后一个是关键 – 没有办法让VBA函数返回一个可用于validation的数组,即使你从一个命名的公式调用它。

可以编写一个返回范围引用的VBA函数,然后从一个命名的公式中调用 。 这可以作为以下技术的一部分,它可以近似实现您实际需要的function。

首先,有一个实际的范围调用你的任意数组返回的VBA UDF。 说你有这个function:

Public Function validationList(someArg, someOtherArg) 'Pretend this got calculated somehow based on the above args... validationList = Array("a", "b", "c") End Function 

你从$ 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 

然后你可以从一个命名的公式调用它,如下所示:

 =extractSeq($Q$42:$Q$50) 

并且指定的公式将返回Excel将接受允许的validation列表的范围引用。 笨重,但副作用免费!

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

我只是做了一些关于访问Shapes下拉控件的内容的研究,并发现了另一种解决这个问题的方法,你可能会觉得有帮助。

任何可以应用validation规则的范围都可以通过编程应用该规则。 因此,如果要将规则应用于单元格A1,可以这样做:

 ActiveSheet.Range("A1").Validation.Add xlValidateList, , , "use, this, list" 

上面添加了包含项目“use”,“this”和“list”的单元格内下拉validation。 如果覆盖Worksheet_SelectionChange()事件并检查其中的特定范围,则可以调用任意数量的例程来创build/删除validation规则。 这种方法的优点是所引用的列表可以是可以在VBA中创build的任何列表。 我需要一个dynamic生成的工作簿中不断变化的工作表子集的列表,然后将它们连接在一起以创buildvalidation列表。

Worksheet_SelectionChange()事件中,我检查范围,然后如果匹配,则触发validation规则子,从而:

 Private Sub Worksheet_SelectionChange(ByVal Target as Range) If Target.Address = "$A$1" Then UpdateValidation End If End Sub 

UpdateValidation()中的validation列表生成器代码执行以下操作:

 Public Sub UpdateValidation() Dim sList as String Dim oSheet as Worksheet For Each oSheet in Worksheets sList = sList & oSheet.Name & "," Next sList = left(sList, len(sList) -1) ' Trim off the trailing comma ActiveSheet.Range("A1").Validation.Delete ActiveSheet.Range("A1").Validation.Add xlValidateList, , , sList End Sub 

而现在,当用户点击下拉箭头时,他/她将被呈现更新的validation列表。

听起来像你的rNames函数可能会返回一维数组(这将被视为一个行)。
尝试让你的函数返回一个列作为基于1的二维数组(Ansa(1,1),然后Ansa(2,1)等)

你不是使用dynamic范围名称吗? 这很容易,不需要任何vba。

为将来:

然后在命名范围内使用以下命名范围,并将命名范围设置为“数据validation”“列表”值

 Function uniqueList(R_NonUnique As Range) As Variant Dim R_TempList As Range Dim V_Iterator As Variant Dim C_UniqueItems As New Collection On Error Resume Next For Each V_Iterator In R_NonUnique C_UniqueItems.Add "'" & V_Iterator.Parent.Name & "'!" & V_Iterator.Address, CStr(V_Iterator.Value2) Next V_Iterator On Error GoTo 0 For Each V_Iterator In C_UniqueItems If R_TempList Is Nothing Then Set R_TempList = Range(V_Iterator) End If Set R_TempList = Union(R_TempList, Range(V_Iterator)) Next V_Iterator Set uniqueList = R_TempList End Function