Access 2010 using stored procedure as record source - vba

I am in the process of converting an ADP (SQL Server back end, Access front end) to an ACCDB (as ADPs are not supported in later versions of Access). From what I gather, this requires reworking any forms with stored procedure recordsources. All sources I've found on how to use a stored procedure as a recordsource use something like the approach below, but I am getting an error message any time I try to assign an ADODB recordset to a form: "3251 - Operation is not supported for this type of object." Any idea what I'm doing wrong? (Error triggers on Forms!New_frm_DIV_Master_View.Form.Recordset = RS.)
Private Sub DivMasterView_Click()
On Error GoTo ErrorHandler
'PROMPT FOR SCAR
Dim SCAR As String
SCAR = InputBox("Please enter a SCAR.")
'STOP IF NO SCAR ENTERED
If IsNull(SCAR) Or SCAR = "" Then Exit Sub
'STOP IF INVALID SCAR ENTERED
If IsNull(DLookup("[SCAR]", "dbo_Client Listing", "[SCAR] = '" & SCAR & "'")) Then
MsgBox "SCAR not found."
Exit Sub
End If
'OPEN FORM
DoCmd.OpenForm "NEW_frm_DIV_Master_View", , , , , acHidden
'SET UP CONNECTION
Dim WCDenialManagerConnection As New ADODB.Connection
WCDenialManagerConnection.ConnectionString = "Server=PS2PW601940;DSN=WCDenialManager2016;User Id = ACCOUNTS\" & Environ("USERNAME") & "'"
WCDenialManagerConnection.ConnectionTimeout = 0
WCDenialManagerConnection.Open
'SET UP STORED PROCEDURE COMMAND
Dim CMD As ADODB.Command
Set CMD = New ADODB.Command
Set CMD.ActiveConnection = WCDenialManagerConnection
CMD.CommandType = adCmdStoredProc
CMD.CommandTimeout = 0
CMD.CommandText = "storproc_Client_Data_by_DIV"
'SET UP PARAMETER
Dim PRM As ADODB.Parameter
Set PRM = CMD.CreateParameter("#SCAR", adVarChar, adParamInput, 10, SCAR)
CMD.Parameters.Append PRM
'SET UP RECORDSET
Dim RS As New ADODB.Recordset
'EXECUTE COMMAND AND SET RECORDSET
Set RS = CMD.Execute
Forms!New_frm_DIV_Master_View.Form.Recordset = RS
'SHOW FORM
Forms!New_frm_DIV_Master_View.Form.Visible = True
'CLEANUP
CMD.Parameters.Delete "#SCAR"
Set PRM = Nothing
Set CMD = Nothing
WCDenialManagerConnection.Close
Set WCDenialManagerConnection = Nothing
Exit Sub
ErrorHandler:
MsgBox Err.Description
End Sub

Related

Using VBA to query a VIEW from SQL Server

