MS Access VBA - First Record In List is Overwritten on Form Close? - vba

I just learning how to create forms in Microsoft Access 2013 and using VBA programming to control but I'm having an issue I don't quite understand.
I have created a form with a List Box where the source originates from a query that contains the following fields the Query Builder in order from left to right:
|ParentNumber|ParentName|ChildNumber|ChildName|
|------------|----------|-----------|---------|
|------------|----------|-----------|---------|
|------------|----------|-----------|---------|
Some fields from the Query are hidden with a Column Width of 0".
I also have 4 Text Box below the List Box corresponding to the appropriate ParentNumber, ParentName, ChildNumber, and ChildName values.
When I select a record in the List Box, it populates the data to the appropriate Text Box.
When the form first loads, the first row in the List Box is selected:
Private Sub Form_Load()
On Error Resume Next
DoCmd.GoToRecord , , acFirst
Me.List = Me.List.ItemData(0)
End Sub
The issue is that if I select a different row, then close the form, and reopen the form, the first row in the List Box is overwritten with the last selected row before the form is closed.
Even if I start out with any other row selected initially when the form opens, the first row is always overwritten by the last selected row when the form is closed.
The following subroutine handles the update of the Text Box data:
Private Sub List_AfterUpdate()
Dim rowIndex As Integer
rowIndex = Me.List.ListIndex
Me.textBox_ParentNumber = Me.List.Column(3, rowIndex)
Me.textBox_ParentName = Me.List.Column(4, rowIndex)
Me.textBox_ChildNumber = Me.List.Column(6, rowIndex)
Me.textBox_ChildName = Me.List.Column(7, rowIndex)
End Sub
I found a somewhat similar problem to mine, but I tried the suggested solution, which didn't seem to work: MS Access - First record in table is overwritten on form close
I'm completely baffled as to what could cause this based on the code above.
What's my issue?
Thanks.

Few things
Private Sub Form_Load()
'remove this so you can see errors.
'On Error Resume Next
' this goes to the first record of the *form*, not the list.
' you might want this, or not.
DoCmd.GoToRecord , , acFirst
' ItemData returns the data in the *bound column* of the list,
' the data from one specific column. the list is set to that
' data every time the form loads. not what you want; remove it.
'Me.List = Me.List.ItemData(0)
End Sub
This should get rid of the problem. What you want to do next is another question.

Your form should be bound to a record set (table or query).

I had same problem, After hours of verification -
In my case - the problem was that the MainForm , And SubForm (table) - was binded to the same recordset. I just Un-Binded data RS from MainForm.

Related

Edit a field in record(s) selected from a listbox with a value from a combobox

I'm working on a way to keep track of the workflow of some paper forms in my office. So far, I have a form with a listbox that will display all incomplete paperwork. In order to keep track of where the physical paperwork moved, I would like to highlight the record(s) in the list and assign them to an employee -- editing the field "QCByName" in tblForms from its current value (most often blank) to the value selected in a combobox that's pulling the options from tblStaff.
Form with listbox and combobox selection:
I'm having trouble with the VBA code for the command button, though. I have a decent working example from an older database someone else designed but haven't been successful in adapting the code to my similar situation. This post seemed helpful, but I can't get it to work.
If I try to assign one row in the list box to someone, I get a run-time error:
3075: syntax error (missing operator) in query expression 'ID=15T362'
Where 15T362 is the FormNumber row I selected. The listbox is unbound, I think, but the primary key and first (hidden) field is the ID.
Here's the current code. Any ideas what I'm doing wrong? Many thanks.
Private Sub cmdAssigntoQC_Click()
Dim strSQL As String
Dim tblForms As Recordset
If IsNull(Combo5) Then
MsgBox "No Changes Made"
Else
strSQL = "SELECT * FROM [tblForms] WHERE ID=" & List0
Set tblForms = CurrentDb.OpenRecordset(strSQL)
tblForms.Edit
tblForms![QCByName] = Me.Combo5
tblForms.Update
tblForms.Close
Set tblForms = Nothing
Forms!frmOutstanding.L0Req
End If
End Sub
To pull value from selected listbox item, have to use Column property and reference column by its index, index begins with 0: Me.List0.Column(0)
Using Me. qualifier is not required but it will trigger intellisense tips.

