Here is the stringgrid sort routine - I use the stock standard VCL
stringgrid in many places and sort it using this.
 
I usually add a row of buttons above the grid which the user can click to
sort the column it is above, and no fixed rows, so it looks similar to the
Windows Explorer sort options.
 
The onclick event for each button just calls the relevant sort:
 
eg
 
procedure Tform1.SortGridbyName;
begin
  xcSortGrid(strgrdSearch,3,4,'A',true);
  strgrdSearch.setfocus;
end;

The sorting is a Tstringlist sort, that is alpha,  but there is facility in
the routine to specify other column types eg Integer or Date.
(Internally the routine formats these into a string so the alpha sort works
- se the jkblSortGridKeyType1 etc)
 
 
procedure xcSortGrid(var
PGrid:TStringGrid;SortColumn1:Integer;SortColumn2:integer;AscDesc:char;CaseI
nSensitive:Boolean);
//NOTE there are extra sort types possible, defined in
jkblSortGridKeyType1&2
var
TmpSortList:TStringList;
olddefrow,newdefrow:integer; //keep same data row as default
oldrow,datalhs,ptr,colptr,rowptr:integer;
keydata1,keydata2,tempstr:string;
firstrow:integer; //first row after fixed rows
lAscDesc:char;
tempcells:array of array of string;
begin
  if PGrid.rowcount < 2 then exit; //nothing to sort
  TmpSortList:=TStringList.Create;
  TmpSortList.sorted:=false;
  olddefrow:=-1;
  NewDefRow:=-1;
  if PGrid.row>0 then oldDefRow:=PGrid.row;
  firstrow:=0;
  if PGrid.FixedRows >0 then
    firstrow:=PGrid.FixedRows;    //1 fixed row-> 1=1st data row
  for ptr:=firstrow to PGrid.rowcount-1 do
  begin
    //put sort col plus orig pointer into stringlist
    keydata1:=PGrid.cells[SortColumn1,ptr];
    keydata2:=PGrid.cells[SortColumn2,ptr];
    //this can be extended to specify decimal columns/Date - ideally need
more data checking though
    //if jkblSortGridKeyType1='I' then
keydata1:=format('%12d',[strtoint(keydata1)]);
    //if jkblSortGridKeyType2='I' then
keydata2:=format('%12d',[strtoint(keydata2)]);
 
    tempstr:=keydata1+keydata2;
    if CaseInsensitive=true then uppercase(tempstr);
    xcstrpad(tempstr,60);        //see below
    tempstr:=tempstr+inttostr(ptr);
    TmpSortList.Add(tempstr);
  end;
  //sort it
  TmpSortList.sorted:=true;
  //now copy original cells to tempcells dynamic array
  //this is to keep original data as grid is now being overwritten
  setlength(tempcells,PGrid.colcount,PGrid.rowcount);
  for rowptr:=firstrow to PGrid.rowcount-1 do
  begin
    for colptr:=0 to PGrid.colcount-1 do
    begin
      tempcells[colptr,rowptr]:=PGrid.cells[colptr,rowptr];
    end;
  end;
  //now write tempcells back to grid - note grid may have more than sorted
list if
  //fixed rows, so 2 counters, ptr (list) and rowptr(grid)
  lAscDesc:=upcase(AscDesc);
  if lAscDesc='A' then
  begin
    for ptr:=0 to TmpSortList.Count-1 do
    begin
      tempstr:=copy(TmpSortList[ptr],61,10);
      oldrow:=strtoint(tempstr);
      if oldrow=oldDefRow then NewDefRow:=ptr;
      //oldptr is orig row number, ptr is new row number
      rowptr:=ptr+firstrow;
      for colptr:=0 to PGrid.colcount-1 do
      begin
        PGrid.cells[colptr,rowptr]:=tempcells[colptr,oldrow];
      end;
    end;
  end
  else
  begin
    for ptr:=TmpSortList.count-1 downto 0 do
    begin
      tempstr:=copy(TmpSortList[ptr],61,10);
      oldrow:=strtoint(tempstr);
      if oldrow=oldDefRow then NewDefRow:=ptr;
      //oldptr is orig row number, ptr is new row number
      rowptr:=ptr+firstrow;
      for colptr:=0 to PGrid.colcount-1 do
      begin
        PGrid.cells[colptr,rowptr]:=tempcells[colptr,oldrow];
      end;
    end;
  end;
  TmpSortList.free;
  tempcells:=nil;
  if (OldDefRow>0) and (NewDefRow > FirstRow) then PGrid.row:=NewDefRow;
  //in case row not set, makes sure is valid...otherwise grid can sort of
scroll
  //or duplicate fixed row...
  if (PGrid.Row<firstrow) or (PGrid.Row > PGrid.RowCount-1) then
PGrid.Row:=firstrow+1;
  jkblSortGridKeyType1:='';
  jkblSortGridKeyType2:='';
end;

procedure xcstrpad(var strec:string;stlen:integer);
var
Rsize,I:integer;
begin
  Rsize:=length(strec);
  if Rsize < Stlen then
    for i:=Rsize+1 to Stlen do Strec:=Strec+' ';
end;

 
Note:
These are global variables, if wanted (remove them if not needed) to further
extend the sort column types.
I added these later to extend the possible sort types.
 
jkblSortGridKeyType1,jkblSortGridKeyType2:string;  //for more sort types

 

John

Web www.jbcl.co.nz <http://www.jbcl.co.nz/> 

 

 

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On
Behalf Of Eion McIntosh (Christchurch)
Sent: Friday, 2 February 2007 9:07 a.m.
To: NZ Borland Developers Group - Delphi List
Subject: [DUG] Stringgrids



Hi 

I havd a look, but can't see anything, but can you take 2 rows within a
TStringGrid and swap them? I have some details in a stringgrid but would
like to sort it on one of the rows after it has been filled. I can't fill it
in order to start with because the source data is coming from two different
sources.

Regards 
Eion McIntosh 
PPCS Ltd 



__________ NOD32 1.1461 (20060329) Information __________

This message was checked by NOD32 antivirus system.
http://www.eset.com


_______________________________________________
Delphi mailing list
Delphi@ns3.123.co.nz
http://ns3.123.co.nz/mailman/listinfo/delphi

Reply via email to