簡體   English   中英

VBA大SQL查詢-對象“范圍”的方法“ CopyFromRecordset”失敗

[英]VBA big SQL-Query - Method 'CopyFromRecordset' of object 'Range' failed

下面發布的代碼連接到oracle數據庫,處理SQL查詢並將結果表保存在新工作簿中。 它最多可以處理約200.000行。 但是,對於較大的數據集,當我嘗試將數據從記錄集對象復制到工作簿時,對象“范圍”的錯誤方法“ CopyFromRecordset”失敗

dataWs.Range("A2").CopyFromRecordset dataset 

有什么解決辦法嗎? 我嘗試遍歷數據集的所有元素,然后將它們復制到工作表中,但是對於大型數據集,這花費了極長時間。 你有什么想法? 我感謝您的幫助! 現在是代碼:

Sub QueryExecute(sqlString, userPW, userID, serverName)
'Connect to database <serverName> using user name <userID> and 
'password <userPW> to process SQL query <sqlString> and save the
'query result in a new workbook

   Dim ConnStr As String
   Dim Cn As ADODB.Connection
   Dim dataset As ADODB.Recordset
   Dim dataWs As Worksheet
   Dim dataWb As Workbook
   Dim icols As Integer

   'Create new workbook that will hold the query result/table:
   Set dataWb = Excel.Application.Workbooks.Add
   Set dataWs = dataWb.Sheets(1)

   Application.Calculation = xlManual

   'Trim trailing/leading blanks from sqlString:
   sqlString = Trim(sqlString)

   'Create string for database connection:
   ConnStr = "UID=" & userID & ";PWD=" & userPW & ";DRIVER={Microsoft ODBC for Oracle};" _
                    & "SERVER=" & serverName & ";"

   'Connect to database:
   Set Cn = New ADODB.Connection

   On Error Resume Next 'Error handling in case connection does not work

   With Cn
     .ConnectionString = ConnStr
     .CursorLocation = adUseClient
     .Open
   End With

   'Error handling for failed connection:
   If Err.Number <> 0 Then

     dataWb.Close
     MsgBox "Connection to database failed. Check username and password."
     Exit Sub

   End If

   'Send SQL query to database:
   Set dataset = Cn.Execute(sqlString)

   'Error handling for failed query:
   If Err.Number <> 0 Then

     dataWb.Close
     MsgBox "SQL-query could not be processed."
     Exit Sub

   End If

   On Error GoTo 0

   'Copy column names in first row of table worksheet:
   For icols = 0 To dataset.Fields.count - 1
     dataWs.Cells(1, icols + 1).Value = dataset.Fields(icols).Name
   Next

   dataWs.Range(dataWs.Cells(1, 1), _
   dataWs.Cells(1, dataset.Fields.count)).Font.Bold = True 'Format column names

   'Copy data to workbook:
   '***THIS WILL FAIL FOR LARGE DATASETS***
   dataWs.Range("A2").CopyFromRecordset dataset 


   dataset.Close
   Cn.Close

   MsgBox "Query successful."

   Application.Calculation = xlCalculationAutomatic

End Sub

根據Microsoft的文章 -最大行為1,048,576行乘以16,384列。 鑒於此,操縱或檢查一百萬行是不現實的-我們是否可以假設電子表格正在匯總這些行? 如果是這種情況,您應該一直在尋找最小化返回給Excel的記錄集的大小。 為此,您需要將數據的處理/匯總工作卸載到數據庫中。

這可以在SQL查詢或返回SYS_REFCURSOR的數據庫過程中完成。 這本質上是指向結果集的指針。

就像@OraNob所說的那樣,通過在數據庫端進行過濾,聚合和排序來最大程度地減少返回的數據量。 如果必須檢索大型數據集(以減少多次調用),則可以考慮保持記錄集處於打開狀態,並僅使用數據的各個子集所需的數據填充工作表。 如果記錄集的行數超過百萬左右,則可以將結果寫到多個工作表中。

我還建議您使用GetRows函數,並且您需要對其進行轉置,因為GetRows數組的大小將按列接行的方式確定,而Excel最適合於行接列的方式。

同樣,在給定數據集大小的情況下,並假設使用32位Office,您將無法依靠Application.Worksheet.Transpose進行轉置,因為這可能會耗盡內存,並且可能需要如果自己進行轉置,無論如何都要小心存儲。 考慮將轉置和插入分為幾批。

最后,請記住在做插入到工作表的范圍,因為它會比細胞通過細胞快得多 例如:

Dim aData(1 to 10000, 1 to 16)
aRecordset = rst.GetRows(10000)
'Transpose the aRecordset into aData
'...
Sheet1.Range(Sheet1.cells(1,1),Sheet1.Cells(10000,16) = aData

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM