Assign control source dynamically from a different recordset - ms-access

I have the following VBA code in my access.
Dim subform As Object
Dim formFilter As String
formFilter = "..." 'a SQL statement
Set subform = Me!my_subform.Form
subform.RecordSource = formFilter
subform.field1.ControlSource = "f1"
subform.field2.ControlSource = "f2"
subform.field3.ControlSource = "f3"
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT TOP 1 f4 FROM my_table " _
& "WHERE tableF1= '" & [f1] & "' AND tableF2 = '" & [f2] & "' " _
& "ORDER BY tableF5 DESC")
subform.field4.ControlSource = rs(0)
I have first bound my first 3 fields in subform to the fields of my record source. Then I need to bind the 4th field to a different recordset. This recordset has to refer to the first 2 fields of my subform.
However, I got a run-time error 2465. Access is not able to refer to the field [f1] and [f2] of my OpenRecordSet statement.
How should I fix this?
I use this form in a datasheet view. So I need to refer to not a single value of field1 and field2, but the entire columns of records have to be linked.
Thanks a lot.

(from an earlier edit to the question, since rolled back:)
Apparently the solution in this case was to use the following code in the On Load event handler for the subform instead of the main form
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT TOP 1 f4 FROM my_table " _
& "WHERE tableF1= '" & [f1] & "' AND tableF2 = '" & [f2] & "' " _
& "ORDER BY tableF5 DESC")
subform.field4.ControlSource = rs(0)
because the [f1] and [f2] controls were on the subform and therefore not visible from the Class Module code for the main form.

Related

TempVars - Get ID for use in next form

In my database the user creates a new record via a form like so;
Upon pressing the save button, the record then gets inserted into ConTblConsumables, Here is the code sample behind the save button;
Private Sub btnSave_Click()
Dim strAddNewConsumable As String
Dim strCompany As String
Dim strConName As String
Dim strConID As String
Dim strCboConSupplier As String
Dim strConTargetLevel As String
Dim strConCost As String
strCompany = Me.ConCompany
strConName = Me.txtConName
strConID = Me.txtConID
strCboConSupplier = Me.CboConSupplier
strConTargetLevel = Me.txtConTargetLevel
strConCost = Me.txtConCost
strAddNewConsumable = "INSERT INTO ConTblConsumables(strConCost, ConName, ConExtraID, Supplier, ConTargetLevel, Cost)" _
& "VALUES('" & strCompany & "', '" & strConName & "', '" & strConID & "', '" & strCboConSupplier & "', '" & strConTargetLevel & "', '" & strConCost & "')"
CurrentDb.Execute (strAddNewConsumable)
MsgBox "Record Inserted", vbExclamation
End Sub
Once the record has been inserted I then wish to pop-up another form where the user can then assign a parent machine to this part. The reason I wish to do it this way is that several machines can use the same part (Many-to-Many). Which when the machine is selected will then update this table;
The consumable column is a ComboBox with a relationship to the ConTblConsumables table and thus why I require to have the ID from previous to be retained in a TempVar.
I believe that if I was to use TempVars towards the end of the code on the save button, that when the record is inserted into the table ConTblConsumables, that the TempVars records the ID of the row that the record has been inserted into, thus being about to attain the ID for use in the next form.
My question is how do I write this in code? Or even if this is possible?
Thank you
As I understand, in table ConTblConsumables you have a key column ID with Autonumber data type and you need to know ID of inserted row. If so, you'd better to use recordset instead of INSERT statement. Something like this:
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("select * from ConTblConsumables")
With rst
.AddNew
'here ID already known and you can store it in your variable
TempVars!MyID = !ID.Value
!strConCost = Me.ConCompany
!ConName = Me.txtConName
....
.Update
End With
rst.Close
Set rst = Nothing

listbox loads more data than it should

