I have a dynamic search box filtering a subform based on user input. I also have a few filter buttons that filter the same subform. I set up the search box to incorporate preexisting filters applied by those buttons.
All that works fine. The problem I have is:
The dynamic filter using the LIKE statement only seems to work correctly when the length of the filter text is >= 3. Go below that and it applies some wonky filtering. Maybe I am using the statement wrong. I thought it would look if the field's value contains the search string somewhere in it. But it seemingly accepts values like "Natronlauge 50% techn. EN 896" for a search string of "Hä", which seems weird to me. It works once I add a third character though. Lines 11 and 13:
Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe & "*' AND [kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'"
Would be nice if someone has some ideas how to go about these issues.
Here the full code for my searchbox:
Private Sub SearchBoxStoffe_KeyUp(KeyCode As Integer, Shift As Integer)
On Error GoTo errHandler
Dim filterText As String
'Apply dynamic filter for current filter category.
If Len(SearchBoxStoffe.Text) > 0 Then
filterText = SearchBoxStoffe.Text
If Forms![HUB]![FilterAlleLink] = "" Then
Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe & "*'"
Else
Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe & "*' AND [kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'"
End If
Me.FilterOn = True
'Retain filter text in search box after refreshing.
SearchBoxStoffe.Text = filterText
SearchBoxStoffe.SelStart = Len(SearchBoxStoffe.Text)
Else
'Revert to current main filter category.
If Forms![HUB]![FilterAlleLink] <> "" Then
Call FilterStoffe("[kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'")
Else
If Forms![HUB]![FilterAlleLink] = "" Then
Me.Filter = ""
Me.FilterOn = False
End If
End If
End If
'Set focus back to search box
SearchBoxStoffe.SetFocus
Exit Sub
errHandler:
MsgBox Err.Number & " - " & Err.Description, vbOKOnly, "Error ..."
End Sub
The dynamic filter using the LIKE statement only seems to work
correctly when the length of the filter text is >= 3. Go below that
and it applies some wonky filtering.
I don't really know why this is happening, but try the below. It makes use of the Change() event and covers 4 scenarios:
Both filters applicable.
Search Box only.
Main category only.
Nothing (clear the filter).
Also, I don't know what the FilterStoffe() method does, but I assume it just applies the main filter only.
Private Sub SearchBoxStoffe_Change()
On Error GoTo Trap
Select Case True
'both filters
Case Len(SearchBoxStoffe.Text) > 0 And Not IsNull(Forms.HUB.FilterAlleLink.Value):
Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe.Text & "*' AND [kategorie] = '" & Forms.HUB.FilterAlleLink.Value & "'"
FilterOn = True
'SearchBox only
Case Len(SearchBoxStoffe.Text) > 0:
Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe.Text & "*'"
FilterOn = True
'FilterAlleLink only
Case Not IsNull(Forms.HUB.FilterAlleLink.Value):
Form.Filter = "[kategorie] = '" & Forms.HUB.FilterAlleLink.Value & "'"
FilterOn = True
'Nothing
Case Else:
FilterOn = False
Filter = vbNullString
End Select
Leave:
On Error Resume Next
SearchBoxStoffe.SetFocus
Exit Sub
Trap:
MsgBox Err.Number & " - " & Err.Description, vbOKOnly, "Error ..."
Resume Leave
End Sub
Keep in mind, within the Change() event, the Text property gets updated with every keystroke and when the control loses the focus, it gets copied to the Value property.
However, the Value is the default property when you just reference the control.
So this
Me.SearchBoxStoffe
is the same as this:
Me.SearchBoxStoffe.Value
There were 2 issues that prevented the searchbox from running as intended:
Object references in the project were created with 2 different language versions of access. Objects would call other objects using the formulation of one language, which in turn called objects using referencing in another language etc. In cases where fields and/or queries would return empty, this would cause some of the references to no longer function as intended. The result was the program running out of stack space, empty controls on subforms that returned empty queries, objects not being found and more.
The searchbox filter was lagging behind the text in the searchbox by one event. If entering a new search string, the applied filter would always be missing the last character when using SearchBoxStoffe in the filter statement. Entering "Wood" would cause the filter to apply "Woo" etc.
The solutions are the following:
Fix all the references in the file manually to either language version and do not mix them up going forward.
The Value of the search box SearchBoxStoffe is not yet updated on either the KeyUp or the Change event when entering a new character. This can be fixed by substituting the Text value instead, which is updated already. Simply change line 11 to Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe.Text & "*'" and line 13 to Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe.Text & "*' AND [kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'". The info originally came from #KostasK in his solution:
Keep in mind, within the Change() event, the Text property gets updated with every keystroke and when the control loses the focus, it gets copied to the Value property.
Which works too btw, just wasn't able to be verified since issue 1 prevented the code from running correctly. Answer by Kostas K.
Related
I have a dynamic search box filtering a subform based on user input. I also have a few filter buttons that filter the same subform. I set up the search box to incorporate preexisting filters applied by those buttons.
The problem:
Currently, I save the string entered into the search box as a variable I call filterText (so I don't lose the value when the form gets refreshed). After the form gets refreshed, I set the content of the search box to that saved value. Then I set the location of the insertion point to the length of the string currently in the search box (lines 9,17,18). This however, does not account for blank space. If a user types something that includes a blank space, say "Homebrew 50%", the insertion point will immediately update back to the end of the text string only and the input will end up missing the space like so "Homebrew50%". How can I get the length of the current user input including spaces?
Here the full code of my search box, there are other things wrong with it but the current question is only regarding the blank space issue:
Private Sub SearchBoxStoffe_KeyUp(KeyCode As Integer, Shift As Integer)
On Error GoTo errHandler
Dim filterText As String
'Apply dynamic filter for current filter category.
If Len(SearchBoxStoffe.Text) > 0 Then
filterText = SearchBoxStoffe.Text
If Forms![HUB]![FilterAlleLink] = "" Then
Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe & "*'"
Else
Me.Form.Filter = "[bezeichnung] LIKE '*" & SearchBoxStoffe & "*' AND [kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'"
End If
Me.FilterOn = True
'Retain filter text in search box after refreshing.
SearchBoxStoffe.Text = filterText
SearchBoxStoffe.SelStart = Len(SearchBoxStoffe.Text)
Else
'Revert to current main filter category.
If Forms![HUB]![FilterAlleLink] <> "" Then
Call FilterStoffe("[kategorie] = '" & Forms![HUB]![FilterAlleLink] & "'")
Else
If Forms![HUB]![FilterAlleLink] = "" Then
Me.Filter = ""
Me.FilterOn = False
End If
End If
End If
'Set focus back to search box
SearchBoxStoffe.SetFocus
Exit Sub
errHandler:
MsgBox Err.Number & " - " & Err.Description, vbOKOnly, "Error ..."
End Sub
So, I figured out the solution eventually.
When inserting the saved user input into the searchbox, you need to actually refer to the Value, not the Text of the searchbox. This will transfer any blank space in the user input correctly.
Change line 17 to:
SearchBoxStoffe = filterText
I started a thread here: Access Form Combobox Partial Filter but it was a bit too specific, and now that I moved past that, I am struggling to get the behavior I want.
Here is the layout:
A form with the detail hidden. The header has an unbound combobox for filtering the form. Once there is a filter to apply, that record is set for the filter on the form, and the detail is shown. The users want to be able to type in the combo, for partial matches, instead of only being able to click the drop down and click to choose an option.
This is the rowsource of the combo:
SELECT [vw_Info_Records]![recordName] & " (" & [vw_Info_Records]![recordNo] & ")" AS frecord, vw_Info_Records.INF_RID
FROM vw_Info_Records
WHERE ((([vw_Info_Records]![recordName] & " (" & [vw_Info_Records]![recordNo] & ")") Like "*" & [Forms]![frmrecords]![cboFindrecord] & "*"))
ORDER BY [vw_Info_Records]![recordName] & " (" & [vw_Info_Records]![recordNo] & ")";
It is set to auto-expand Yes. It is not bound to anything, and limit to list is set to yes.
This is the onchange event:
Private Sub cboFindRecord_Change()
Dim MyCriteria As String
If Me.cboFindRecord.SelStart > 0 Then
Me.cboFindRecord.Dropdown
End If
End Sub
This is the after update:
Private Sub cboFindRecord_AfterUpdate()
Dim Criteria As String
Dim myfilter As String
If Me.cboFindRecord.ListIndex = -1 Then
Me.Form.Filter = ""
Me.FilterOn = False
Me.Detail.Visible = False
Else
Criteria = "[INF_RID] = " & Me.cboFindRecord.Column(1)
With Me.Form
.Filter = Criteria
.FilterOn = True
End With
Me.Detail.Visible = True
End If
End Sub
The first character that is typed in, makes the dropdown expand, and filter to any results that contain that character. Any subsequent characters, and the drop down list doesn't update the filter to re-filter based on the added characters. If I add a requery in the change, I get an error about saving the field, before I do a requery. It wants me to set that "filter" value as a value for the combo, which I wouldn't do, because it's really an in string filter. The user still needs to pick a value from whatever is left in the list, before I can filter the form to that record.
Thanks for any advice as to how to fix this!
Hopefully, I'll make this question as precise and understandable as possible - but you'll tell me if i don't ! Thanks in advance.
Firstly, a little background and what I've found that DOES work, then on to a small change that I cannot get to work. Rather than use the whole code, I've used snippets that should give enough information for you to understand that I have initiated things correctly first.
I use a menu system (a turbo-charged version of the original MS one) that has additional fields to store information needed to make changes depending upon what wording the user wants to use, so I may name a field Product, whereas a user may want to call it Goods or Items or Stuff or whatever he desires! So I store the user preferences in a separate table (we'll call that tblWORDS). When the menu is populated (remember it operates in a similar fashion to the standard SwitchBoard) with the data from fields: ItemText, Command & Argument the menu normally displays the text from ItemText, which I use. But, I have added a NEW field called CAPTION in SWITCHBOARD table because the VBA code does not allow for formatting the labels as I want them. So, when the VBA code reads ItemText for the label, from the recordset, and it encounters a | (pipe), my added VBA code then looks to the field Caption for a string. Hopefully, enough background info!!??
[SwitchBoard].[Caption] originally contained the following: (EVERYTHING INCLUDED)
"" & dlookup("fldProduct","tblWORDS") & ""
This worked perfectly!! But...
Instead of performing a lookup every time I need the WORD, I decided to create GLOBAL VARIABLES, so I have a Global Variable of glProduct, which obtains the word from the tblWORDS table correctly and retains that just fine. This is then available throughout the session anywhere.
I have substituted the string above to read the Global Variable instead of performing a lookup each time, to: (again, EVERYTHING INCLUDED)
"" & glProduct & ""
So, my code is as follows:
While (Not (rs.EOF))
Me("Option" & rs![ItemNumber]).Visible = True
'MY PIPE DEVIATION
If Left(Trim(rs![ItemText] & ""), 1) = "|" Then
'THIS LINE WORKS JUST FINE
'DISPLAYS CORRECTLY (rs!Caption = "" & dlookup("fldProduct","tblWORDS") & "")
szTemp = DLookup(rs![Caption], "tblWORDS")
'AS DOES THIS (but, I'm explicitly naming the variable in code! Only entered this line to show that the variable is working!)
szTemp = "" & glbProduct & ""
'THIS DOES TOO (Just a BYREF function for testing)
szTemp = fnGetValue(DLookup(rs![Caption], "tblWORDS"))
Me("Option" & rs![ItemNumber]).Caption = szTemp
Else
If rs![ItemNumber] = 0 Then
Me("OptionLabel" & rs![ItemNumber]).Caption = VBA.Trim(rs![ItemText] & " (" & rs![SwitchboardID] & ")")
Me("OptionLabel" & rs![ItemNumber]).Visible = True
Me("Option" & rs![ItemNumber]).Visible = False
Else
Me("Option" & rs![ItemNumber]).Caption = VBA.Trim(rs![ItemText] & "")
End If
End If
rs.MoveNext
Wend
REVISED TO:
While (Not (rs.EOF))
Me("Option" & rs![ItemNumber]).Visible = True
'MY PIPE DEVIATION
If Left(Trim(rs![ItemText] & ""), 1) = "|" Then
'THIS WORKS (but, I'm explicitly naming the variable in code! Only entered this line to show that the variable is working!)
szTemp = "" & glbProduct & ""
'THIS DOES NOT (FYI: rs!Caption = "" & glbProduct & "")
szTemp = rs!Caption
'NOR DOES THIS (Just a BYREF function for testing)
szTemp = fnGetValue(rs!Caption)
Me("Option" & rs![ItemNumber]).Caption = szTemp
Else
If rs![ItemNumber] = 0 Then
Me("OptionLabel" & rs![ItemNumber]).Caption = VBA.Trim(rs![ItemText] & " (" & rs![SwitchboardID] & ")")
Me("OptionLabel" & rs![ItemNumber]).Visible = True
Me("Option" & rs![ItemNumber]).Visible = False
Else
Me("Option" & rs![ItemNumber]).Caption = VBA.Trim(rs![ItemText] & "")
End If
End If
rs.MoveNext
Wend
What IS displayed is the literal string as entered ("" _glProduct "") not Product as it was prior to my revision!
So... the first problem is that you're confusing everybody with what you're doing it and where it's happening - where did rs![Caption] come from???
The second problem is you can't access global variables in your form or control properties.
You need to set the caption via code. I'm going to make some big guesses as to what you're using and what each element is, so let's start here:
First
Replace the Caption property with something else - just "Caption" for example.
Second
Add this code after your loop - I think that will work - hard to really know because you don't show where this code is and when it runs
[SwitchBoard].Caption = "" & glProduct & ""
Firstly I apologise for my lack of knowledge on SQL.
I currently have two Comboboxes on a form and a list box which looks like the attached image
TroubleshootPage
The first combobox references a table with the list of manufacturers and then the second "Model" combobox updates with model numbers which match the first combobox' data
The List box below needs to display data from the "Solutions" Table. ONLY THE "SolutionText" COLUMN
The Manufacturer selected in "cboManfact" has to match the "ManufacturerSolution" in table "Solutions" and then return "SolutionText" if they match. Same for "cboModel" and "ModelSolution".
I dont want the listbox to display any manufacturer or model text, just the "SolutionText" field when a button db_search is pressed.
Thanks to the help of #LiamH, i currently have the following SQL Command on the RowSource of my list box
This can happen either as the user selects options in the comboboxes or when clicking the green search icon
The problem I am having is with the SQL Query. I currently have this below happening when the user clicks the search button
SELECT [SolutionText] FROM [Solutions] WHERE solutions.ManufacturerSolution like forms![Troubleshoot]!cboManfact & "*" AND solutions.ModelSolution like forms![Troubleshoot]!cboModel & "*"
It displays the SolutionText value in the listbox, but on clicking the "db_search" button, the listbox becomes empty
Private Sub dbSearch_Click()
me.listbox.requery
end sub
Very close to getting this one now, any advice
I have assumed you are using MS-Access, correct me if I am wrong. You may want to consider using access-vba tag if this is correct.
There are a few things wrong with your code. Firstly, docmd.RunSQL cannot be used on select queries. This (SELECT) is not an action query and this command is reserved for action queries only. e.g. DELETE, UPDATE, ALTER, SELECT...INTO.
When you use multiple where clauses use the word AND instead of the ampersand. You don't need to concatenate SQL strings together. String values that are in a query and related to form values need encapsulating in single quotes, like so:
"...WHERE NAME='" & Me.name & "'"
You can use debug.print strSQL or msgbox strSQL to see how your SQL query reads for any errors.
So here's what I would do:
Change the rowsource of the listbox to a query:
SELECT [SolutionText] FROM [Solutions] WHERE solutions.ManufacturerSolution like forms![FORM_NAME]!cboManfact.Column(1) & "*" AND solutions.ModelSolution like forms![FORM_NAME]!cboModel.Column(1) & "*"
The like ... & "*" means that if the combobox is empty it will show all.
You will need some VBA on the on_click event, which will be:
Private Sub dbSearch_Click()
me.listbox.requery
end sub
The requery will change the listbox items based on the records selected in the combo boxes.
I don't know what your intention is when using [Solution Text]?
Are you sure you require column(1) and not column(0)?
I am not sure what your intention was with strTableName?
Solved the issue using the following code:
Private Sub dbSearch_Click()
Dim ManfactQuery As String
Dim ModelQuery As String
Dim strSQL As String
ManfactQuery = Me.cboManfact.Column(1)
ModelQuery = Me.cboModel.Column(1)
If Nz(ManfactQuery) = "" Then
strSQL = "SELECT [Solutions].SolutionText FROM [Solutions] WHERE [Solutions].ModelSolution = '" & ModelQuery & "'"
Else
If Nz(ModelQuery) = "" Then
strSQL = "SELECT [Solutions].SolutionText FROM [Solutions] WHERE [Solutions].ManufacturerSolution = '" & ManfactQuery & "'"
Else
strSQL = "SELECT [Solutions].SolutionText FROM [Solutions] WHERE [Solutions].ManufacturerSolution = " & ManfactQuery & " AND [Solutions].ModelSolution = " & ModelQuery & ""
End If
End If
Me.lstSolution.RowSource = strSQL
End Sub
I am trying to update a record using Subform. When I update the first time it updates properly but when I try to update the same record again I am getting the error:
Run-time error '-2147352567 (80020009)': The value you entered isn't valid for this field
The following is the form.
When I click edit, the information from the selected record is populated into the respective text-boxes. Once I update the information and click update, the record gets successfully updated for the first time.
When I try to update the same record again I get the mentioned error.
Here is the VB script that runs on clicking edit.
Private Sub cmdEdit_Click()
'Check if data exists in the list
If Not (Me.frmschoolsub.Form.Recordset.EOF And Me.frmschoolsub.Form.Recordset.BOF) Then
'get data to text box control
With Me.frmschoolsub.Form.Recordset
Me.Schooltxt = .Fields("School_Name")
Me.Desctxt = .Fields("Description")
Me.Deantxt = .Fields("Dean")
Me.Adeantxt = .Fields("Associate_Dean")
'store id of student in tag
Me.Schooltxt.Tag = .Fields("School_ID")
'change caption of button to update
Me.cmdAdd.Caption = "Update"
Me.cmdEdit.Enabled = False
End With
End If
End Sub
When I click on Debug it highlights the following line.
Me.Schooltxt = .Fields("School_Name")
Can you help me in identifying what is the issue here.
I figured that after the each update, I am losing the position of record. I added the following statement after update and Requery
Me.frmschoolsub.Form.Recordset.MoveFirst
Following is the code snippet.
Else
CurrentDb.Execute "Update School " & _
" SET School_Name ='" & Me.Schooltxt & "'" & _
", Description ='" & Me.Desctxt & "'" & _
", Dean ='" & Me.Deantxt & "'" & _
", Associate_Dean='" & Me.Adeantxt & "'" & _
"where School_ID=" & Me.Schooltxt.Tag
End If
'Clear the Fields
cmdClr_Click
'Refresh the table
frmschoolsub.Form.Requery
Me.frmschoolsub.Form.Recordset.MoveFirst
This fixed the issue.
This error is happening that a form field cannot be referenced to a textbox like you did.
You can do it as below.
With Me.frmschoolsub.Form.Recordset
Me.Schooltxt = Forms![<<if you have main form >>]![frmschoolsub].form![School_Name]