Is it possible to pass a NULL
value to QueryTable.Parameters
for use in a (My)SQL query?
From this other answer, we can see that it's possible to do this with ADODB.Command
, but unfortunately, ADODB
is not available in Excel for Mac, and the application I'm developing should work on both Windows & Mac.
The below is confirmed to error with Windows (and I'd assume Mac).
The following VBA code works fine if you set param_value
to anything but Null, but as soon as you try with a Null, it fails terribly.
Option Explicit
Sub Test()
' SQL '
Dim sql As String
sql = "SELECT ? AS `something`"
Dim param_value As Variant
'param_value = "hello" ' this works
'param_value = Null ' this does NOT work
' QUERY & TABLE CONFIG '
Dim my_dsn As String
Dim sheet_name As String
Dim sheet_range As Range
Dim table_name As String
my_dsn = "ODBC;DSN=my_dsn;"
sheet_name = "Sheet1"
Set sheet_range = Range("$A$1")
table_name = "test_table"
' EXECUTE QUERY '
Dim qt As QueryTable
Set qt = ActiveWorkbook.Worksheets(sheet_name).ListObjects.Add( _
SourceType:=xlSrcExternal, _
Source:=my_dsn, _
Destination:=sheet_range _
).QueryTable
With qt
.ListObject.Name = table_name
.ListObject.DisplayName = table_name
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = False
.CommandText = sql
End With
Dim param As Parameter
Set param = qt.Parameters.Add( _
"param for something", _
xlParamTypeUnknown _
)
param.SetParam xlConstant, param_value
qt.Refresh BackgroundQuery:=False
End Sub
When setting param_value
to "hello", the successful result looks like this:
(This bottom part with command prompt screenshot is what was recorded by MySQL's logging).
This is the error when setting param_value
to Null:
You can see from the MySQL log that the successful query first does a Prepare
, followed by an Execute
of the query.
Whereas the failing, Null query does the Prepare
, but never makes it to the Execute
.
Searching online for run-time error -2147417848 (80010108)
is no help; people report getting that for everything from "freeze pane" issues to "userform" issues, and I don't see anything about this related to QueryTable
.
Not only does the VBA code fail to work as expected, it also corrupts the workbook in some way:
(This occurs when attempting to save the file after the failed query; close without saving and you can re-open).
The fact that the MySQL log is showing the VBA connection failing to Quit
, and that the Excel file gets corrupted, makes me think that not only is it not possible to use Null in QueryTable.Parameters
, but that it is also a bug in the underlying software.
Am I missing something, or is it impossible to pass a Null Parameter to a QueryTable?
Update
In response to close votes: my point is that there should be a way to pass a parameter as NULL
, just as is referenced here.
Update
Due to this issue with Null, as well as xlParamTypeDate not being converted from a decimal to 'yyyy-mm-dd', I ended up rolling my own parameterizing class module. It has been posted below as an answer to this question.
If anyone knows how to accomplish this with
QueryTable.Parameters
, then post and I'll select your answer. But following is a custom solution.For all
SqlTypes
except, the parameterization is custom, butchar
.char
still usesQueryTable.Parameters
due to the various escaping corner cases that can occur when trying to implement thatEdit to above strikethrough: I have actually reverted to also manually handling char params with this custom parameterization. I forget the exact corner case encountered, but the definitive conclusion reached was that the VBA parameterization was failing for a singular case of a specific char param with a specific query string... I have absolutely no idea where the point of failure was as it was generated within the black-box of Microsoft's VBA method, but I validated as a factual certainty that the string param was simply not getting passed to the (My)SQL engine for this one seemingly random case. Suffice it to say that my experience has been that the
QueryTable.Parameters
method can simply not be trusted at all. My recommendation is to uncomment the line ofGetValueAsSqlString = Replace$(Replace$(Replace$(CStr(value), "\", "\\"), "'", "\'"), """", "\""")
and to remove theIF char THEN
logic withinSetQueryTableSqlAndParams
. Since different engines have different literal characters, I leave this as an exercise for the reader to handle in their circumstance; for example, the aboveReplace$()
code may (or may not) have the behavior you desire to see with a VBA string containing\n
.One inconsistency I noticed with QueryTable is that if you execute a non-parameterized query of
SELECT "hello\r\nthere" AS s
, the query will return with a newline (as expected), but if you use QueryTable.ParametersxlParamTypeChar
with"hello\r\nthere"
, then it will return with raw backslashes. So you must usevbCrLf
, etc. when parameterizing string literals.SqlParams
class module:Dependency Module:
Example Usage: