Access 2013 Compile error - object required - vba

I use Access quite a bit but only dabble in VBA code. I have some code that works, but I tried to compile the code and get the following error.
Private Sub Report_Open(Cancel As Integer)
Dim RS As Date
Set RS = CurrentDb.OpenRecordset("tblDate")
MsgBox ("The month and year are: " & RS)
DoCmd.OutputTo acOutputReport, "LP Completions", "PDFFormat(*.pdf)", Chr(34) & "\\sharepoint.xx.yyyy.zzz\Reports\" & Format(RS.Fields(0), "yyyy-mm") & Chr(32) & " - LP Completions - Exec Report.pdf" & Chr(34), False
End Sub
I get a Compile Error: Object Required. In the code view the RS = is highlighted.
I have no clue why this is coming up. Can someone provide some guidance as to how to fix this? Thanks so much!

If you're opening a recordset the variable should be a recordset. You then reference the field in the table you're after in the messagebox.
If you have more than one record in the table it will return the first value - so either create a temporary query to return the value you're after, or search the recordset and go to the correct record.
Private Sub Test()
Dim RS As dao.Recordset
Set RS = CurrentDb.OpenRecordset("tblDate")
MsgBox "The month and year are: " & Format(RS.Fields("MyDateField"), "yyyy-mm")
End Sub
Edit:
If you're using a query to get the record:
Private Sub Test2()
Dim qdf As DAO.QueryDef
Dim rs As DAO.Recordset
Set qdf = CurrentDb.CreateQueryDef("", "SELECT MAX(MyDateField) AS MaxDateField FROM tblDate")
Set rs = qdf.OpenRecordset
MsgBox "The month and year are: " & Format(rs.Fields("MaxDateField"), "yyyy-mm")
End Sub

In VBA, Set is only to be used when assigning to object variables. A variable of type Date is not an object variable, so you just say
RS = CurrentDb.OpenRecordset("tblDate")
(note that you can, if you really want to, put a Let in front, but pretty much no one ever does).

Related

Access - Reference a Access Form unbound textbox in TSQL Server Query? [duplicate]

