Truncating trailing spaces in Access for Search-As-You-Type - ms-access

I am creating a dynamic search-as-you-type that filters a list of data as the user types in a text box.
Private Sub TxtSearch_Change()
Dim CursorPosition As Long
Dim strSearch As String
Dim sqlSearch As String
CursorPosition = TxtSearch.SelStart
Me.Dirty = False 'set the dirty property to false to save the current value
strSearch = ""
If Not IsNull(Me.TxtSearch.Value) Then
strSearch = Me.TxtSearch.Value
End If
searchLength = Len(strSearch)
If searchLength < CursorPosition Then
For i = 1 To (CursorPosition- searchLength)
strSearch = strSearch + " "
Next
End If
'Check if a keyword has been entered or not
If strSearch = "" Then
Me.TxtSearch.SetFocus
sqlShowAll = "SELECT * FROM qrySearch"
Forms![frmSearch]!fsubTest.Form.RecordSource = sqlShowAll
Else
sqlSelect = "SELECT * FROM qrySearch WHERE ("
sqlLastName = "(LastName Like ""*" & strSearch & "*"")"
sqlFirstName = " OR (FirstName Like ""*" & strSearch & "*"")"
sqlFullName = " OR (FullName Like ""*" & strSearch & "*"")"
sqlEnd = ")"
sqlAllNames = sqlLastName & sqlFirstName & sqlFullName
sqlSearch = sqlSelect & sqlAllNames & sqlEnd
Forms![frmSearch]!fsubTest.Form.RecordSource = sqlSearch
End If
TxtSearch.SelStart = CursorPosition
End Sub
Access truncates trailing spaces in text fields. Is there a way to get around this? I have already implemented a for loop to restore the trailing space for search purposes, but I'd like to save the trailing space so that as the user continues typing the space has not disappeared. For example, I could enter "Jane " and search for "Jane " but when returned to the text box, I would see "Jane" so I could never type "Jane Doe" but only "JaneDoe".

Here's the code I use to accomplish what you're looking for. I have the search box "Searchfor" as where I type, and "SearchResults" as a combobox with the data. There's also a text box "SrchText" which is used by the query "QRY_SearchAll." That query is a series of "Like "" & [Forms]![FRM_SearchMulti]![SrchText] & """ for each field I want displayed in the combo box, see picture.
Private Sub SearchFor_Change()
'Create a string (text) variable
Dim vSearchString As String
'Populate the string variable with the text entered in the Text Box SearchFor
vSearchString = SearchFor.Text
'Pass the value contained in the string variable to the hidden text box SrchText,
'that is used as the sear4ch criteria for the Query QRY_SearchAll
SrchText = vSearchString
'Requery the List Box to show the latest results for the text entered in Text Box SearchFor
Me.SearchResults.Requery
'Tests for a trailing space and exits the sub routine at this point
'so as to preserve the trailing space, which would be lost if focus was shifted from Text Box SearchFor
If Len(Me.SrchText) <> 0 And InStr(Len(SrchText), SrchText, " ", vbTextCompare) Then
'Set the focus on the first item in the list box
Me.SearchResults = Me.SearchResults.ItemData(1)
Me.SearchResults.SetFocus
'Requery the form to refresh the content of any unbound text box that might be feeding off the record source of the List Box
DoCmd.Requery
'Returns the cursor to the the end of the text in Text Box SearchFor,
'and restores trailing space lost when focus is shifted to the list box
Me.SearchFor = vSearchString
Me.SearchFor.SetFocus
Me.SearchFor.SelStart = Me.SearchFor.SelLength
Exit Sub
End If
'Set the focus on the first item in the list box
Me.SearchResults = Me.SearchResults.ItemData(1)
Me.SearchResults.SetFocus
'Requery the form to refresh the content of any unbound text box that might be feeding off the record source of the List Box
DoCmd.Requery
'Returns the cursor to the the end of the text in Text Box SearchFor
Me.SearchFor.SetFocus
If Not IsNull(Len(Me.SearchFor)) Then
Me.SearchFor.SelStart = Len(Me.SearchFor)
End If
End Sub
One warning about this sytem: It uses requery instead of refresh. This is fine for a reasonable number of records on a reasonbly fast system. I found that when I tried to use this same code for data on an ancient Sharepoint server, I'd be hitting a 10 second delay after each letter I type. So if you're dealing with a lot of records or a slow server, you may want to change 'requery' to 'refresh.'

Related

Using textboxes to search entries based on a keyword (There are multiple textboxes for separate entities) and implementing a combo box

