TempVars - Get ID for use in next form - ms-access

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

Related

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

Error 3218: Could not update; currently locked

I've been looking through the other questions related to mine, but most are about multi-user and this one came close but not quite.
System
MS Access 2013
with Linked Tables to Office 365 Sharepoint
tblQuote - frmQuote
tblQuoteItems - sbfrmQuoteItems
No Record Locks
I'm attempting to setup a select all/deselect all button that when clicked runs db.Execute Update on the tblQuoteItems where equal to Quote ID and Quote Version.
I have a button on the main form that calls the below process.
Public Sub SelectLineItems(strTable As String, strID As String, _
intID As Integer, bln As Boolean, Optional intVersion As Integer)
Dim db As Database
Dim strSQL As String
Dim strVersion As String
Set db = CurrentDb
strSQL = "UPDATE " & strTable & " SET [Selected] = "
If intVersion > 0 Then
strVersion = " AND [QuoteVersion] = " & intVersion
Else
strVersion = ""
End If
If bln Then
strSQL = strSQL + "False WHERE " & strID & " = " & intID & strVersion & ";"
Else
strSQL = strSQL + "True WHERE " & strID & " = " & intID & strVersion & ";"
End If
db.Execute strSQL, dbFailOnError
db.Close
Set db = Nothing
Exit Sub
It's pretty simple, nothing to crazy. The problem occurs when I try to run this after a record has been modified by the form and it still has focus. Because of the dbFailOnError I get the error message, If I remove dbFailOnError it will update every record except the one that has been modified through the form.
If I modify the record then select a different record manually by clicking with the mouse, the record is no longer locked and the Update works with no errors.
I have tried to replicate the process of clicking on a new record and have put the below code
If Me.Dirty Then Me.Dirty = False
In every Event I could think of like:
The subform_Current, subform_Dirty, subform.Control.Dirty/Lost_focus/subform_Before and After Update, The exit event of the subform control on the main form...etc
Placing the code in different areas doesn't make any difference, the first time the code is called it updates the record and I can confirm this in the table, the new value is present.
I've attempted to requery the subform
I've tried
DoCmd.GoToRecord , , acFirst
Then setting focus to the first control of the record.
I've even tried changing the update from the db.Execute to using a recordset object
Dim db As Dao.Database
Dim rs As Dao.Recordset
Dim strSQL As String
Dim strVersion As String
If intVersion > 0 Then
strVersion = " AND [QuoteVersion] = " & intVersion
Else
strVersion = ""
End If
strSQL = "SELECT * FROM " & strTable & " WHERE " & strID & "= " & intID & strVersion
Set db = CurrentDb
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset)
With rs
Do Until .EOF
.Edit
!Selected = bln
.Update
.MoveNext
Loop
End With
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
But again it will cycle through every unlocked record and update, until it gets to the one modified by the form which then throws the same error.
I've tried opening the recordset then closing it then reopening it. But it doesn't seem to matter it's the form that's holding onto the locked record.
The only solution that has worked for me was to Set the subform recordsource to nothing, then run the update, then reset the recordsource to what it was.
The Selected column is within the QuoteItems table itself, and not in it's own table with reference to the QuoteItems ID
My question is how do I get the form to release the record through code that mimics the action of manually clicking on a new record without resetting the subform's recordsource.
Your approach with using Dirty=False is the right thing to do. But you have to apply it to the subform, as this is where the recordlock occurs. If your Code is in the Main form, you need to add this before your code to update the records.
Me.sbfrmQuoteItems.Form.Dirty = False
In that line sbfrmQuoteItems is supposed to be the name of the SubForm-Control in your main form!

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).

Assign control source dynamically from a different recordset

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.

Getting the value from the first row where column name is <value>

I have a form where a user inserts some values
When the user clicks the "ok" button Access makes a new table to save the values from disappearing when the form closes.
strSQL = "CREATE TABLE tblTempProjectGegevens (Project varchar(32),ProjectNummer varchar(32), Opdrachtgever varchar(32));"
DoCmd.RunSQL (strSQL)
strSQL = "INSERT INTO tblTempProjectGegevens (Project, ProjectNummer, Opdrachtgever)" & _
"VALUES ('" & ProjectInvoer.Value & "', '" & ProjectNrInvoer.Value & "', '" & OpdrachtgeverInvoer.Value & "');"
DoCmd.RunSQL (strSQL)
DoCmd.OpenForm "frmMain", acNormal, , , acFormAdd
DoCmd.Close acForm, "frmProjectInvoer", acSaveNo
I save these values in a table, because my program requires the form to be closed.
When the user is done using my access file, there are some reports to be printed. On these reports are headers in wich I want the values I have saved in the temp table.
How do I get the values from the table in my report headers? During a report_load() event?
Private Sub Report_Open(Cancel as Integer)
Dim db as Database
Dim rec as Recordset
Set db = CurrentDb
Set rec = db.OpenRecordset("tblTempProjectGegevens")
Me.Project.Value = rec("Project")
Etc...
End Sub