I am trying to create a VBA script that will pull the results from a View (SELECT * FROM view_name) from the RecordSet.Source property, but when attempted, my CloseConnection error handler keeps getting caught. I can get results from a table using a simple query like SELECT * FROM tbl_name with no issues.
Below is the code I am using. Note: my Const variable has the Provider and Database information removed.
I guess it really comes down to is it even possible to get results from a View like I would from a table?
Option Explicit
Const ConStrMSSQL As String = _
"Provider=provider_name;Database=database_name;Trusted_Connection=yes;"
Sub test()
Dim formConnect As ADODB.connection
Dim formData As ADODB.recordSet
Dim formField As ADODB.Field
Set formConnect = New ADODB.connection
Set formData = New ADODB.recordSet
formConnect.ConnectionString = ConStrMSSQL
formConnect.Open
On Error GoTo CloseConnection
With formData
.ActiveConnection = formConnect
.Source = "SELECT * FROM v_data_extract_658"
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
On Error GoTo CloseRecordset
Sheets("test").Range("A1").Select
For Each formField In formData.Fields
ActiveCell.Value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Sheets("test").Range("A2").CopyFromRecordset formData
On Error GoTo 0
CloseRecordset:
formData.Close
CloseConnection:
formConnect.Close
End Sub
This is the error message:
run-time error 2147467259 (80004005): unknown token received from SQL Server
I think the big issue here is that you haven't defined a Command Object.
I somewhat put this together "freehand" and for certain, didn't test it but it should get you to where you need to go.
Sub test()
On Error GoTo ErrorHandle:
Dim formConnect As ADODB.Connection
Set formConnect = New ADODB.Connection
formConnect.ConnectionString = ConStrMSSQL
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
formConnect.Open
With cmd
.ActiveConnection = formConnect
.CommandType = adCmdText
.CommandText = "SELECT * FROM v_data_extract_658"
.CommandTimeout = 30
End With
Dim formData As ADODB.Recordset
Set formData = New ADODB.Recordset
formData.Open cmd, , adOpenStatic, adLockReadOnly
Sheets("test").Range("A1").Select
Dim formField As ADODB.Field
For Each formField In formData.Fields
ActiveCell.value = formField.Name
ActiveCell.Offset(0, 1).Select
Next formField
Range("A2").CopyFromRecordset formData
On Error GoTo 0
Cleanup:
If Not formData Is Nothing Then
If formData.State <> adStateClosed Then formData.Close
Set formData = Nothing
End If
If Not formConnect Is Nothing Then
If formConnect.State <> adStateClosed Then formConnect.Close
Set formConnect = Nothing
End If
Set cmd = Nothing
Exit Sub
ErrorHandle:
MsgBox Err.Description
'Do whatever else is needed to respond to errors.
Resume Cleanup
End Sub
Using Excel & VBA to fetch dta from SLQ Server is quite easy (not always, but these days).
Sub ADOExcelSQLServer()
' Carl SQL Server Connection
'
' FOR THIS CODE TO WORK
' In VBE you need to go Tools References and check Microsoft Active X Data Objects 2.x library
'
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "EXCEL-PC\SQLEXPRESS" ' Enter your server name here
Database_Name = "NORTHWND" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
SQLStr = "SELECT * FROM [Customers]" ' Enter your SQL here
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";"
rs.Open SQLStr, Cn, adOpenStatic
' Dump to spreadsheet
For iCols = 0 To rs.Fields.Count - 1
Worksheets("Sheet1").Cells(1, iCols + 1).Value = rs.Fields(iCols).Name
Next
With Worksheets("sheet1").Range("a2:z500") ' Enter your sheet name and range here
'.ClearContents
.CopyFromRecordset rs
End With
' Tidy up
rs.Close
Set rs = Nothing
Cn.Close
Set Cn = Nothing
End Sub
As an aside, you can try this as well (please change to suit your specific setup/configuration)...
Sub Working2()
Dim con As Connection
Dim rst As Recordset
Dim strConn As String
Set con = New Connection
strConn = "EXCEL-PC\SQLEXPRESS;Database=Northwind;Trusted_Connection=True"
con.Open strConn
'Put a country name in Cell E1
Set rst = con.Execute("Exec dbo.MyOrders '" & ActiveSheet.Range("E1").Text & "'" & ActiveSheet.Range("E2").Text & "'")
'The total count of records is returned to Cell A5
ActiveSheet.Range("A5").CopyFromRecordset rst
rst.Close
con.Close
End Sub
Please see the link below for more details.
https://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm#Excel%20Data%20Export%20to%20SQL%20Server%20Test%20Code

Excel VBA - Run SQL Stored Procedure Error

I have the following code in my Excel workbook that I copied from this page.
Code:
Sub Button1_Click()
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
'''Clear extract area'''
Worksheets("Extract").UsedRange.Delete
'''Log into SQL Server'''
con.Open "Provider = SQLOLEDB;" & _
"Data Source = MySource;" & _
"Initial Catalog = MyDB;" & _
"User ID = MyID;" & _
"Password = MyPassword;"
cmd.ActiveConnection = con
'''Set up parameters for stored procedure'''
cmd.Parameters.Append cmd.CreateParameter("startDate", adDate, adParamInput, , Range("C2"))
cmd.Parameters.Append cmd.CreateParameter("endDate", adDate, adParamInput, , Range("C3"))
cmd.CommandText = "DB.StoredProc"
Set rs = cmd.Execute(, , adCmdStoredProc)
Set WSP1 = Worksheets("Extract")
WSP1.Activate
If rs.EOF = False Then WSP1.Cells(1, 1).CopyFromRecordset rs
rs.Close
Set rs = Nothing
Set cmd = Nothing
con.Close
Set con = Nothing
End Sub
I get the following error message on the line 'If rs.EOF = False Then'
"Operation is not allowed when the object is closed."
This is the first time I've used these functions. What have I done wrong?
Also, have I set up the multiple parameters correctly?
---Quick Edit---
Not sure if it's worth mentioning that I have formatted my date as yyyy-mm-dd, as it is in SQL server.
I've solved the issue by adding SET NOCOUNT ON to my stored procedure.
I wasn't initially sure if I would have access to be able to make that change. I have a new issue though. It works if I only use a single parameter but not when I use multiple parameters.
I will close this thread, do some research and potentially open a new one.
Thanks for your help.
cmd.CommandText = "DB.StoredProc"
should be the actual name of your stored procedure - unless you've actually named it StoredProc?
Here are two options for you to consider.
Option Explicit
Sub RunSProc()
'USE [Northwind]
'GO
'DECLARE #return_value int
'EXEC #return_value = [dbo].[TestNewProc]
' #ShipCountry = NULL
'SELECT 'Return Value' = #return_value
'GO
Dim con As Connection
Dim rst As Recordset
Dim strConn As String
Set con = New Connection
strConn = "Provider=SQLOLEDB;"
strConn = strConn & "Data Source=YOUR_SERVER_NAME;"
strConn = strConn & "Initial Catalog=YOUR_DB_NAME;"
strConn = strConn & "Integrated Security=SSPI;"
con.Open strConn
'Put a country name in Cell E1
Set rst = con.Execute("Exec dbo.TestNewProc '" & ActiveSheet.Range("E1").Text & "'")
'The total count of records is returned to Cell A5
ActiveSheet.Range("A5").CopyFromRecordset rst
rst.Close
con.Close
End Sub
Sub TryThis()
'USE [Northwind]
'GO
'DECLARE #return_value int
'EXEC #return_value = [dbo].[Ten Most Expensive Products]
'SELECT 'Return Value' = #return_value
'GO
Dim con As Connection
Dim rst As Recordset
Set con = New Connection
con.Open "Provider=SQLOLEDB;Data Source=YOUR_SERVER_NAME;Initial Catalog=YOUR_DB_NAME;Integrated Security=SSPI;"
Set rst = con.Execute("Exec dbo.[Ten Most Expensive Products]")
'Results of SProc are returned to Cell A1
ActiveSheet.Range("A1").CopyFromRecordset rst
rst.Close
con.Close
End Sub