How to handle Access "Run-Time Error 3021 - No current record" after DoCmd.Requery?

I have been having a quite annoying issue on my access project.
It is an Access 2007 - 2016 file.
My database has two queries that I intend to use to filter data to feed combo-boxes.
On one of my forms I have done that with success. The first list is fed from a table, and the succeeding ones are fed by filtering their respective table based on the previous list selection.
Here is a screenshot of my form that worked out.
And here is part of the code that goes with it:
Private Sub frm01ListSetor_Click()
DoCmd.Requery (qry01_frm01ListArea)
Me![frm01ListArea] = Null
DoCmd.Requery (qry02_frm01ListEquip)
Me![frm01ListEquip] = Null
Me![frm01TextID] = Null
End Sub
Private Sub frm01ListArea_Click()
DoCmd.Requery (qry02_frm01ListEquip)
Me![frm01ListEquip] = Null
Me![frm01TextID] = Null
End Sub
Here are the queries that goes along with the code above:
qry01_frm01ListArea
SELECT tblAreas.ID_Area, tblAreas.NomeArea
FROM tblAreas
WHERE (((tblAreas.SetorArea)=[Forms]![frm01_AddEquip]![frm01ListSetor]));
qry02_frm01ListEquip
SELECT tblEquipamentos.ID_Equipamento, tblEquipamentos.NomeEquipamento
FROM tblEquipamentos
WHERE (((tblEquipamentos.SetorEquipamento)=[Forms]![frm01_AddEquip]![frm01ListSetor]) AND ((tblEquipamentos.AreaEquipamento)=[Forms]![frm01_AddEquip]![frm01ListArea]))
ORDER BY tblEquipamentos.ID_Equipamento;
The code above works just fine. It filters data to previous selection accordingly and it also clears the data and selection of the "righter" lists every time another value is selected on the "lefter" ones.
So that was a form I created to help me out on populating my equipment database.
Let us get to the problematic twin now:
I created another form for Maintenance Orders of these equipment.
This one must be more user friendly since other people will use it. Therefore I used Combo-boxes for value selection instead of List Boxes. I say this before hand because it is the only thing I could notice that differs the new form from the one above.
Here I have this:
Screenshot of troubled form
After the expanded Combo-box on image 2 is selected I should run the following code:
Private Sub frm02SetorOM_Click()
DoCmd.Requery (qry04_frm02CBArea)
Me![frm02AreaOM] = Null
DoCmd.Requery (qry05_frm02CBEquip)
Me![frm02EquipamentoOM] = Null
End Sub
Private Sub frm02AreaOM_Change()
DoCmd.Requery (qry05_frm02CBEquip)
Me![frm02EquipamentoOM] = Null
End Sub
It is basically the very same thing I have done on the first form but with different variables.
But I get a "Run-time error 3021: No current record" every time I select a value on my "Setor" field.
The crash happens at the "DoCmd.Requery (qry04_frm02CBArea)" line.
Here is the query for this form's Area field (qry04_frm02CBArea):
SELECT tblAreas.ID_Area, tblAreas.NomeArea
FROM tblAreas
WHERE (((tblAreas.SetorArea)=[Forms]![frm02_SubmitOM]![frm02SetorOM]));
But the thing that is confusing me the most is that when I click "End" on the Run-time error dialog box, my Area combo-box - that was empty before - even with the error gets the proper options like if it actually "requeried".
How can I fix this issue?
Thank you in advance.
Btw, this is my first Access project so please consider that on the response.

MS-Access Form shows Number, not Name on load

