将不同的函数传递到同一个迭代循环(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)的主要内容,如果未能解决你的问题,请参考以下文章

没有 VBA 的迭代/循环替换

VBA Solver禁用每次迭代后弹出的对话框

VBA - 如何有条件地跳过for循环迭代

VBA循环迭代

Python生成器

03:迭代器和生成器