在 VBA 中添加或相乘变体
Posted
技术标签:
【中文标题】在 VBA 中添加或相乘变体【英文标题】:Adding or multiplying variants in VBA 【发布时间】:2014-08-29 19:56:19 【问题描述】:假设我们有两个变体,X
和 Y
,它们可能是数字、范围或数组。
有没有一种简单的方法可以像在工作表公式=X+Y
和=X*Y
中那样添加或相乘?
我想到的一种可能性是使用 Evaluate 操作,如下所示:
Dim X, Y
Sub AddMult()
Dim Add, Mult
X = Array(Array(1, 3), Array(2, 4))
Y = Array(1, 2)
Add = [GetX()+GetY()]
Mult = [GetX()*GetY()]
End Sub
Function GetX()
GetX = X
End Function
Function GetY()
GetY = Y
End Function
这似乎有点尴尬。还有其他想法吗?
(这里有一个相关问题:Multiplying arrays with scalars and adding in VBA。)
【问题讨论】:
为了争论 - 不是有很多可能的方法来解释这一点吗?该问题询问在相等大小的数组中的等效位置乘以值。我们是否假设我们只处理等效维度和大小的数组和范围?因此,您将创建具有不同步骤的函数来将 var 乘以 var、将 var 乘以 range/array 以及将 range/array 乘以 range/array? 所以您正在寻找一种无论变量是数字、范围还是变量数组都有效的方法? 是的,它应该允许相称的数组/范围/数字。例如,使用Set X = Range("a1:b2")
和 Y = 2
返回一个 2x2 数组,其中每个元素递增/乘以 2。
【参考方案1】:
在查看了各种选项后,我选择了 Worksheetfunction 方法。算术计算最可行的候选者似乎是金融类。从rate
= 0 时PV
函数的 Excel 帮助中,参数之间存在以下关系:pmt * nper + pv + fv = 0
。这种关系也适用于其他相应的功能。因此,一种选择是:
Sub AddMult()
Dim X, Y, Add, Mult
X = Array(Array(1, 3), Array(2, 4))
Y = Array(1, 2)
With Application
Add = .Pmt(, -1, X, Y)
Mult = .PV(, 1, .PV(, X, Y))
End With
End Sub
对于变体的其他操作,可以使用更多 WorksheetFunction 方法:
.SLN(x,y,1) 'x-y
.SLN(x,,y) 'x/y
.Power(x,y) 'x^y
.Quotient(x,y) 'x\y
.Delta(x,y) 'x=y
.GeStep(x,y) 'x>=y
注意:前缀为Application
(不是 Worksheetfunction
不允许其他数据类型。)
【讨论】:
【参考方案2】:提供的代码在模块中工作。那里的函数 GetX() 和 GetY() 是 UDF,因此 [GetX()] 和 [GetY()] 可以评估它们。但是你的代码可能是最好的解决方案吗?当然,全局范围内有两个 UDF 和两个变量。但是另一个试图避免这种情况的解决方案会导致无休止地检查变体真正包含的可能性。
进一步的测试表明,如果模块中的函数被声明为私有,它们甚至可以被评估。此外,全局变量不得公开。所以在我看来,您的解决方案是最好的解决方案。
Private X, Y
Sub AddMult()
Dim Add, Mult
X = [4,5,6]
Set Y = Range("A1:C200")
Add = [GetX() + GetY()]
Mult = [GetX() * GetY()]
End Sub
Private Function GetX()
GetX = X
End Function
Private Function GetY()
GetY = Y
End Function
问候
阿克塞尔
【讨论】:
谢谢 - 测试用例似乎没问题,但这仅适用于小型数组,因为字符串转换过于严格。发布的代码可能看起来很杂乱无章,但在下结论之前,请尝试粘贴到新模块中并运行 - 在我的测试中它工作正常。 是的,你是对的。抱歉,我没有在模块中测试您的代码。那里的函数 SetX() 和 GetX() 是 UDF,当然 Evaluate("GetX()") 和 [GetX()] 可以评估它们。但是你的代码可能是最好的解决方案吗?当然,全局范围内有两个 UDF 和两个变量。但是另一种解决方案会导致无休止地检查 Variants 真正包含的可能性,例如在我的 getAsLiteral() 中。以上是关于在 VBA 中添加或相乘变体的主要内容,如果未能解决你的问题,请参考以下文章
VBA:只有在公共对象模块中定义的用户定义类型才能被强制转换为变体或从变体强制转换或传递给后期绑定函数