MS Access 2016 SQL in VBA - sql

I'm sure I'm making a simple mistake. I have a SQL Server with tables that I have linked in MS Access. I am trying to run a SQL query in Form OnLoad to populate a text box based on a value in my form.
Below is my code. The field I want returned TE is varchar in MSSQL and short text in Access. I am getting a 'Type Mismatch' on the textbox. When I try outputting to a MsgBox I get:
'rst!TE not in collection'.
TN and TN_1 are smallint, in Access they are Number.
Dim rst As DAO.Database
Set rst = CurrentDb
rst.OpenRecordset "SELECT dbo_STCH.TE FROM dbo_STCH RIGHT JOIN dbo_SCVR ON dbo_STCH.TN = dbo_SCVR.TN_1 WHERE dbo_SCVR.TN_1=99;"
Me.Text22.Text = rst!TE
rst.Close
Set rst = Nothing

You are conflating DAO recordsets and databases and hence the message is correct as the item is not found in collection. Simply initialize rst as a recordset and assign it to OpenRecordset call.
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("SELECT dbo_STCH.TE FROM dbo_STCH" _
& " RIGHT JOIN dbo_SCVR ON dbo_STCH.TN = dbo_SCVR.TN_1" _
& " WHERE dbo_SCVR.TN_1=99;")
Me.Text22.Text = rst!TE
rst.Close
Set rst = Nothing

You have to use rst.MoveFirst to move to the first record of the opened recordset before reading any values from it.
Also as the answer above you have to Set rst = CurrentDb.OpenRecordset

Related

Access VBA: Recordset doesn't work with a specific query?

first off: I'm not an expert, I'm pretty much a noob at VBA.
onto my question:
So I'm using a Recordset in VBA, if the Recordset I open is a table or a simple query, it works,
but I have another query that I want to base that recordset on, but when I do that, it doesn't work.
The query I'm trying to use with the Recordset basically contains a field "user" that changes based on the textbox of a form. Is it not possible to open that query as recordset because it depends on the textbox of a form or am I missing something in the code?
Here my code for reference:
Dim db As Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tblExample")
Do Until rs.EOF
Debug.Print rs.Fields("FieldExample")
rs.MoveNext
Loop
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
I also tried replacing "tblExample" with an SQL string that is basically the same as the query I'm trying to use, with no success. The query itself does work without any problems though.
The query I'm trying to use (shortened version):
SELECT Inventar.nutzName FROM Inventar WHERE (((Inventar.nutzName) Like "*" & [Formulare]![frmInventarNutzerFilter]![cbxNutzer] & "*"))
Your code cannot "see" the parameter value, so you will have to pass this explicetly:
Dim db As DAO.Database
Dim qd As DAO.QueryDef
Dim rs As DAO.Recordset
Set db = CurrentDb
Set qd = db.QueryDefs("YourQuery")
qd.Parameters(0).Value = [Forms]![frmInventarNutzerFilter]![cbxNutzer]
Set rs = qd.OpenRecordset()
Do Until rs.EOF
Debug.Print rs.Fields("FieldExample")
rs.MoveNext
Loop
rs.Close
qd.Close
db.Close
Set rs = Nothing
Set db = Nothing

access VBA error "operation not supported for this type of object"