VBA Crashes Excel When Closing an Access Connection

The following VBA code creates a new database from within Excel and adds a table to it. Everything works great until the line objConn.Close. This line causes Excel to crash with a BEX error. If I comment out that line the code runs fine but the database lock remains. Any help would be appreciated.
Option Explicit
Sub openADB()
Dim adoxTab As ADOX.Table
Dim adoxCat As ADOX.Catalog
Dim adoxCol As ADOX.Column
Dim adoxInd As New ADOX.Index
Dim objConn As New ADODB.Connection
Dim oCatalog As Object
Const DB_NAME = "item_details.accdb"
Const DB_PATH = "c:\temp\"
'create the database
Set oCatalog = CreateObject("ADOX.Catalog")
oCatalog.Create "Provider='Microsoft.ACE.OLEDB.12.0';Data Source=" & DB_PATH & DB_NAME
objConn.Open "Provider='Microsoft.ACE.OLEDB.12.0';Data Source=" & DB_PATH & DB_NAME
If (objConn.State <> adStateOpen) Then
MsgBox "A connection to the database " & DB_PATH & DB_NAME & " could not be established. Program terminated."
objConn.Close
Set objConn = Nothing
End
End If
'create a table for currency
Set adoxTab = CreateObject("ADOX.Table")
Set adoxCat = CreateObject("ADOX.Catalog")
Set adoxCat.ActiveConnection = objConn
'field properties
adoxTab.Name = "tblCurrency"
adoxTab.Columns.Append "Currency", adVarWChar, 3
adoxTab.Columns.Append "Factor", adSingle
adoxTab.Columns("Currency").ParentCatalog = adoxCat
adoxTab.Columns("Currency").Properties("JET OLEDB:Compressed Unicode Strings") = True
adoxTab.Columns("Currency").Properties("JET OLEDB:Allow Zero Length") = False
adoxTab.Columns("Currency").Properties("Nullable") = True
adoxTab.Columns("Factor").ParentCatalog = adoxCat
adoxTab.Columns("Factor").Properties("Nullable") = True
adoxCat.Tables.Append adoxTab
'set up a primary key for Item
adoxTab.Keys.Append "PrimaryKey", adKeyPrimary, "Currency"
'give back memory
Set adoxCat = Nothing
Set adoxTab = Nothing
Set oCatalog = Nothing
objConn.Close '<== this is the line that causes the error
Set objConn = Nothing
End Sub

VBA: How to capture a stored procedure return value

