从VBA用户定义的函数返回Excel数组常量

时间:2019-05-16 15:36:50

标签: excel vba excel-formula

我有一个像这样的电子表格:

A1: APPLE
A2: BANANA
A3: ORANGE
A4: APPLE
A5: BANANA
A6: ORANGE

(重复直到A20)

因此,此公式将计算“ APPLE”的所有实例:

=COUNTIF(A1:A20, "APPLE")

此公式的作用相同,但范围不连续:

=SUM(COUNTIF(INDIRECT({"A1:A6", "A8:A20"}), "APPLE"))

INDIRECT函数将array constant的范围定义为字符串。注意花括号和每个范围内的引号。 (这基于here中描述的技术。)

但是,如果我定义了一个VBA函数,该函数返回一个字符串数组并将那个传递给INDIRECT,则似乎只尊重第一个范围。

这是我的VBA功能:

Function TestFn() As Variant
    TestFn = Array("A1:A6", "A8:A20")
End Function

这是我的公式:

=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))

如果我使用Excel的“求值公式”按钮,则可以看到TestFn()解析为单个字符串“ B1:B6”。但是,如果使用VBA调试器,则会看到两个字符串都在其中。

Expression      Value       Type
TestFn                      Variant/Variant(0 to 1)
 - TestFn(0)    "B1:B6"     Variant/String
 - TestFn(1)    "B8:B20"    Variant/String

如何从Excel VBA函数返回可以以相同方式传递到INDIRECT的字符串数组?

我认为这可以归结为:在不使用VBA构造公式时使用花括号创建了哪个内部对象,我可以在VBA中创建相同的内部对象吗?


我还尝试过返回一个字符串数组,而不是返回一个包含字符串数组的变体。

Function TestFn() As String()
    TestFn = Split("B1:B6,B8:B20", ",")
End Function

这些是调试器中的类型:

Expression      Value       Type
TestFn                      String(0 to 1)
 - TestFn(0)    "B1:B6"     String
 - TestFn(1)    "B8:B20"    String

但是结果是一样的。我想我需要使用某种类型的容器类型,但是我不确定该使用什么或如何弄清楚该使用什么。


如果有更好的方法,我实际上不需要使用SUM ... INDIRECT hack,如果合适的话,我很乐意使用数组公式。

如果我可以让我的函数直接返回范围,而不是代表范围的字符串,那将比我目前的方法更好。

如果我可以设置类似这样的数组公式(不必完全像这样):

{=COUNTIF(TestFn(), "APPLE")}

然后让我的UDF看起来像这样:

Function TestFn() As Range()
    TestFn = Array(Range("A1:A6"), Range("A8:A20"))
End Function

或者也许是这样:

Function TestFn() As Range
    TestFn = Union(Range("A1:A6"), Range("A8:A20"))
End Function

那会满足我的需求。

这里的关键是我只希望VBA仅定义要对哪些单元格进行操作,而不是对操作进行定义,并且我想处理非连续范围。我希望在excel公式中定义实际的操作,因为这些操作将由不希望了解如何读写VBA代码的人员进行修改。 (哎呀,我也不想再看VBA代码。)在这种情况下,我使用的是COUNTIF,但是我的VBA函数也将与其他excel公式函数一起使用。

1 个答案:

答案 0 :(得分:3)

当然有人可以更好地解释这一点,但让我尝试。您都使用过:

=SUM(COUNTIF(INDIRECT({"A1:A6","A8:A20"}), "APPLE"))

然后...

=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))

关于第一个公式;您基本上已经使用INDIRECT()函数将文本字符串转换为实际范围。我必须说INDIRECT()实际上是一个很好的用法。

但是使用大括号告诉您Excel不仅是一个字符串,还为函数提供了多个数据和数组!通常,Excel中的数组是一组简单的数据。此数据可以是文本,数字或两者。您已使用文字。

在第二个公式中,已通过UDF向该公式提供了数组,但是缺少大括号。 Excel不知道您要比较多个范围,只会评估数组中的第一项。

但是,使用 Ctrl Shift Enter 告诉Excel,您要向公式中提供一个数组,该数组是一组数据/范围比较。

所以:

{=SUM(COUNTIF(INDIRECT(TestFn()), "APPLE"))}

会工作:)

我敢肯定,别人会更好地解释;)