I got a Database, where I apply to a name a Main and Subgroup.
When I enter a MainGroup f.e. Granades, just subgroup elements like "attack-granades" etc. should be shown.
In genereal it works by writing in this into the MainGroup-Combobox at my Form.
Private Sub MunHauptgruppeRef_AfterUpdate()
Me.MunUntergruppeRef.Requery
Me.MunUntergruppeRef.RowSource = " SELECT UnterGrpNR, UnterGrpName FROM tbl_UnterGruppen WHERE UnterHauptGruppenNr = " & MunHauptgruppeRef.Value & " ORDER BY UnterGrpName ASC"
The Problem is, if I load the datas in my form again, it just shows the related Number to the "Sub-Combobox data" 1( f.e. 35 for Attack-Grenade ) , but not the Name itself. After I reselect the entry in my Main-Combobox(Grenade), it shows the right sub-data which was saved. 2
Tried Requery on Form_Load or Requery of the Combo-Boxes itself. nothing helped so far.
Made some Video3
You need to add the code from Private Sub MunHauptgruppeRef_AfterUpdate() to your Form_Current event, this will refresh your combo box row source to the current value of your MunHauptgruppeRef combobox as you cycle through your records. Also you need to call the Me.MunUntergruppeRef.Requery after you've set the Me.MunUntergruppeRef.RowSource.
You can also add a check when your in a New Record, for the code not to run on the Current Event. See here https://learn.microsoft.com/en-us/office/vba/api/access.form.newrecord

MS Access Can't go to specified record because of another control's VB where clause

I have a lookup listbox which is programmed to allow the user to find a specific record/help topic from the list and view it. Now when the list box is used the where clause locks in the record and the first, previous, next, last buttons freeze up and you cannot use them to go to a record. Is there a way to free up the functionality of the buttons to navigate through the records along with the where clause to select.
Here is the code that operates the listbox selections:
Private Sub List35_AfterUpdate()
Dim myTopic As String
myTopic = "Select * from FormsHelpTable where ([ID] = " & Me.List35 & ")"
Me.Form.RecordSource = myTopic
Me.Comment.Requery
End Sub
I believe since the where clause locks in the selection in the box it does not allow navigation from other controls to interfere. What might be a way around this?
You get the runtime error:
You can't go to specified record.
It appears not to be reading the other record in the source table named Help once it updates using the listbox.
Instead of changing the recordset (this is the 'pool' of records which the form could display), you just need to go to the record the user selects from the listbox.
Method 1 (probably the easiest way if your listbox is in the same order as the records of your form)
Use this code:
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
End Sub
You need to ensure that:
The recordset of the form is ordered the same as the listbox. So, for example, you could order both by ID, or by Title.
Note that the +1 comes from the fact that the ListIndex starts at 0, whereas the record indexes start at 1.
Method 2
Ensure each record's Title is unique (set No Duplicates on this field).
Change your listbox to return the Title of the record, rather than it's ID.
Then use this:
Private Sub lstSelect_AfterUpdate()
Me.Title.SetFocus
DoCmd.FindRecord Me.lstSelect
Me.lstSelect.SetFocus
End Sub
Things to note:
It works by searching the field with focus for the string specified. That's why we have to SetFocus on the Title textbox on our form.
We could use ID instead, (which would mean we could have duplicate titles if we wanted), but then we would have to have an ID control on the form to SetFocus to. You can't hide this control either, because it needs to have focus whilst using FindRecord.
Update: Method 1 with reverse-selection
Add an Event Procedure in the Form_Current event, with this code. Then update the code in the lstSelect_AfterUpdate procedure as shown after.
Private Sub Form_Current()
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Note that, depending on how your lstSelect is set up, it may be Column(1, Form.CurrentRecord - 1) instead. Read on for details!
Private Sub lstSelect_AfterUpdate()
DoCmd.GoToRecord acDataForm, "HelpForm", acGoTo, Me.lstSelect.ListIndex + 1
Me.lstSelect = Me.lstSelect.Column(0, Form.CurrentRecord - 1)
End Sub
Explanation of new lines:
The Form_Current event fires every time we go to a new record. We need to look at the index of the record (ie. the position of it in the recordset), which we get by using Form.CurrentRecord. We then want to make the listbox select that record. However, we can't use me.lstSelect.ListIndex as before, because that is a read-only property (we can access it to read it, but we can't set it).
Therefore, we use me.lstSelect.Column(colNum,rowNum) instead, where we specify a column number and a row number. If your listbox has two columns (eg. ID and Title), we want to choose the second column. The index starts at 0, so we would use a value of 1. If, like my lstSelect, you only have one column (Title) then we use 0. Note: it doesn't matter if a column is hidden (ie. has width 0). It still 'counts'.
The row number is Form.CurrentRecord - 1. Remember that the forms recordset index starts at 1, but the index of our listbox starts at 0; hence the - 1.
So why do we need a duplicate of this new row in the AfterUpdate event? Try and comment it out to see what happens if we don't put it in. It's has to do with the Form_Current event firing after we use the listbox.
I fixed this issue with a union clause in the SQL lookup code. The UNION ALL clause and the following union on the table used in the other part had allowed all the records to be used.