I want to be able to enter in a keyword into a textbox that would search records for that keyword and present reports based on that word that are found.
Please Note: There are multiple textboxes for this to separate specific information so that I need this to work for each individual textbox. There is one text box that will search for entries based on the date (month/day/year) and I have been having issues with it not displaying certain date ranges.
I am also looking to add in a combo box as well.
I have tried code that another individual has given me, but the issue that I have run into with the normal textboxes is that it requires me to put in everything that is in the entry as opposed to search based on a keyword to which nothing pops up when other criteria have been put in place (I know that there is an entry that fits, but for some reason when I add in the textbox element it does not work unless I put in the exact entry that is in the textbox that I am search the specific information from).
I have been trying to find information for combo boxes, but I have not found anything that really works with what I want to do.
Function SelectedItems(objBox As ListBox) As String
Dim strRtn As String, varItm
For Each varItm In objBox.ItemsSelected
strRtn = strRtn & ",'" & objBox.ItemData(varItm) & "'"
Next varItm
If strRtn <> vbNullString Then SelectedItems = Mid(strRtn, 2)
End Function
Private Sub Command62_Click()
Dim strSQL As String
Dim strArr As String
Dim varItm
For Each varItm In Array("District", "Circumstance", "Location", "Method", "Point", "Rank", "Description", "Missing", "IDNumber", "Dateto", "Datefrom", "Address")
strArr = vbNullString
Select Case Me.Controls(varItm).ControlType
Case acListBox
strArr = SelectedItems(Me.Controls(varItm))
Case acTextBox
If Not IsNull(Me.Controls(varItm).Value) Then
strArr = "'" & Me.Controls(varItm).Value & "'"
End If
End Select
If strArr <> vbNullString Then
strSQL = strSQL & "t." & varItm & " in (" & strArr & ") and "
End If
Next varItm
If strSQL <> vbNullString Then strSQL = "where " & Left(strSQL, Len(strSQL) - 5)
With CurrentDb.QueryDefs("qryMultiselect")
.SQL = "select * from tblDataEntry t " & strSQL
End With
DoCmd.OpenQuery "qryMultiselect"
End Sub
What I want is to be able to use my multi-select listboxes in conjunction with my textboxes as well as my combo box that I have as well. Using all of that or at least a combination of them, I want to be able to sort through my data to be able to create reports based on what is being looked for. Along with making sure that the user has the freedom to not having to enter in information for all fields and only the ones that they feel they need to enter in information on.
With the textboxes: I want to be able to search based on a keywords that corresponds with a specific section of the data that I am looking for and to be able to leave others blank and be able to pull up results.
The same goes for the date/time textboxes and my combo box.

Why does Access VBA dropdown method not work?

I'm using a text box to filter a combo box list in Access 2013. I put the filter code in the Form_Timer sub so as to give users time to type the entire filter string before applying the filter, and I invoke the timer from the text box Change sub. It works great except for one thing: I want the combo box list to drop down and display results, and it just won't work. However I put the exact same line of code in the GotFocus sub for the combo box, and that line works perfectly.
I also tried executing the filter code within the Change sub, just in case there was some weirdness regarding Form_Timer execution. Same result. Here is the code:
Private Sub cboCENamesMain_GotFocus()
Me.cboCENamesMain.Dropdown '<---This line works perfectly.
End Sub
Private Sub Form_Timer()
Dim strSQL As String
Me.TimerInterval = 0
Me.txtFilter.Value = Me.txtFilter.Text
Me.cboCENamesMain.SetFocus
strSQL = ""
strSQL = strSQL & "Select DISTINCT [CE ID] "
strSQL = strSQL & "From [tblMyTable] "
If Len(Me.txtFilter) > 0 Then
strSQL = strSQL & "Where [CE ID] Like ""*" & Me.txtFilter & "*"" "
End If
strSQL = strSQL & "Order By [CE ID];"
Me.cboCENamesMain.RowSource = strSQL
Me.cboCENamesMain.Dropdown '<---This line doesn't do what it's supposed to.
Me.txtFilter.SetFocus
Me.txtFilter.SelStart = Len(Me.txtFilter.Text)
Me.txtFilter.SelLength = 0
End Sub
Private Sub txtFilter_Change()
If Len(Me.txtFilter.Text) = 0 _
Or Len(Me.txtFilter.Text) > 2 Then
Me.TimerInterval = 500
End If
End Sub
I could use a list box instead of a combo box to allow users to see the results of their filter typing, but that would seriously detract from my form design. I have searched on Google and on StackOverflow, and have not found anybody else discussing this issue. Any ideas?
Here is my final code. This works just the way I want. The user types a few characters, and the timer automatically filters the combo box list down to items containing the typed string.
StackOverflow is a great place to file stuff like this - going from job to job it will save some time reinventing the wheel.
The extensive comments in the code are for the analysts who will need to maintain the applications after my contract ends. Neither of them has ever written VBA.
Private Sub cboCENamesMain_Change()
' Ordinarily the AfterUpdate event would automatically fire off the Change event.
' We set a flag to avoid that - otherwise the list would be filtered to only the selected record.
If booCancelChange = False Then
' Don't bother filtering the combo box list unless the filter text is null or longer than
' 1 character.
If Len(Me.cboCENamesMain.Text) <> 1 Then
' Set the Form_Timer event to fire off in 0.3 second to give them time to type a few characters.
Me.TimerInterval = 300
End If
Else
' Reset the flag, otherwise the Change code would stop working after the first record selection.
booCancelChange = False
End If
End Sub
Private Sub Form_Timer()
Dim strSQL As String
' Reset the timer to not fire off, so that it won't keep running without a change
' in the combo box.
Me.TimerInterval = 0
' If they have tabbed out of the combo box after selecting an item, we don't want to
' do this. It's unnecessary and it throws errors from references to the control's
' properties when focus is no longer on the control.
If Screen.ActiveControl.Name = Me.cboCENamesMain.Name Then
' Create a SQL filter for the combo box using the entered text.
strSQL = ""
strSQL = strSQL & "Select DISTINCT [CE ID] "
strSQL = strSQL & "From [Covered Entities] "
If Len(Me.cboCENamesMain.Text) > 0 Then
strSQL = strSQL & "Where [CE ID] Like ""*" & Me.cboCENamesMain.Text & "*"" "
End If
strSQL = strSQL & "Order By [CE ID];"
' Apply the filter.
Me.cboCENamesMain.RowSource = strSQL
Me.txtRowCount = Me.cboCENamesMain.ListCount
' Drop down the combo list so they can see the results of their filter text.
Me.cboCENamesMain.Dropdown
End If
End Sub

