Recordset的Excel VBA函数(性能问题)

时间:2015-12-02 16:46:13

标签: excel vba excel-vba recordset

我在SQL Server中有一个数据库,用于在Excel中提供一些财务报告。我通过自定义Excel函数使用Recordset,该函数使用来自Cells的参数来构建SQL查询。以下是代码的外观:

 Public Function Test(arg1 As String, arg2 As String, arg3 As Integer, arg4 As Integer, arg5 As String) As Variant
    Dim oConnection As ADODB.Connection
    Set oConnection = New ADODB.Connection
    Dim oRecordset As ADODB.Recordset
    Set oRecordset = New ADODB.Recordset

    Dim strSQL As String

    strSQL = "SELECT SUM(BALANCE) as Total FROM Accounting WHERE ARGUMENT1 = " & Chr$(39) & arg1 & Chr$(39) & " AND ARGUMENT2 = " & Chr$(39) & arg2 & Chr$(39) & " AND ARGUMENT3 = " & Chr$(39) & arg3 & Chr$(39) & " AND ARGUMENT4 = " & arg4 & "  AND ARGUMENT5 = " & arg5 & ""

    oConnection.Open "Provider=SQLOLEDB;" & _
                         "Data Source=(IP of database);" & _
                         "Initial Catalog=(catalog of database);" & _
                         "Trusted_connection=yes;"

    oRecordset.Open Source:=strSQL, ActiveConnection:=oConnection, CursorType:=adOpenForwardOnly, LockType:=adLockReadOnly, Options:=adCmdText


    Test = oRecordset!Total

        oRecordset.Close
        Set oRecordset = Nothing


End Function

因此,此代码运行良好,但我遇到了性能问题。我必须填充数十个单元格,每个单元格使用来自不同单元格的不同参数。所以我的报告需要1分多钟才能完全加载。

我正在使用adOpenForwardOnly,但是我可以对代码进行任何其他微调以加快速度吗?

非常感谢

1 个答案:

答案 0 :(得分:0)

如果您的数据不是特别时间敏感,那么您可以通过使用字典对象缓存以前查询的结果来“记忆”您的UDF。

未测试:

Public Function Test(arg1 As String, arg2 As String, arg3 As Integer, _
                            arg4 As Integer, arg5 As String) As Variant

    Static dict As Object
    Dim k As String, rv
    Dim oConnection As ADODB.Connection
    Dim oRecordset As ADODB.Recordset
    Dim strSQL As String

    'create the dictionary if not already created
    If dict Is Nothing Then
        Set dict = CreateObject("scripting.dictionary")
    End If

    'create a unique "key" from the arguments
    k = Join(Array(arg1, arg2, arg3, arg4, arg5), Chr(0))

    'need to run this query?
    If Not dict.exists(k) Then

        Set oConnection = New ADODB.Connection
        Set oRecordset = New ADODB.Recordset

        strSQL = "SELECT SUM(BALANCE) as Total FROM Accounting WHERE ARGUMENT1 = '" & _
                 arg1 & "' AND ARGUMENT2 = '" & arg2 & _
                 "' AND ARGUMENT3 = '" & arg3 & "' AND ARGUMENT4 = " & arg4 & _
                 "  AND ARGUMENT5 = " & arg5 & ""

        oConnection.Open "Provider=SQLOLEDB;" & _
                             "Data Source=(IP of database);" & _
                             "Initial Catalog=(catalog of database);" & _
                             "Trusted_connection=yes;"

        oRecordset.Open Source:=strSQL, ActiveConnection:=oConnection, _
                        CursorType:=adOpenForwardOnly, LockType:=adLockReadOnly, _
                        Options:=adCmdText


        rv = oRecordset!Total

        dict.Add k, rv

        oRecordset.Close
        Set oRecordset = Nothing

    Else
        'already ran the SQL - just return the result
        rv = dict(k)
    End If

    Test = rv

End Function