I have a listbox on a form which loads using the following code, which is called directly from the form_load event only once.
Private Sub LoadList()
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
Dim condition As String
Set db = CurrentDb
condition = " WHERE Schedule_ID = " & ScheduleID
strSQL = "SELECT Shifts.Shift_ID, Shifts.Start_Date_Time, Shifts.End_Date_Time, Locations.Location_Name FROM Shifts, Locations " & _
"WHERE Schedule_ID = " & ScheduleID & " AND Locations.Location_ID = Shifts.Location ORDER BY Start_Date_Time"
'Set Recordset Query
Set rs = db.OpenRecordset(strSQL)
RecCount = recordCount("Shifts", condition)
Me.lblCount.Caption = "Shift Count: " & RecCount
rs.MoveFirst
For i = 0 To RecCount - 1
Me.lstShifts.AddItem rs!Shift_ID & ";" & rs!Start_Date_Time & " TO " & rs!End_Date_Time & " AT " & rs!Location_Name
rs.MoveNext
Next i
'Close Connections and Reset Variables
rs.Close
Set rs = Nothing
Set db = Nothing
listdirty = False
End Sub
There are only ten records in the database and yet the listbox loads the data three times (30 in all). I stepped through the code and on the RecCount variable it gets initialized properly to ten and the for loop iterates ten times as expected. This LoadList sub doesn't get called more than once, so I don't understand why the records are showing up in the listbox multiple times. Any ideas?
Each time your LoadList() procedure is called, it adds rows to the list box. Since the list box contains 30 rows despite the source recordset containing only 10, either LoadList() is called 3 times or you're saving the form with a non-empty value list and adding 10 more rows at each Form Load.
You could avoid that problem by emptying out the RowSource value list before the loop where you do AddItem ...
rs.MoveFirst
Me.lstShifts.RowSource = vbNullString ' make sure value list starts empty
For i = 0 To RecCount - 1
Me.lstShifts.AddItem rs!Shift_ID & ";" & rs!Start_Date_Time & " TO " & rs!End_Date_Time & " AT " & rs!Location_Name
rs.MoveNext
Next i
However you have a query which is almost what you want the list box to display. It should be simpler to revise that query and use it as the list box RowSource:
Change the list box's RowSourceType property from "Value List" to "Table/Query".
Make sure you have the list box's column count property set to 2.
In your LoadList() procedure, revise the query field list to SELECT Shifts.Shift_ID, Shifts.Start_Date_Time & ' TO ' & Shifts.End_Date_Time & ' AT ' & Locations.Location_Name
Finally, assign the updated query to the list box's RowSource property: Me.lstShifts.RowSource = strSQL

Getting current selected record value in access subform

I have 2 subforms in access 2010 database; Based on selection of subform1 field value , the vba program will run the subform2 output which common text fields in subform 1 and 2 as "supplier_name".
So, I tried the "on double click" event on subform1 to write the currentRecord method see below,
Private Sub Supplier_name_DblClick(Cancel As Integer)
strSQL = "Select * from [Query1] where"
strSQL = strSQL & "[Supplier_name] ="'" & "Me!current record![Supplier_name]" &"'"
Form![Mainform]![Subform2].Form.RecordSource = strSQL
End Sub
I am getting Run-time error 3075 at the 2nd line; Syntax error (missing operator) in query expression '[Supplier_name] =Me!current record![Supplier_name]'
Please help
Thanks it worked for me but without the currentrecord property
strSQL = strSQL & "[Supplier_name] ='" & Me![Supplier_name] & "'"
You are missing a space after the where in the second row of your code:
strSQL = "Select * from [Query1] where "
and there is also a problem with your " and ' chars in the third line:
strSQL = strSQL & "[Supplier_name] ='" & Me!current record![Supplier_name] & "'"

display a table field in a list using condition