first item is getting selected in simple type access list box

Find my vba
Private Sub Search_Click()
Dim VarItem As Variant
Dim Strsearch As String
Dim Sql As String
Dim ctrl As Control
Set ctrl = Me.LbobDriveType
If ctrl.ItemsSelected.Count > 0 Then
For Each VerItem In ctrl.ItemsSelected
Strsearch = Strsearch & ctrl.Column(VarItem)
Next VerItem
MsgBox (Strsearch)
Sql = "SELECT Database.[Record _ID], Database.PhysicalVIN, Database.LogicalVIN, Database.VERSION, Database.BODY_STYLE, Database.ENGINE_TYPES, Database.BODY_EXTERIOR_COLOR, Database.INDIA_OR_EXPORT, Database.DRIVE_TYPES, Database.TRANSMISSION_TYPES, Database.FUEL_TYPE, Database.MARKET, Database.MARKET_CATEGORY " _
& "FROM [Database] where DRIVE_TYPES in('" & Strsearch & "')"
MsgBox (Sql)
End If
Me.SbfRecord.Form.RecordSource = Sql
Me.SbfRecord.Form.Requery
end sub
enter image description here
enter image description here
I expect you want the two marked entries of the listbox to be displayed in the message box instead of twice the first one?
If so, the code should work well except of the fact that there is a typo (VarItem vs VerItem) and an End If missing.
So I think your problem could be that there is more than one column defined in the listbox?
Maybe the first column is hidden and contains RHD for all rows?

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

When clicking on text will link me to table

Currently I have a textbox that will display some text based on the search criteria. The text that is displayed will be the name of a table. Is it possible for me to make it so that if I click on the name of the table in the textbox, it will open the table for me?
In the click event of the textbox:
DoCmd.OpenTable Me.MyTextbox
Edit re comment, this is a sketch and will not work if the table name has spaces.
Private Sub Text0_Click()
i = Me.Text0.SelStart
j = InStr(i, Me.Text0, " ")
k = InStrRev(Me.Text0, " ", i)
tbl = Mid(Me.Text0, k, j - k)
DoCmd.OpenTable tbl
End Sub
Or better, capture the construction in a listbox by row, rather than in a textbox.
Based on you code sample, you can say:
Public Sub SearchTables(SearchString As String)
Dim tdf As DAO.TableDef
Dim sTable As String
Dim sField As String
Dim sMsg As String
sMsg = ""
For Each tdf In CurrentDb.TableDefs
sTable = tdf.Name
sField = SearchTable(sTable, SearchString)
If sField <> vbNullString Then
sMsg = sMsg & ";" & sTable & ";" & sField
End If
Next
'listbox0
'Row source type: Value List
'Column count: 2
'You will get a two column listbox with table in one column
'and field in another
Forms!Search!listbox0.RowSource = Mid(sMsg, 2)
End Sub
Then in the click event for listbox0:
Private Sub listbox0_Click()
DoCmd.OpenTable Me.listbox0
End Sub
Do you mean specifically clicking on the text that is the name...
so if the text were "John 12345 THE TABLE" you want just THE TABLE to open?
Not enough information to give a solid answer, but if you wanted to just get THE TABLE from the above text then you could use screen coordinates based on where you click in relation to the position of text. It would be far easier to do it another way...
If the format of your text is like this:
Table = NAMEOFTABLE Field = NAMEOFSEARCH Table = NAMEOFTABLE2 Field = NAMEOFSEARCH2
You could use this code:
Private Sub Text0_Click()
i = Me.Text0.SelStart
If i > 0 Then
startTable = InStrRev(Me.Text0, "Table = ", i)
startField = InStr(startTable + 8, Me.Text0, "Field = ")
If startTable > 0 And i < InStr(startTable + 8, Me.Text0, "Field = ") Then
DoCmd.OpenTable Mid(Me.Text0, startTable + 8, startField - startTable - 9)
End If
End If
End Sub
If you click on the name of any table, it will open that table.
Here a little explanation: using current position of the cursor, I'm searching backwards for the "Table = " string, and from there I'm searching for the next string "Field = ". All we have to do is to check if the cursor is before next field.