VBA big SQL-Query – 对象'Range'的方法'CopyFromRecordset'失败

下面发布的代码连接到一个oracle数据库,处理一个SQL查询并将结果表保存在一个新的工作簿中。 它可以运行到约200,000行。 但是,对于较大的数据集,当我试图将数据从logging集对象复制到工作簿时,对象'范围'的错误方法'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 

根据微软的文章 – 最大的行数是1,048,576行16,384列。 鉴于操纵或审查一百万行是不现实的 – 我们可以假设电子表格正在总结行吗? 如果是这种情况 – 你应该总是希望尽量减less返回到Excel的logging集的大小。 要做到这一点,你可以将数据的处理/汇总卸载到数据库上。

这可以在SQL查询或返回SYS_REFCURSOR的数据库过程中完成。 这本质上是一个指向结果集的指针。

就像@OraNob所说的那样,通过在数据库端过滤,聚合和sorting来最小化您要返回的数据量。 如果您必须检索大型数据集(以减less多次调用),则可以考虑将logging集保持打开状态,并仅为工作表填充各种数据子集所需的数据。 如果您的logging集有超过几百万行,那么您可以将结果写出到多个工作表中。

我还build议使用GetRows函数,并且需要转置它,因为GetRows数组的大小将被定为列和行,并且Excel对行和列的效果最好。

此外,考虑到数据集的大小,并假定32位Office,您将无法依赖Application.Worksheet.Transpose来执行转置,因为您可能会耗尽内存,并且可能需要无论如何要记住,如果做自己的转置。 考虑分批转换和插入。

最后,请记住以范围的forms插入到工作表中,因为它将比单元格更快。 例如:

 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