Possible to set filter on subform from parent form before subform data loads - ms-access

I have frmParentForm with multiple controls used to build a filter for frmSubForm.
On frmParentForm_Load, I am doing (simplified example):
Me.sbfInvoice_List.Form.filter = "[created_on] >= #" & Me.RecentOrderDateCutoff & "#"
Me.sbfInvoice_List.Form.FilterOn = True
The problem is, on initial load, it seems the subform load is occurring first, so the entire table is loaded.
Is there a way (in a different event perhaps) to properly set the subform filter from the parent form so it is applied before the subform does its initial data load? (The subform can exist on its own, or as a child of many different parent forms (sometimes filtered, sometimes not), so I'd rather not put some complicated hack in the subform itself to accomplish this.)

Because the subform loads before the parent form, the parent form can not set a subform filter before the subform initially loads.
If you want to use the subform flexibly (all records when stand alone, but different subsets of records when included on different parent forms), I think you have to modify the subform to do it.
Private Sub Form_Open(Cancel As Integer)
Dim strParent As String
Dim strMsg As String
On Error GoTo ErrorHandler
strParent = Me.Parent.Name
Select Case strParent
Case "frmYourParentForm"
'set filter to only records from today '
Me.Filter = "[created_on] >= #" & Date() & "#"
Me.FilterOn = True
Case "frmSomeOtherParent"
'do something else '
End Select
ExitHere:
On Error GoTo 0
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 2452
'The expression you entered has an invalid reference to '
'the Parent property. '
Resume Next
Case Else
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure Form_Open"
MsgBox strMsg
End Select
GoTo ExitHere
End Sub
Edit: If you want to track the sequence of events in the parent form and subform, you can add procedures like this one to the forms' modules.
Private Sub Form_Load()
Debug.Print Me.Name & ": Form_Load"
End Sub
Here is what I get when tracking the Open and Load events for my parent form and subform.
fsubChild: Form_Open
fsubChild: Form_Load
frmParent: Form_Open
frmParent: Form_Load

Related

Move to another record via combobox doesn't work in some circumstances

I have two forms: ‘frmClient’, (which has a subform that lists applicants), and ‘frmDisclosure’, which shows details of applicants. On frmClient there is a command button that opens a specified record in frmDisclosure. The procedure is Private Sub Command10_Click() - see below. This works.
The problem is that once in frmDisclosure via frmClient, it is not possible to move to another record. The procedure for opening another record in frmDiscloure is in a combobox control: Private Sub ComboFind_AfterUpdate().
This normally works, but it never works if frmDiscloure has been opened via frmClient. I have tried ‘requery’ and ‘refresh’ in various situations, and have tried closing frmClient once frmDisclosure is open. None of this works. If I want to get to a different record, the only solution I have at present is to close frmDisclosure and reopen it.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Private Sub Command10_Click()
If NumForms > 0 Then
DoCmd.OpenForm "frmDisclosure"
Forms!frmDisclosure.FilterOn = False
DoCmd.OpenForm "frmDisclosure", acNormal, "", "[DiscPK]=" & Me.DiscPK, , acNormal
Else
DisplayMessage ("No form ref for this application.")
Exit Sub
End If
End Sub
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
Private Sub ComboFind_AfterUpdate()
Dim rs As Object
Set rs = Me.RecordsetClone
rs.FindFirst "[DiscPK] = " & Str(Nz(Me![ComboFind], 0))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
End Sub
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
frmDisclosure is opened to a single record, there are no other records to navigate. The RecordsetClone has only one record, so of course code won't find any others. Turn off the filter first:
Private Sub ComboFind_AfterUpdate()
Me.FilterOn = False
With Me.RecordsetClone
.FindFirst "[DiscPK] = " & Nz(Me.ComboFind, 0)
If Not .NoMatch Then Me.Bookmark = .Bookmark
End With
End Sub
As you can see, declaring and setting a recordset object variable is not required. .EOF would probably work just as well, I have just always used NoMatch. This will set focus to record, not filter the form.
If you prefer to display single record, then set the Filter property.
Private Sub ComboFind_AfterUpdate()
Me.Filter = "DiscPK=" & Nz(Me.ComboFind, 0)
End Sub

How is this returning a blank value?

So this code is meant to serve as a simple search system to go to certain records in a recordset. I originally had it so they had to click the btnGoToID button in order to perform the search. I decided to just make it a little more user friendly and make it so the search field listened for the Enter button and that would perform the search as well.
The issue that I am running into when the code gets to strID = Trim(Nz(Me.txtSearch.Value, "")) the value will randomly come back as an empty string even though visually I can see that there is a value in the textbox.
I haven't been able to narrow down any pattern for when this issue occurs. At this point I don't really even know how to troubleshoot this problem, nor the words to search for that could yield any results in Google. All I can say is that it SEEMS like changing between records will affect whether or not the search goes through.
This has always worked up until I put in the txtSearch_KeyPress sub procedure.
'============================================================================
' txtSearch_KeyPress
'============================================================================
Private Sub txtSearch_KeyPress(KeyAscii As Integer)
'If user pressed enter
If KeyAscii = 13 Then
Call btnGoToID_Click
End If
End Sub
'============================================================================
' btnGoToID_Click
'============================================================================
' <<Purpose>>
' Allow the user to search for a specific ID
'============================================================================
Private Sub btnGoToID_Click()
On Error GoTo Err_Handler
Dim rs As Recordset
Dim strID As String
Set rs = Me.RecordsetClone
strID = Trim(Nz(Me.txtSearch.Value, ""))
If (strID <> "") Then
'Go to the ID
rs.FindFirst "ID = '" & strID & "'"
If rs.NoMatch Then
MsgBox "ID does not exist"
Else
'If we have a match, set the record as the current record
Me.Bookmark = rs.Bookmark
End If
Else
MsgBox "Please enter a valid ID.", vbOKOnly, "Invalid ID"
End If
Exit_Handler:
On Error Resume Next
Me.txtSearch.Value = ""
rs.Close
Set rs = Nothing
Exit Sub
Err_Handler:
Call LogError(Err.Number, Err.Description, "txtSearch on " & Me.Name)
Resume Exit_Handler
End Sub
After the conversation in the comments I have narrowed down this question to be a whole lot simpler. This yields an "Invalid use of null" error message even after there are several characters in the text field. Why would that happen, and what can I do to make it pick up the values in the textbox?
'============================================================================
' txtUnitNoToSearch_KeyPress
'============================================================================
Private Sub txtUnitNoToSearch_KeyPress(KeyAscii As Integer)
MsgBox Me.txtUnitNoToSearch
End Sub
I think your problem is related to the fact that a text box has 2 properties, .Value and .Text, which appear similar but behave differently.
While you have an edit in progress in the text box, the changing content is available via the .Text property. However, the content of the .Value property has not yet been updated to match.
After the text box's After Update event, .Value will contain the new content. And if focus has moved away from the text box, its .Text property will no longer even be available.
Sorry, I couldn't think how to explain that better. But I think the situation will be clearer with this KeyPress event procedure:
Private Sub txtUnitNoToSearch_KeyPress(KeyAscii As Integer)
Debug.Print "Text: '" & Me.txtUnitNoToSearch.Text & "'"
Debug.Print "Value: '" & Me.txtUnitNoToSearch.Value & "'"
End Sub
Watch the output from Debug.Print in the Immediate window as you make changes to the context of the text box. (Ctrl+g will open the Immediate window.)
One final point is that just Me.txtUnitNoToSearch gets you its default property which is .Value. Keep that in mind as you work through the rest of your code.

Can two different continuous forms run off the same queryi in access 2010?

So I have two subforms, one to show internal training course completion for an employee and the other is the same thing but for vendor training.
Both subforms pull the same data from the same table, but display different selective data (different columns from the table).
I added the employee search combobox code to reflect the second "vendor training" subform:
Private Sub cboEmployee_AfterUpdate()
On Error GoTo Proc_Error
If IsNull(Me.cboEmployee) Then
Me.subEmployeeCourseTrainingCompletion.Form.Filter = ""
Me.subEmployeeCourseTrainingCompletion.Form.FilterOn = False
Me.subEmployeeVendorCourseTrainingCompletion.Form.Filter = ""
Me.subEmployeeVendorCourseTrainingCompletion.Form.FilterOn = False
Else
Me.subEmployeeCourseTrainingCompletion.Form.Filter = "[EmployeeID]=" & Me.cboEmployee
Me.subEmployeeCourseTrainingCompletion.Form.FilterOn = True
Debug.Print Me.subEmployeeCourseTrainingCompletion.Form.Filter
Me.subEmployeeVendorCourseTrainingCompletion.Form.Filter = "[EmployeeID]=" & Me.cboEmployee
Me.subEmployeeVendorCourseTrainingCompletion.Form.FilterOn = True
Debug.Print Me.subEmployeeVendorCourseTrainingCompletion.Form.Filter
End If
Proc_Exit:
Exit Sub
Proc_Error:
MsgBox "Error " & Err.Number & " in setting subEmployeeCourseTrainingCompletion filter:" & vbCrLf & Err.Description
MsgBox "Error " & Err.Number & " in setting subEmployeeVendorCourseTrainingCompletion filter:" & vbCrLf & Err.Description
Resume Proc_Exit
End Sub
The internval training subform still works and updates based on the employee ID in the combobox, but the second, vendor, subform doesn't update.
Any ideas as to why and possible solutions?
Force the update of the second form once you have made changes and saved the data in the first one:
Me.subEmployeeVendorCourseTrainingCompletion.Form.Requery
You could do this in the Form_AfterUpdate of the first subform:
Private Sub Form_AfterUpdate()
Parent.subEmployeeVendorCourseTrainingCompletion.Form.Requery
End Sub
UPDATE
Try another approach. Instead of setting filters use the Link Child Fields and Link Master Fields properties of the subforms in order to link the subforms to the main form.

Auto Populate Access Form using simple VBA code by setting a variable

I was recently given the task of creating a form that will autofill with the information from a table. The information the form autofills is selected using a primary key called ModID. I have a combo box that has a List of the ModIDs that are listed as Active.
SELECT ModID
FROM P_Review
WHERE Status = "Active"
Simple enough. I then have VBA code running on the event After Update. So after the value for the combo box is select or changed it will run this VBA code.
Option Compare Database
Option Explicit
Private Sub selectModID_AfterUpdate()
'Find the record that matches the control.
On Error GoTo ProcError
Dim rs As Object
Set rs = Me.RecordsetClone
With rs
.FindFirst "ModID=" & Me.selectModID
If Not .NoMatch Then
Me.Bookmark = .Bookmark
Else
DoCmd.RunCommand acCmdRecordsGoToNew
Me!localModID = Me.selectModID.Column(0)
End If
End With
ExitProc:
Exit Sub
ProcError:
MsgBox "Error: " & Err.Number & ". " & Err.Description
Resume ExitProc
End Sub
The code runs fine (I get no errors when I debug or run).
Now for the access text box. I would like to populate certain fields based off the variable localModID. I have a dlookup in a text box to find the information in the table P_Review.
=DLookUp("Threshold","P_Review","ModID =" & [localModID])
So the DlookUp should find the value for the column threshold, in the table P_Review, where the ModID in P_Review equals the localModID set in the VBA code. But when I go to form view and select a ModID I get the Error 3070: The Microsoft Access database engine does not recognize as a valid field name or expression. I did copy this code from another database we are already using but it fails in this new instance.
Private Sub ModID_AfterUpdate()
Dim rs As Object
Set rs = Me.RecordsetClone
With rs
.FindFirst "ModID='" & Me.ModID & "'"
If Not .NoMatch Then
Me.Bookmark = .Bookmark
Else
DoCmd.GoToRecord , , acNewRec
Me!ModID = Me.ModID
End If
End With
End Sub
This is the answer to question. I used this code to auto update.
Try
Forms!<whatever_this_form_name_is>![localModID]
in your DLOOKUP

Microsoft Access: Attempting to detect an insert triggered by a subform within the parent form

Is it at all possible to detect an insert operation performed by a subform while still in the parent form?
To clarify: I have a series of forms for data entry, they each have a button for adding an entry to the appropriate table (using the data provided in the form). I am attempting to set each of them in turn to a subform in a 'wizard' parent form that will cycle through all the data entry forms.
My problem arises when it comes to switching between forms, as it became clear that the AfterInsert event in this parent form was not detecting the insert triggered by the form contained in the subform. I know I could move the trigger for the insert to a button in the parent form; however, to my knowledge, this would require setting the code for the click event for each of the buttons in the data entry forms as public so that they may be called from the parent form's code. I am leery to do this and was thus hoping for other options.
Create a public procedure in the parent form.
Public Sub Listener(ByVal pMsg As String)
MsgBox pMsg
End Sub
Then, in each of your subforms, call that procedure from After Insert.
Private Sub Form_AfterInsert()
Dim strMsg As String
strMsg = Me.Name & " inserted row."
Call Me.Parent.Listener(strMsg)
End Sub
If the subform may also be used stand-alone (without a parent), Me.Parent will throw error #2452, "The expression you entered has an invalid reference to the Parent property." You can create a separate function to check whether the current form has a parent, and base your code on the function's return value.
Private Sub Form_Open(Cancel As Integer)
Dim strPrompt As String
If HaveParentForm(Me) = True Then
strPrompt = "I am a subform to '" & _
Me.Parent.Name & "'."
Else
strPrompt = "I am a top level form."
End If
MsgBox strPrompt
End Sub
The function ...
Public Function HaveParentForm(ByRef frm As Form) As Boolean
Dim blnReturn As Boolean
Dim strMsg As String
On Error GoTo ErrorHandler
blnReturn = (Len(frm.Parent.Name) > 0)
ExitHere:
HaveParentForm = blnReturn
On Error GoTo 0
Exit Function
ErrorHandler:
Select Case Err.Number
Case 2452 ' The expression you entered has an invalid '
' reference to the Parent property. '
Case Else
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure HaveParentForm"
MsgBox strMsg
End Select
blnReturn = False
GoTo ExitHere
End Function