I have Access front end which is powered by SQL Server in backend.
I made a form which requires user input, based on the input it should run a pass through query and should display result in the subform. I have read on internet this cannot be done through sql command and it requires sql coding to be wrapped in VBA coding.
I have made a code this like this:
Private Sub id_AfterUpdate()
Dim MyDb As Database, MyQry As QueryDef
Set MyDb = CurrentDb()
Set MyQry = MyDb.CreateQueryDef("")
MyQry.Connect = "ODBC;DSN=mikecollections;UID=***;PWD=****;DATABASE=mikecollections;"
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id=[forms]![test_form]![id]"
End Sub
This code should fire after I enter value in the id field in the form, but nothing happens. I do not know how to make this code work. Im new to SQL and VBA, Pls help!
I created a stored procedure in sql server and created a parameter in access to pass into sql server and got it working. Thank you Hansup and iDevlop for all the help.
Private Sub userinput_AfterUpdate()
Dim qrypass As DAO.QueryDef
Dim rst As DAO.Recordset
Set qrypass = CurrentDb.QueryDefs("qu_test")
qrypass.SQL = _
"exec collectibles.sp_coinsvsdocuments " _
& "#userinput=" _
& Forms!test_form!userinput
End Sub
You logically can't refer to an Access object in a passthru query.
So your sql should pass the value of the control, instead of referencing the control itself.
If id is a long:
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id= " & [forms]![test_form]![id]
Then you need to add the code to assign that querydef to a recordset, in order to read it. Something like:
set rs = myQry.OpenRecordset
If you prefer, you can also name your queryDef. it will then be available like any other query:
Set MyQry = MyDb.CreateQueryDef("someName")
'''specify all properties here...
doCmd.OpenQuery "someName"
Here is a solution for all Microsoft Access
just copy the below code into a Microsoft Access Module and change the parameter
Sub test()
' The "Kim_ZZ_Orderlines" has a string 'arg1' in the sql so we just replace this
' with the new value
RunPassThrough "KIM_ZZ_Orderlines", "Indput value", "10"
End Sub
Sub RunPassThrough(QueryToRun, ArgPrompt, ArgDefault)
' John Henriksen
' 2021-09-23
' Sub procedure to run a Pass-through query with argument
' in the query there must be the string 'Arg1" you want to replace
' e.g. AND APPS.OE_ORDER_LINES_ALL.ATTRIBUTE1 = 'arg1'
arg1 = VBA.InputBox(ArgPrompt, ArgPrompt, ArgDefault)
Dim db As DAO.Database
Dim qry, qryNy As String
Dim qrydefOrginal As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs(QueryToRun)
' Save the original sql
qry = qdef.sql
' Make a new sql, here we search for the string "arg1" and replace with our arg1 value
qryNy = VBA.Replace(qry, "arg1", arg1)
' Set the new sql
qdef.sql = qryNy
DoCmd.OpenQuery QueryToRun
' Set the original sql
qdef.sql = qry
Set qdef = Nothing
Set db = Nothing
End Sub

Pass through query with userinput in access form

I have Access front end which is powered by SQL Server in backend.
I made a form which requires user input, based on the input it should run a pass through query and should display result in the subform. I have read on internet this cannot be done through sql command and it requires sql coding to be wrapped in VBA coding.
I have made a code this like this:
Private Sub id_AfterUpdate()
Dim MyDb As Database, MyQry As QueryDef
Set MyDb = CurrentDb()
Set MyQry = MyDb.CreateQueryDef("")
MyQry.Connect = "ODBC;DSN=mikecollections;UID=***;PWD=****;DATABASE=mikecollections;"
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id=[forms]![test_form]![id]"
End Sub
This code should fire after I enter value in the id field in the form, but nothing happens. I do not know how to make this code work. Im new to SQL and VBA, Pls help!
I created a stored procedure in sql server and created a parameter in access to pass into sql server and got it working. Thank you Hansup and iDevlop for all the help.
Private Sub userinput_AfterUpdate()
Dim qrypass As DAO.QueryDef
Dim rst As DAO.Recordset
Set qrypass = CurrentDb.QueryDefs("qu_test")
qrypass.SQL = _
"exec collectibles.sp_coinsvsdocuments " _
& "#userinput=" _
& Forms!test_form!userinput
End Sub
You logically can't refer to an Access object in a passthru query.
So your sql should pass the value of the control, instead of referencing the control itself.
If id is a long:
MyQry.SQL = "select currency.tb_coins.id,documenttype,documentsubtype,documentname" & _
"from currency.tb_coins" & _
"inner join collectibles.tb_documents on tb_coins.id=collectibles.tb_documents.prodid" & _
"where currency.tb_coins.id= " & [forms]![test_form]![id]
Then you need to add the code to assign that querydef to a recordset, in order to read it. Something like:
set rs = myQry.OpenRecordset
If you prefer, you can also name your queryDef. it will then be available like any other query:
Set MyQry = MyDb.CreateQueryDef("someName")
'''specify all properties here...
doCmd.OpenQuery "someName"
Here is a solution for all Microsoft Access
just copy the below code into a Microsoft Access Module and change the parameter
Sub test()
' The "Kim_ZZ_Orderlines" has a string 'arg1' in the sql so we just replace this
' with the new value
RunPassThrough "KIM_ZZ_Orderlines", "Indput value", "10"
End Sub
Sub RunPassThrough(QueryToRun, ArgPrompt, ArgDefault)
' John Henriksen
' 2021-09-23
' Sub procedure to run a Pass-through query with argument
' in the query there must be the string 'Arg1" you want to replace
' e.g. AND APPS.OE_ORDER_LINES_ALL.ATTRIBUTE1 = 'arg1'
arg1 = VBA.InputBox(ArgPrompt, ArgPrompt, ArgDefault)
Dim db As DAO.Database
Dim qry, qryNy As String
Dim qrydefOrginal As DAO.QueryDef
Set db = CurrentDb
Set qdef = db.QueryDefs(QueryToRun)
' Save the original sql
qry = qdef.sql
' Make a new sql, here we search for the string "arg1" and replace with our arg1 value
qryNy = VBA.Replace(qry, "arg1", arg1)
' Set the new sql
qdef.sql = qryNy
DoCmd.OpenQuery QueryToRun
' Set the original sql
qdef.sql = qry
Set qdef = Nothing
Set db = Nothing
End Sub

SetFocus is getting ignored - Why?

