Waking this one up...
ExecuteNonQuery
Return value never assigned
`ExecuteNonQuery` never has its return value assigned.
Return value type
You have an opportunity here to return a richer value than a Boolean. Very often when executing a command, you're interested in the number of records affected. You can return the number of records affected, or -1 if there is an error.
Execution Options
You're not explicitly setting any Options on the ADODB.Command.Execute. As per MSDN:
Use the ExecuteOptionEnum value adExecuteNoRecords to improve performance by minimizing internal processing.
Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Long
Dim cmd As New ADODB.Command
cmd.ActiveConnection = connection
cmd.CommandType = adCmdText
cmd.CommandText = sql
Dim i As Integer
Dim value As Variant
For i = LBound(parameterValues) To UBound(parameterValues)
value = parameterValues(i)
cmd.parameters.Append ToSqlInputParameter(value)
Next
Dim result As Long
On Error Resume Next
Dim recordsAffected As Long
cmd.Execute recordsAffected, Options:=ExecuteOptionEnum.adExecuteNoRecords
If Err.Number = 0 Then
result = recordsAffected
Else
result = -1
End If
On Error GoTo 0
ExecuteNonQuery = result
End Function
CreateCommand factory method
Checking for valid ParamArray arguments
As per MSDN
If IsMissing is used on a ParamArray argument, it always returns False. To detect an empty ParamArray, test to see if the array's upper bound is less than its lower bound.
Despite the documentation above, IsMissing does actually seem to return True when the ParamArray argument is missing, but it's still safer to check the array bounds.
You obviously have a private helper function in IsArrayInitialized, but it is not necessary - if the ParamArray variable is "missing", it will be an array, but its upperbound will be -1, and its lowerbound will be 0, so the For statement is sufficient.
Private Function CreateCommand(connection As ADODB.connection, ByVal cmdType As ADODB.CommandTypeEnum, ByVal sql As String, parameterValues() As Variant) As ADODB.Command
Dim cmd As New ADODB.Command
cmd.ActiveConnection = connection
cmd.CommandType = cmdType
cmd.CommandText = sql
Dim i As Integer
Dim value As Variant
For i = LBound(parameterValues) To UBound(parameterValues)
value = parameterValues(i)
cmd.parameters.Append ToSqlInputParameter(value)
Next
Set CreateCommand = cmd
End Function
Having said that, you're going through some variable gymnastics to pass a ParamArray argument to a private method. You can avoid that by declaring the helper function's parameterValues parameter as ByVal parameterValues As Variant, but then you do need to check that it is an array before enumerating it.
Private Function CreateCommand(connection As ADODB.connection, ByVal cmdType As ADODB.CommandTypeEnum, ByVal sql As String, ByVal parameterValues As Variant) As ADODB.Command
Dim cmd As New ADODB.Command
cmd.ActiveConnection = connection
cmd.CommandType = cmdType
cmd.CommandText = sql
Dim i As Integer
Dim value As Variant
If IsArray(parameterValues) Then
For i = LBound(parameterValues) To UBound(parameterValues)
value = parameterValues(i)
cmd.parameters.Append ToSqlInputParameter(value)
Next
End If
Set CreateCommand = cmd
End Function
Then, you can simplify a public method like ExecuteStoredProc to:
Public Function ExecuteStoredProc(connection As ADODB.connection, ByVal spName As String, ParamArray parameterValues()) As ADODB.Recordset
Set ExecuteStoredProc = CreateCommand(connection, adCmdStoredProc, spName, values).Execute
End Function