Excel/ADO: 访问记录集时出错
Excel/ADO: Error Accessing Recordset
我通常可以 运行 下面的代码没有问题,但有时无法在记录集中找到任何记录。文件本身很大——超过 20 万行。此外,它有一些合并的单元格,并且列宽不够宽,无法在不自动调整的情况下查看数据(我不确定这是否是一个促成因素)。我还想补充一点,没有发现记录的次数大多发生在 运行ning Excel 2010 的机器上,而成功的实例发生在 运行ning [=] 的机器上 Excel 2013.
这是我的代码:
Dim oConn As New ADODB.Connection
Dim oRS As New ADODB.Recordset
Dim sPath
Dim sSQL As String
Dim fd As Office.FileDialog
Dim fr11 As String
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "FR11".
sSQL = "select F3,F6,F8,F9,F10,F18,F22,F23,F28 from [Natural Detail $] where F18 = '0000121046' or F25 = 'Natural GL Acct Nbr'"
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = False
.Title = "Please select the file." box.
.Filters.Clear
.Filters.Add "Excel", "*.xlsx"
.Filters.Add "All Files", "*.*"
If .Show = True Then
fr11 = .SelectedItems(1)
End If
End With
DBPath = fr11
oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & DBPath & "';" & _
"Extended Properties='Excel 12.0 Xml;HDR=No;IMEX=1;MaxScanRows=0';"
oRS.Open sSQL, oConn
If Not (oRS.BOF And oRS.EOF) Then
Worksheets("FR11").Range("A1").CopyFromRecordset oRS
Else
MsgBox "No records found"
End If
oRS.Close
oConn.Close
Set oConn = Nothing
您是否看到任何可能导致上述有时失败的情况,或者总体上会改进代码的情况。非常感谢任何反馈。
这是数据示例:
Company Name
Company Name
Company Info
Accounting Date: 04/12/2016
Company Code Company Code Type Group TP RES Band Name Arrival Date Departure Date ACCTING CENTER1 ACCTING CENTER2 Center Name GL AL Tran Type Name Acctng Tran Type Name Natural Posting Item Name Creation User Id SAP Account Name Paymnet Method Document Number Payment Originator Name Natural Posting Amt ID Acctng Tran Id Natural GL Acct Nbr Natural CAC Id PAY ID ID Totals
222 7887878 Master 4696941 0 4696941 random name 04/09/2016 04/23/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 5857 0000121046 4 1616165 649848
777 7768 Master 7575 0 783783 random name 12/01/2015 02/26/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 8778 0000121046 5 6168161 128572150
783783 4696941 Master 4696941 0 783783 random name 04/09/2016 04/25/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 8 0000121046 7 198816313 5464
4696941 78666 Master 4696941 0 4696941 random name 04/10/2016 04/22/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 1097152750 0000121046 3 171984 5616
78 4696941 Master 786 0 783783 random name 02/19/2016 03/04/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 27217 0000121046 1 515678 115616
66 786 Master 4696941 0 78378 random name 04/02/2016 04/06/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 4177 0000121046 2 56468 117980742
22 666/// Master 4696941 0 42753 random name 04/09/2016 04/29/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 9 0000121046 32 198805200 42742
783 86788 Master 4696941 0 4696941 random name 04/01/2016 04/17/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 879 0000121046 7 254948 1561
66676 4696941 Master 4696941 0 4696941 random name 02/29/2016 03/15/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 78 0000121046 7 45618 615
从语法上讲,您的 VBA 代码没有任何问题。只是您的 SQL 查询的 WHERE
条件没有 return 记录,因此它偶尔会起作用。对于您发布的示例数据,F18 和 F25 在列中没有这样的 WHERE
子句值,如下所示:
如果删除 WHERE
条件,所有记录都将 returned:
工作表的列排列可能不同,因此 F18 和 F25 可能指向不同的字段。因此,请考虑显式引用列以及包含记录集的工作表部分。确保每个工作表中都存在此类列,否则查询将失败。最后,在连接字符串中指定 HDR=Yes
以指示第一行包含列名:
sSQL = "select [Company1], [Group], [RES], [Band], [Name1]," _
& " [CENTER2], [AL], [Tran], [Type2]" _
& " from [Natural Detail$A10:BL19]" _
& " where [CENTER2]='0000121046' or [Name2]='Natural GL Acct Nbr'"
...
oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & DBpath & "';" & _
"Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";"
你会注意到上面的 SQL 语句有一些列名的数字后缀,这是由于数据源中重复的列名:(公司,代码,类型,名称,...)其中 Jet/ACE SQL 记录集中带有数字的引擎后缀,因为每个字段必须唯一标识。第一个实例没有编号,后面的每个实例都带有递增的后缀编号:Company、Company1、Company2...还要注意:使用 HDR=Yes
,没有字段名称将导致记录集:
最后但同样重要的是,对于最佳实践,始终错误处理您的代码以显示运行时错误的明确消息,并在全局 space 中使用 Option Explicit
以确保正确声明 variables/objects:
Option Explicit
Sub RunSQL()
On Error GoTo ErrHandle
Dim oConn As New ADODB.Connection
Dim oRS As New ADODB.Recordset
...
oRS.Close
oConn.Close
Set oConn = Nothing
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Sub
End Sub
我通常可以 运行 下面的代码没有问题,但有时无法在记录集中找到任何记录。文件本身很大——超过 20 万行。此外,它有一些合并的单元格,并且列宽不够宽,无法在不自动调整的情况下查看数据(我不确定这是否是一个促成因素)。我还想补充一点,没有发现记录的次数大多发生在 运行ning Excel 2010 的机器上,而成功的实例发生在 运行ning [=] 的机器上 Excel 2013.
这是我的代码:
Dim oConn As New ADODB.Connection
Dim oRS As New ADODB.Recordset
Dim sPath
Dim sSQL As String
Dim fd As Office.FileDialog
Dim fr11 As String
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = "FR11".
sSQL = "select F3,F6,F8,F9,F10,F18,F22,F23,F28 from [Natural Detail $] where F18 = '0000121046' or F25 = 'Natural GL Acct Nbr'"
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = False
.Title = "Please select the file." box.
.Filters.Clear
.Filters.Add "Excel", "*.xlsx"
.Filters.Add "All Files", "*.*"
If .Show = True Then
fr11 = .SelectedItems(1)
End If
End With
DBPath = fr11
oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & DBPath & "';" & _
"Extended Properties='Excel 12.0 Xml;HDR=No;IMEX=1;MaxScanRows=0';"
oRS.Open sSQL, oConn
If Not (oRS.BOF And oRS.EOF) Then
Worksheets("FR11").Range("A1").CopyFromRecordset oRS
Else
MsgBox "No records found"
End If
oRS.Close
oConn.Close
Set oConn = Nothing
您是否看到任何可能导致上述有时失败的情况,或者总体上会改进代码的情况。非常感谢任何反馈。
这是数据示例:
Company Name
Company Name
Company Info
Accounting Date: 04/12/2016
Company Code Company Code Type Group TP RES Band Name Arrival Date Departure Date ACCTING CENTER1 ACCTING CENTER2 Center Name GL AL Tran Type Name Acctng Tran Type Name Natural Posting Item Name Creation User Id SAP Account Name Paymnet Method Document Number Payment Originator Name Natural Posting Amt ID Acctng Tran Id Natural GL Acct Nbr Natural CAC Id PAY ID ID Totals
222 7887878 Master 4696941 0 4696941 random name 04/09/2016 04/23/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 5857 0000121046 4 1616165 649848
777 7768 Master 7575 0 783783 random name 12/01/2015 02/26/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 8778 0000121046 5 6168161 128572150
783783 4696941 Master 4696941 0 783783 random name 04/09/2016 04/25/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 8 0000121046 7 198816313 5464
4696941 78666 Master 4696941 0 4696941 random name 04/10/2016 04/22/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 1097152750 0000121046 3 171984 5616
78 4696941 Master 786 0 783783 random name 02/19/2016 03/04/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 27217 0000121046 1 515678 115616
66 786 Master 4696941 0 78378 random name 04/02/2016 04/06/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 4177 0000121046 2 56468 117980742
22 666/// Master 4696941 0 42753 random name 04/09/2016 04/29/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 9 0000121046 32 198805200 42742
783 86788 Master 4696941 0 4696941 random name 04/01/2016 04/17/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 879 0000121046 7 254948 1561
66676 4696941 Master 4696941 0 4696941 random name 02/29/2016 03/15/2016 Undistributed Undistributed Company Info REC Ledger RE Ledger CC ******* random name 4696941 4696941 78 0000121046 7 45618 615
从语法上讲,您的 VBA 代码没有任何问题。只是您的 SQL 查询的 WHERE
条件没有 return 记录,因此它偶尔会起作用。对于您发布的示例数据,F18 和 F25 在列中没有这样的 WHERE
子句值,如下所示:
如果删除 WHERE
条件,所有记录都将 returned:
工作表的列排列可能不同,因此 F18 和 F25 可能指向不同的字段。因此,请考虑显式引用列以及包含记录集的工作表部分。确保每个工作表中都存在此类列,否则查询将失败。最后,在连接字符串中指定 HDR=Yes
以指示第一行包含列名:
sSQL = "select [Company1], [Group], [RES], [Band], [Name1]," _
& " [CENTER2], [AL], [Tran], [Type2]" _
& " from [Natural Detail$A10:BL19]" _
& " where [CENTER2]='0000121046' or [Name2]='Natural GL Acct Nbr'"
...
oConn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & DBpath & "';" & _
"Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";"
你会注意到上面的 SQL 语句有一些列名的数字后缀,这是由于数据源中重复的列名:(公司,代码,类型,名称,...)其中 Jet/ACE SQL 记录集中带有数字的引擎后缀,因为每个字段必须唯一标识。第一个实例没有编号,后面的每个实例都带有递增的后缀编号:Company、Company1、Company2...还要注意:使用 HDR=Yes
,没有字段名称将导致记录集:
最后但同样重要的是,对于最佳实践,始终错误处理您的代码以显示运行时错误的明确消息,并在全局 space 中使用 Option Explicit
以确保正确声明 variables/objects:
Option Explicit
Sub RunSQL()
On Error GoTo ErrHandle
Dim oConn As New ADODB.Connection
Dim oRS As New ADODB.Recordset
...
oRS.Close
oConn.Close
Set oConn = Nothing
Exit Sub
ErrHandle:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "RUNTIME ERROR"
Exit Sub
End Sub