![](/img/trans.png)
[英]Get Query Result from SQL Server with VBA without 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.