【发布时间】:2015-05-18 23:48:45
【问题描述】:
假设我们在单元格 A1 中保存了一些长公式:
=SomeArrayFunction(
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 01",
"part_one"),
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 02",
IF(SUM(D3:D6)>1,"A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X 03",
"part_two"))
)
它使用以下 VBA 函数
Public Function SomeArrayFunction(sOne As String, sTwo As String) As Variant
Dim V() As Variant
ReDim V(1 To 2, 1 To 1)
V(1, 1) = sOne
V(2, 1) = sTwo
SomeArrayFunction = V
End Function
返回一个 2×1 数组。
现在当我调用这个 VBA 函数时
Public Sub EvaluateFormula()
Dim vOutput As Variant
vOutput = Application.Evaluate(Selection.Formula)
If VarType(vOutput) >= vbArray Then
MsgBox "Array:" & vbCrLf & vOutput(1, 1) & vbCrLf & vOutput(2, 1)
Else
MsgBox "Single Value: " & vbCrLf & vOutput
End If
End Sub
选择单元格 A1 时出现错误,因为 Application.Evaluate 无法处理超过 255 个字符的公式(例如,请参阅 VBA - Error when using Application.Evaluate on Long Formula)。另一方面,如果我写
vOutput = Application.Evaluate(Selection.Address)
相反(如上面链接中所建议的那样),它就可以正常工作。除了不再计算数组这一事实,即调用 MsgBox "Single Value:" 而不是 MsgBox "Array:"。
所以我的问题是:如何使用 VBA 评估长公式(返回数组)?
编辑:让我强调一下,当我只选择包含公式的一个单元格(不是一个区域或多个单元格)时,我需要它来工作。而且我没有将它作为数组公式输入(即没有大括号):
Edit2:让我回答一下原因:我目前的工作要求我在电子表格中列出一长串如此庞大的公式。而且由于它们被组织在一个列表中,每个这样的公式只能占用一个单元格。在几乎所有情况下,公式都返回单个值(因此一个单元格足以存储/显示输出)。但是,当计算公式时出现内部错误时,公式会返回错误消息。这些错误消息通常很长,因此以不同大小的数组形式返回(取决于错误消息的长度)。所以我的目标是编写一个 VBA 函数,该函数将首先获取并输出列表中给定选定条目的完整错误消息。
【问题讨论】:
-
谢谢你的原因。现在这变得有趣了。阅读您的描述后,我的第一个想法是:您可以输入填充到当前列(“列表”)旁边的列的数组公式吗?您可以在公式上调用
TRANSPOSE以将列转换为行。这有点“脏”,但如果足够大以捕获所有错误输出,您可以将它们全部设为 10 个单元格。我真的不认为你会得到一个没有像公式数组这样的数组输出。问题将是如何最好地做到这一点。 -
您的错误消息的长度是否真的超过 32k(或者您是否试图绕过单元内显示限制)?无论如何,您似乎可以使用“临时”范围来放置公式,然后对它们调用 Evaluate。
-
@Byron:我也想过转置它,但我经常有几个相邻的列表,这使得这种方法变得不可能。
-
@TimWilliams:消息并不大,但如果错误字符串的长度超过某个阈值,公式只会返回数组(我无法更改这些公式,以便它们返回更长的字符串而不是到数组)。
-
我的一个想法是在 VBA 中创建一个空的虚拟工作表对象并将公式复制到其中。然后我可能会执行下面讨论的方法。但是我没有足够的经验来判断这是否是一种可行的方法。
标签: arrays vba excel excel-formula