Position in a TStringGrid based on keyboard ...

In my Delphi application, on a form, I have a TStringGrid containing a list of names.
Names are located in column 1 (column 0 is a reference number). Names are sorted.
I want to have row N selected in the grid, when I click on a letter of the keyboard (A to Z), that row being the first row whose column 1 starts with that letter...
Thanks
LVL 1
LeTayAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jimyXCommented:
Use StringGrid's OnKeyPress event to test for the key value against the first char of the required column:
procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
const
  c= 1;   // The target column
var
  i: integer;
begin
  i:= 0;  //set it to one to exclude highlighting the first row if it was the header
  while i <= StringGrid1.RowCount-1 do  // loop through the rows
    begin
      if UpperCase(StringGrid1.Cells[c, i][1]) = UpperCase(Key) then  // remove "UpperCase()" if case sensitivity is desired
        begin
          StringGrid1.Row:= i;  // There is a match, highlight this row and exit
          break;
        end;
      inc(i);
    end;
end;

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Geert GOracle dbaCommented:
when you "click" on a letter of the keyboard
i've never used the mouse in that context ... seems rather clumsy to me

in startrek there was a very advanced (and hilarious at the time) scenario when scotty talked into the mouse

is this an excercise ?
i expect this is not a request from a customer ... unless they wanted to play a prank on you ?
Geert GOracle dbaCommented:
jimyx ...
all that code ?
you could have done that in 1 line ...

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  stringgrid1.Row := Ord(UpperCase(Key)[1])-64;
end;
C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

LeTayAuthor Commented:
Hello Geert,
Your code just put the selection on a row which number is the order of the letter in the alphabet
For example, pressing E sets the selection on the 5th row
I do not need that
I need to set the selection on the first row where the cell's content starts with the letter pressed !
LeTayAuthor Commented:
Okay jimyX,
Replace click by press
LeTayAuthor Commented:
Many thanks for the solution
Between us, I prefer to write I := I +1; instead of inc(I);
Same performance, better reading ...
Have a good week-end
LeTayAuthor Commented:
There is still a small problem : some keypress do not start the keypress event, like the S key !
Geert GOracle dbaCommented:
you want a search in your grid
and as you type it selects the first match ?
LeTayAuthor Commented:
Yes
The code proposed by jimyX is fine except for some keystroke like S where nothing happens
Geert GOracle dbaCommented:
if you want to search your whole grid and select the first match...
then you need to buffer input or use an edit field
when the edit field ... changes start a timer for 1 sec
reset the timer if you get a keystroke within that time > this leaves people the possibility to type a bit before the search starts

for the timer, run through all the cells ...
for c := 1 to grid.columns do
  for r := 1 to grid.rows do
    if SameText(SearchEdit.Text, Copy(grid.Cells[c, r], 1, Length(SearchEdit.Text)) then
    begin
      // found a match
      // and then select the matching pattern in the cell with below link
http://www.delphigroups.info/2/09/159168.html
jimyXCommented:
All alphabet works fine here, I tested that 'S', no issues at all.
Did you remove the "UpperCase()"? KeyPress is case sensitive, i.e 's' <> 'S'.
Or, probably you have trailing space, trim will solve it, if there is.

procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
const
  c= 1;          // The target column
var
  i: integer;
  s: string;     // cell content
begin
  if not (UpCase(Key) in ['A'..'Z']) then Exit;  // do not loop any non-alpha keys

  i:= 0;         //set it to one to exclude highlighting the first row if it was the header
  while i <= StringGrid1.RowCount-1 do  // loop through the rows
    begin
      s:= Trim(StringGrid1.Cells[c, i]);
      if (s <> '') and (UpperCase(s[1]) = UpperCase(Key)) then  // remove "UpperCase()" if case sensitivity is desired
        begin
          StringGrid1.Row:= i;  // There is a match, highlight this row and exit
          break;
        end;
      i:= i + 1;  // will not be any issue ;)
    end;
end;

Open in new window

LeTayAuthor Commented:
I have two buttons with caption starting with &R and &S !
The alt button is not taken into account in the keypress, how can I verify that the alt is not pressed ?
jimyXCommented:
"Alt" can not be detected in KeyPress. You need to use KeyUp or KeyDown events and test for "ssAlt" in "ShiftState":
procedure TForm1.StringGrid1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ssAlt in Shift then
    begin
      //Alt is pressed
    end;
end;

Open in new window

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.