I have table x that contains id and name fields.
I want to display the id when I select the name in the list.
I wrote this but it doesn't work.
The error msg is: either BOF or EOF or current record has been deleted.
Requested operation requires a current record.
I think simply the default record is record 1, so what's wrong ?!
Dim con As Connection
Dim rs As New Recordset
Set con = CurrentProject.Connection
rs.Open "select id from tbl where namen = '" & list1.ListIndex & "'", con, adOpenDynamic, adLockOptimistic
ttt.SetFocus
ttt.Text = rs!id
thank you so much pteranodon for your help
I changed the code to be like this
Private Sub list1_Click()
Dim strSQL As String
strSQL = "select id from tbl where namen = '" & list1.Value & "'"
ttt.SetFocus
ttt = DLookup("id", "tbl", "namen='" & list1.Value & "'")
rs.Open strSQL, con, adOpenDynamic, adLockOptimistic
End Sub
but I got this msg
operation is not allowed when the object is open ?
I didn't add the items to the list1 by using vba code I just followed the window that show up after adding the list1 to the form cus I also have problem with code
if you please can you add the complete code 1 and 2
You want the value of the listbox, not ListIndex. ListIndex contains a number, the zero-based index of the current selection in the listbox. You are passing in something like select id from tbl where namen = '13' Since no records match, you get that error message.
I really reccommend using a string to hold any constructed SQL so that you can debug it easily. If you had
Dim strSQL As String
strSQL = "select id from tbl where namen = '" & list1.Value & "'"
Debug.Print strSQL
rs.Open strSQL, con, adOpenDynamic, adLockOptimistic
it would be easier to read and much easier to debug. Also, you'll want to check for rs.BOF and rs.EOF right after opening a recordset:
If Not (rs.BOF Or rs.EOF) Then
'Do stuff
Else
'No records in recordset
End
Unlike VB textboxes, you can't use .Text in VBA textboxes unless the textbox has the focus. Use ttt.Value (or just ttt instead).
And if you are only looking up a single value like this you can replace all of your code like this:
Private Sub list1_Click()
ttt = DLookup("id", "tbl", "namen='" & list1.Value & "'")
End Sub
Using DLookup instead of manually opening a recordsest yourself. I would also go back through the listbox wizard. If you put the id in the first column and the name in the second, then hide the first column (the wizard will help you do this), the list will show the name but store the id. Then you don't even need the extra textbox. The id is stored in List1.Value and the name is available as List1.Column(1).

Show saved date in label

I´m saving a date in a table like this:
Me!lastchangedate.Caption = Now
Set db = CurrentDb
Set rs = db.OpenRecordset("background", dbOpenTable)
rs.AddNew
rs![date] = Me!lastchangedate.Caption
rs.Update
rs.Close
Later I want to read this date out of the database and show it in a Label:
sqlstrdate = "SELECT date FROM background " _
& " WHERE SAP_ID = '" _
& Me!sapidtxt.Value & "'"
retvaldate = CurrentDb.OpenRecordset(sqlstrdate)
Until here it´s working but if I now try to show "retvaldate" as MsgBox or in a label I always get the error message: Error 13 type mismatch.
Im trying to use this to show the saved date in a label.
Me!lastchangedate.Caption = (retvaldate)
Is there an option to change the label type or do I have to change the "retvaldate" to a date type (which also gives me the same error).
You are trying to set 'retvaldate' like opening a recordset. The following should provide the correct result (BTW, why do you use reserved words like 'date' as a field name?)
Dim rs As Recordset
Dim sqlstrdate As String
sqlstrdate = "SELECT date FROM background " _
& " WHERE SAP_ID = '" _
& Me!sapidtxt.Value & "'"
Set rs = CurrentDb.OpenRecordset(sqlstrdate)
If Not rs.EOF Then
retvaldate = rs.Fields("Date")
Else
retvaldate = "No Records"
End If
rs.Close
Set rs = Nothing
'Then later... but I hope the variable is in scope (Global, form, subroutine)
Me!lastchangedate.Caption = retvaldate