Filter form records by date range using two unbound text boxes - vba

Good afternoon.
I have a continuous form which I want to allow the user to filter by using unbound boxes in the form header. See screenshot of form below:
Form Design View
I can filter error type (Unbound: cboErrorType) and responsibility (Unbound: cboResponsibility) without any issues, but I cannot get the date range to work (Records outside of the selected date range are being returned). Please see screenshot:
Form - filtered
Please see my code below:
Private Sub cmdFilter_Click()
Dim strWhere As String
Dim lngLen As Long
Const conJetDate = "\#dd\/mm\/yyyy\#"
If Not IsNull(Me.cboErrorType) Then
strWhere = strWhere & "([ErrorType] = """ & Me.cboErrorType & """) AND "
End If
If Not IsNull(Me.cboResponsibility) Then
strWhere = strWhere & "([Decision] = """ & Me.cboResponsibility & """) AND "
End If
If Not IsNull(Me.txtStartDate) Then
strWhere = strWhere & "([Date of Error] >= " & Format(Me.txtStartDate, conJetDate) & ") AND "
End If
If Not IsNull(Me.txtEndDate) Then
strWhere = strWhere & "([Date of Error] < " & Format(Me.txtEndDate + 1, conJetDate) & ") AND "
End If
lngLen = Len(strWhere) - 5
If lngLen <= 0 Then
MsgBox "No criteria", vbInformation, "Nothing to do."
Else
strWhere = Left$(strWhere, lngLen)
'Debug.Print strWhere
Me.Filter = strWhere
Me.FilterOn = True
End If
End Sub
I am removing the filters with the following code:
Private Sub cmdResetFilter_Click()
Dim ctl As Control
For Each ctl In Me.Section(acHeader).Controls
Select Case ctl.ControlType
Case acTextBox, acComboBox
ctl.value = Null
End Select
Next
Me.FilterOn = False
End Sub
Please can someone suggest a solution?
If further information is required, let me know and I will oblige.
Many thanks.

The date format must be either the "reverse" US format (mm/dd/yyyy) or the ISO format (which also works for ADO). So try:
Const conJetDate = "\#yyyy\/mm\/dd\#"

Related

VBA Search Using Text Box in Access

I'm very new to both Access and VBA. I've created a search button that looks for different items depending on what is selected on the different combo boxes. However, I would like to add another search criteria where if I type text into a texbox called "txtNotes" I can look for records that look like a match on a table field called "Notes" inside the "tbl_ContructionOrders" table. The matches have to be somewhat loose as everyone types notes differently and would like to use this box to find work orders where we had similar issues and maybe have an easier way finding a solution for said problems.
This is what I have so far and it is not working
Private Sub btnLookup_Click()
Dim strWhere As String
Me.Filter = True
strWhere = ""
If IsNull(Me.txtNotes) Then
If Not IsNull(Me.txtNotes) Then
If strWhere <> "" Then
strWhere = strWhere & " like [Notes] = """ & Me.txtNotes & """"
Else
strWhere = strWhere & "[Notes] = """ & Me.txtNotes & """"
End If
End If
If Len(strWhere) <= 0 Then
MsgBox "No Criteria", vbInformation, "No Input."
Else
Me.Filter = strWhere
Me.FilterOn = True
Me.Requery
End If
If Me.FilterOn Then
If Me.Recordset.RecordCount = 0 Then
MsgBox "Nothing Found."
End If
End If
End Sub
Try this:
Private Sub Command0_Click()
'empty notes
If IsNull(txtNotes.Value) Then
MsgBox "No Criteria", vbInformation, "No Input."
Exit Sub
End If
'search
Filter = "[Notes] Like '*" & txtNotes.Value & "*'"
FilterOn = True
'count records
If RecordsetClone.RecordCount = 0 Then
MsgBox "Nothing Found."
FilterOn = False
End If
End Sub
If you want to search (filter) as you type, use this:
Private Sub txtNotes_Change()
'search after x number of chars
If Len(txtNotes.Text) <= 3 Then
FilterOn = False
Filter = vbNullString
Else
Filter = "[Notes] Like '*" & txtNotes.Text & "*'"
FilterOn = True
End If
End Sub
It sounds like you want an auto-complete object. Jut the words that are to be auto-filled in a table. Use a combo box control on the form to select the word. Here is an instructional video that shows you how to set this up.
https://www.youtube.com/watch?v=ptRb8ffv4f0
If you need something else, post back.

Quick Filters in a Split Form Datasheet

Creating an access database for work. Users will use a split form with only the datasheet visible to review and manipulate numeric data. On the form I have built in quick filters that consist of of textboxes in which the values are either raised or lowered with arrow buttons that have on-click events. I currently have the text boxes linked to the recordsource query criteria.
With all of this stated, the problem that I am having is that I need the filter to act in the following manner:
If the value in the text box equals 0 I want to see all records. If the value is greater than 0, I want all records greater than or equal to the text box value to show. Finally, if the value in the text box is less than 0, I want to see all values less than or equal to 0.
I have considered trying to use multiple sql statements but I typically have about 3 of these quick filters on each form, and my project will eventually have about 20 forms. That is a lot of sql statements to potentially mess up.
What ideas do you guys have to solve this problem? I really need help.
If you only have 1 textbox on each form, then you may want to consider using the form's Filter property:
Private Sub txtFilter_AfterUpdate()
On Error GoTo E_Handle
If Not IsNull(Me!txtFilter) Then
If IsNumeric(Me!txtFilter) Then
Select Case Me!txtFilter
Case Is < 0
Me.Filter = "Price<=0"
Me.FilterOn = True
Case 0
Me.FilterOn = False
Case Is > 0
Me.Filter = "Price>=" & Me!txtFilter
Me.FilterOn = True
End Select
End If
End If
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "Form2!txtFilter_AfterUpdate", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
If need to have multiple filters, then consider moving the filter creation to a procedure by itself that handles all cases, and just call this procedure from each text box. You may have to think about the logic here of what happens if one text box is 0 (No filter), but another text box is 5 (display all values >= 5) and another text box is -3 (display all values <= 0):
Private Sub txtFilter2_AfterUpdate()
On Error GoTo E_Handle
Call sFilterForm2
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "Form2!txtFilter2_AfterUpdate", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Private Sub sFilterForm2()
On Error GoTo E_Handle
Dim strSQL As String
If Not IsNull(Me!txtFilter) Then
If IsNumeric(Me!txtFilter) Then
Select Case Me!txtFilter
Case Is < 0
strSQL = " AND Price<=0 "
Case 0
Case Is > 0
strSQL = strSQL & " AND Price>=" & Me!txtFilter
End Select
End If
End If
If Not IsNull(Me!txtFilter2) Then
If IsNumeric(Me!txtFilter2) Then
Select Case Me!txtFilter2
Case Is < 0
strSQL = " AND Price<=0 "
Case 0
Case Is > 0
strSQL = strSQL & " AND Price>=" & Me!txtFilter2
End Select
End If
End If
If Len(strSQL) > 0 Then
strSQL = Mid(strSQL, 5)
Me.Filter = strSQL
Me.FilterOn = True
Else
Me.FilterOn = False
End If
sExit:
On Error Resume Next
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "Form2!sFilterForm2", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Regards
Given a text box control CriteriaField1 and a corresponding field to filter Field1 in the record source I would use this:
Private Sub CriteriaField1_AfterUpdate()
Const FIELD_NAME As String = "Field1"
Dim value As Long
value = Nz(Me("Criteria" & FIELD_NAME).Value, 0)
Dim condition As String
condition = FIELD_NAME & IIf(value < 0, " <= 0", " >= " & value)
Me.FilterOn = value <> 0
End Sub
If you need to combine multiple fields to a filter condition, you would have to use and set form-global variables instead of local ones.
You could call a helper function which holds a set of arrays and builds and sets the filter dynamically:
Private Sub Filter0_AfterUpdate()
SetFilter
End Sub
Private Sub Filter1_AfterUpdate()
SetFilter
End Sub
Private Sub Filter2_AfterUpdate()
SetFilter
End Sub
Private Sub SetFilter()
Dim FieldNames() As Variant
Dim TextboxNames() As Variant
Dim Criteria() As String
Dim Index As Integer
Dim Value As Long
' Specify the field names to filter on.
FieldNames = Array("Quantity", "Stock", "Size")
' Specify the names of the textboxes to enter filter values.
TextboxNames() = Array("Filter0", "Filter1", "Filter2")
ReDim Criteria(LBound(TextboxNames) To UBound(TextboxNames))
For Index = LBound(Criteria) To UBound(Criteria)
Value = Val(Nz(Me(TextboxNames(Index)).Value))
If Value < 0 Then
Criteria(Index) = FieldNames(Index) & " <= 0"
ElseIf Value > 0 Then
Criteria(Index) = FieldNames(Index) & " >= " & CStr(Value)
Else
Criteria(Index) = "True"
End If
Next
' Assemble and apply the filter.
Me.Filter = Join(Criteria, " And ")
Me.FilterOn = True
Debug.Print Me.Filter
End Sub

Opening a Report based on two date values on a form if they exist

I have a form (frmReports) that has two unbound textboxes which are used to enter dates. One is FROM, one is TO.
These are used to filter out a report (rptAllCommissions). If there are values in the textboxes, it filters. If there aren't, or if there's one date and not both, it creates a WHERE statement for opening the report. Here is the code:
Private Sub cmdCommissions_Click()
Dim strDateFrom As String
Dim strDateTo As String
Dim strWhere As String
Const strcJetDate = "\#mm\/dd\/yyyy\#"
strDateFrom = "[ClosingDate]"
If IsDate(Me.txtFrom) Then
strWhere = "(" & strDateFrom & " >=" & Format(Me.txtFrom, strcJetDate) & ")"
End If
If IsDate(Me.txtTo) Then
If strWhere <> vbNullString Then
strWhere = strWhere & " AND "
End If
strWhere = strWhere & "(" & strDateFrom & " <= " & Format(Me.txtTo + 1, strcJetDate) & ")"
End If
If CurrentProject.AllReports("rptAllCommissions").IsLoaded Then
DoCmd.Close acReport, "rptAllCommissions"
End If
Debug.Print strWhere
DoCmd.OpenReport "rptAllCommissions", acViewReport, strWhere
Exit_Handler:
Exit Sub
Err_Handler:
If Err.Number <> 2501 Then
MsgBox "Error" & Err.Number & ": " & Err.Description, vbExclamation, "Cannot Open Report!"
End If
Resume Exit_Handler
End Sub
The problem I'm having is no matter what I try, the report never filters the records based on the WHERE statement created by the above routine. Trying debugging, it outputs:
If two dates are entered: ([ClosingDate] >=#04/01/2019#) AND ([ClosingDate] <= #05/25/2019#)
If one date is entered: ([ClosingDate] >=#05/13/2019#)
That seems right to me, but it's not filtering. What the heck am I doing wrong?
EDIT: I should give credit the person who wrote the original routine, but I can't for the life of me find where I got it. Sorry! But whoever it was that originally wrote the routine, THANKS!
The WhereCondition should be the 4th argument in the OpenReport method. You have it in the FilterName argument's spot.
OpenReport

MS Access filter form to open report to specific records

I'm trying to create a form, ReportSearch that has multiple comboboxes and textboxes that will allow the user to narrow down the results shown on the report. Not all fields would have to be used in the search.
On click the following code will ask for the parameter value to be entered for the specific IDs used. If I just click OK without entering anything in the MsgBox the report will be opened with no records.
Private Sub cmdFilter_Click()
Dim strWhere As String
Dim lngLen As Long
Const conJetDate = "\#mm\/dd\/yy\#"
If Not IsNull(Me.cboSearchJob) Then
strWhere = strWhere & "(Job.id = " & Me.cboSearchJob & ") AND "
End If
If Not IsNull(Me.cboSearchEmployee) Then
strWhere = strWhere & "(Employee.ID = " & Me.cboSearchEmployee & ") AND "
End If
If Not IsNull(Me.cboSearchService) Then
strWhere = strWhere & "(Service.ID = " & Me.cboSearchService & ") AND "
End If
If Not IsNull(Me.tboStartDate) Then
strWhere = strWhere & "(DateWorked >= " & Format(Me.tboStartDate, conJetDate) & ") AND "
End If
If Not IsNull(Me.tboEndDate) Then
strWhere = strWhere & "(DateWorked < " & Format(Me.tboEndDate + 1, conJetDate) & ") AND "
End If
lngLen = Len(strWhere) - 5
If lngLen <= 0 Then
MsgBox "No Results", vbInformation, "No Search Available."
Else
strWhere = Left$(strWhere, lngLen)
DoCmd.OpenReport "JobReport", acViewPreview
Reports!JobReport.Filter = strWhere
Reports!JobReport.FilterOn = True
End If
End Sub
For the report I'm using
SELECT [Employees].[FirstName] & " " & [Employees].[LastName] AS EmployeeName, Jobs.JobName, Equipment.Model, Service.Service, Labor.Labor, EmployeeWorkLog.LaborHours, EmployeeWorkLog.EquipmentHours, EmployeeWorkLog.Notes, EmployeeWorkLog.DateWorked, Service.ID
FROM Service RIGHT JOIN (Labor RIGHT JOIN (Jobs RIGHT JOIN (Equipment RIGHT JOIN (Employees RIGHT JOIN EmployeeWorkLog ON Employees.ID = EmployeeWorkLog.EmployeeID) ON Equipment.ID = EmployeeWorkLog.EquipmentID) ON Jobs.ID = EmployeeWorkLog.JobID) ON Labor.ID = EmployeeWorkLog.LaborID) ON Service.ID = EmployeeWorkLog.ServiceID
ORDER BY [Employees].[FirstName] & " " & [Employees].[LastName];
At this point I'm at a complete loss.
Obviously there is something that I'm missing here. Let me know in what way I need to modify this code to get it to open my report JobReport filtered based on my form ReportSearch.
Thanks.
A report isn't dynamic like a form, you can't filter it after it has been opened. When a report is opened in print preview, it reads its data, does the layout and formatting, then it's completely static.
To open a report with filtered data, use the WhereCondition parameter of DoCmd.OpenReport:
DoCmd.OpenReport "JobReport", acViewPreview, WhereCondition:=strWhere

Search Query Works First Time but subsequent runs get run-time error 3075 extra ) in query expression

I have gone through all previous questions asked and even tried the solutions but to no avail so here's my dilemna. I have used a search query from Allenbrowne which was initially great. However, I wanted to add to the search criteria which again I have done and when searching for the first time I got the results I was looking for. I now use a different code to remove all the search criteria and to unfilter the form (split form). Again everything works. Now I want to search again either using the same of different parameters and this time I get the run-time error 3075 stating that I have an extra ) in the query expression. I have even looked up the query to see where this extra ) is but to no avail. The code is as follows and it errors on Me.Filter = strWhere. I have also provided the reset filter when clearing the search screen and wanting to start a new search. Any help would really be appreciated.
Option Compare Database
Option Explicit
Private Sub cmdFilter_Click()
Dim strWhere As String 'The criteria string.
Dim lngLen As Long 'Length of the criteria string to append to.
'***********************************************************************
'Look at each search box, and build up the criteria string from the non-blank ones.
'***********************************************************************
If Not IsNull(Me.txtCustID) Then
strWhere = strWhere & "([Customer_ID] = " & Me.txtCustID & ") AND "
End If
If Not IsNull(Me.txtJobID) Then
strWhere = strWhere & "([Job_ID] = " & Me.txtJobID & ") AND "
End If
If Not IsNull(Me.txtName) Then
strWhere = strWhere & "([Name] Like ""*" & Me.txtName & "*"") AND "
End If
If Not IsNull(Me.TxtPostcode) Then
strWhere = strWhere & "([Postcode] = ""*" & Me.TxtPostcode & "*"") AND "
End If
If Not IsNull(Me.txtCompany) Then
strWhere = strWhere & "([CompanyName] Like ""*" & Me.txtCompany & "*"") AND "
End If
If Not IsNull(Me.txtLocation) Then
strWhere = strWhere & "([Location] Like ""*" & Me.txtLocation & "*"") AND "
End If
If Not IsNull(Me.CboStatus) Then
strWhere = strWhere & "([Status] = " & Me.CboStatus & ") AND "
End If
If Not IsNull(Me.CboSource) Then
strWhere = strWhere & "([EnquirySource] = " & Me.CboSource & ") AND "
End If
'See if the string has more than 4 characters (a trailng " AND ") to remove.
lngLen = Len(strWhere) - 4
If lngLen <= 0 Then 'Nah: there was nothing in the string.
MsgBox "No criteria", vbInformation, "Nothing to do."
Else 'Yep: there is something there, so remove the " AND " at the end.
strWhere = Left$(strWhere, lngLen)
'For debugging, remove the leading quote on the next line. Prints to Immediate Window (Ctrl+G).
Debug.Print strWhere
'Finally, apply the string as the form's Filter.
Me.Filter = strWhere
Me.FilterOn = True
End If
End Sub
Private Sub cmdReset_Click()
'Purpose: Clear all the search boxes in the Form Header, and show all records again.
Dim ctl As Control
'Clear all the controls in the Form Header section.
For Each ctl In Me.Section(acHeader).Controls
Select Case ctl.ControlType
Case acTextBox, acComboBox
ctl.Value = ""
Case acCheckBox
ctl.Value = False
End Select
Next
'Remove the form's filter.
Me.FilterOn = False
End Sub
See this ctl.Value = "" in cmdReset_Click()? I would guess that when you clear the controls, one of them is ending up a zero-length string, but your test in building the filter is for null, not zero-length strings, so something, most likely one of the numerics, is ending up somefield=<blank>. Try:
ctl.Value = Null
As an aside, there is no point in using equals with a wild card:
strWhere = strWhere & "([Postcode] = ""*" & Me.TxtPostcode & "*"") AND "
Should be:
strWhere = strWhere & "([Postcode] Like ""*" & Me.TxtPostcode & "*"") AND "
Or
strWhere = strWhere & "([Postcode] = """ & Me.TxtPostcode & """) AND "