How can I refer to Saved Queries in Access VBA? - ms-access

I'm trying to check records in a saved query to determine whether VBA should disable certain form controls:
Dim SavedQry
SavedQry = Queries!qryCurrentItems 'or Queries("qryCurrentItems")
Won't compile because it wants me to define the variable "Queries."
You can do this sort of thing with Forms!FormName!ControlName to refer to the data in a control, so why not like this?
For clarity; the query in question has "parameters" filled by a form. The code is below.
SELECT tblColour.Colour AS Colour
FROM tblColour
INNER JOIN (tblGenCol
INNER JOIN tblAutCol ON tblAutCol.Colour = tblGenCol.Colour)
ON tblGenCol.Colour = tblColour.ID
WHERE tblGenCol.Genre = Forms!frmColourChoice!cmbGenre
AND tblAutCol.Author = Forms!frmColourChoice!cmbAuthor;
The parameters are Forms!frmColourChoice!cmbGenre and Forms!frmColourChoice!cmbAuthor.

Use an object or two:
Dim SavedQry As DAO.QueryDef
Dim rs As DAO.Recordset
Set SavedQry = CurrentDb.QueryDefs("qryCurrentItems")
SavedQry.Parameter("ParameterName1").Value = SomeValue
SavedQry.Parameter("ParameterName2").Value = AnotherValue
Set rs = SavedQry.OpenRecordset()
' Investigate records.

Related

VBA Access Object Type Returned For Combobox Field

How can I iterate a record set that returns a field of type field2?
Is there a way to tell how many objects are in the field2 type?
Let me describe the relevant aspects of my table:
The table fields has field NMR which contains a list of possible options a user can select in another table. In the Experiments table, the field NMR is a combobox with populates the options from the other table.
The way I do this is in the Experiments table design, I have set the field this way:
Now in one of my forms, I need to read the value in Experiments!NMR which can be a multiple selections allowed combobox. The recordset rs!NMR is of type Field2.
To get the values, you iterate using an integer (i.e. rs!NMR(0) would return the first selected option). The problem is I don't know how to get the field count and calling !NMR(i) where i is greater than the number of elements will invoke a Run time error '3265', Object doesn't exist in this collection.
Their exist a size method only returns the field width size (4?) and the documentation states this is the size of the data type within the field2 object.
There doesn't seem to be a count method associated with field2 as using !NMR.Count invokes runtime error 438, Object doesn't support this method.
Code:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
With rs
Do While Not .EOF
Dim i As Integer
For i = 0 to !NMR.Count ' or SOMETHING - this is the problem
' this is irrelevant, I need to know how to iterate the list
Next i
.MoveNext
Loop
End With
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
I've also tried logic control such as
Do While(!NMR(i) <> vbNullString) since the individual components are strings, but no luck. This issues the same 3265: Item isn't found error. Same for a loop with this check Do While Not IsNull(!NMR(i))
Is there a way to tell how many objects are in the Field !NMR?
You need to assign the complex Field2 to a Recordset2 object and loop through it.
Sub Whatever()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim rsComplex As DAO.Recordset2
Dim qry As String
qry = "SELECT * FROM Experiments"
Set db = CurrentDb
Set rs = db.OpenRecordset(qry, dbOpenSnapshot)
Do While Not rs.EOF
Set rsComplex = rs("NMR").Value
rsComplex.MoveLast
rsComplex.MoveFirst
Dim i As Integer
For i = 0 To rsComplex.RecordCount - 1 ' Asker modified
Debug.Print rsComplex(0)
rsComplex.MoveNext
Next i
rsComplex.Close
Set rsComplex = Nothing
rs.MoveNext
Loop
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
End Sub

Using an Input Box to assign value to a parameter

I have the following code
command_Click()
rDate = InputBox("MM/YYYY")
end sub
When I click the command the input box appears and I input my value. But then I get another pop up asking for the parameter value for rDate.
Any thoughts?
I assume you have a query that's like
Select *
From SomeTable
Where acolumn = rDate
The rDate defined in your command_click() sub is not the same thing. That rDate is a local variable which has nothing to do with your query.
You likely want to pass your parameter to a query. Let's say your query is called vikesQuery. Your command button click code would look like this
Dim qdef As DAO.QueryDef
Set qdef = CurrentDb.QueryDefs("vikesQuery")
If qdef Is Nothing Then
Exit Sub
End If
qdef.Parameters("rDate") = InputBox("MM/YYYY") 'though there are much better ways of getting your parameter like a textbox on a form
Dim rs As DAO.Recordset
Set rs = qdef.OpenRecordset
Now your query is in a recordset where you can do lots with it. Typically you would show this on a form.
Dim frm As Form
DoCmd.OpenForm "vikesForm", acNormal
Set frm = Forms("vikesForm")
Set frm.Recordset = rs 'sets the recordset of the form to the recordset you generated from your query.
This last step assumes you have a form set up to accept the structure of this recordset. i.e. textboxes bound to the right columns.

insert data to a record already saved to a table

I have a recordset that is missing one field for each record and would like to add some data from a form by looking up certain criteria. I used a select query to get data onto the form in the first place and tried to reverse the assigning of values but it doesnt work as it says Run-time error 3027 'the Database or Object is Read only.' I think this is because I ran a select query to get the information but how do I input the data to the same records. the code I used is below -
Private Sub CmdAppend_Click()
Dim dbsNorthwind As dao.Database
Dim rstAmend As dao.Recordset
Dim qdfAmend As dao.QueryDef
Dim n As Integer
Set dbsNorthwind = CurrentDb
Set qdfAmend = dbsNorthwind.QueryDefs("Get_Questions_NTL")
qdfAmend.Parameters(0) = [Forms]![TeamLeader]![ComClientNotFin]
qdfAmend.Parameters(1) = [Forms]![TeamLeader]![ComDateSelect]
Set rstAmend = qdfAmend.OpenRecordset(dbOpenDynaset)
n = 0
rstAmend.MoveFirst
Do Until rstAmend.EOF
n = n + 1
rstAmend.Fields("ManagerID") = Form.Controls("SC" & n).Value
rstAmend.MoveNext
Loop
End Sub
You'd have to use the .Edit and .Update methods of the recordset object to update records. You received the error because you are trying to assign a value to a read only property.

