Re: Searching in a ListBox

Posted by webmaster Guido on July 22, 2008

In Reply to Searching in a ListBox posted by RussCAp12602 on July 17, 2008

: I have an application that shows a series of input Edit fields, which are combined to form a retrieval key. These consist of LastName, FirstName and MiddleInitial. The key is formed as "LastName, FirstName MiddleInitial" as the fields are entered.

: There is also a ListBox which displays the retrieval keys from a file. What I want to do is search in the ListBox for the retrieval key as it is entered, and highlight the best match so far. The file is maintained in key order.

Let's analyse what the routine should do:

1. From the text of the 3 edit boxes, construct a search-string.
2. Remove the current highlighting from the listbox.
3. Compare the search-string with every item of the listbox. To make the comparison case-insensitive, convert everything to uppercase.
When a match is found, highlight that item and stop searching.
4. Optionally, at the end display a message indicating if a match was found or not.

The trick lies in the smart construction of your search-string, so that also partial matches are found.
For example: suppose that the first listbox item starting with an 'S' is Smith, John T
Then you expect to find this by entering Smith in in Edit1, John in Edit2 and T in Edit3. The search-string should be 'SMITH, JOHN T'
But when you leave Edit3 empty, the search-string should be 'SMITH, JOHN' i.e. without a space after 'JOHN'.
And when you also leave Edit2 empty, you don't want a comma after the text of Edit1. For example, when you enter 'Smi' in Edit1 and nothing in the other two boxes, you expect searching for 'SMI' but not for 'SMI,' because then no item starting with 'Smith' would be found.

A source code example:

procedure TForm1.btnSearchClick(Sender: TObject);
  i: integer;
  SearchString, Item: string;
  // 1. Construct search-string
  SearchString := UpperCase(Trim(Edit1.Text));
  if Length(Trim(Edit2.Text)) > 0 then begin
    SearchString := SearchString + ', ' + UpperCase(Trim(Edit2.Text));
    if Length(Trim(Edit3.Text)) > 0 then
      SearchString := SearchString + ' ' + UpperCase(Trim(Edit3.Text));

  // 2. Remove highlighting
  ListBox1.ItemIndex := -1; //

  // 3. Search in all ListBox items
  for i := 0 to ListBox1.Items.Count - 1 do begin
    Item := UpperCase(ListBox1.Items[i]);
    // Check if Item starts with SearchString
    if Pos(SearchString, Item) = 1 then begin
      ListBox1.ItemIndex := i;  // highlight item
      ListBox1.SetFocus;        // (optional)
      break;                    // found, so stop searching

  // 4. Optional: show a message with the result
  if ListBox1.ItemIndex >= 0 then
    Label1.Caption := 'Match found'
    Label1.Caption := 'No match';

Related articles


Follow Ups