【问题标题】:How can I unpack a VBA variant into multiple arguments to ParamArray?如何将 VBA 变体解压缩为 ParamArray 的多个参数?
【发布时间】:2021-03-17 13:54:54
【问题描述】:

我有一个将执行参数化 SQL 的 VBA 函数。

Public Function Execute(connection As ADODB.connection, ByVal sql As String, ParamArray parameterValues()) As ADODB.Recordset
    'Returns a connected ADODB.Recordset that contains the results of the specified parameterized query.

    Dim parameters() As Variant
    parameters = parameterValues
    
    Set Execute = ExecuteInternal(connection, sql, parameters)
    
End Function

参数的数量在运行时会有所不同,我使用选定的范围动态构造 sql 字符串。一个示例 sql 字符串是:

DELETE FROM my_table WHERE id NOT IN (?, ?, ?)

我也希望将范围内的值传递给函数,但是将 range.value 传递给 Execute 函数的天真方法当然不会导致范围被解包。

With New SqlCommand
    Set rs = .Execute(con, sql, myRange.value)
End With

如何将变体解压到 ParamArray 中?我基本上是在寻找 Python * 解包运算符。

如果这是一个愚蠢的问题,请原谅我,但 VBA 不是我的主要语言。

【问题讨论】:

  • 这行不通。在 VBA 中调用具有 ParamArray 的过程时,进行调用的行不传递数组。它传递一个或多个谨慎的参数(作为最后一个参数),VBA 将这些特殊参数捆绑为一个数组的工作(在幕后)。您的代码不能这样做。您正在传递一个恰好是数组的参数。要在使用 ParamArray 时获得您想要的效果,您的调用代码需要是这样的:Set rs = .Execute(con, sql, myRange1.Value, myRange2.Value, myRange3.Value)
  • 感谢@ExcelHero,这也是我得出的结论。如果您想将此添加为答案,我会接受。

标签: excel vba


【解决方案1】:

在 VBA 中调用接受 ParamArray 的过程时,进行调用的行实际上并未传递数组。它传递一个或多个谨慎的参数(作为最后一个参数),VBA 完成将这些特殊参数捆绑为 ParamArray 的工作(在幕后)。

您的代码不能这样做。您正在传递一个恰好是数组的参数,并且在幕后,VBA 将您的整个数组分配为 ParamArray 中唯一的元素。

要获得您想要的结果,您的调用代码需要是这样的(假设每个范围只是一个单元格):

Set rs = .Execute(con, sql, myRange1.Value, myRange2.Value, myRange3.Value)

【讨论】:

    【解决方案2】:

    你可以试试这个。这基本上将 paramArray “解包”到命令对象的参数中。

    Public Function Execute(connection As ADODB.connection, ByVal sql As String, ParamArray parameterValues()) As ADODB.Recordset
        'Returns a connected ADODB.Recordset that contains the results of the specified parameterized query.
    
        Dim i As Long
        Dim Cm As ADODB.Command
        Set Cm = New ADODB.Command
        Cm.AcctiveConnection = cn
        Cm.CommandType = adCmdText
        Cm.CommandText = sql
    
        For i = LBound(parameterValues) To UBound(parameterValues
           Cm.Parameters.Append Cm.CreateParameter("Param", adBigInt, adParamInput, 0, parameterValues(i))
        Next i
        
        Set Execute = Cm.Execute
        Set Cm = Nothing
    End Function
    

    【讨论】:

    • 感谢@MG92,但我试图将变体范围放入 ParamArray(这是我正在使用的库的签名),而不是解压缩 ParamArray 本身。
    猜你喜欢
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2021-08-30
    相关资源
    最近更新 更多