Fatman121898
asked on
StringGrid sorting
Does anyone knows some easy way to sort StringGrid Rows on a given Column's content?
Jo.
Jo.
The sample
var L : TStringList;
begin
L := TStringList.Create;
L.Sorted:=true;
L.Assign(StringGrid1.Cols[ 2]);
StringGrid1.Cols[2].Assign (L);
L.Free;
end;
---------
Igor
var L : TStringList;
begin
L := TStringList.Create;
L.Sorted:=true;
L.Assign(StringGrid1.Cols[
StringGrid1.Cols[2].Assign
L.Free;
end;
---------
Igor
ASKER
Hi Igor,
it's nice to hear you again.
What I'm trying is to sort whole stringgrid, not items in its rows separately.
That means to swap rows in such way that the values in key column are sorted in accendant (descendant) order.
Jo.
it's nice to hear you again.
What I'm trying is to sort whole stringgrid, not items in its rows separately.
That means to swap rows in such way that the values in key column are sorted in accendant (descendant) order.
Jo.
ASKER
Hi Igor,
it's nice to hear you again.
What I'm trying is to sort whole stringgrid, not items in its rows separately.
That means to swap rows in such way that the values in key column are sorted in accendant (descendant) order.
Jo.
it's nice to hear you again.
What I'm trying is to sort whole stringgrid, not items in its rows separately.
That means to swap rows in such way that the values in key column are sorted in accendant (descendant) order.
Jo.
Hi,
bit more complex I think: you can copy the column you want to sort on to the first column. Then put all rows in a stringgrid. Sort it, remove the first column and then place it back (got idea from website).
have it working in programm, I also took those up-down arrows from Outlook and place them 'on' the grid when it's sorted.
getsort does the sorting, setImage switches between the images and in the mousedown event a leftclick in the header is detected. OmgekeerdResult is dutch for reversed-result.
some vars that I set on create:
//init globals
omgekeerdResult := false;
sortedOnColumn := 0; //invisible in UMS, so safe to set first
globalWaitDblClick := false;
globalCol := 0;
globalRow := 0;
//init form
imUp.visible := false;
imDown.visible := false;
imUp.parent := grdResult;
imDown.parent := grdResult;
//vul grid a.d.h.v. sql
grdResult.FixedRows := 1;
grdResult.TopRow := 2;
with some copy-pasting you must be able to use my post, I expect...:-)
Floris.
procedure TResultaten.GetSort(var GenStrGrid : TStringGrid; ThatCol : Integer;omgekeerdResult : boolean);
{ Description : sort stringlist, by copying to stringlist
(column that has to be sorted is move to beginning line, sort
is done automatically and column is placed back)
Pre : rowcount has to be set correctly!
Post : genstrgrid sorted on Column:ThatCol
Input : -
Returns : -
Creator : Floris
Date : 5-2}
const
TheSeparator = '@'; // Define the Separator
var
CountItem, I, J, K, ThePosition : Integer;
MyList : TStringList;
MyString, TempString : String;
begin
CountItem := GenStrGrid.RowCount; // Give the number of rows in the StringGrid
MyList := TStringList.Create;//Creat e the List
MyList.Sorted := False;
try
begin
for I := 1 to (CountItem - 1) do
begin
MyList.Add(GenStrGrid.Rows [I].String s[ThatCol] + TheSeparator + GenStrGrid.Rows[I].Text);
end;
Mylist.Sort;//Sort the List
for K := 1 to Mylist.Count do
begin
MyString := MyList.Strings[(K - 1)];//Take the String of the line (K – 1)
ThePosition := Pos(TheSeparator, MyString);//Find the position of the Separator in the String
TempString := '';
//element waarop gesorteerd is kan nu verwijderd worden van eerste positie
TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
MyList.Strings[(K - 1)] := '';
MyList.Strings[(K - 1)] := TempString;
end;
if not omgekeerdResult then
begin
for J := 1 to (CountItem - 1) do
GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];//Refill the StringGrid
end
else
begin
for J := 1 to (CountItem - 1) do
GenStrGrid.Rows[J].Text := MyList.Strings[((CountItem -2)-(J - 1))];//Refill the StringGrid
end;
setImage(thatCol,omgekeerd Result); //plaats Outlookalike bitmap in columnheader.
end;
finally
MyList.Free;//Free the List
end;
end;
procedure TResultaten.setImage(thatC ol: integer;down: boolean);
const
distance = 20;
var
MyLeft,y,z : integer;
begin
y := grdResult.LeftCol;
//loop column with till end thatCol
myLeft := 0;
for z := 0 to thatCol do
myLeft := myLeft +grdResult.ColWidths[z];
if not(down) then
begin
imUp.Left := (y+myLeft) - distance;
imUp.Top := 1;
imDown.visible := false;
imUp.visible := true;
end
else
begin
imDown.Left := (y+myLeft) - distance;
imDown.Top := 1;
imUp.visible := false;
imDown.visible := true;
end
end;
procedure TResultaten.grdResultMouse Down(Sende r: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
{ Description : right and leftmouse handling, sort if column click.
Pre :
Post :
Input : -
Returns : -
Creator : Floris
Date : 3-2, update 4-2}
begin
if not (globalWaitDblClick) then //dubbel click was -> overslaan
begin
grdResult.MouseToCell(x,y, globalCol, globalRow) ;
//right mouseclick
if Button = mbright then
begin
if activeResultSet = false then //no activerestul, no pop-up at all.
grdResult.popupMenu := nil
else
begin
// grdResult.MouseToCell(x,y, Col,Row); //HALELUJA! (wist niet dat deze functie bestond)
if globalRow = -1 then
exit
else if globalRow = 0 then
grdResult.popupMenu := popupTop //show popup for upper columns
else
begin
grdResult.row := globalrow; //show normal popup and set current row here
grdResult.popupMenu := popupGrid;
end;
end;
end
//left mouseclick
else if (not (activeResultSet = false)) and (ssLeft in Shift) then
begin
// grdResult.MouseToCell(x,y, Col,Row); //get row
if globalRow = -1 then
exit
else if globalrow = 0 then
begin
screen.cursor := crHourGlass;
//bepaal of er up of down gesort wordt.
if (globalcol = sortedOnColumn) then
begin
if not omgekeerdResult then //switch after third clicks on same column
omgekeerdResult := true
else
omgekeerdResult := false;
end
else
omgekeerdResult := false;
GetSort(grdResult,globalco l, omgekeerdResult);
sortedOnColumn := globalcol;
screen.cursor := crDefault;
end;
end;
end
else
globalWaitDblClick := false;
//grdResult.refresh; //how to refresh that move column line?
//grdResult.repaint;
end;
bit more complex I think: you can copy the column you want to sort on to the first column. Then put all rows in a stringgrid. Sort it, remove the first column and then place it back (got idea from website).
have it working in programm, I also took those up-down arrows from Outlook and place them 'on' the grid when it's sorted.
getsort does the sorting, setImage switches between the images and in the mousedown event a leftclick in the header is detected. OmgekeerdResult is dutch for reversed-result.
some vars that I set on create:
//init globals
omgekeerdResult := false;
sortedOnColumn := 0; //invisible in UMS, so safe to set first
globalWaitDblClick := false;
globalCol := 0;
globalRow := 0;
//init form
imUp.visible := false;
imDown.visible := false;
imUp.parent := grdResult;
imDown.parent := grdResult;
//vul grid a.d.h.v. sql
grdResult.FixedRows := 1;
grdResult.TopRow := 2;
with some copy-pasting you must be able to use my post, I expect...:-)
Floris.
procedure TResultaten.GetSort(var GenStrGrid : TStringGrid; ThatCol : Integer;omgekeerdResult : boolean);
{ Description : sort stringlist, by copying to stringlist
(column that has to be sorted is move to beginning line, sort
is done automatically and column is placed back)
Pre : rowcount has to be set correctly!
Post : genstrgrid sorted on Column:ThatCol
Input : -
Returns : -
Creator : Floris
Date : 5-2}
const
TheSeparator = '@'; // Define the Separator
var
CountItem, I, J, K, ThePosition : Integer;
MyList : TStringList;
MyString, TempString : String;
begin
CountItem := GenStrGrid.RowCount; // Give the number of rows in the StringGrid
MyList := TStringList.Create;//Creat
MyList.Sorted := False;
try
begin
for I := 1 to (CountItem - 1) do
begin
MyList.Add(GenStrGrid.Rows
end;
Mylist.Sort;//Sort the List
for K := 1 to Mylist.Count do
begin
MyString := MyList.Strings[(K - 1)];//Take the String of the line (K – 1)
ThePosition := Pos(TheSeparator, MyString);//Find the position of the Separator in the String
TempString := '';
//element waarop gesorteerd is kan nu verwijderd worden van eerste positie
TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
MyList.Strings[(K - 1)] := '';
MyList.Strings[(K - 1)] := TempString;
end;
if not omgekeerdResult then
begin
for J := 1 to (CountItem - 1) do
GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];//Refill the StringGrid
end
else
begin
for J := 1 to (CountItem - 1) do
GenStrGrid.Rows[J].Text := MyList.Strings[((CountItem
end;
setImage(thatCol,omgekeerd
end;
finally
MyList.Free;//Free the List
end;
end;
procedure TResultaten.setImage(thatC
const
distance = 20;
var
MyLeft,y,z : integer;
begin
y := grdResult.LeftCol;
//loop column with till end thatCol
myLeft := 0;
for z := 0 to thatCol do
myLeft := myLeft +grdResult.ColWidths[z];
if not(down) then
begin
imUp.Left := (y+myLeft) - distance;
imUp.Top := 1;
imDown.visible := false;
imUp.visible := true;
end
else
begin
imDown.Left := (y+myLeft) - distance;
imDown.Top := 1;
imUp.visible := false;
imDown.visible := true;
end
end;
procedure TResultaten.grdResultMouse
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
{ Description : right and leftmouse handling, sort if column click.
Pre :
Post :
Input : -
Returns : -
Creator : Floris
Date : 3-2, update 4-2}
begin
if not (globalWaitDblClick) then //dubbel click was -> overslaan
begin
grdResult.MouseToCell(x,y,
//right mouseclick
if Button = mbright then
begin
if activeResultSet = false then //no activerestul, no pop-up at all.
grdResult.popupMenu := nil
else
begin
// grdResult.MouseToCell(x,y,
if globalRow = -1 then
exit
else if globalRow = 0 then
grdResult.popupMenu := popupTop //show popup for upper columns
else
begin
grdResult.row := globalrow; //show normal popup and set current row here
grdResult.popupMenu := popupGrid;
end;
end;
end
//left mouseclick
else if (not (activeResultSet = false)) and (ssLeft in Shift) then
begin
// grdResult.MouseToCell(x,y,
if globalRow = -1 then
exit
else if globalrow = 0 then
begin
screen.cursor := crHourGlass;
//bepaal of er up of down gesort wordt.
if (globalcol = sortedOnColumn) then
begin
if not omgekeerdResult then //switch after third clicks on same column
omgekeerdResult := true
else
omgekeerdResult := false;
end
else
omgekeerdResult := false;
GetSort(grdResult,globalco
sortedOnColumn := globalcol;
screen.cursor := crDefault;
end;
end;
end
else
globalWaitDblClick := false;
//grdResult.refresh; //how to refresh that move column line?
//grdResult.repaint;
end;
Hi Jo,
Hi floris (it's a comment!;)
Yes I'm wrong. Of course you need to sort whole stringgrid;) Just a moment, I have simply idea. TStringList can store not only strings but some associated data too. You may put as data number of original position in ROW. After sorting, it's possible to know where is new position. Just a moment, I will check it........
Igor.
Hi floris (it's a comment!;)
Yes I'm wrong. Of course you need to sort whole stringgrid;) Just a moment, I have simply idea. TStringList can store not only strings but some associated data too. You may put as data number of original position in ROW. After sorting, it's possible to know where is new position. Just a moment, I will check it........
Igor.
ASKER
Hi Floris,
This is not what I meant 'easy' ;-).
Anyway, I'll test it for a while, and be back soon.
Jo.
This is not what I meant 'easy' ;-).
Anyway, I'll test it for a while, and be back soon.
Jo.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Igor, that is what I needed.
You got the points.
Floris, thank you too.
Jo.
You got the points.
Floris, thank you too.
Jo.
Cheers,
Igor.
PS: do not forget TStringList.Sorted:=true;