Writing values back to a form

I have a form called Main. On it I have
a text box to hold the record ID
a combobox to select from existing records or enter a name for the new record
a text box to hold the name from the combobox
a button to open a form that lets us enter additional data and create a new record
a button to open a form that lets us edit an existing record
I cascade the row source for the list in the combobox. If the entry is not in the list,
the NotInList event
Copies the name in the combobox is moved to a text box on Main
Loads the create form's and copies the name from Main to the appropriate field on the create form.
All that works fine. The problem is that when I hit Save on the create form, I cannot write values back to the Main form correctly. I want to write the name that came from the combobox back to the combobox on Main, and write the record ID to the text field on Main.
It's two lines of code. If I change their order, the output changes. Either the combobox ends up blank, or the record ID text field ends up blank.
While I was debugging this I can see the values exist, but I could not make the assignments. The last time I tried combobox.text it complained about the value not being
in the list, so I ran the query for the row source, but the record did not show up in the combobox list, but is in the table. See the two lines of code (bold) below.
Private Sub cmbSaveClose_Click()
Dim x As Integer
x = MsgBox("Are you sure you want to save changes?", 4, "Exit?")
'VbNo constant throws back #7
'VbYes constant throws back #6
Me.Txt32 = DLookup("InsuranceCarrierContractID", "ICCDupRecordCheckQ")
If x = 7 Then
Exit Sub
End If
If IsNull(Me.Txt32) Then
Me.Txt31 = Form_frmMain.Txt65
DoCmd.RunCommand acCmdSaveRecord
**Forms!frmMain.cboInsuranceCarrierContract = Me.InsuranceCarrierContractID
Forms!frmMain.Txt66 = Me.InsuranceCarrierContractID**
DoCmd.Close
Forms!frmMain!InsuranceCarrierContract.RowSource =
" SELECT InsuranceCarrierContract.ContractNumber " & _
" FROM InsuranceCarrierContract " & _
" ORDER BY InsuranceCarrierContract.ContractNumber;"
'Other stuff,works fine.
Form_frmMain.cboInsuranceCarrierContract.Locked = False
Form_frmMain.cboInsuranceCarrierContract.BackColor =
Form_frmMain.cboInsuranceCarrier.BackColor
Else
Me.Undo
DoCmd.Close
End If
End Sub
This worked for David, so adding it as an Answer:
ReQuery and ReFresh the form after you change the data.
Me.Requery
Me.Refresh
from within the form module, or externally:
Forms("MyFormName").Requery
Forms("MyFormName").Refresh
http://msdn.microsoft.com/en-us/library/office/ff191903.aspx
http://msdn.microsoft.com/en-us/library/office/ff836021.aspx