My goal is to execute a sql server stored procedure from a vba function, and to check if the stored procedure returned any records.
In the vba code I gotten this far:
Function TestStoredProcedure()
Dim strMsg As String
Dim ADOCon As ADODB.Connection
Dim ADOQD As ADODB.Command
Dim ADORS As ADODB.Recordset
Set ADOCon = New ADODB.Connection
ADOCon.ConnectionString = GetConnectionString("Dev")
ADOCon.CommandTimeout = 0
ADOCon.Open
Set ADOQD = New ADODB.Command
ADOQD.ActiveConnection = ADOCon
ADOQD.CommandTimeout = 0
ADOQD.CommandType = adCmdStoredProc
ADOQD.CommandText = "mn_CheckForInvalidEntries"
'Execute
Set ADORS = ADOQD.Execute
If ADORS.RecordCount > 0 Then
strMsg = "The SLI Search Feed was not successful."
MsgBox strMsg, vbExclamation, "foo"
Else
strMsg = "The SLI Search Feed successful."
MsgBox strMsg, vbExclamation, "foo"
End If
ADOCon.Close
Set ADOQD = Nothing
Set ADOCon = Nothing
strMsg = ""
End Function
And the stored procedure:
ALTER PROCEDURE [dbo].[mn_CheckForInvalidEntries]
AS
BEGIN
SET NOCOUNT ON;
SELECT
[ProductID]
, [ForSale]
FROM [Product]
WHERE [ProductID] IN
(
SELECT
[SearchIndex].[ProductID]
FROM [dbo].[SearchIndex]
INNER JOIN [ProductData]
ON [dbo].[SearchIndex].[ProductID] = [ProductData].[ProductID]
WHERE [ForSale] = 1
AND [SearchIndex].[ProductID] NOT LIKE 'mn[d-g]%'
AND [Record] IS NULL
AND [SearchIndex].[ProductID] NOT LIKE 'mn[a-z]%'
END;
If I could get any help in getting the part of the check if the sp returned any values, that would be great.
Thank you.
To store the results you can use a recordset.
Dim adoRs As ADODB.Recordset
Set adoRs = ADOQD.Execute
Then you can ask whether the recordset is empty.
isEmpty = (adoRs.BOF And adoRs.EOF)
All you want to do is run a stored procedure from Excel, right? Here are two options for you to try.
Option Explicit
Sub Working2()
Dim con As Connection
Dim rst As Recordset
Dim strConn As String
Set con = New Connection
strConn = "Provider=SQLOLEDB;"
strConn = strConn & "Data Source=LAPTOP\SQL_EXPRESS;"
strConn = strConn & "Initial Catalog=Northwind;"
strConn = strConn & "Integrated Security=SSPI;"
con.Open strConn
'Put a country name in Cell E1
Set rst = con.Execute("Exec dbo.TestNewProc '" & ActiveSheet.Range("E1").Text & "'")
'The total count of records is returned to Cell A5
ActiveSheet.Range("A5").CopyFromRecordset rst
rst.Close
con.Close
End Sub
Sub Working()
Dim con As Connection
Dim rst As Recordset
Set con = New Connection
con.Open "Provider=SQLOLEDB;Data Source=LAPTOP\SQL_EXPRESS;Initial Catalog=Northwind;Integrated Security=SSPI;"
Set rst = con.Execute("Exec dbo.[Ten Most Expensive Products]")
'Results of SProc are returned to Cell A1
ActiveSheet.Range("A1").CopyFromRecordset rst
rst.Close
con.Close
End Sub

Trouble to display a recordset

Public Function `RecordsetSybase(sqlstr As String) As ADODB.Recordset
If TestSybaseConnection() = False Then
setLogin
End If
Dim commandObject As ADODB.Command
Set commandObject = New ADODB.Command
Dim data As New ADODB.Recordset
With commandObject
.CommandText = sqlstr
.ActiveConnection = SybaseConnection(getUID, getPASS)
.CommandTimeout = 350
End With
data.Open commandObject.CommandText, commandObject.ActiveConnection
'Do Until data.EOF = True
'MsgBox data(0)
'data.MoveNext
'Loop
commandObject.ActiveConnection.Close
Set RecordsetSybase = data
Set commandObject = Nothing
End Function
Sub classific()
Dim conn As WorkbookConnection
Dim strSQL As String
Dim rs As New ADODB.Recordset
'Query
strSQL = "SELECT DISTINCT name_short_orig, cl_rating " & _
"FROM pbsm_hist.dbo.pbsm_auths_hist_adjusted " & _
"WHERE name_short_orig IS NOT Null " & _
"AND cl_rating NOT IN ('F+','F','Z') "
Set rs = RecordsetSybase(strSQL)
MsgBox rs
End Sub
I can display the recordset in the function (see comments).
But I cannot do it in the sub, I get the following error message:
Run-time error '13':
Type mismatch
You are completely bypassing the command object, currently its just sitting there storing the command text and connection.
To actually use the command object:
set data = commandObject.execute()
As for the error, MsgBox rs is not valid - what would you expect to see as the string representation of the rs object?
If you wanted the 1st value:
if not rs.eof then msgbox rs.collect(0)