Problem: How To Implement a Quick Find feature
Solution: This article describes a technique for implementing a Quick Find feature in your application, enabling your users to incrementally search through a large list. As the user enters characters one by one, the closest matching record wil be located.
You've got a list of 5000 items in your application, sorted by name, and you want to make it easy for the user to select the right item in a flash. Forcing the user to scroll page by page through 5000 items won't cut it: this job calls for a Quick Find approach using a binary search!
The Binarysearch function requires that your table be sorted on the field that you are searching. If it is not sorted correctly, the Binarysearch function will return undefined results.
Add an edit control to the form labeled Find (the control name in this sample is edFind). Add a short script to the form's AfterChange event that binary searches the table for the Find text, and positions the form on that matching record, like this:
dim bFound, iFoundRow
bFound = Tables().BinarySearch("Product", True, edFind, iFoundRow)
forms().currentrecord = iFoundRow
Now as the user enters characters, the form will instantly jump down to the matching record, highlighted in the list! This technique works on the PalmOS & PocketPC platforms.
If an exact match is not found, the Binarysearch function returns the record number in which a match should be found if it was in the database (the correct sort position).
Want to spice it up a little more? You can add some additional code to show the complete matched value in the Find edit control, with the characters not yet entered shown as selected, and the input cursor positioned right after the last entered char.
eg: FIND: Smith
You'll need to do a bit of extra work to keep track of how many chars were entered by the user, so you know how many to show as selected in the edFind control. Here's an updated AfterChange script with the additional code.
dim bFound, iFoundRow, iFindLen, iMatchLen
iFindLen = Len(edFind) 'how many chars entered by user
bFound = Tables().BinarySearch("Product", True, edFind, iFoundRow)
forms().currentrecord = iFoundRow
edFind = Tables().Fields("Product") 'show match in edFind
edFind.SetSelection(iFindLen, Len(edFind)) 'highlight non-entered chars and set cursor position
The trick here is that because you highlight the non-entered chars and set the cursor position after the chars that were entered, the next character that is entered overwrites the highlighted selection. This enables the iFindLen = Len(edFind) code in the AfterChange event to get the new length of entered characters, before the edFind field is updated again with the rest of the matched data.
Tip: You can change the length of time before the AfterChange event is fired (called the AfterChange delay), either on an application wide basis or on an immediate runtime basis. To change the AfterChange delay (the default delay is 2 seconds) on a project wide basis, go to the Build | Options menu and modify the OnChange Delay value. To change that value as your application is running you can use the script function SetDelayToChangeEvent.
Keywords: Find, search, incremental, quick, lookup, binarysearch, binsearch, typeahead
KB ID: 10047
Updated: 2007-02-01
Satellite Forms KnowledgeBase Online