“Too many fields defined” when querying Excel using ADO
Question
I'm querying an Excel 2010 workbook using the following ADO:
Function WorksheetRecordsetSQL(workbookPath As String, sheetName As String, selectSQL As String) As ADODB.Recordset
Dim objconnection As New ADODB.Connection
Dim objrecordset As New ADODB.Recordset
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
objconnection.CommandTimeout = 99999999
objconnection.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & workbookPath & ";" & _
"Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
objrecordset.Open selectSQL, _
objconnection, adOpenStatic, adLockOptimistic, adCmdText
Set WorksheetRecordsetSQL = objrecordset
End Function
When I call it with this SQL:
Select * FROM [someWorksheet$]
the function executes successfully. But if I call it with:
Select *,cdate(someField) FROM [someWorksheet$]
then I get this error:
Too many fields defined.
I found that the select *
query was producing a recordset with 255 fields (the maximum that the Access engine can have in a query), even though there are only 58 columns in the sheet. So that one extra cdate()
column overloaded the engine and produced the error.
Is there a way that I can keep a select *
query from picking up blank columns from an Excel sheet? Or some parameters that I can set that will allow more than 255 fields?
Solution
You can specify the range which should be read and so reduce the number of columns entering into the query. Here from cell A1 to column BF (58) all rows:
FROM [Source_sheet$A1:BF]
Sub main()
Dim reultingRecordset As ADODB.Recordset
Set reultingRecordset = WorksheetRecordsetSQL( _
"C:\Temp\VBA\ReadWithADOSource.xlsx", _
"Source_sheet", _
"Select * FROM [Source_sheet$]")
Debug.Print "Select * FROM [Source_sheet$] >"
Debug.Print "Fields: " & reultingRecordset.Fields.Count & " Records: " & reultingRecordset.RecordCount
Set reultingRecordset = WorksheetRecordsetSQL( _
"C:\Temp\VBA\ReadWithADOSource.xlsx", _
"Source_sheet", _
"Select *,cdate(Col2) FROM [Source_sheet$A1:BF]")
Debug.Print "Select *,cdate(Col2) FROM [Source_sheet$A1:BC] > "
Debug.Print "Fields: " & reultingRecordset.Fields.Count & " Records: " & reultingRecordset.RecordCount
End Sub
Output:
Select * FROM [Source_sheet$] >
Fields: 255 Records: 8
Select *,cdate(Col2) FROM [Source_sheet$A1:BC] >
Fields: 59 Records: 8