将不同的函数传递到同一个迭代循环(VBA)
Posted
技术标签:
【中文标题】将不同的函数传递到同一个迭代循环(VBA)【英文标题】:Passing a different function into the same iteration loop (VBA) 【发布时间】:2021-07-27 20:09:26 【问题描述】:我的总体目标是将基于 Excel 的财务模型转换为 VBA。金融模型具有多种场景(例如 3)和开发类型(例如 3 - 住宅、商业、工业)。目前,该模型有两个组成部分 - 收入和成本,但我的解决方案需要大规模扩展。
九个实例中的每一个实例的收入计算都是相同的,但输入会发生变化。我从工作簿中获取输入并将它们放在集合中。我将计算结果添加到另一个集合中。成本计算会有所不同,但会使用完全相同的迭代循环。
我要做的是编写一次迭代代码,但将不同的计算传递给循环。我通过在类对象中编码公式然后将类对象传递给函数来完成它。请看下面的沙盒示例。
' Passing different classes into iteration loop
Sub Main()
Dim clsAdd As CAdd
Dim colAdd As Collection
Set clsAdd = New CAdd
Set colAdd = New Collection
Set colAdd = Iteration(clsAdd)
Dim clsMul As CMult
Dim colMul As Collection
Set clsMul = New CMult
Set colMul = New Collection
Set colMul = Iteration(clsMul)
End Sub
' Same iteration loop required for different calculations
Function Iteration(ByRef colClass As Object) As Collection
Dim varArray01() As Variant
Dim varArray02() As Variant
Dim itA As Integer
Set Iteration = New Collection
varArray01 = Array(1, 2, 3, 4)
varArray02 = Array(11, 12, 13, 14)
For itA = 0 To UBound(varArray01)
Iteration.Add colClass.ICalculation_Calculation(varArray01(itA), varArray02(itA))
Next itA
End Function
'Add Class
Public Function Calculation(ByVal intA As Integer, ByVal intB As Integer) As Integer
Calculation = intA + intB
End Function
'Multiply Class
Public Function Calculation(ByVal intA As Integer, ByVal intB As Integer) As Integer
Calculation = intA * intB
End Function
虽然这可行,但我觉得必须有比为我想要的每个公式创建一个新的类对象更好的解决方案,因为每个公式都必须使用名为“计算”的函数进行计算。欢迎您提出建议。
【问题讨论】:
看起来我没有让你阅读这个问题,我也无法更好地理解你的意思,即使是现在......你不需要为每个人写一个不同的Calculation
函数吗三种情况?如果是,为什么要在不同的类中写它们?您可以使用字符串键使用Select Case
,让我们说devType
并根据(仅)三种情况调用相应的函数:“res”,“com”,“ind”......为什么需要/like/想使用相同的Calcualation
函数吗?如果您坚持,请创建这样一个独特的函数,但在其中使用Select Case
,并使用devtType
参数调用。
【参考方案1】:
您显然已经为您的计算类定义了一个接口。直接把Iteration
的参数改成带接口就好了。
您已经实现了Command 设计模式。小型、单一用途的 Command 对象(您的 CAdd 和 CMult)是 (IMO) 好的设计。我不会试图说服您采用不同的方法。
' Same iteration loop required for different calculations
Function Iteration(ByRef calculator As ICalculation) As Collection
Dim varArray01() As Variant
Dim varArray02() As Variant
Dim itA As Integer
Set Iteration = New Collection
varArray01 = Array(1, 2, 3, 4)
varArray02 = Array(11, 12, 13, 14)
For itA = 0 To UBound(varArray01)
Iteration.Add calculator.Calculation(varArray01(itA), varArray02(itA))
Next itA
End Function
子主变成:
' Passing different classes into iteration loop
Sub Main()
Dim colAdd As Collection
Set colAdd = Iteration(New CAdd)
Dim colMul As Collection
Set colMul = Iteration(New CMult)
End Sub
如果创建几个小的“无状态”类不是您正在寻找的解决方案,那么命令模式也可以使用包含最少量“状态”的单个类来实现。
在下面使用类似Calculator
的类:
Option Explicit
Implements ICalculation
Public Enum CalcID
Add
Multiply
End Enum
Private mCalculationID As CalcID
Private Sub Class_Initialize()
mCalculationID = Add
End Sub
Public Property Get CalculationID() As CalcID
CalculationID = mCalculationID
End Property
Public Property Let CalculationID(ByVal RHS As CalcID)
Select Case RHS
Case Add, Multiply
mCalculationID = RHS
Case Else
Err.Raise -1, "Invalid calculationID: " & CStr(RHS)
End Select
End Property
Private Function ICalculation_Calculation(ByVal intA As Integer, ByVal intB As Integer) As Integer
Select Case mCalculationID
Case Multiply
ICalculation_Calculation = intA * intB
Case Add
ICalculation_Calculation = intA + intB
Case Else
'Raise an error
End Select
End Function
现在您要管理一个计算器类...调用模块负责管理计算器的配置。 Main
子程序略有变化,Iteration
函数保持不变。
Sub Main()
Dim calc As Calculator
Set calc = New Calculator
calc.CalculationID = CalcID.Add
Dim colAdd As Collection
Set colAdd = Iteration(calc)
calc.CalculationID = CalcID.Multiply
Dim colMul As Collection
Set colMul = Iteration(calc)
End Sub
【讨论】:
感谢 BZngr。也许我真正在寻找的是我正在遵循良好实践的保证。到这个项目结束时,我可能会有很多课程,但听起来这不是问题。以上是关于将不同的函数传递到同一个迭代循环(VBA)的主要内容,如果未能解决你的问题,请参考以下文章