Access VBA recordets - updating a field based on the result of a function that uses other fields as input

I have a simple_table with 4 fields:
a,b,x,P
I am trying to update the field p based on the output of a function that uses the other fields as input parameters. In this case the function is an excel function.
I was using SQL server but really need to access some statistical functions. So yesterday I opened access for the first time. Eeek. I've spent the last day trying to learn vba and following various tutorials on recordsets.
The bit I'm struggling with is how to I update a the P field based on the other fields? In a loop?
Thanks very much.
Dim objExcel As Excel.Application
Set objExcel = CreateObject("Excel.Application")
'Test it works
MsgBox objExcel.Application.BetaDist(0.4, 2, 5)
'OK, that works :)
'set up the ADO stuff
Dim cnn1 As ADODB.Connection
Dim MyRecordSet As New ADODB.Recordset
Set cnn1 = CurrentProject.Connection
MyRecordSet.ActiveConnection = cnn1
'Load data into MyRecordSet
MySQLcmd = "SELECT * FROM simple_table"
MyRecordSet.Open MySQLcmd
'HELP WITH THE NEXT BIT PLEASE!
'Some kind of loop to go through the recordset to set the field P
' equal to the result of the excel function betadist(x,a,b)
'I imagine looping through something like the following semi pseudo code ???
myRecordSet.Fields(“P”).Value = objExcel.Application.BetaDist(myRecordSet.Fields(“x”).Value, myRecordSet.Fields(“a”).Value, myRecordSet.Fields(“b”).Value)
'end of the loop
objExcel.Quit
Set objExcel = Nothing
MyRecordSet.Close
cnn1.Close
Set MyRecordSet = Nothing
Set cnn1 = Nothing
Since your code works with "Dim objExcel As Excel.Application", that means you have a reference set for the Excel object library. In that case, you don't need a full Excel application instance in order to use the BetaDist function. You can set an object variable to Excel.WorksheetFunction and call the function as a method of that object. However, I don't know whether that makes a significant difference. I didn't test the CreateObject("Excel.Application") alternative.
In this sample, I used a DAO recordset instead of ADO. The reason is I've found DAO can be significantly faster with native Access (Jet/ACE) data sources. You can switch to ADO if you prefer, but I don't see an advantage.
Notice I opened the table directly rather than via a query. The DAO dbOpenTable option can also benefit performance.
With those details out of the way, it's just a simple matter of looping through the recordset, calling the function with values from the current row, and storing the function's result in the P field ... pretty much what you outlined in your pseudo-code. :-)
Dim objWFunction As Object ' Excel.WorksheetFunction
Dim MyRecordSet As DAO.Recordset
Dim db As DAO.database
Set objWFunction = Excel.WorksheetFunction ' Excel reference required
Set db = CurrentDb
Set MyRecordSet = db.OpenRecordset("simple_table", dbOpenTable)
With MyRecordSet
Do While Not .EOF
'Debug.Print objWFunction.BetaDist(!x, !a, !b)
.Edit
!p = objWFunction.BetaDist(!x, !a, !b)
.Update
.MoveNext
Loop
.Close
End With
Set MyRecordSet = Nothing
Set db = Nothing
Set objWFunction = Nothing

Add query to child form

I have been looking for some time now, but I can't see the problem here:
Option Compare Database
Option Explicit
Private Sub cmd_Refresh_Click()
Dim sSQL_Select As String
Dim Qdb As Database
Dim Qry As QueryDef
sSQL_Select = "SELECT * FROM T_TIME_SCHEDULE"
Set Qdb = CurrentDb
Set Qry = Qdb.CreateQueryDef("QTS", sSQL_Select)
DoCmd.OpenQuery "QTS", acViewNormal
Me.F_Child_Result.Form.RecordSource = "QTS"
Me.F_Child_Result.Requery
Qdb.QueryDefs.Delete ("QTS")
Set Qdb = Nothing
End Sub
This line:
Me.F_Child_Result.Form.RecordSource = "QTS"
results in the following error:
Run-Time error '2467': The expression you entered refers to an object that is closed or doesn't exist.
The syntax should be correctly constructed, and I double checked the name of the subform.
Desipte, the error remains.
Do not set the record source to a query, just the SQL string.
sSQL_Select = "SELECT * FROM T_TIME_SCHEDULE"
''Set Qdb = CurrentDb
''Set Qry = Qdb.CreateQueryDef("QTS", sSQL_Select)
''DoCmd.OpenQuery "QTS", acViewNormal
Me.F_Child_Result.Form.RecordSource = sSQL
''Me.F_Child_Result.Requery
There is no need to requery, the form will be requeried when the record source is changed.
Note that even if you could set the record source to a query (which you can't), it would not be quoted.
FROM Chat
It appears that there are two mixed strands in the question. What is required is a means to set the Source Object of the subform control to a query, not the Record Source of a form contained by the subform control.
The source object can be set like so:
Me.F_Child_Result.SourceObject="Query." & sQueryName
If the Source Object is already set to the name of a saved query that is used only for this form, there is no need to reset it, you can just modify the sql of the query:
Set qdf = CurrentDB.QueryDefs("JunkQuery")
qdf.SQL = sSQL