In Access, I have a main form with a listbox. The listbox is used to navigate to different records on the main form. The main form also has a button with the following code to open a dialog form on which I add a new record.
Private Sub New_Btn_Click()
DoCmd.OpenForm "New Issue", , , , acFormAdd, acDialog
Requery
Me.ID_Box.SetFocus
End Sub
After I close the dialog form, I want the listbox to update and to select the new record that added on the "New Issue" form AND I want the main form to navigate to the new record.
I cannot figure out how to make either of these actions occur. Please help me find the best method for these steps.
Assuming the listbox has a rowsource, you can requery the ListBox to show the new record like this:
ListBox1.Requery
Then to move the 'main' form to the latest record (assuming the ID/PK is an autonumber field, which is how the form recordsource is sorted):
DoCmd.GoToRecord , "MainFormNameHere",acLast
If you don't have an ordered recordset, you can use
Me.Recordset.FindFirst "PrimaryKeyField = " & NewRecordPK
Where NewRecordPK is a variable with the new records primary key stored.
You could call this from the dialog if you like. Just make sure you save the record first using something like Docmd.Save Then,
Forms!frmMainForm.Form.Recordset.FindFirst "PrimaryKeyField = " & Me.PrimaryKeyField
Related
I'm beginning to develop a UI for various departments in my office to support the viewing and editing of customer records.
I have a navigation form with each tab being a separate table within the database. One is customer specific info like SSN, first/last name, etc. The next would be address, the following is contact info, orders, etc.
The first form is where they select the customer. All following forms will depend upon who they select here. I need to be able to retain the Record ID from the first form as they navigate elsewhere. Currently, the form resets each time it loses focus.
Is there a way to enable this? The following forms will be filtered according to what they select in the first couple.
Store the Record ID in the Form's Tag property.
Then:
If loading a new form, you can pass it to the form's .OpenArgs property.
If loading a subform, you can get it through the .Parent.Tag property.
User selects a record:
Me.Tag = Me![Record ID]
Opening a new form:
'Open form
DoCmd.OpenForm "frmName", acNormal, , , acFormPropertySettings, acWindowNormal, Me.Tag
'Filter Form
Private Sub Form_Load()
With Me
If Not IsNull(.OpenArgs) Then
.Filter = "[Record ID]=" & .OpenArgs
.FilterOn = True
End If
End With
End Sub
Loading a subform:
'Filter Form
Private Sub Form_Load()
With Me
If Not IsNull(.Parent.Tag) Then
.Filter = "[Record ID]=" & .Parent.Tag
.FilterOn = True
End If
End With
End Sub
Lastly, if navigating between forms, store it in each form's Tag property.
Although not implemented with the navigation form, an article and a full demo on syncing subforms is here:
Synchronizing Multiple Subforms in Access
I have a form in access ("F_Filter") where I indicate parameters to filter a datable. Form F_Filter also contains a subform which shows the filtered datatable results on the same screen. This subform with the filtered results is named "Child400." Its Source Object is "F_FilterResults".
I would like to be able to 1) open the subform in a new window so all I see are the filtered results and 2) export the results to Excel.
Normally I would be able to open a form in a new window by creating a button and creating an on click event with the following code
DoCmd.OpenForm "NameOfForm", acFormDS
However, this code does not work when I put in "Child400" as the NameOfForm. I think this is because Child400 is a subform and is not recognized by Access.
I also tried DoCmd.OpenForm "[F_Filter]![Child400]", acFormDS to no avail. Note that I have also tried DoCmd.OpenForm "F_FilterResults", acFormDS which works fine but this table only contains the prefiltered results.
DoCmd.OpenForm "F_FilterResults"
is the correct form to open. "Child400" is (I assume) the name of the subform control. That is not a form that you can open.
Then you need to apply the same filter as you did to the subform instance. The same method you use now for the subform can be used for the separate form.
If you have trouble with that, please add the existing filter code to your question.
Edit
There is no magic behind what records a form shows. It is controlled by a couple of properties. The easiest way is probably to simply take them over to the new form.
Something like:
Sub OpenResults()
Dim fSub As Form, fNew As Form
Set fSub = Me!Child400.Form
DoCmd.OpenForm "F_FilterResults", acFormDS
Set fNew = Forms!F_FilterResults
fNew.RecordSource = fSub.RecordSource ' if you change the RecordSource in your code
fNew.Filter = fSub.Filter
fNew.FilterOn = fSub.FilterOn
fNew.OrderBy = fSub.OrderBy
fNew.OrderByOn = fSub.OrderByOn
End Sub
I have a main form with a subform. The subform is continuous and shows all of the records. The main form works great for adding and editing records. I need to be able to double click on a record in the subform and that record be displayed on the main form for editing.
By experience I reccomend you to achieve what you are trying by placing two subforms into the master one. In one you have the list and in the other the details.
In the master form you place a hidden link field that is populated when you doubleclik on the list.
This field, let´s call it [link] is the Link Master Field in the detail subform, and the Link Child Field is the id (primary key) to identify your selection.
This will link your double click (or simple) with showing the details.
I found a solution that works to move to display the record from the subform in the master for editing.
In the DblClick event on the subform I put in the following code:
Let Forms!FrmNotes.CboNotesID = TxtNotesID 'TxtNotesID is the ID on the subform
Call Me.Parent.DisplayRecord
On the main for I created
Public Sub DisplayRecord()
CboNotesID.SetFocus
DoCmd.SearchForRecord , "", acFirst, "[NotesID] = " & "'" & Screen.ActiveControl & "'"
End Sub
I have a form with two subforms (1 and 2). Subform 1 stores the data continously for account breakdowns. Using a pop-up subform (subform 2), the user enters data to change or update the account breakdown stored on subform 1. On submit, the information is stored in the sub-table linked to subform 1, but the data does not refresh and add the new information in a new record in subform 1 unless I manually click the refresh all button in the home tab.
So far, I have tried the following code on form_afterupdate of subform 2, which does requery subform 1 automatically but creates a run-time error (2450) when the main form is closed:
Private Sub Form_AfterUpdate()
On Error GoTo Err_Form_AfterUpdate
Forms!frmSpendPlan!frmSpendPlanSub.Form.Requery
Exit_Form_AfterUpdate:
Exit Sub
Err_Form_AfterUpdate:
MsgBox Err.Description
Resume Exit_Form_AfterUpdate
End Sub
If anyone has a way to automatically requery subform 1 data once subform 2 is submitted without creating an error please let me know, I appreciate any help you can provide.
Thanks!
I have the same problem as you sometimes! The form doesn't refresh properly.
Method 1
try this line of code instead of the current requery code. It shouldn't give you an error but may still not work due to bugs...
Form_frmSpendPlanSub.Requery
I use this format to reference across forms and it works well usually.
Method 2
1) What you can try is in design view click on the form that is doing the "After_Update"
2) Right-Click on the form and click "BUILD EVENT.." and select "Expression Builder"
In expression builder you can see exactly how the form you are in links to the form you want to get to and what you want to do...
So you would navigate yourself by going to FORMS--> Loaded Forms--> frmSpendPlanSub and then from the list you can double click on " "
This will get you referenced to the form you want to affect.
Then all you have to do is copy the code that it gives you in the box above into your VBA code and then reference what you want to do...
E.g.
Forms![frmMainForm]![frmSecondForm].Form![frmThirdForm].Form.Requery
Anyway hope that helps...
I have a set of ComboBox's in an MS Access 2003 DB that are all bound to fields in a single table. However, the data that they allow you to select doesn't come from that table and instead comes from various other tables. This works fine for the record creation story but now I want to be able to edit the record retroactively. The problem is that I can't figure out how to refill the form elements without writing a bunch of custom code.
My initial inclination is to provide a combo box that limits your choices to record IDs and then do a custom query and use that to set the selected values in all of different form elements. However, I feel like I should be able to do something as simple as DoCmd.GoToRecord , , , ID and the form should repopulate just fine. I'm not opposed to doing the busy work but I'm sure I'm just missing something in my relatively puny knowledge of VBA and Access.
Just to add to the mix, I would offer two approaches, one recommended, the other not.
Approach 1: If you've bound your form to the whole data table (this is the non-recommended approach), you can use the combo box wizard to navigate to the requested record, but I wouldn't recommend it in recent versions of Access:
a. it doesn't allow you to properly name the combo box before it creates code.
b. the code is just WRONG.
Here's the code I just produced in my test database:
Dim rs As Object
Set rs = Me.Recordset.Clone
rs.FindFirst "[InventoryID] = " & Str(Nz(Me![Combo2], 0))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
This is wrong in so many ways it's just remarkable. This is what the code should be:
With Me.RecordsetClone
.FindFirst "[ID]=" & Me!cmbMyComboBox
If Not .NoMatch Then
If Me.Dirty Then Me.Dirty = False
Me.Bookmark = .Bookmark
Else
MsgBox "Not Found!"
End If
End With
There is no need to clone the form's recordset when the RecordsetClone already exists.
There is no reason to use an object variable when you can just directly use the pre-existing object.
There needs to be a check for a dirty record before departing the record because if you don't force the save, errors in the save process can lead to lost data.
But the better approach is this:
Approach 2: Use the combo box to change the form's underlying recordsource.
The AfterUpdate event of your combo box would look something like this:
If Not IsNull(Me!cmbMyComboBox) Then
Me.Recordsource = Me.Recordsource & " WHERE [ID]=" & Me!cmbMyComboBox
End If
Now, this only works the first time, as on the second resetting of the Recordsource, you end up with two WHERE clauses, which is not good. There are two approaches:
a. assuming that the form opens without a WHERE clause, store the opening recordsource value in a module-level variable in the form's OnLoad event:
Private Sub Form_Load()
strRecordsource = Left(Me.Recordsource,Len(Me.Recordsource)-1)
End Sub
And at the module level, define strRecordsource accordingly:
Dim strRecordsource As String
Then in the combo box's AfterUpdate event, you have this instead:
Me.Recordsource = strRecordsource & " WHERE [ID]=" & Me!cmbMyComboBox
Now, if your form opens with a WHERE clause already defined, it gets more complicated, but I'll not go into that and leave it as an exercise to the reader what the best approach might be.
I presume that you've already set up the row sources for each combo box. So long as you haven't limited the combo box to that list; it should display what you have stored in that column.
However, if your Combo Box changes its list for each row you can do something like this in the record's OnCurrent event or the field's GotFocus event:
Me.combo_box_name.Requery
After re-reading your question, I think I see what you are trying to achieve. You're on the right track with GotoRecord, although I would probably use OpenForm in this case, because it has a WhereCondition property that allows you to use SQL to specify exactly what record to open. It sounds like you want to implement a "jump to record" type functionality in your form, where the user selects a record ID from a list and the form changes to display the selected record.
One possibility is to switch to the new record each time the user selects an item in the ComboBox. You can handle this in the ComboBox's Click event.
I'll use a simple example: suppose you have a Students table, and a StudentForm for viewing/editing records in the Students table. The StudentForm has a ComboBox cboStudentID that is bound to the Students.ID column via it's RowSource property. When you select a student ID in the ComboBox, the StudentsForm will switch to display the corresponding student record.
In the Click event handler for the ComboBox, you can code this "jump to record" functionality with something like the following:
Private Sub cboStudentID_Click()
Dim recordID As Long
'The ItemData property will return the value of the bound'
'column at the specified index.'
recordID = cboStudentID.ItemData(cboStudentID.ListIndex)
'Jump to the record. This assumes we want to use the same form.'
'You can change the form name if you want to open a different form when'
'the user selects an ID from the ComboBox.'
DoCmd.OpenForm "StudentForm", WhereCondition:="Student.ID=" & recordID
End Sub
As David W. Fenton points out in the comments, you can shorten the following line:
recordID = cboStudentID.ItemData(cboStudentID.ListIndex)
to this:
recordID = Me!cboStudentID
or just:
recordID = cboStudentID
since the default value of the ComboBox in this case will be the value of the bound column at the current ListIndex. In this case, you could just remove recordID altogether and code the Click event as follows:
Private Sub cboStudentID_Click()
DoCmd.OpenForm "StudentForm", WhereCondition:="Student.ID=" & cboStudentID
End Sub