I am trying to insert values from VB6 to SQL Server with a stored procedure but when I want to execute the process, I get this error:
The precision is invalid
I have already changed so many times the way that I try to enter them that I no longer know what to do.
This is the code in VB6
Dim strSQL As String
strSQL = "INSERT INTO FacturasPendientes (IdFactura,FechaFactura,CodigoProveedor,NombreProveedor," _
& " SubTotal,Iva,Total,FechaVencimiento,DiasDescuento,DescProntoPago,Pagado) VALUES (?,?,?,?,?,?,?,?)"
Dim CmdCont As ADODB.Command
Set CmdCont = New ADODB.Command
With CmdCont
Set .ActiveConnection = Cnn
.CommandType = adCmdStoredProc
.CommandText = "sp_FacturasCompras"
.Parameters.Append CmdCont.CreateParameter("#IdFactura", adVarChar, adParamInput, 50, TxtFactura.Text)
.Parameters.Append CmdCont.CreateParameter("#FechaFactura", adDate, adParamInput, 50, dtpFactura.Value)
.Parameters.Append CmdCont.CreateParameter("#CodigoProveedor", adVarChar, adParamInput, 50, TxtCodigoProveedor.Text)
.Parameters.Append CmdCont.CreateParameter("#NombreProveedor", adVarChar, adParamInput, 100, txtProveedor.Text)
.Parameters.Append CmdCont.CreateParameter("#SubTotal", adNumeric, adParamInput, 18, Round(Val(m_Subtotal), 2))
.Parameters.Append CmdCont.CreateParameter("#Iva", adNumeric, adParamInput, 18, Round(Val(m_Iva), 2))
.Parameters.Append CmdCont.CreateParameter("#Total", adNumeric, adParamInput, 18, Round(Val(m_Total), 2))
.Parameters.Append CmdCont.CreateParameter("#FechaVencimiento", adDate, adParamInput, 50, FechaFinal)
.Parameters.Append CmdCont.CreateParameter("#DiasDescuento", adVarChar, adParamInput, 50, txtDias.Text)
.Parameters.Append CmdCont.CreateParameter("#DescProntoPago", adVarChar, adParamInput, 50, txtDescuento.Text)
.Parameters.Append CmdCont.CreateParameter("#Pagado", adBigInt, adParamInput, chkPago.Value)
.Prepared = True
.Execute
End With
MsgBox "Se Grabaron los datos"
And the stored procedure is this:
ALTER PROCEDURE [dbo].[sp_FacturasCompras]
-- agregamos los valores de la consulta
#IdFactura VARCHAR(50),
#FechaFactura DATE,
#CodigoProveedor VARCHAR(50),
#NombreProveedor VARCHAR(100),
#SubTotal NUMERIC(18),
#Iva NUMERIC(18),
#Total NUMERIC(18),
#FechaVencimiento DATE,
#DiasDescuento VARCHAR(50),
#DescProntoPago VARCHAR(50),
#Pagado BIGINT
AS
BEGIN
INSERT INTO FacturasPendientes (IdFactura, FechaFactura, CodigoProveedor, NombreProveedor,
SubTotal, Iva, Total, FechaVencimiento,
DiasDescuento, DescProntoPago, Pagado)
VALUES (#IdFactura, #FechaFactura, #CodigoProveedor, #NombreProveedor,
#SubTotal, #Iva, #Total, #FechaVencimiento,
#DiasDescuento, #DescProntoPago, #Pagado)
END
The easiest way to call a stored procedure is to use Cnn connection object like this
Cnn.sp_FacturasCompras TxtFactura.Text, dtpFactura.Value, _
TxtCodigoProveedor.Text, txtProveedor.Text, _
Round(Val(m_Subtotal), 2), Round(Val(m_Iva), 2), _
Round(Val(m_Total), 2), FechaFinal, txtDias.Text, _
txtDescuento.Text, chkPago.Value
. . . which looks like an ordinary method call on the Cnn object.
If you have to use ADODB.Command then best would be to use some helper function for initializing ADODB.Parameter instances and ADODB.Command instances like this
Option Explicit
Private m_Subtotal As Double
Private m_Iva As Double
Private m_Total As Double
Private Sub Form_Load()
Dim oCmd As ADODB.Command
Set oCmd = InitCommandHelper("sp_FacturasCompras", _
InitParamHelper(TxtFactura.Text, adVarChar, 50), _
InitParamHelper(dtpFactura.Value, adDBDate), _
InitParamHelper(TxtCodigoProveedor.Text, adVarChar, 50), _
InitParamHelper(txtProveedor.Text, adVarChar, 100), _
InitParamHelper(Round(Val(m_Subtotal), 2), adDecimal, Precision:=18, NumericScale:=2), _
InitParamHelper(Round(Val(m_Iva), 2), adDecimal, Precision:=18, NumericScale:=2), _
InitParamHelper(Round(Val(m_Total), 2), adDecimal, Precision:=18, NumericScale:=2), _
InitParamHelper(FechaFinal, adVarChar, 50), _
InitParamHelper(txtDias.Text, adVarChar, 50), _
InitParamHelper(txtDescuento.Text, adVarChar, 50), _
InitParamHelper(chkPago.Value, adBigInt))
Debug.Print oCmd.Parameters.Count
End Sub
Public Function InitCommandHelper( _
ByVal sStoredProc As String, _
ParamArray Params() As Variant) As ADODB.Command
Const FUNC_NAME As String = "InitCommandHelper"
Dim lIdx As Long
On Error GoTo EH
Set InitCommandHelper = New ADODB.Command
With InitCommandHelper
If InStr(sStoredProc, ".") > 0 Then
.CommandText = sStoredProc
Else
.CommandText = "dbo." & sStoredProc
End If
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("RetVal", adInteger, adParamReturnValue)
lIdx = LBound(Params)
Do While lIdx <= UBound(Params)
.Parameters.Append Params(lIdx)
lIdx = lIdx + 1
Loop
End With
Exit Function
EH:
Debug.Print "Critical error: " & Err.Description & "[Form1." & FUNC_NAME & "]", Timer
End Function
Public Function InitParamHelper( _
ByVal vValue As Variant, _
ByVal eType As ADODB.DataTypeEnum, _
Optional ByVal Size As Long, _
Optional Direction As ADODB.ParameterDirectionEnum = adParamInput, _
Optional ByVal Name As String, _
Optional ByVal Precision As Long, _
Optional ByVal NumericScale As Long) As ADODB.Parameter
Const FUNC_NAME As String = "InitParamHelper"
Const DBL_NUM_LIMIT As Double = 10# ^ 12 ' 922337203685477#
Const EMPTY_GUID As String = "{00000000-0000-0000-0000-000000000000}"
On Error GoTo EH
Select Case eType
Case adVarChar, adVarWChar, adChar, adWChar
'--- trim varchar params'
If Not IsNull(vValue) And Not IsEmpty(vValue) Then
vValue = Left$(vValue, Size)
End If
Case adLongVarChar, adLongVarWChar, adLongVarBinary
'--- fix default size for BLOB params'
If Size = 0 Then
Size = -1
End If
Case adDBTimeStamp
If CDate(vValue) = CLng(CDate(vValue)) Then
eType = adDBDate
ElseIf CLng(CDate(vValue)) = 0 Then
eType = adDBTime
Else
eType = adDate
End If
Case adNumeric, adDecimal, adCurrency
'--- numeric range'
If IsNumeric(vValue) Then
If vValue > DBL_NUM_LIMIT Then
vValue = DBL_NUM_LIMIT
ElseIf vValue < -DBL_NUM_LIMIT Then
vValue = -DBL_NUM_LIMIT
End If
End If
Case adGUID
If Direction = adParamInput Then
If IsEmpty(vValue) Then
vValue = EMPTY_GUID
End If
End If
End Select
Set InitParamHelper = New ADODB.Parameter
InitParamHelper.Name = Name
InitParamHelper.Type = eType
InitParamHelper.Direction = Direction
InitParamHelper.Size = Size
InitParamHelper.Value = vValue
If Precision > 0 Then
InitParamHelper.Precision = Precision
End If
If NumericScale > 0 Then
InitParamHelper.NumericScale = NumericScale
End If
Exit Function
EH:
Debug.Print "Critical error: " & Err.Description & "[Form1." & FUNC_NAME & "]", Timer
Set InitParamHelper = Nothing
End Function
Note that NUMERIC(18) gets parsed as NUMERIC(18, 0) which has 0 digits after floating-point but you use Round(..., 2) for these params so probably an error. Just use NUMERIC(18, 2) or evern better DECIMAL(19, 2) as precision 18 and precision 19 use the same 5 bytes for storage.
Also note that sp_ prefix is reserved for system stored procedures, don't use it for user-defined stored procedures. You have to come up with different prefix like usp_ for sp (without underscore).
I suspect the issue is with the adNumeric columns. Try code like the following:
Dim p As Parameter
With CmdCont
Set p = .CreateParameter("#SubTotal", adNumeric, adParamInput)
p.Precision = 18
p.NumericScale = 2
p.Value = Round(Val(m_Subtotal), 2)
.Parameters.Append p
End With
You can adjust the precision and scale as needed.
Related
My form in MS Access has 10 fields on it - three are date fields updated in sequence - ('Start Date', 'Expected End Date', 'Actual End Date'.) Actual End Date is always NULL the first time the form is updated and Expected End Date may be null on the first few edits too.
When I edit the form and click the update button, a VBA routine calls the SQL Server stored procedure to update the database with changes/new values.
All works good - except if I leave any date fields as NULL (which they have to be for the business process) I get an error when the VBA executes the stored procedure. Please see the code I have used to date (and I have spent many hours on this with no luck)
Error Details: 3421
Application uses a value of the wrong type for the current operation.
Private Sub cmdUpdate_Click()
Dim Con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rtn As Integer
Dim dtStartDate As Date
Dim dtProjectedEnd As Date
Dim dtActualEnd As Date
On Error GoTo HandleErr
Set Con = New ADODB.Connection
Con.ConnectionString = fnProvider
Con.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = Con
.CommandType = adCmdStoredProc
Select Case frmStatus
Case "Add"
.CommandText = "dbo.spAddProjectPhaseDetail"
Case "Edit"
.CommandText = "dbo.spEditProjectPhaseDetail"
End Select
.Parameters.Append .CreateParameter("#PhaseDetailID", adinteger, adparaminput, , Me.txtPhaseDetailID)
.Parameters.Append .CreateParameter("#ProjPhaseID", adinteger, adparaminput, , Me.cboProjPhase)
.Parameters.Append .CreateParameter("#ProjectID", adVarChar, adparaminput, 10, Me.txtProjectID)
.Parameters.Append .CreateParameter("#PhaseLead", adinteger, adparaminput, , Me.cboTestLead)
If IsNull(Me.txtStartDt) Then
MsgBox "You must include a phase start date - this can be an estimate", vbExclamation, "Input Error"
GoTo ExitSub
End If
.Parameters.Append .CreateParameter("#PhaseStartDate", adDate, adparaminput, 9, Me.txtStartDt)
.Parameters.Append .CreateParameter("#PhaseProjectedEndDate", adDBDate, adparaminput, 9, Nz(Me.txtProjectedEnd, Null))
.Parameters.Append .CreateParameter("#PhaseActualEndDate", adDBDate, adparaminput, 9, Nz(Me.txtActualEnd, Null))
.Parameters.Append .CreateParameter("#SoftwareBuild", adVarChar, adparaminput, 20, Nz(Me.txtSoftwareBuild, ""))
.Parameters.Append .CreateParameter("#SysEnvironmentID", adVarChar, adparaminput, 50, Nz(Me.txtSysEnvironment, ""))
.Parameters.Append .CreateParameter("#IsCurrent", adinteger, adparaminput, , Nz(Me.chkCurrent, 0))
.Execute rtn
End With
If rtn = 0 Then
Err.Raise 10005, , "Could not add record to database."
Else
MsgBox IIf(frmStatus = "Edit", "Record Updated", "Record Added"), vbInformation, "Data Update"
End If
ExitSub:
Con.Close
Set Con = Nothing
Set cmd = Nothing
frmStatus = ""
DoCmd.Close acForm, "frmAddProjectPhases"
Exit Sub
HandleErr:
MsgBox "[" & Err.Number & "] " & Err.Description & vbCrLf & "If the error persisits, please contact support."
Call sbSysErrorLogUpdate(Err.Number, Err.Description, "Target:frmAddProjectProjectPhases/cmdUpdate_Click()")
Err.Clear
GoTo ExitSub
The Stored Procedure:
ALTER PROCEDURE [dbo].[spEditProjectPhaseDetail]
#PhaseDetailID Integer,
#ProjPhaseID Integer,
#ProjectID varchar(10),
#PhaseLead integer,
#PhaseStartDate DATE,
#PhaseProjectedEndDate date = NULL,
#PhaseActualEndDate date = NULL,
#SoftwareBuild varchar(50) = NULL,
#SysEnvironmentID varchar(50) = NULL,
#IsCurrent bit = 0
AS
BEGIN
SET NOCOUNT ON;
UPDATE dbo.tblProjPhaseDetail
Set
fPROJ_PHASE_ID = #ProjPhaseID,
fPROJECT_ID = #ProjectID,
fPHASE_LEAD = #PhaseLead,
PHASE_START_DT = #PhaseStartDate,
PHASE_PROJECTED_END_DT = #PhaseProjectedEndDate,
PHASE_ACTUAL_END_DT = #PhaseActualEndDate,
SOFTWARE_BUILD = #SoftwareBuild,
SYS_ENVIRONMENT_ID = #SysEnvironmentID
WHERE PHASE_DETAIL_ID = #PhaseDetailID
END
I'd be grateful for any getting this procedure to run with the Null dates. Thanks
Apologies - the answer is quite simple. I changed the parameter type from adDAte to adDBDate fro the parameters that need to pass null and it worked. Also there was a coding error - I had left the 'size' value in the parameters for the dates - in a previous attempt I had tried passing the dates as strings.-
I'm passing values from excel to sql-server via stored procedure.
There are two columns in excel in wich the cells contain integers or are empty.
But in sql-server, the empty cells from one column are shown as NULL, and the empty cells from the other are shown as "0". Why is that? Both variables are declared as integers in vba, and in sql.
What do I have to do to get everywhere NULL if the cell is empty?
This is part of the vba-code:
Dim rst As New ADODB.Recordset
Dim cmd As ADODB.Command
Dim query As String
Global ktghnev As String
Global ktghID As Integer
Dim elsosor As Integer
Dim pt, bank As Integer
Dim fizmod As String
Dim honap As String
With ActiveSheet
elsosor = 3
Do Until .Cells(elsosor, 1) = ""
nevID = .Cells(elsosor, 1)
pt = .Cells(elsosor, 4)
bank = .Cells(elsosor, 5)
If IsEmpty(Range("D" & elsosor)) = False Or IsEmpty(Range("E" & elsosor)) = False Then
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "EURfeltoltes"
cmd.Parameters.Append cmd.CreateParameter("#nevID", adInteger, adParamInput, , nevID)
cmd.Parameters.Append cmd.CreateParameter("#ktghID", adInteger, adParamInput, , ktghID)
cmd.Parameters.Append cmd.CreateParameter("#honap", adVarChar, adParamInput, 10, honap)
cmd.Parameters.Append cmd.CreateParameter("#pt", adInteger, adParamInput, , pt)
cmd.Parameters.Append cmd.CreateParameter("#bank", adInteger, adParamInput, , bank)
cmd.Execute
End If
elsosor = elsosor + 1
Loop
End With
This is the stored procedure:
ALTER PROCEDURE [dbo].[EURfeltoltes]
#nevID int = null,
#ktghID int = null,
#honap nvarchar(10) = null,
#pt int = null,
#bank int = null
AS
BEGIN
SET NOCOUNT ON;
insert into bertabla (nevID, ktghelyID, honap, eurpt, eurbank) values (#nevID, #ktghID, #honap, #pt, #bank)
END
I'm trying to push a button in an excel worksheet and it should send the data from the a worksheet to the sql table. But this vba code is not uploading the data from excel to the database. I have similar other table and it works fine. Any suggestions or thoughts on this would be great.
Sub Send2SQL()
Dim cmd As New ADODB.Command
Dim rst As ADODB.Recordset
Dim UploadTime, SubmissionNumber, WorkbookSection, DataDescription1, DataDescription2, DataDescription3
Dim iValue, sValue, fValue, bValue, dValue, Omit
Dim UploadRow As Integer
Dim LastRow As Integer
'Establish Error Handler
On Error GoTo ErrorHandler
'Determine UploadTime
UploadTime = Format(Now, "mm\/dd\/yyyy hh\:mm\:ss")
'Loop Through Upload
For UploadRow = 2 To LastRow
With Sheets("DataCapture")
WorkbookSection = .Cells(UploadRow, WorkbookSectionColumn).Value
DataDescription1 = .Cells(UploadRow, DataDescription1Column).Value
DataDescription2 = .Cells(UploadRow, DataDescription2Column).Value
DataDescription3 = .Cells(UploadRow, DataDescription3Column).Value
iValue = .Cells(UploadRow, iValueColumn).Value
sValue = Left(.Cells(UploadRow, sValueColumn).Value, 400)
If sValue = "" Then sValue = Empty
fValue = .Cells(UploadRow, fValueColumn).Value
bValue = .Cells(UploadRow, bValueColumn).Value
dValue = .Cells(UploadRow, dValueColumn).Value
End With
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "[DataUpload]"
.Parameters.Append .CreateParameter("#TimeOfUpload", adDBTimeStamp, adParamInput, , UploadTime)
.Parameters.Append .CreateParameter("#WorkbookSection", adVarChar, adParamInput, 60, WorkbookSection)
.Parameters.Append .CreateParameter("#DataDescription1", adVarChar, adParamInput, 255, DataDescription1)
.Parameters.Append .CreateParameter("#DataDescription2", adVarChar, adParamInput, 60, DataDescription2)
.Parameters.Append .CreateParameter("#DataDescription3", adVarChar, adParamInput, 60, DataDescription3)
.Parameters.Append .CreateParameter("#iValue", adBigInt, adParamInput, , iValue)
.Parameters.Append .CreateParameter("#sValue", adVarChar, adParamInput, 400, sValue)
.Parameters.Append .CreateParameter("#fValue", adDouble, adParamInput, , fValue)
.Parameters.Append .CreateParameter("#bValue", adBoolean, adParamInput, , bValue)
.Parameters.Append .CreateParameter("#dValue", adDate, adParamInput, , dValue)
.Parameters.Append .CreateParameter("#FileID", adBigInt, adParamInput, , rstOut)
Set rst = .Execute
End With
Set cmd = New ADODB.Command
Next UploadRow
'Turn off ErrorHandler & Exit Sub
On Error GoTo 0
Exit Sub
ErrorHandler:
MsgBox "There was an Error Uploading your data" & vbNewLine & vbNewLine & "An Automated Email has been sent to Sai Latha Suresh from Acturaial"
On Error GoTo 0
End
End Sub
You are using Execute on your Recordset, when you should be using Execute on your Command object.
From Excel to SQL Server? Try it this way.
Sub Rectangle1_Click()
'TRUSTED CONNECTION
On Error GoTo errH
Dim con As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strPath As String
Dim intImportRow As Integer
Dim strFirstName, strLastName As String
Dim server, username, password, table, database As String
With Sheets("Sheet1")
server = .TextBox1.Text
table = .TextBox4.Text
database = .TextBox5.Text
If con.State <> 1 Then
con.Open "Provider=SQLOLEDB;Data Source=" & server & ";Initial Catalog=" & database & ";Integrated Security=SSPI;"
'con.Open
End If
'this is the TRUSTED connection string
Set rs.ActiveConnection = con
'delete all records first if checkbox checked
If .CheckBox1 Then
con.Execute "delete from tbl_demo"
End If
'set first row with records to import
'you could also just loop thru a range if you want.
intImportRow = 10
Do Until .Cells(intImportRow, 1) = ""
strFirstName = .Cells(intImportRow, 1)
strLastName = .Cells(intImportRow, 2)
'insert row into database
con.Execute "insert into tbl_demo (firstname, lastname) values ('" & strFirstName & "', '" & strLastName & "')"
intImportRow = intImportRow + 1
Loop
MsgBox "Done importing", vbInformation
con.Close
Set con = Nothing
End With
Exit Sub
errH:
MsgBox Err.Description
End Sub
My setup looks like this.
Also.......Excel VBA - Update SQL Server Table:
http://www.cnblogs.com/anorthwolf/archive/2012/04/25/2470250.html
http://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm
...More
http://www.ozgrid.com/forum/showthread.php?t=169953
http://stackoverflow.com/questions/2567150/excel-vba-sql-data
http://msgroups.net/microsoft.public.excel.programming/vba-to-export-large-tables/61433
http://www.codeproject.com/Questions/475817/Howplustoplusupdateplussqlplusserverplusdataplusfr
http://www.excelguru.ca/forums/showthread.php?992-SQL-Select-Insert-Update-queries-from-Excel-vba
http://www.mrexcel.com/forum/excel-questions/617303-updating-records-access-table-using-excel-visual-basic-applications.html
http://www.excelforum.com/excel-programming-vba-macros/501147-how-to-use-vba-to-update-a-sql-server-table-from-a-spreadsheet.html
Would like to be able to write all rows that have data in them to SQL table, with the below I can only export the 1st row. If I add more rows of data and click the Export Button I will only send the first row. Can some one help me script my request?
Sub Button1_Click()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim strSQL As String
strSQL = "INSERT INTO dbo.TimeLog" & _
"(EventDate, ID, DeptCode, Opcode, StartTime, FinishTime, Units) " & _
"VALUES (?,?,?,?,?,?,?);"
Set conn = New ADODB.Connection
conn.Open "Provider=SQLOLEDB;Data Source=db\db1;Initial Catalog=Table1;Integrated Security=SSPI;"
'Skip the header row
iRowNo = 2
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdText
cmd.CommandText = strSQL
iRowNo = 2
With Sheets("Sheet1")
'Loop until empty cell in EventDate
Do Until .Cells(iRowNo, 1) = ""
cmd.Parameters.Append _
cmd.CreateParameter("pEventDate", adVarChar, adParamInput, 8, .Cells(iRowNo, 1))
cmd.Parameters.Append _
cmd.CreateParameter("pID", adInteger, adParamInput, , .Cells(iRowNo, 2))
cmd.Parameters.Append _
cmd.CreateParameter("pDeptCode", adVarChar, adParamInput, 2, .Cells(iRowNo, 3))
cmd.Parameters.Append _
cmd.CreateParameter("pOpCode", adVarChar, adParamInput, 2, .Cells(iRowNo, 4))
cmd.Parameters.Append _
cmd.CreateParameter("pStartTime", adDBTime, adParamInput, 0, .Cells(iRowNo, 5))
cmd.Parameters.Append _
cmd.CreateParameter("pFinishTime", adDBTime, adParamInput, 0, .Cells(iRowNo, 6))
cmd.Parameters.Append _
cmd.CreateParameter("pUnits", adInteger, adParamInput, , .Cells(iRowNo, 7))
cmd.Execute
iRowNo = iRowNo + 20
Loop
MsgBox "Success!"
End With
conn.Close
Set conn = Nothing
End Sub
I have the following SQL query:
SELECT SUM(OpenInterest) *(SELECT DISTINCT Future
FROM MTM
WHERE Expiry = [dbo].fx_GetRelativeExpiry(#date, 1, #Code)
and TradeDate = #date
and Code = #Code
and type = #Type
and Class = 'Foreign Exchange Future') / 1000
FROM MTM
WHERE Expiry = [dbo].fx_GetRelativeExpiry(#date, #N, #Code)
and TradeDate = #date
and Code = #Code
and type = #Type
and Class = 'Foreign Exchange Future'
Which I want to use as a function in Excel. The issue is that I reuse parameters many times in the above query and I don't know how to do that in excel without creating a new (and basically redundant) parameter. This is my VBA code:
Function GetTotalOI(TradeDate As Date, Code As String, OptionType As String, N As Integer) As Variant
'Create and open the connection
Dim oConnection As Connection
Set oConnection = New Connection
oConnection.ConnectionString = strConnectionStringYieldX
oConnection.Open
'Create the command object
Dim oCommand As Command
Set oCommand = New Command
oCommand.CommandType = adCmdText
Dim SQLString As String
SQLString = "SELECT SUM(OpenInterest) * (SELECT DISTINCT Future" _
& " FROM MTM" _
& " WHERE Expiry = [dbo].fx_GetRelativeExpiry(?, 1, ?)" _
& " and TradeDate = ?" _
& " and Code = ?" _
& " and type = ?" _
& " and Class = 'Foreign Exchange Future') / 1000" _
& " FROM MTM" _
& " WHERE Expiry = [dbo].fx_GetRelativeExpiry(?, ?, ?)" _
& " and TradeDate = ?" _
& " and Code = ?" _
& " and type = ?" _
& " and Class = 'Foreign Exchange Future'"
oCommand.CommandText = SQLString
oCommand.ActiveConnection = oConnection
oCommand.Parameters.Append oCommand.CreateParameter("Date1a", adDBTimeStamp, adParamInput)
oCommand.Parameters.Append oCommand.CreateParameter("Code1a", adVarChar, adParamInput, 50)
oCommand.Parameters.Append oCommand.CreateParameter("Date2a", adDBTimeStamp, adParamInput)
oCommand.Parameters.Append oCommand.CreateParameter("Code2a", adVarChar, adParamInput, 50)
oCommand.Parameters.Append oCommand.CreateParameter("Typea", adVarChar, adParamInput, 1)
oCommand.Parameters.Append oCommand.CreateParameter("Date1", adDBTimeStamp, adParamInput)
oCommand.Parameters.Append oCommand.CreateParameter("N", adInteger, adParamInput)
oCommand.Parameters.Append oCommand.CreateParameter("Code1", adVarChar, adParamInput, 50)
oCommand.Parameters.Append oCommand.CreateParameter("Date2", adDBTimeStamp, adParamInput)
oCommand.Parameters.Append oCommand.CreateParameter("Code2", adVarChar, adParamInput, 50)
oCommand.Parameters.Append oCommand.CreateParameter("Type", adVarChar, adParamInput, 1)
oCommand.Parameters.Item("Date1a").Value = TradeDate
oCommand.Parameters.Item("Code1a").Value = Code
oCommand.Parameters.Item("Date2a").Value = TradeDate
oCommand.Parameters.Item("Code2a").Value = Code
oCommand.Parameters.Item("Typea").Value = OptionType
oCommand.Parameters.Item("Date1").Value = TradeDate
oCommand.Parameters.Item("Code1").Value = Code
oCommand.Parameters.Item("N").Value = N
oCommand.Parameters.Item("Date2").Value = TradeDate
oCommand.Parameters.Item("Code2").Value = Code
oCommand.Parameters.Item("Type").Value = OptionType
Dim result As New ADODB.Recordset
Set result = oCommand.Execute
Dim resultA As Variant
GetTotalOI = WorksheetFunction.Transpose(result.GetRows)
oConnection.Close
End Function
The code works, but it is a mess. I only need 4 parameters. Any idea how to do it? Like is there a way to specify parameters by name instead of just as ? in the query string?
My connection string looks like this:
Const strConnectionStringYieldX As String = "Provider=SQLNCLI10.1;Data Source=xxxx;Initial Catalog=xxxx;Uid=xxxx;Pwd=xxxx;"
EDIT
To clarify the question, in ADO you have to specify parameters as ? rather than something like #ParamName which means if you use the same parameter twice, you have to recreate the parameter in your code. Which is ugly and unpleasant. So in this query where I really only use 4 parameters, because I repeat them a lot I have to uniquely name and create 11 parameters. So if you read the vba code you'll see I have parameters named date1a, date2a, date1 and date2 - BUT THESE ARE ALL THE SAME DATE! I am certain there is a native way to used some sort of named parameter in the query and thus only have to declare the 4 parameters.
I'm sure there is a proper way to do this but in the end I just made a UDF on the DB which allows me to use only 4 parameters and also certain T-SQL commands and procedures that otherwise wouldn't work. But if someone knows of a suitable alternative, please post it!