I have put together a small wrapper class to simplify creating parameterized ADODB queries with VB6/VBA. At this point I'm keeping things simple, so it's only supporting input parameters and from what I've tested it seems to work exactly as intended.
The main reason for writing this, is because creating SQL Injection -safe queries with ADODB involves creating an ADODB.Parameter for each parameter value, which can be combersome; to a beginner it's much easier to just concatenate the values into the command string.
The first thing I did was creating a "converter" class to take any value and spit out an ADODB.Parameter object - I called that class AdoValueConverter:
AdoValueConverter Class
Option Explicit
Public Function ToStringParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
   
    Dim stringValue As String
    stringValue = CStr(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adVarChar
        .direction = direction
        .size = Len(stringValue)
        .value = stringValue
    End With
    
    Set ToStringParameter = result
    
End Function
Public Function ToIntegerParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    
    Dim integerValue As Long
    integerValue = CLng(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adInteger
        .direction = direction
        .value = integerValue
    End With
    
    Set ToIntegerParameter = result
    
End Function
Public Function ToLongParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    
    Set ToLongParameter = ToIntegerParameter(value, direction)
    
End Function
Public Function ToDoubleParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    
    Dim doubleValue As Double
    doubleValue = CDbl(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adDouble
        .direction = direction
        .value = doubleValue
    End With
    
    Set ToDoubleParameter = result
    
End Function
Public Function ToSingleParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    
    Dim singleValue As Single
    singleValue = CSng(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adSingle
        .direction = direction
        .value = singleValue
    End With
    
    Set ToSingleParameter = result
    
End Function
Public Function ToCurrencyParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    
    Dim currencyValue As Currency
    currencyValue = CCur(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adCurrency
        .direction = direction
        .value = currencyValue
    End With
    
    Set ToCurrencyParameter = result
    
End Function
Public Function ToBooleanParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    Dim boolValue As Boolean
    boolValue = CBool(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adBoolean
        .direction = direction
        .value = boolValue
    End With
    
    Set ToBooleanParameter = result
    
End Function
Public Function ToDateParameter(ByVal value As Variant, ByVal direction As ADODB.ParameterDirectionEnum) As ADODB.Parameter
    Dim dateValue As Date
    dateValue = CDate(value)
    
    Dim result As New ADODB.Parameter
    With result
        .type = adDate
        .direction = direction
        .value = dateValue
    End With
    
    Set ToDateParameter = result
    
End Function
Then I wrote the actual wrapper class, which I've called SqlCommand:
SqlCommand Class
Private converter As New AdoValueConverter
Option Explicit
Public Function Execute(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As ADODB.Recordset
    
    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
    
    Set Execute = cmd.Execute
    
End Function
Public Function SelectSingleValue(sql As String, ParamArray parameterValues()) As Variant
    
    Dim connection As New ADODB.connection
    connection.ConnectionString = Application.ConnectionString
    connection.Open
    
    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 rs As ADODB.Recordset
    Set rs = cmd.Execute
    
    Dim result As Variant
    If Not rs.BOF And Not rs.EOF Then result = rs.Fields(0).value
    
    rs.Close
    Set rs = Nothing
    connection.Close
    Set connection = Nothing
    
    SelectSingleValue = result
    
End Function
Public Function ExecuteNonQuery(connection As ADODB.connection, sql As String, ParamArray parameterValues()) As Boolean
    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 Boolean
    On Error Resume Next
        cmd.Execute
        result = (Err.Number = 0)
    On Error GoTo 0
    
End Function
Private Function ToSqlInputParameter(ByVal value As Variant, Optional ByVal size As Integer, Optional ByVal precision As Integer) As ADODB.Parameter
    
    Dim result As ADODB.Parameter
    Set result = CallByName(converter, "To" & TypeName(value) & "Parameter", VbMethod, value, ADODB.ParameterDirectionEnum.adParamInput)
    
    If size <> 0 Then result.size = size
    If precision <> 0 Then result.precision = precision
    
    Set ToSqlInputParameter = result
    
End Function
The Execute method returns a ADODB.Recordset object, and it's up to the client code to close it - the client code owns the connection being used.
The ExecuteNonQuery method returns a Boolean value indicating whether the command was executed successfully (that is, without throwing any errors) - again, the client code owns the connection being used.
The SelectSingleValue method returns a Variant value that represents the value of the first field of the first returned record, if anything is returned from the specified SQL statement.
Usage
Dim cmd As New SqlCommand
Dim result As Variant
result = cmd.SelectSingleValue("SELECT SomeField FROM SomeTable WHERE SomeValue = ?", 123)
Dim cmd As New SqlCommand
Dim result As ADODB.Recordset
Dim conn As New ADODB.Connection
conn.ConnectionString = "connection string"
conn.Open
Set result = cmd.Execute(conn, "SELECT * FROM SomeTable WHERE SomeField = ?", 123)
'use result
result.Close
conn.Close
Dim cmd As New SqlCommand
Dim conn As New ADODB.Connection
Dim result As Boolean
conn.ConnectionString = "connection string"
conn.Open
result = cmd.ExecuteNonQuery(conn, "UPDATE SomeTable SET SomeField = ? WHERE SomeValue = ?", 123, "abc")
conn.Close
Although the Precision doesn't get set (I have yet to figure that one out) for Double, Single and Currency parameters, tests have shown that all decimals are being correctly passed to the server, so there's [surprisingly] no immediately apparent bug here.



SqlCommand.SelectSingleValue("SELECT SomeField FROM SomeTable WHERE SomeValue = ?", 123)is all you need to code to get a full-fledged parameterized query, without the hassle of creating the parameters yourself. \$\endgroup\$