I have this vba code and I don't understand why it return error
me.ID is stored as string btw
Private Sub ID_AfterUpdate()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Me.ID = UCase(Me.ID)
Set db = CurrentDb
Set rs = db.OpenRecordset("Products")
rs.FindFirst ("[SKU] =""" & Me.ID & """") //this is the one giving error
If Not rs.NoMatch Then
MsgBox ("SKU Existed")
Me.ID.Value = Null
Me.Next.SetFocus //just for the sake of moving to this field then
Me.ID.SetFocus //to this field coz sometimes it won't go straight to
End If
rs.Close
Set rs = Nothing
Set db = Nothing End Sub
db.OpenRecordset("<a local Table>")
will open a recordset of type Table, for which .FindFirst etc. are not valid.
Either use dbOpenDynaset or use the .Seek method.
Database.OpenRecordset Method (DAO)
If you open a Recordset in a Microsoft Access workspace and you don't specify a type, OpenRecordset creates a table-type Recordset, if possible. If you specify a linked table or query, OpenRecordset creates a dynaset-type Recordset.

MS Access VBA Pass Through Query Connection String Error (ODBC)

I am currently trying to write a pass through query using VBA that connects to an oracle database. Using the answer provided from SQL Server Passthrough query as basis for a DAO recordset in Access as a starting poing, I have the following VBA code.
Option Compare Database
Sub Test_PassThroughQuery()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("")
qdf.Connect = "ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"
qdf.SQL = "SELECT * FROM DATE_TABLE"
qdf.ReturnsRecords = True
Set rst = qdf.OpenRecordset
Debug.Print rst
rst.Close
Set rst = Nothing
Set qdf = Nothing
End Sub
However, this prompts an error Type mismatch on the Debug.Print rst.
For the connection string I am using the ODBC connection string from the Property tab.
EDIT Am I calling the Debug.print rst line incorrectly?
There are many ways to create pass-through queries. If you want to save a pass-through query in Access, you can set the first parameter of CreateQueryDef:
Sub Test_PassThroughQuery()
Dim qdf As DAO.QueryDef, rst As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("MyPassthroughQuery")
qdf.Connect = "ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;"
qdf.SQL = "SELECT * FROM DATE_TABLE"
qdf.ReturnsRecords = True
DoCmd.OpenQuery "MyPassthroughQuery"
End Sub
This creates a saved query, and opens it.
You could also query an external data source in Access, which allows you to use the query designer, and use local tables and external data in a single query:
SELECT *
FROM [ODBC;DSN=database_name;UID=username;PWD=password;DBQ=ADPR;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BNF=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=F;CSR=F;FWC=F;FBS=64000;TLO=O;MLD=0;ODA=F;].DATE_TABLE

Select query to Access from VBA not returning duplicate values

Any help with this issue is greatly appreciated.
I am trying to retrieve from Access, by means of Select, multiple values with the same ID and have it pasted into an Excel sheet. I am running the code from Excel VBA.
The query I am using to retrieve said values is:
SELECT Role
FROM Roles
WHERE App_ID=(SELECT ID FROM Apps WHERE NAME='app name');
which is assigned to a variable and afterwards executed by using Set variable = cn.Execute(variable). The problem is that this query, executed from Excel VBA, returns only the first value found. Now, if I run this query from Access it returns every value with the ID for the specified app.
I have tried tried using INNER JOIN, IN, HAVING, etc. but it just wont retrieve all of the values into Excel. Like I said, the query works fine when used in Access so I know this must be limitation in Excel.
Thank you for any help you guys can provide.
Assuming you are using ADODB in Excel, keep in mind that the Execute function returns a Recordset. You can loop through the Recordset to see the additional rows.
Set rng = ActiveSheet.Range("A2")
Set rst = cn.Execute(strSQL)
With rst
Do While Not .EOF
rng = CStr(!Role)
Set rng = rng.Offset(1)
.MoveNext
Loop
End With
'Applies to Access 2010
'Reference Microsoft ActiveX Data Objects 6.1 Library
Dim strSQL As String
Dim strDBPathName As String
Dim strConProvider As String
Dim strPersist As String
Dim conADODB As ADODB.Connection
Dim rsADODB As ADODB.Recordset
Set conADODB = New ADODB.Connection
strConProvider = "Provider=Microsoft.ACE.OLEDB.12.0;"
'Database path name
strDBPathName = "Data Source=C:\Temp\Database.accdb;"
strPersist = "Persist Security Info=False;"
With conADODB
.ConnectionString = strConProvider & strDBPathName & strPersist
.Open
End With
strSQL = "SELECT Role FROM Roles WHERE App_ID=(SELECT ID FROM Apps WHERE NAME='app name')"
Set rsADODB = New ADODB.Recordset
With rsADODB
.Open strSQL, conADODB, adOpenStatic, adLockPessimistic
If Not (.EOF And .BOF) Then
'Range of spreadsheet to paste records
Cells(1, 1).CopyFromRecordset rsADODB
End If
.Close
End With
Set rsADODB = Nothing
conADODB.Close
Set conADODB = Nothing

VBA OpenRecordset Producing Too few parameters. Expected 2. Error

I have a query called qryAlloc_Source that has two paramaters under one criteria:
>=[forms]![frmReportingMain]![txtAllocStart] And <=[forms]![frmReportingMain]![txtAllocEnd])
A have a separate query that ultimately references qryAlloc_Source (there are a couple queries in between), and that query runs fine when I double click it in the UI, but if I try to open it in VBA, I get an error. My code is:
Dim rst As Recordset
Set rst = CurrentDb.OpenRecordset("qryAlloc_Debits")
I am getting run-time error 3061, Too few parameters. Expected 2. I've read that I may need to build out the SQL in VBA using the form parameters, but it would be pretty complex SQL given that there are a few queries in the chain.
Any suggestions as to a workaround? I considered using VBA to create a table from the query and then just referencing that table--I hate to make extra steps though.
The reason you get the error when you just try to open the recordset is that your form is not open and when you try to access [forms]![frmReportingMain] it's null then you try to get a property on that null reference and things blow up. The OpenRecordset function has no way of poping up a dialog box to prompt for user inputs like the UI does if it gets this error.
You can change your query to use parameters that are not bound to a form
yourTableAllocStart >= pAllocStart
and yourTableAllocEnd <= pAllocEnd
Then you can use this function to get the recordset of that query.
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim db As DAO.Database
Dim qdef As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs("qryAlloc_Debits")
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
The disadvantage to this is that when you call this now on a form that is bound to it it doesn't dynamically 'fill in the blanks' for you.
In that case you can bind forms qryAlloc_debts and have no where clause on the saved query, then use the forms Filter to make your where clause. In that instance you can use your where clause exactly how you have it written.
Then if you want to still open a recordset you can do it like this
Function GetQryAllocDebits(pAllocStart As String, pAllocEnd As String) As DAO.Recordset
Dim qdef As DAO.QueryDef
Set qdef = New DAO.QueryDef
qdef.SQL = "Select * from qryAlloc_Debits where AllocStart >= pAllocStart and pAllocEnd <= pAllocEnd"
qdef.Parameters.Refresh
qdef.Parameters("pAllocStart").Value = pAllocStart
qdef.Parameters("pAllocEnd").Value = pAllocEnd
Set GetQryAllocDebits = qdef.OpenRecordset
End Function
While a [Forms]!... reference does default to a form reference when a QueryDef is run from the GUI, it is actually just another Parameter in the query in VBA. The upshot is you don't have to recode your query/create a new one at all. Also, as #Brad mentioned, whether a parameter is in the final query of a chain of queries or not, you are able to refer to the parameter as if it is in the collection of the final query. That being the case, you should be able to use code similar to this:
Sub GetQryAllocDebits(dteAllocStart As Date, dteAllocEnd as Date)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Set db = CurrentDb()
Set qdf = db.QueryDefs("qryAlloc_Debit")
If CurrentProject.AllForms("frmReportingMain").IsLoaded Then
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = [forms]![frmReportingMain]![txtAllocStart]
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = [forms]![frmReportingMain]![txtAllocEnd]
Else
qdf.Parameters("[forms]![frmReportingMain]![txtAllocStart]") = CStr(dteAllocStart)
qdf.Parameters("[forms]![frmReportingMain]![txtAllocEnd]") = CStr(dteAllocEnd)
End If
Set rst = qdf.OpenRecordset
Do Until rst.EOF
'...do stuff here.
Loop
Set rst = Nothing
Set qdf = Nothing
Set db = Nothing
End Function
If the referenced form is open, the code is smart enough to use the referenced controls on the form. If not, it will use the dates supplied to the subroutine as parameters. A gotcha here is that the parameters did not like when I set them as date types (#xx/xx/xx#), even if the field were dates. It only seemed to work properly if I set the params as strings. It didn't seem to be an issue when pulling the values straight out of the controls on the forms, though.
I know it's been a while since this was posted, but I'd like to throw in my tuppence worth as I'm always searching this problem:
A stored query can be resolved:
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
For SQL:
Set db = CurrentDb
Set qdf = db.CreateQueryDef("", "SELECT * FROM MyTable " & _
"WHERE ID = " & Me.lstID & _
" AND dWeekCommencing = " & CDbl(Me.frm_SomeForm.Controls("txtWkCommencing")) & _
" AND DB_Status = 'Used'")
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
This assumes that all parameter values are accessible - i.e. forms are open and controls have values.
'I have two parameters in my recordset and I was getting the "Too few parameters. Expected 2" 'error when using an OpenRecordset in MS Access vba, and this is how I got around it and IT WORKS! see the below sub routine:
'Private Sub DisplayID_Click()
'1. I created variables for my two parameter fields xEventID and xExID as seen below:
Dim db As Database
Dim rst As Recordset
Dim xEventID As Integer
Dim xExId As Integer
'2. Sets the variables to the parameter fields as seen below:
Set db = CurrentDb
xEventID = Forms!frmExhibitorEntry!txtEventID
xExId = Forms!frmExhibitorEntry!subExhibitors!ExID
'3. Set the rst to OpenRecordSet and assign the Set the variables to the WHERE clause. Be sure to include all quotations, ampersand, and spaces exactly the way it is displayed. Otherwise the code will break!exactly as it is seen below:
Set rst = db.OpenRecordset("SELECT tblInfo_Exhibitor.EventID,tblInfo_Display.ExID, tblMstr_DisplayItems.Display " _
& "FROM tblInfo_Exhibitor INNER JOIN (tblMstr_DisplayItems INNER JOIN tblInfo_Display ON tblMstr_DisplayItems.DisplayID = tblInfo_Display.DisplayID) ON tblInfo_Exhibitor.ExID = tblInfo_Display.ExID " _
& "WHERE (((tblInfo_Exhibitor.EventID) =" & xEventID & " ) and ((tblInfo_Exhibitor.ExID) =" & xExId & " ));")
rst.Close
Set rst = Nothing
db.Close
'End Sub