VBA error when when running sql against Excel data

Rhino_Dance

Board Regular
Joined
Jul 23, 2008
Messages
74
I have an Excel file with a table of data on Sheet1. The table of data has 3 fields which are Code (a Text field) , Date (a Date field) and Amt (a Number field). I'm using vba with sql code to query that table and return the results of the query to a different sheet in the same file. So just to reiterate, Excel is my data source. I've done my research and largely worked this code out.

I'm also plugging a date parameter into the WHERE CLAUSE of the vba/sql code and this date is drawn from cell D4. This way, the user can change the date in cell D4 and this will change the criteria in the WHERE clause of the sql query to give them the results they want.

However I am getting an error that reads 'Data type mismatch in criteria expression' when I run the below code, so there must be something wrong with the specific syntax I'm using to plug in the date from cell D4.

Note that I can get the code and parameter to work if I make the CODE field the parameter with the query definition line of :

query = "SELECT
Code:
, sum([Amt]) as Ttl FROM [Main$] WHERE [Code] = '" & Range("D4").Value & "' group by [Code]" 

Can anyone tell me how I can make the date field work as the parameter? The line in question is highlighted in [COLOR=#ff0000]red[/COLOR]

Thanks & Happy New Year


Sub Pull_Data_from_Excel_with_ADODB()

    Dim cnStr As String
    Dim rs As ADODB.Recordset
    Dim query As String

    Dim fileName As String
    fileName = "C:\Price_Data\P180_Main_Dec23a.xlsm"

    cnStr = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
               "Data Source=" & fileName & ";" & _
               "Extended Properties=Excel 12.0"

   
    [COLOR=#ff0000]query = "SELECT [Code], sum([Amt]) as Ttl FROM [Main$] WHERE [Date] = '" & Range("D4") & "' group by [Code]"[/COLOR]
    Set rs = New ADODB.Recordset
    rs.Open query, cnStr, adOpenUnspecified, adLockUnspecified

    
    'Field Headers goes here
    Range("B9").CopyFromRecordset rs

    Dim cell As Range, i As Long
    With Range("B8").CurrentRegion
        For i = 0 To rs.Fields.Count - 1
            .Cells(1, i + 1).Value = rs.Fields(i).Name
        Next i
        .EntireColumn.AutoFit
    End With
      
End Sub
 
try this SQL statement instead of the long one that you have

query = "Select * FROM [Main$];"
rs.Open query, cnStr, adOpenUnspecified, adLockUnspecified

i also think that the cnStr should be a connection object, not the connection string

i have previously posted some code that may help you here http://www.mrexcel.com/forum/excel-questions/748763-ms-query-error-odbc-excel-driver-login-failed.html
 
Upvote 0

Excel Facts

Bring active cell back into view
Start at A1 and select to A9999 while writing a formula, you can't see A1 anymore. Press Ctrl+Backspace to bring active cell into view.
Fazza,
The easiest way for you to look at my Excel file would be for me to email it to you. But Mr Excel does not appear to have that capability. Can you email me so I can send it back to you as an attachment? My email address is 'ariesorb' and that would be a Yahoo email. Then later I will make sure the final solution is posted so that others can benefit from the knowledge.

Thanks!
John
 
Upvote 0
OK, John

Two things

1. some sample data (including your headers)

2. to be sure the values pulled from the named ranges are OK, please add a 'debug.print query' line and show me what that gives

regards

POST SCRIPT : before answering the above two points, please check a really simple query like SELECT * FROM table to be sure that everything else is OK.

earlier comments are still valid. Per the post script, the simple SELECT * FROM table working shows the error is only in the SQL.

if you can provide some sample data including headers & a debug.print of the SQL it should be a simple fix from there


regards
 
Upvote 0
Fazza, I've discovered an error in my vba code- but the query still doesn't work after fixing it. In the code the reference to cell 'C9' should be 'C10' and the reference to cell 'C10' should be 'C9'. I had the header landing spot and the recordset landing spot mixed up. (So my comment in the code about where the headers go is wrong) . I fixed that- but still get the error which is 'Invalid use of null' when I run the vba code. I also added the 'debug.print query' line to the vba code but nothing appears in the Immediate Window when the code is run.

Here is my new code:

Sub Pull_ADODB_Compact()

Dim cnStr As String
Dim rs As ADODB.Recordset
Dim query As String

Dim fileName As String

fileName = "C:\Price_Data\P180_Price_Index_Major.xlsm"

cnStr = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & fileName & ";" & _
"Extended Properties=Excel 12.0"


query = "SELECT M.[Item], M.[Prod_Type], M.[Prod_Cat], sum(M.[QtyShp]) as QtyShp,"
query = query & " sum(M.[Rev]) as Rev, sum(M.[Cost]) as Cost,sum(M.[Margin]) as Margin "
query = query & " FROM [Main$] M WHERE CLng(M.[Inv_MO]) >= " & CLng(Range("StartDt1").Value) & ""
query = query & " and CLng(M.[Inv_MO]) <= " & CLng(Range("EndDt1").Value) & ""
query = query & " GROUP BY M.[Item], M.[Prod_Type], M.[Prod_Cat]"
Set rs = New ADODB.Recordset
rs.Open query, cnStr, adOpenUnspecified, adLockUnspecified

Debug.Print query



Range("C10").CopyFromRecordset rs

Dim cell As Range, i As Long
With Range("C9").CurrentRegion
For i = 0 To rs.Fields.Count - 1
.Cells(1, i + 1).Value = rs.Fields(i).Name
Next i
.EntireColumn.AutoFit
End With

End Sub




And here my sample data on the 'MAIN' worksheet


For the record, because the field headers aren't well aligned, the field names are: Prod_Type, Prod_Cat, Item, InvDt, Inv_MO, QtyShp, Rev, Cost, Margin


[TABLE="width: 809"]
<colgroup><col><col><col><col><col><col><col><col><col></colgroup><tbody>[TR]
[TD]Prod_Type
[/TD]
[TD]Prod_Cat[/TD]
[TD]Item[/TD]
[TD]InvDt[/TD]
[TD]Inv_MO[/TD]
[TD]QtyShp[/TD]
[TD]Rev
[/TD]
[TD]Cost[/TD]
[TD]Margin[/TD]
[/TR]
[TR]
[TD]Gas[/TD]
[TD]17 - Mixes Spec[/TD]
[TD]SM K95OX5CD [/TD]
[TD="align: right"]12/5/2013[/TD]
[TD="align: right"]12/1/2013[/TD]
[TD="align: right"]1[/TD]
[TD="align: right"]29.54[/TD]
[TD="align: right"]13.55[/TD]
[TD="align: right"]15.99[/TD]
[/TR]
[TR]
[TD]Gas[/TD]
[TD]07 - Helium Ind[/TD]
[TD]HE T [/TD]
[TD="align: right"]7/29/2013[/TD]
[TD="align: right"]7/1/2013[/TD]
[TD="align: right"]2[/TD]
[TD="align: right"]290[/TD]
[TD="align: right"]162.9[/TD]
[TD="align: right"]127.1[/TD]
[/TR]
[TR]
[TD]Gas
[/TD]
[TD]17 - Mixes Spec[/TD]
[TD]SM K95OX5CD [/TD]
[TD="align: right"]12/5/2013[/TD]
[TD="align: right"]12/1/2013[/TD]
[TD="align: right"]1[/TD]
[TD="align: right"]29.54[/TD]
[TD="align: right"]13.55[/TD]
[TD="align: right"]15.99[/TD]
[/TR]
[TR]
[TD]Gas
[/TD]
[TD]07 - Helium Ind[/TD]
[TD]HE T [/TD]
[TD="align: right"]7/29/2013[/TD]
[TD="align: right"]7/1/2013[/TD]
[TD="align: right"]2[/TD]
[TD="align: right"]290[/TD]
[TD="align: right"]162.9[/TD]
[TD="align: right"]127.1[/TD]
[/TR]
[TR]
[TD]Gas
[/TD]
[TD]17 - Mixes Spec[/TD]
[TD]SM K95OX5CD [/TD]
[TD="align: right"]12/5/2013[/TD]
[TD="align: right"]12/1/2013[/TD]
[TD="align: right"]1[/TD]
[TD="align: right"]29.54[/TD]
[TD="align: right"]13.55[/TD]
[TD="align: right"]15.99[/TD]
[/TR]
[TR]
[TD]Gas
[/TD]
[TD]07 - Helium Ind[/TD]
[TD]HE T [/TD]
[TD="align: right"]7/29/2013[/TD]
[TD="align: right"]7/1/2013[/TD]
[TD="align: right"]2[/TD]
[TD="align: right"]290[/TD]
[TD="align: right"]162.9[/TD]
[TD="align: right"]127.1[/TD]
[/TR]
</tbody>[/TABLE]



I appreciate all the help you're giving me. Cheers, John
 
Upvote 0
John,

the debug.print lines need to be straight after the final line query = whatever

so instead of

Rich (BB code):
query = "SELECT M.[Item], M.[Prod_Type], M.[Prod_Cat], sum(M.[QtyShp]) as QtyShp,"
query = query & " sum(M.[Rev]) as Rev, sum(M.[Cost]) as Cost,sum(M.[Margin]) as Margin "
query = query & " FROM [Main$] M WHERE CLng(M.[Inv_MO]) >= " & CLng(Range("StartDt1").Value) & ""
query = query & " and CLng(M.[Inv_MO]) <= " & CLng(Range("EndDt1").Value) & ""
query = query & " GROUP BY M.[Item], M.[Prod_Type], M.[Prod_Cat]"
Set rs = New ADODB.Recordset
rs.Open query, cnStr, adOpenUnspecified, adLockUnspecified

Debug.Print query


have
Rich (BB code):
query = "SELECT M.[Item], M.[Prod_Type], M.[Prod_Cat], sum(M.[QtyShp]) as QtyShp,"
query = query & " sum(M.[Rev]) as Rev, sum(M.[Cost]) as Cost,sum(M.[Margin]) as Margin "
query = query & " FROM [Main$] M WHERE CLng(M.[Inv_MO]) >= " & CLng(Range("StartDt1").Value) & ""
query = query & " and CLng(M.[Inv_MO]) <= " & CLng(Range("EndDt1").Value) & ""
query = query & " GROUP BY M.[Item], M.[Prod_Type], M.[Prod_Cat]"

Debug.Print query

Set rs = New ADODB.Recordset
rs.Open query, cnStr, adOpenUnspecified, adLockUnspecified
 
Upvote 0
From a quick check the SQL looks OK. I'm wondering what values are in the named ranges StartDt1 and EndDt1

We'll see soon enough when you have the debug.print of the SQL
 
Upvote 0
Maybe those input date ranges need a worksheet reference added?

So instead of Clng(range("StartDt1").value)

clng(sheet_code_name.range("StartDt1").value)

regards
 
Upvote 0
FYI, a site showing something similar without VBA, using a parameterised query,

http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/

These can readily be set to refresh on change to an input (parameter) cell. Only trick is if distributing to others the query needs a little VBA to change the query's connection to suit changing file path.

regards
 
Upvote 0
Thanks Fazza. I put the Debug.Print query in the correct place and now have the sql statement which is:

SELECT M.[Item],
M.[Prod_Type],
M.[Prod_Cat],
Sum(M.[QtyShp]) AS QtyShp,
Sum(M.[Rev]) AS Rev,
Sum(M.[Cost]) AS Cost,
Sum(M.[Margin]) AS Margin
FROM [Main$] M
WHERE Clng(M.[Inv_MO]) >= 40878
AND Clng(M.[Inv_MO]) <= 41974
GROUP BY M.[Item],
M.[Prod_Type],
M.[Prod_Cat]

This looks ok, so I don't know what the problem is. The dates on the sheet are simply normal Excel dates that are formatted as dates. As you can see, the query is definitely pulling those dates and turning them into a number as intended. I also tried the code with a sheet reference for StartDt1 and EndDt1 so a portion of that code looks like this:

WHERE CLng(M.[Inv_MO]) >= " & CLng(Sheets("Rpt").Range("StartDt1").Value)

But I got the same output from Debug.Print query and the same error which is 'Invalid Use of Null'.

As to your other suggestion about using another method via Microsoft Query... I have gone down that road and been burned and wasted much time in this. Last month I put several days worth of effort into such a methodology- reading many posts similar to the one you shared- and I abandoned it because it is way too buggy and unreliable. MS Query is a very old and unsupported tool that is good for limited purposes under well structured conditions. The placement of parameters in MS Query is determined by the position of Question Marks in the sql code. This is about as primitive as it gets.

It is possible to have moments of fleeting success when implementing sql in MS Query that sources parameters from worksheet cells. But then if you change one thing in the code the errors begin to pour in and my experience is that the longer you work on a solution the more likely the workbook is to become corrupted and jettison the whole query.

After the experience I had with MS Query I turned to the methodologies that I am trying now with ADO / VBA. I am determined to find my solution in the code that we have been discussing. It is the more sophisticated, flexible and reliable way to get what I want. I intend to add several more parameters to the code we are working with so I must have methodologies which are very reliable. If I can only get past this current error I think I will be fine.

Thanks for any more feedback you have. I appreciate your efforts to help me.
 
Upvote 0

Forum statistics

Threads
1,224,013
Messages
6,175,941
Members
452,688
Latest member
Cyb3r_Ang3l

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top