MS Access Choosing Filter with ComboBox - ms-access

I have returned with yet another Question regarding MS Access and its VBA environment.
I'm currently constructing a database in MS Access 2016.
The main View headview has a combobox viewcombo and a subform listview.
What I need: I want the combobox to filter the listview depending on the chosen entry of it.
What I did:
Private Sub ViewCombo_AfterUpdate()
On Error GoTo Proc_Error
If IsNull(Me.ViewCombo) Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Dim selectedOption As AccessObject
selectedOption = Me.ViewCombo
Select Case selectedOption
Case selectedOption = "open"
Me.ListView.Form.Filter = "Column1='" & "'"
End Select
End If
Proc_Exit:
Exit Sub
Proc_Error:
MsgBox "Error " & Err.Number & " Setting Filter:" & vbCrLf & Err.Description
Resume Proc_Exit
End Sub
Note: The Me.ListView.form.Filter = "Column1='" & "'" is supposed to be empty if the chosen entry of viewCombo is open, the available entries are Open, Closed, ovedue, cancel and "as seleced
However, it seems that Access doesnt work this way. How do I properly write the select case statements?
Edit 1:
The Values of the ComboBox ViewCombo are manualy written in it. Depending on the selection of a value, different Filters are to be set on the ListView
Example:
The selected value is open
The Listview is filtered with the statement: Column1 is empty
The selected value is closed
The Listview is filtered with the statement Column 1 is not empty, Column 2 contains the value 10 (10 is an ID for a status, these are given to me by the employees I work with, those are internal and have no meaning for the database)
Hope that helps to clarify the situation.

You will use the value of the combobox, not the combobox as an object, similar to:
If IsNull(Me.ViewCombo.Value) Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Select Case Me.ViewCombo.Value
Case Is "open"
Me.ListView.Form.Filter = "[SomeFieldName] = 'open'" ' or other filter value.
End Select
Me.ListView.Form.FilterOn = True
End If

I solved it with the Input you guys gave me:
Private Sub AuswahlFilter_AfterUpdate()
On Error GoTo Proc_Error
If Me.ViewCombo.Value = "All" Then
Me.ListView.Form.Filter = ""
Me.ListView.Form.FilterOn = False
Else
Select Case Me.ViewCombo.Value
Case Is = "Open"
Me.ListView.Form.Filter = "FlagOpenClosed='1'"
Me.ListView.Form.FilterOn = True
End Select
End If
Proc_Exit:
Exit Sub
Proc_Error:
MsgBox "Error " & Err.Number & " when creating Filter:" & vbCrLf & Err.Description
Resume Proc_Exit
End Sub
I created some additional Columns on the ListView. The Table listviewis based on now has additional columns filled with values from statements like When(IsNull(Column1);1;0). Then I set the filter for those values.
I guess there is a better way to do it, however, I am a noob in VBA, so that is the best solution I came up with. If there is a better way to do it, please dont hesitate to write it as an answer here, I am glad to learn new things, and love to hear from you guys.
-Ninsa

Related

MS Access: Subform Datasheet - Variable RecordSources