I have 2 fields - txtTR1_Unit and cmbTR2_Unit. Together, these 2 fields represent the total UNIT.
cmbTR2_Unit has a list of unique values that when selected - txtTR1_Unit automatically gets the related value.
I've created a function called Tier1from2 - that accepts a 'string' and returns the related Tier1 value.
So when I update cmbTR2_Unit in my After_Update event, I'd like to automatically tab to the next field. - Another combo box. I figured that I shouldn't need to set any focus, because it would automatically go to the next field after updating.
txtTR1 gets updated just as expected from my Function, but then it just sits there and won't go to the next field. So I have attempted to 'SetFocus' to the next field after the update.
Still no go. What did I miss??
Private Sub cmbTR2_UNIT_AfterUpdate()
If Len(Me.cmbTR2_UNIT.Value) <> 0 Then
Me.txtTR1_UNIT.Value = Tier1From2(Me.cmbTR2_UNIT.Text)
'cmb_CostCenter.setfocus - 'this doesn't seem necessary - but it doesn't work anyway.
End If
End Sub
As a test I tried removing the function "Tier1From2(Me.cmbTR2_UNIT.text)" simply hard coding the word 'RESULT' in txtTR1_UNIT and it works without a hitch. I know I used to write a more simple function but I haven't touched VBA in awhile - How can I simplify this function:
Private Function Tier1From2(strTier2 As String) As String
Dim qdf As DAO.QueryDef
Dim db As DAO.Database
Dim strQry As String
Dim rs As Recordset
Set db = CurrentDb
Set qdf = db.QueryDefs("qUNIT_HUB")
strQry = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
qdf.SQL = strQry
db.QueryDefs.Refresh
Set rs = db.OpenRecordset(strQry)
Tier1From2 = rs![Tier1_Unit]
Set db = Nothing
Set qdf = Nothing
Set Recordset = Nothing
End Function
It turns out that something in this function was causing the field and form to loose focus. db.QueryDefs.refresh perhaps? The solution was to update my Function as follows
Private Function Tier1From2(strTier2 As String) As String
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
Dim strTier1 As String
Set db = CurrentDb
strSQL = "SELECT Tier1_Unit, Tier2_Unit " & _
" FROM LTBL_Cost_Collector " & _
" GROUP BY Tier1_Unit, Tier2_Unit " & _
" HAVING (((Tier2_Unit) = '" & strTier2 & "'));"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
strTier1 = rs!Tier1_Unit
Set rs = Nothing
Set db = Nothing
Tier1From2 = strTier1
End Function
This worked without a hitch.

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

How to pass inequal operators for parameters in SQL Access VBA

I have a stored query below in Access call "1PreviousEWBS":
SELECT f.ewbs AS EWBS, SUM(f.[total hours]) AS [Total Hours], SUM(f.[total cost]) AS [Total Cost], T.description AS Activity, T.AWBS AS AWBS
FROM FindHrCostByEWBS AS f, AllProjectsCodes AS T
WHERE (f.project)=Forms!x!cboProjects
And f.[period end date]<Forms!x!cboDate
And f.ewbs=T.oldewbs
GROUP BY f.ewbs,T.description, T.AWBS;
Bascially I wrote this so users can use the combo box to select their data.
But now, I am curious to see how can i set the parameters directly through VBA. I had something like this set up.
Sub TestSeePreviousData
Dim rS As DAO.Recordset
Dim db As DAO.Database
Dim queryDef As DAO.queryDef
Dim ProjectNumber As String
Dim FiscalDate As Date
FiscalDate = #4/25/2014#
Set db = CurrentDb
Set queryDef = db.QueryDefs("1PreviousEWBS")
'Parameter 0 is to input the Project number
queryDef.Parameters(0) = "173221"
'Parameter 1 is to give the fiscal period end date
queryDef.Parameters(1) = "'" & FiscalDate & "
Set rS = queryDef.OpenRecordset
Do While Not rS.EOF
'The lines for 1PreviousEWBS
Debug.Print rS.Fields("EWBS") & vbTab & rS.Fields("AWBS") & vbTab & rS.Fields("Total Hours") & vbTab & rS.Fields("Total Cost")
rS.MoveNext
Loop
End Sub
My problem is, I want to recreate the initial "less than" condition, ie
f.[period end date] < [Input Date], and this:
queryDef.Parameters(1) < "'" & FiscalDate & "'"
does not work, it returns an error message of "Invalid Use of Properties"
my question is, how can i show inequal condition when setting parameters for SQL in vba?
I believe the comparison operator should be hard-coded in the QueryDef SQL, and the Parameter which represents the fiscal date is the only one which needs to be set at runtime. Have you tried that?
And not sure if your query 1PreviousEWBS is using the same exact SQL you listed, but you would change the Form reference (Forms!x!cboDate) to a standard parameter reference - [pFiscalDate] - for example.
Your code should look to replace [pFiscalDate] at run-time, and the < should be part of the QueryDef code.