Calling Stored Procedure while passing parameters from Access Module in VBA - sql

I am working in Access 2010 with a Microsoft SQL Server 2008 backend. I have a stored procedure that inserts new values(supplied by the parameters) into a table. The values assigned to the parameters are obtained from files stored in a folder. The Windows File System is used to scan a particular folder to make a list of the files in it. For each scanned file the stored procedure is called and the FileName and QueueId (Filename without extension) along with other values are used as parameters for the stored procedure called. The stored procedure is used to create new records for each file for a table.
Public Function CreateInstrumentInterfaceLogRecords(BatchID As Long, InstrumentName As String) As Boolean
On Error GoTo HandleError
Dim objFSO As FileSystemObject
Dim AllFiles As Object
Dim objFolder As Object
Dim objFile As Object
Dim FileExt As String
Dim strSQL As String
CreateInstrumentInterfaceLogRecords = False
strSQL = "SELECT FileExt FROM tlkpInstrument"
FileExt = ExecuteScalar(strSQL)
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(NewPath)
'NewPath is a public variable that holds the path to the folder'
Set AllFiles = objFolder.Files
For Each objFile In AllFiles
FileName = objFile.FileName
QuenueId = Replace(FileName, FileExt, "")
'call procedure to pass values'
Next objFile
ExitProc:
Exit Function
HandleError:
MsgBox Err.Number & " " & Err.Description & " in CreateInstrumentInterfaceLogRecords"
GoTo ExitProc
End Function
and the stored procedure is:
CREATE PROCEDURE upInsertToInstrumentInterfaceLog #BatchID nvarchar(60),#InstrumentName nvarchar(60) ,#FIleName nvarchar(60), #QueueId nvarchar(60)
AS
INSERT INTO tblInstrumentInterfaceLog (BatchID,InstrumentName,FileName,QueueID,DateOfBatch,Folder)
VALUES (#BatchID, #InstrumentName,#FileName, #QueueId,getdate(),'New');
GO
All the examples haven't really given me a solid idea of to create the connection and call the procedure. Some advice I have been given is to study how ExecuteNonquery works so I have been trying to find examples related to that. The following is one of the example templates I've found
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
conn.ConnectionString = “your connection String here”
conn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "put stored procedure name here"
cmd.Execute
conn.Close
Set conn = Nothing
Set cmd = Nothing
I am not really sure what I should take from this example and how to incorporate passing values. Also even though I have visited http://www.connectionstrings.com/ I am still confused on how to make them. Any help would be greatly appreciated

Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
conn.ConnectionString = “your connection String here”
conn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "upInsertToInstrumentInterfaceLog"
cmd.parameters.Append cmd.CreateParameter("#BatchID", adVarChar, adParamInput, 60, "value for BatchID")
cmd.parameters.Append cmd.CreateParameter("#InstrumentName", adVarChar, adParamInput, 60, "value for InstrumentName")
'...
cmd.Execute
conn.Close

Use a saved pass-though query.
You code then becomes:
With currentdb.querydefs("MyPass")
.sql = "exec StoreProcName " & strBach & “,” & strInstrmentName
.execute
End With
So, you only need two lines of code here. You don't even have to declare any connection strings or even any variables if you use a saved pass-through query.

Related

Using Variable in SQL Query Raises ADO Error

I am trying to get a single itemcode from a SQL Server table (items) to be compared with an itemcode entered in an Excel sheet. To make this possible I have written the following VBA code in Excel 2019.
Function GetItemcodeFromSQLTable(sSQLArtikel As String) As String
Dim connection As New ADODB.connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Data Source=SQL01;Initial Catalog=110"
Dim query As String
query = "select itemcode from items where itemcode = " & sSQLArtikel
Dim rs As New ADODB.Recordset
rs.Open query, connection
connection.Close
End Function
I keep getting an error executing the line rs.open query, connection.
The purpose of this all is that I want to know if an itemcode already exists in the SQL table or not. If not, the rest of my VBA code wil create a XML file to import a new itemcode into the SQL table.
I have added a reference to "Microsoft Active X Data Objects 6.1 Library" in the VBA window.
Can anybody help me with this problem?
Many thanks.
The code I am using now is
Function CheckIfArticleCodeExistsInSQLDatabase(sSQLArtikel As String) As String
Dim query As String
Dim connection As ADODB.connection
Dim rs As ADODB.Record
Dim cmd As ADODB.Command
' PREPARED STATEMENT WITH PARAM PLACEHOLDERS
query = "select itemcode from items where itemcode = " & "'" & sSQLArtikel & "'"
' OPEN CONNECTION
Set connection = New ADODB.connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;" _
& "Data Source=SQL01;Initial Catalog=110"
' DEFINE COMMAND AND RECORDSET
Set cmd = New ADODB.Command
cmd.ActiveConnection = connection
Set rs = cmd.Execute(query, sSQLArtikel) ' BIND PARAM VALUES
' ... DO SOMETHING WITH rs
rs.Close: connection.Close
Set cmd = Nothing: Set rs = Nothing: Set connection = Nothing
End Function
When executing the command "Set rs = cmd.Execute(query, sSQLArtikel)" an errormessage is displayed "the command text is not set for the command object".
I am doing something wrong but what?
Consider the industry best practice of parameterization whenever running SQL in application layer like VBA. Doing so, you avoid the need to concatenate and punctuate variables to an SQL string.
Specifically, the missing quotes around string literals (sSQLArtikel) is your issue. With ADO Command.Execute, you can define recordsets with binded parameters.
Dim query As String
Dim connection As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
' PREPARED STATEMENT WITH PARAM PLACEHOLDERS
query = "select itemcode from items where itemcode = ?"
' OPEN CONNECTION
Set connection = New ADODB.Connection
connection.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;" _
& "Data Source=SQL01;Initial Catalog=110"
' DEFINE COMMAND AND RECORDSET
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = connection
.CommandType = adCmdText
.CommandText = query
.Parameters.Append .CreateParameter(, adVarChar, adParamInput, _
Len(sSQLArtikel), sSQLArtikel)
Set rs = .Execute
End With
' ... DO SOMETHING WITH rs
rs.Close: connection.Close
Set cmd = Nothing: Set rs = Nothing: Set connection = Nothing

Insert Into Table from Excel via VB button to stored procedure with Variables

I have a simple table AMC_GW_TESTTABLE with two columns, name nvarchar(20) and phone nvarchar(12). I also have a simple stored procedure with two variables.
create procedure AMC_GW_TESTSP (#name nvarchar(20),
#phone nvarchar(12)) as
insert into AMC_GW_Testtable (name,phone)
values (#name, #Phone)
I have been able to get a button in Excel to create the command:
exec dbo.amc_gw_testsp 'fred' '620-555-1212'
But it does not execute it. I copy this to my SSMS exactly like it and execute it and it works fine. Any ideas?
VBA code
Sub Button1_Click()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim connStr As String
Dim param As ADODB.Parameter
Dim param2 As ADODB.Parameter
connStr = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;" _
& "Initial Catalog=am_app);Data Source=bcu-sql-01"
Set conn = New ADODB.Connection
conn.ConnectionString = connStr
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "AMC_GW_TESTSP"
Set param = .CreateParameter("#name", adVarChar, adParamInput, 20, "Christopher")
.Parameters.Append param
Set param2 = .CreateParameter("#phone", adVarChar, adParamInput, 12, "0123456789")
.Parameters.Append param
.Execute
End With
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
I hope I did not scare you with a request for VBA Code
To give you an idea of what you should have:
Sub Button1_Click()
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim connStr As String
Dim param As ADODB.Parameter
Dim param2 As ADODB.Parameter
connStr = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;" & _
"Initial Catalog=dbname;Data Source=servername"
Set conn = New ADODB.Connection
conn.ConnectionString = connStr
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "AMC_GW_TESTSP"
Set param = .CreateParameter("#name", adVarChar, adParamInput, 20, "Christopher")
.Parameters.Append param
Set param2 = .CreateParameter("#phone", adVarChar, adParamInput, 12, "0123456789")
.Parameters.Append param
.Execute
End With
conn.Close
Set cmd = Nothing
Set conn = Nothing
End Sub
Things that you will have to change. Firstly the connection string (connStr). You will need to provide database name in place of dbname and server in place of servername. Also this string is assuming that you are using Windows Authentication for your SQL Server. If not you need to remove Integrated Security=SSPI; and in its place supply User ID=myUser;Password=myPassword;.
Next you will notice that the last parameter in the .CreateParameter function is a fixed string ("Christopher" and "0123456789"). In your case, they should be variables taken from cells in the spreadsheet. Please, please make sure that these strings do not contain ";" before trying to Execute.
I hope this helps, but feel free to contact me, if anything is less than clear!
PS You will need to make sure under Tools References, that you have the highest version of Microsoft ActiveX Data Objects Library checked (mine is 6.1, but anything 2.0 or higher definitely works).

Derive parameters of a stored procedure in VBA

I've tried searching a lot of places and can't quite find what I'm looking for.
I want to write a sub routine in vba that will tell me the parameters of a stored procedure stored on SQL Server.
I know how to execute a stored proc with parameters from excel vba. And I have written a stored proc that takes a stored proc name and returns the parameters. So I could use this. But I thought maybe there is a better way that I don't know about. I found a SQLCommandBuilder Class for VB that would be perfect but I need it in VBA. Is this available in VBA and I just don't know where to activate it?
Thanks
**Additional information: After the helpful comments below I am getting closer to what I am aiming to achieve.
I want to be able to pass any stored procedure into my subroutine and it will be able to figure out how many parameters it needs and what they will be
Here is my code so far
Private Sub execStoredProcedureWithParameters(strServer As String,
strDatabase As String, strSchema As String, strUSPName As String)
'Declare variables
Dim cmd As ADODB.Command
Dim conn As ADODB.Connection
Dim prm As ADODB.Parameter
Dim rs As ADODB.Recordset
Dim intParamCount As Integer
'Open database connection
Set conn = New ADODB.Connection
conn.ConnectionString = "Provider=sqloledb;Data Source=" + strServer + ";Initial Catalog=" + strDatabase + ";Integrated Security=SSPI;"
conn.CommandTimeout = 0
'Here's where the connection is opened.
conn.Open
'This can be very handy to help debug!
'Debug.Print conn.ConnectionString
Set cmd = New ADODB.Command
With cmd
.CommandText = strSchema + "." + strUSPName
.CommandType = adCmdStoredProc
.ActiveConnection = conn
.Parameters.Refresh
For intParamCount = 0 To .Parameters.Count - 1
Debug.Print .Parameters(intParamCount).Name, .Parameters(intParamCount).Type, .Parameters(intParamCounti).Size, .Parameters(intParamCount).Attributes, .Parameters(intParamCount).NumericScale
' Set prm = cmd.CreateParameter(.Parameters(i).Name, adVarChar, adParamInput, 255)
' cmd.Parameters.Append prm
' cmd.Parameters(.Parameters(i).Name).Value = "DBName"
Next
End With
Set rs = New ADODB.Recordset
'Execute the Stored Procedure
Set rs = cmd.Execute
'Populate the sheet with the data from the recordset
Sheet1.Range("RecordSet").CopyFromRecordset rs
'Cleanup
rs.Close
Set rs = Nothing
conn.Close
Set conn = Nothing
End Sub
Concerning the parameters. Is there a way to convert the DataTypeEnum from the value to the constant. So the type is currently coming through as 202 for the first parameter which I would set to adVarWChar according to this table
https://learn.microsoft.com/en-us/sql/ado/reference/ado-api/datatypeenum
You can do this with ADODB, add a reference to Microsoft ActiveX Data Objects then you can:
With New ADODB.Command
Set .ActiveConnection = myAdoDbConnection
.CommandText = "[dbo].[usp_XXX]"
.CommandType = adCmdStoredProc
.Parameters.Refresh
For i = 0 To .Parameters.Count - 1
Debug.Print .Parameters(i).Name, .Parameters(i).Type, .Parameters(i).Direction
Next
End With
There should be a necessity requiring this as it requires a round trip to the server.

Excel VBA executing SQL Server stored procedure - result set throwing error 3704

I am trying to execute a SQL Server stored procedure from Excel VBA. The procedure returns rows into a result set object. However, while running the code, it throws an error:
3704 Operation is not allowed when the object is closed
Note:
There is no problem with the database connection because Select query running on the same connection object are working fine.
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Dim prm As ADODB.Parameter
Dim rst As New ADODB.Recordset
Set cn = New ADODB.Connection
Set cmd = New ADODB.Command
ThisWorkbook.initialize
cn.Provider = "sqloledb"
cn.Properties("Data Source").Value = ThisWorkbook.server
cn.Properties("Initial Catalog").Value = ThisWorkbook.db
cn.Properties("User ID").Value = "xxxxx"
cn.Properties("Password").Value = "xxxxx"
cn.Open
Set cmd = New ADODB.Command
cmd.CommandText = "Generate_KPI_Process_Quality_Check_RunTime"
cmd.CommandType = adCmdStoredProc
cmd.ActiveConnection = cn
Set prm = cmd.CreateParameter("#currentMonth", adChar, adParamInput, 255, cmb_month.Value)
cmd.Parameters.Append prm
Set prm = cmd.CreateParameter("#center", adChar, adParamInput, 255, cmb_center.Value)
cmd.Parameters.Append prm
rst.CursorType = adOpenStatic
rst.CursorLocation = adUseClient
rst.CursorLocation = adUseServer
rst.LockType = adLockOptimistic
rst.Open cmd
If (rst.BOF And rst.EOF) Then
'Some Code
End If
Put
SET NOCOUNT ON
in the stored procedure -- this will prevent output text generation like "1 record(s) updated".
You have to provide more parameters for the Open method of Recordset Object
try rst.Open cmd, cn
Use the Set keyword to assign the object:
Set cmd.ActiveConnection = cn
otherwise, the default property of the Connection object (which happen to be the connection string) will be assigned in lieu of the Connection object itself.
Just put another recordset that will contain resultsets
Dim rst1 As New ADODB.Recordset
SET rst1=rst.NextRecordset 'this will return the first resultset
If rst1.BOF or rst1.EOF Then...
'some code
End If

Running stored procedure from Excel

I am trying to run a stored procedure from Excel. I know how to do it without using dynamic dates but I need the date range to be dynamic.
Sub TestStoredProcedure()
Dim CServer As String
Dim CDatabase As String
Dim CLogon As String
Dim CPass As String
Dim StartDate As Date
Dim EndDate As Date
Dim TStartDate As String
Dim TEndDate As String
CServer = "111111" ' Your server name here
CDatabase = "111111" ' Your database name here
CLogon = "11111111" ' your logon here
CPass = "111111" ' your password here
Dim Cmd1 As New ADODB.Command
Dim rs As New ADODB.Recordset
Dim intTemp As Integer
Set Cmd1 = New ADODB.Command
Cmd1.ActiveConnection = cn
Cmd1.CommandText = "callstatisticsbyQ"
Cmd1.CommandType = adCmdStoredProc
Cmd1.Parameters.Refresh
Cmd1.Parameters(0).Value = Worksheets("Sheet2").Range("A1")
Cmd1.Parameters(1).Value = Worksheets("Sheet2").Range("A2")
Cmd1.Parameters(2).Value = Worksheets("Sheet2").Range("A3")
Set rs = Cmd1.Execute()
rs.Open Cmd1
Worksheets("Procedure Export").Range("A1").CopyFromRecordset rs
Call DumpSP("prcGetData", "", "", Worksheets("Procedure Export").Range("A1"))
End Sub
I get an error saying something about user defined type not defined.
To use ADO you click Tools->references in the VBA IDE & tick "Microsoft ActiveX Data Objects" - preferably the highest version thereof.
Additionally you use cn as the connection but its not defined in that sub (assuming its not global) & you will may need to Set Cmd1.ActiveConnection = cn.
Also take a look at this, it defines the input (adParaminput) paramaters in advance rather than using .Refresh which is pretty inefficient (takes a trip to the server)
Update for example:
rem for create procedure callstatisticsbyQ (#i int, #c varchar(10)) as select 1234;
Dim cn As ADODB.Connection
Dim Cmd1 As ADODB.Command
Dim rs As ADODB.Recordset
Set cn = New ADODB.Connection
Set Cmd1 = New ADODB.Command
Set Cmd1 = New ADODB.Command
cn.Open "Provider=SQLNCLI10;Server=1.2.3.4;Database=x;Uid=x; Pwd=x;"
Set Cmd1.ActiveConnection = cn
Cmd1.CommandText = "callstatisticsbyQ"
Cmd1.CommandType = adCmdStoredProc
Cmd1.Parameters.Append Cmd1.CreateParameter("p1", adInteger, adParamInput, , Worksheets("Sheet2").Range("A1"))
Cmd1.Parameters.Append Cmd1.CreateParameter("p2", adVarChar, adParamInput, 20, Worksheets("Sheet2").Range("A2"))
Set rs = Cmd1.Execute()
MsgBox rs(0)
rs.Close
cn.Close