I have a subform datasheet whose RecordSource can be variable. My database constructs an SQL query based on user selections (a different collection of columns with each query). The resulting query is intended to be the RecordSource for a datasheet on a subform. (Read-only view for user)
Problem:
The various queries produce the desired results when run on their own
Setting a resulting query as the datasheet's RecordSource does not produce any result (no columns/rows)
I suspect I need to insert the query's attributes into the subform in order to see any results (much like "Add Existing Fields" in the menu strip).
Question:
Any pointers to get me off square one?
Thank you!
Remove the datasheet form from your subform object and leave the source object property empty.
Create a new query (sql doesn't matter) and name it qryTemp (or whatever you like).
Then whenever you want to set the source for the subform, use this
CurrentDb.QueryDefs("qryTemp").SQL = "<your new sql here>"
<yoursubformobject>.SourceObject = "Query.qryTemp".
Here is an example I use to populate a sub-form:
Private Sub cmdFind_DisplayName_Click()
Dim dbs As Database, rstPatient As Recordset
Dim txtDisplayName, strQuote As String
strQuote = Chr$(34)
On Error GoTo ErrorHandler
Me.OrderBy = "DISPLAYNAME"
Me.OrderByOn = True
Set dbs = CurrentDb
Set rstPatient = Me.RecordsetClone
txtDisplayName = Trim(InputBox("Please Enter Patient Name ", "Patient Find By Name"))
txtDisplayName = UCase(txtDisplayName) & "*"
If IsNull(txtDisplayName) Then
MsgBox ("No Patient Name Entered - Please Enter a Valid Patient Name")
Else
rstPatient.FindFirst "[DISPLAYNAME] Like " & strQuote & txtDisplayName & strQuote
If Not (rstPatient.NoMatch) Then
Me.Bookmark = rstPatient.Bookmark
Me.Refresh
Else
MsgBox ("Patient Not Found - Please Enter a New Patient Name")
End If
End If
GoTo Exit_cmdFind_Click
ErrorHandler:
MsgBox LTrim(RTrim(Me.NAME)) + "." + "Patient Find By Display Name - " + "Error: " + AccessError(Err.Number)
Exit_cmdFind_Click:
rstPatient.Close
Set dbs = Nothing
Set rstPatient = Nothing
End Sub

Warning for Dynamic Combobox list

I have a combobox that builds it's list upon first usage. I know that the way I want "NotInList" to behave isn't conventional - I don't want to waste adding the item to a table separate from the needed entry, but I'd like to still warn about an item that hasn't been used yet, so that the user has to think twice before accepting the entry.
Once the user adds the item, it will automatically appear in the list next time because the data source for the combo box is as follows:
SELECT tbl_SP.PROGRAM
FROM tbl_SP
GROUP BY tbl_SP.PROGRAM
HAVING (((tbl_SP.PROGRAM) Is Not Null And (tbl_SP.PROGRAM)<>""));
I tried this:
Private Sub cmbPROGRAM_NotInList(NewData As String, Response As Integer)
If MsgBox("'" & Chr(34) & NewData & Chr(34) & " hasn't been used yet. Add to list? ", vbQuestion + vbYesNo, "Add - " & NewData & "?") = vbYes Then
Response = acDataErrAdded
End If
End Sub
but of course, Access wants the item to actually exist before it will release the error. And...if I set LimitToList to "No" then the user doesn't get a warning.
How can I achieve this behavior?
Ok, I tried this which works fine if the user selects YES, but becomes more complicated when the user selects "NO"
Public Function ReturnsRecords(strSQL As String) As Boolean
Dim d As DAO.Database
Dim arr(1 To 3) As DAO.Recordset
'Dim rs As DAO.Recordset
'assume 3 items in array above
Set d = CurrentDb
Set arr(1) = d.OpenRecordset(strSQL)
' MsgBox "Record Count is " & arr(1).RecordCount
If arr(1).RecordCount > 0 Then
ReturnsRecords = True
Else
ReturnsRecords = False
End If
Set d = Nothing
End Function
Private Sub cmbPROGRAM_BeforeUpdate(Cancel As Integer)
Dim strSQL As String
strSQL = "Select * from LU_PROGRAM where PROGRAM ='" & Me.cmbPROGRAM & "'"
If ReturnsRecords(strSQL) = False Then
If MsgBox("'" & Chr(34) & Me.cmbPROGRAM & Chr(34) & " hasn't been used yet. Add to list? ", vbQuestion + vbYesNo, "Add - " & Me.cmbPROGRAM & "?") = vbNo Then
Cancel = True
' how do I reset this? Me.cmbPROGRAM.Text = Null
End If
End If
End Sub
How do I clear the combobox if the user selects NO? If I select me.undo, that will undo all of the entries, but I just want to clear the combobox.
Incidentally, the form is totally unbound and doesn't accept an entry until the user selects "Save"
First, I'm not quite sure what you wish to achieve ...
Then, educate the users to press Escape to cancel. This is mandatory wisdom when operating an Access application.
For your code to work, you can't change the content of a control in the BeforeUpdate event. So try the AfterUpdate event with either:
Me!cmbPROGRAM.Text = ""
or:
Me!cmbPROGRAM.Value = Null

Find next record based on certain criteria

I am trying to use the .FindNext (and .FindPrevious) function on an update form "next button" to find the record that meets certain criteria.
Private Sub NextRecord_Click()
Dim foundmatch As Boolean
For x = 0 To 3 Step 1
With Me.RecordsetClone
.FindNext "[Sensitivity] = " & [TempVars]![AccessLevel] + x
If .NoMatch Then
foundmatch = False
Else
Me.Bookmark = .Bookmark
foundmatch = True
Exit For
End If
End With
Next
If foundmatch = False Then
MsgBox "No More Records"
End If
End Sub
Upon a user entering the database the users accesslevel is assigned to a temp variable (1 to 4), and each project has a sensitivity rating of 1 to 4. The code below was used and worked for both next and previous only in finding records when the sensitivity and accesslevel were equal but not for sensitivities below the users access level which they are qualified to see.
Private Sub PrevRecord_Click()
Dim Stringy As String
Stringy = "[Sensitivity] = " & [txtaccess]
With Me.RecordsetClone
.FindPrevious Stringy
If .NoMatch Then
MsgBox "No More Records"
Else
Me.Bookmark = .Bookmark
End If
End With
End Sub
Note: The form is pulled from a query with Sensitivity one of the fields, and [txtaccess] is a text box on the field with the default value set at [TempVars]![AccessLevel]. I've also tried changing it to:
Stringy = "[Sensitivity] >= " & [txtaccess]
but that doesn't work either
I was able to fix the problem by setting applying a filter for sensitivity on the actual forms On_Load event rather than the command button. It now works using a next record command button added with the default code/settings!

Getting Records from Table in Access

I have this requirement where I have to check the data based on data given in other fields. I have table with 'N' fields. I should allow user to select 4 fields which are from the table. And then I should get all other fields of that particular record and display it to the user so that he can verify that the data he entered into table is correct. Please help.
Thanks
I have a clearer understanding now of what you require - hopefully this is what you need:
Assume you have a table called 'Phones'
The phones table has three primary fields: Manufacturer, Operating System, and Carrier
In addition to these primary fields there are secondary "spec" fields. For now we have three: ScreenSize, Frequencies, and Price.
I create a form with three combo boxes: ManufacturerFilter, OperatingSystemFilter, and CarrierFilter.
Each combo box's row source is similar to:
SELECT Carrier FROM Phones GROUP BY Carrier ORDER BY Carrier;
Where Carrier is replaced by Manufacturer and [Operating System] respectively.
I then add in all of the secondary fields, each bound to their own respective field.
You can also add in a button called "Retrieve" for now leave the click code blank.
At this point you have a few options. I'll highlight two, but both options will require the following procedure:
Private Function FilterStr() As String
Dim myFilterStr As String
' Include each filter if they are entered
If Nz(Me.ManufacturerFilter, "") <> "" Then myFilterStr = myFilterStr & "[Manufacturer]='" & Me.ManufacturerFilter.Value & "' AND"
If Nz(Me.OperatingSystemFilter, "") <> "" Then myFilterStr = myFilterStr & "[Operating System]='" & Me.OperatingSystemFilter.Value & "' AND"
If Nz(Me.CarrierFilter, "") <> "" Then myFilterStr = myFilterStr & "[Carrier]='" & Me.CarrierFilter.Value & "' AND"
' Remove the last AND statement
If myFilterStr <> "" Then myFilterStr = Mid(myFilterStr, 1, Len(myFilterStr) - 4)
FilterStr = myFilterStr
End Function
This function returns a filter string, based on the combo box options selected.
Option #1: Filter the Recordset
What we want to occur, is when a primary field value is selected, the records are filtered to display only those matching the criteria. Add the following code to the OnClick event of your Retrieve button:
Private Sub RetreiveButton_Click()
Dim myFilterStr As String
myFilterStr = FilterStr
If myFilterStr <> "" Then
Me.Filter = myFilterStr
Me.FilterOn = True
Else
Me.Filter = ""
Me.FilterOn = False
End If
End Sub
So what happens when the button is clicked, is that a filter string is created based on the values selected, and then a filter is applied to the form. If no values are selected in the combo boxes, the filter is cleared and turned off.
Option #2: Find a Record based on the Value
What we want is to select the values in the comboboxes, and then move to the record that matches the criteria.
Add the following code to the onClick event of the retrieve button.
Private Sub RetreiveButton_Click()
Dim rst As DAO.Recordset
Dim myFilterStr As String
myFilterStr = FilterStr()
If myFilterStr = "" Then
MsgBox "No Filter Selected", vbOKOnly, "Error"
Exit Sub
End If
Set rst = Me.RecordsetClone
rst.FindFirst myFilterStr
If rst.NoMatch Then
MsgBox "No Matching Records were found", vbOKOnly, "No Data"
Else
Me.Bookmark = rst.Bookmark
End If
Set rst = Nothing
End Sub
This uses the the same FilterStr() function to return a search string, but uses the recordset's FindFirst method to locate a record. If found, it will move to the record.
Hope that answers your question. As I indicated, the exact behaviour will vary but the underlying principle remains the same.

MS Access combo box setting a record with two primary keys

I have a database with 2 primary keys, one for a LINE NUMBER and one for PHASE of construction. The reason for this is that we have projects that may use the same Line Number but must track several Phases of the project entirely seperatly. What I have is a combo box that will drive the record information on a form. This works fine, but now when I have more than one phase it will only bring up the line's first phase and not the other 4 phases. When something other than phas one is picked it results the first phase information.
Is there a way to tie a combo box with 2 fields to select the proper record based on both fields picked?
Or maybe I need to rething the way the form is brought up... Is there a better way to do this?
Code used to select the record:
Sub SetFilter()
Dim LSQL As String
LSQL = "select * from tblLineData_Horizon"
LSQL = LSQL & " where lineno = '" & cboSelected & "'"
Form_frmHorizon_sub.RecordSource = LSQL
End Sub
Private Sub cboSelected_AfterUpdate()
'Call subroutine to set filter based on selected Line Number
SetFilter
End Sub
Private Sub Form_Open(Cancel As Integer)
'Call subroutine to set filter based on selected Line Number
SetFilter
End Sub
A basic idea, but you'll most likely want to tweak the behaviour a bit and have some more checks. When the form loads, you only have the ability to select LineNo. When cbxLineNo has a value in it, it enables cbxPhaseNo for selection and upon selection, it changes the RecordSource of your subform.
Private Sub cbxLineNo_AfterUpdate()
If IsNull(cbxLineNo) Then
cbxPhaseNo.Enabled = False
Else
cbxPhaseNo.Enabled = True
cbxPhaseNo.RowSource = "SELECT PhaseNo FROM tblLineData_Horizon WHERE LineNo = " & cbxLineNo & ";"
End If
End Sub
Private Sub cbxPhaseNo_AfterUpdate()
If IsNull(cbxPhaseNo) = False And IsNull(cbxLineNo) = False Then
tblLineData_Horizon_sub.Form.RecordSource = "SELECT * FROM tblLineData_Horizon WHERE LineNo = " & cbxLineNo & " AND PhaseNo = " & cbxPhaseNo & ";"
End If
End Sub
Private Sub Form_Load()
cbxLineNo.Enabled = True
cbxPhaseNo.Enabled = False
cbxLineNo.RowSource = "SELECT LineNo FROM tblLineData_Horizon GROUP BY LineNo;"
End Sub
You question is a little unclear, but you can create a combobox with more than one column, then your select statement would be:
where lineno = '" & cboSelected.Column(0) & "' And otherfield='"& cboSelected.Column(1)&"'"
Go to the query behind your combobox by clicking into its RowSource property and clicking the Build button (...). Once you've added the columns you need, bring up the Properties for the query and set Unique Values to Yes, so that it doesn't repeat the combinations of the fields.
You will also need to change other properties of the combobox: 'Column Count' and 'Column Widths'.