VBA连接数组元素然后作为多个参数传递给函数

时间:2017-11-15 10:15:20

标签: vba excel-vba excel

[更新:问题已经形成,以便可以将功能直接复制到VBA模块并通过运行test_callback_loop_function_works_with_multiple_parameters方法进行测试]

我正在使用Application.Run函数动态调用我的VBA中的方法。我的想法是,这个助手将节省我在VBA中的各种函数/子函数中循环遍历字典。相反,我可以调用以下帮助器来为我做循环:

Public Function user_func_dictionary_loop(Dictionary As Dictionary, _
                 MethodCallback As String, _
                 Optional Params As Variant) As Boolean

    Dim Key As Variant

    For Each Key In Dictionary

        If IsMissing(Params) Then
            Application.Run MethodCallback, Dictionary(Key)
        Else
            Application.Run MethodCallback, user_param_replace(Dictionary(Key), Params)
        End If

    Next Key

End Function

如果没有为函数提供参数,那么它只使用Dictionary的键值运行MethodCallback。如果有参数,则在下面触发另一个步骤:

Private Function user_param_replace(Item As Variant, Optional Params As Variant) As Variant

    Dim i As Long
    Dim strTest As String
    Dim Output As Variant

    Output = replace_dictionary_values(Item, Params)

    If IsArray(Output) Then
        ReDim Preserve Output(0 To UBound(Output))

        user_param_replace = Join(Output, ",")
        Exit Function

    End If

    user_param_replace = Output

End Function

Private Function replace_dictionary_values(Item As Variant, Optional Params As Variant) As Variant

    Dim l As Long
    Dim varTemp() As Variant
    Dim Param_Item As Variant

    l = 0
    If IsMissing(Params) Or Not IsArray(Params) Then
        replace_dictionary_values = Replace$(Params, "{D:Value}", Item)
        Exit Function
    Else

        ReDim varTemp(0 To UBound(Params))

        For Each Param_Item In Params
            varTemp(l) = Replace$(Param_Item, "{D:Value}", Item)
            l = l + 1
        Next Param_Item

    End If

    replace_dictionary_values = varTemp

End Function

上述步骤允许用户传入包含{D:Value}的参数,然后将其替换为Dictionary的键值。

我在下面做了一个小单元测试,认为它应该测试我的方法的功能。目前我得到的是“Argument not optional”错误:

Function test_callback_loop_function_works_with_multiple_parameters() As Boolean

    Dim dictTest As New Dictionary

    dictTest.Add 1, "1 - Foo"
    dictTest.Add 2, "2 - Foo"
    dictTest.Add 3, "3 - Foo"

    Dim MyArray(0 To 1) As Variant

    MyArray(0) = "{D:Value}"
    MyArray(1) = "Bar"

    user_func_dictionary_loop dictTest, "custom_debug_print_multiple_params", MyArray

    test_callback_loop_function_works_with_multiple_parameters = True

End Function

Function custom_debug_print_multiple_params(strPrint As String, strPrint2 As String) As String

    Debug.Print strPrint & strPrint2

End Function

输出应为:

1 - FooBar
2 - FooBar
3 - FooBar

但我得到了

  

运行时错误'449' - 参数不是可选的

Application.Run MethodCallback, user_param_replace(Dictionary(Key), Params)行上的

错误。

我的预感是,因为我正在尝试将数组元素与“,”一起连接,然后作为参数(在Join(Output, ",")行中)传递给方法,这会导致测试失败。 / p>

所以我的问题是,在VBA中,是否可以将数组的元素连接在一起,以便它们可以动态地传递给另一个方法/函数?

1 个答案:

答案 0 :(得分:1)

这行代码存在问题。

replace_dictionary_values = Replace$(Params, "{D:Value}", Item)

当IsMissing(Params)= True时,调用此行,并且可预测地返回错误。

我还发现你的测试程序无法正常工作。

Function custom_debug_print_multiple_params(strPrint As String, strPrint2 As String) As String

    Debug.Print strPrint & strPrint2

End Function

所有变量都是变体,但上述函数的两个参数是字符串类型。如果要传递字符串类型的变体,则应将参数声明为ByVal。我建议单独测试每个函数,并确保它在使用其返回值作为其他函数的参数之前有效。

我怀疑您的部分问题可能是由于您不加区别地使用变体造成的。例如,您在上面引用的错误行中调用的Replace函数需要3个字符串作为参数。在您的代码中,ItemParams(如果存在)都是变体。您的计划很有可能实际工作,但是当某些事情不能正常工作时,就像这里的情况一样,所有那些被削减的角落都必须进行检查,从而增加了调试工作的时间。在编码期间保存。

在下面的第一个示例中,调用过程提供了被调用过程所需的两个字符串。传递字符串类型的变体,它们通过ByVal参数转换为字符串。

Function Test_TestPrint() As Boolean

    Dim dictTest As New Scripting.Dictionary
    Dim MyArray(0 To 1) As Variant

    dictTest.Add 1, "1 - Foo"
    dictTest.Add 2, "2 - Foo"
    dictTest.Add 3, "3 - Foo"
    MyArray(0) = "{D:Value}"
    MyArray(1) = "Bar"

    TestPrint MyArray(0), MyArray(1)
'    user_func_dictionary_loop dictTest, "TestPrint", MyArray
    Test_TestPrint = True
End Function

Sub TestPrint(ByVal strPrint As String, ByVal strPrint2 As String)
    Debug.Print strPrint & strPrint2
End Sub

在下面的代码中,数组被传递给执行过程,该过程需要这样一个数组并打印出它的元素。

Function Test_TestPrint2() As Boolean

    Dim dictTest As New Scripting.Dictionary
    Dim MyArray(0 To 1) As Variant

    dictTest.Add 1, "1 - Foo"
    dictTest.Add 2, "2 - Foo"
    dictTest.Add 3, "3 - Foo"
    MyArray(0) = "{D:Value}"
    MyArray(1) = "Bar"

Sub TestPrint2 MyArray
'    user_func_dictionary_loop dictTest, "TestPrint", MyArray
    Test_TestPrint2 = True
End Function