Click Column to Sort TwwDBGrid Data

This question is specific to Infopower 's TwwDBGrid. In infopower grid, there is no direct property that enable clicking on header column to sort data. We have to set TitleButton to True and write 2 of its event handler. Set Title 's imagelist etc....

If I want to make a component to do this, which is a best solution between:-
      1. Inherited from it and add new features to the new component.
      2. Make sorting component and link to TwwDBGrid.

I want also a feature like clicking on title column but using hidden data to sort. Multiple column sort using SHIFT key.
LVL 1
soapsiamAsked:
Who is Participating?
 
Wim ten BrinkConnect With a Mentor Self-employed developerCommented:
If it's a DBGrid, then the sort order depends on the index you've selected or the way you've sorted the records in your database. Am not familiar with the TwwDBGrid but I think they do have an event for it. (Probably called OnTitleClick) Depending on the functionality you want, you might either start your new component on the TCustomDBGrid or the TwwDBGrid but it will be a reasonable amount of work. There might be other grid components out there that might be easier to use.
0
 
BaTy_GiRlConnect With a Mentor Commented:
>There might be other grid components out there that might be easier to use.

Im agree with alex, for example you can use a TStringGrid an paste the followining code  (this source code is for
sort a column when you click someone header, it orders integers, real values, strings, you can configure descending or ascending if u want)

on Mouse Up Event


procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  c:integer;
  w:integer;
begin
  with stringgrid1 do
  if y<=rowheights[0] then
  begin
    c:=0;
    w:=colwidths[0];
    while (c<colcount) and (w<=x) do
    begin
      inc(c);
      w:=w+colwidths[c]+gridlinewidth;
    end;
    sortgrid(StringGrid1,c,1);  //the grid name, the grid the column to sort, the datatype 1-integer
 end;
end;

procedure Tform1.Sortgrid(Grid : TStringGrid; sortcol,datatype:integer);
var
   i : integer;
   tempgrid:tstringGrid;
   list:array of integer;
begin
  screen.cursor:=crhourglass;
  tempgrid:=TStringgrid.create(self);
  with tempgrid do
  begin
    rowcount:=grid.rowcount;
    colcount:=grid.colcount;
    fixedrows:=grid.fixedrows;
  end;
  with Grid do
  begin
    setlength(list,rowcount-fixedrows);
    for i:= fixedrows to rowcount-1 do
    begin
      list[i-fixedrows]:=i;
      tempgrid.rows[i].assign(grid.rows[i]);
    end;
    quicksort(Grid, list,0,rowcount-fixedrows-1,sortcol,datatype, True);  //last is for ascendig or descending
    for i:=0 to rowcount-fixedrows-1 do
    begin
      rows[i+fixedrows].assign(tempgrid.rows[list[i]])
    end;
    row:=fixedrows;
  end;
  tempgrid.free;
  setlength(list,0);
  screen.cursor:=crdefault;
end;

procedure TForm1.Quicksort(Grid:TStringGrid; var List:array of integer;
    min, max,sortcol,datatype: Integer; Ascending:boolean);
{List is a list of rownumbers in the grid being sorted}
var
    med_value : integer;
    hi, lo, i : Integer;

    function compare(val1,val2:string):integer;
    var
      int1,int2:integer;
      float1,float2:extended;
      errcode:integer;
    begin
      case datatype of
        0: result:=ANSIComparetext(val1,val2);  //if are characters
        1: begin
             int1:=strtointdef(val1,0);         //if are integers
             int2:=strtointdef(val2,0);
             if (int1>int2) then result:=1
             else if int1<int2 then result:=-1
             else result:=0;
           end;

        2: begin                                     //if are floats
             val(val1,float1,errcode);
             if errcode<>0 then float1:=0;
             val(val2,float2,errcode);
             if errcode<>0 then float2:=0;
             if float1>float2 then result:=1
             else if float1<float2 then result:=-1
             else result:=0;
           end;
         else result:=0;
      end;
   end; {compare}

begin
    {If the list has <= 1 element, it's sorted}
    if (min >= max) then Exit;
    {Pick a dividing item randomly}
    i := min + Trunc(Random(max - min + 1));
    med_value := List[i];
    List[i] := List[min]; { Swap it to the front so we can find it easily}
    {Move the items smaller than this into the left
     half of the list. Move the others into the right}
    lo := min;
    hi := max;
    while (True) do
    begin
        // Look down from hi for a value < med_value (for ascending)
        while
           (ascending and (compare(Grid.cells[sortcol,List[hi]]
                             ,grid.cells[sortcol,med_value])>=0))
           or ((not ascending) and (compare(Grid.cells[sortcol,List[hi]]
                             ,grid.cells[sortcol,med_value])<=0))
        do
        begin
            dec(hi);
            if (hi <= lo) then Break;
        end;
        if (hi <= lo) then
        begin {We're done separating the items}
          List[lo] := med_value;
          Break;
        end;

        // Swap the lo and hi values.
        List[lo] := List[hi];
        inc(lo); {Look up from lo for a value >= med_value}

        while
          (ascending and (Compare(grid.cells[sortcol,List[lo]],
                 grid.cells[sortcol,med_value])<0))
          or ((not ascending) and (Compare(grid.cells[sortcol,List[lo]],
                 grid.cells[sortcol,med_value])>0))
        do
        begin
            inc(lo);
            if (lo >= hi) then break;
        end;
        if (lo >= hi) then
        begin  {We're done separating the items}
          lo := hi;
          List[hi] := med_value;
          break;
        end;
        List[hi] := List[lo];
    end;
    {Sort the two sublists}
    Quicksort(Grid,List, min, lo - 1,sortcol,datatype, ascending);
    Quicksort(Grid,List, lo + 1, max,sortcol,datatype, ascending);
end;


Just paste this code on a form and put a TString Grid, fill values of course and you´ll see how the rows sorts
Greetings =)
   B@ty
0
 
Wim ten BrinkSelf-employed developerCommented:
B@aty, the TwwDBGrid is a data-aware component and could be linked to millions of records. You're not going to read it all in just to do simple sorts. This seems a bit more complicated in my opinion. Sorting shouldn't be a problem either since basically this means just selecting a different index. If ADO is used then you can even specify to the ADO query or table to sort it on whatever column by setting the "Sort" property. (Which is why I love ADO so much.) And yes, you can sort on multiple columns easily this way.
The only problem here is responding to a click on the title... I just don't know how to capture that.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
bpanaConnect With a Mentor Commented:
I didn't work with TwwDBGrid, but it should be the same as any DataGrid. It should have an OnTitleClick event.

Here's a simple example to implement the sort in response to the title click.
http://delphi.about.com/library/weekly/aa042203a.htm
0
 
soapsiamAuthor Commented:
I can write event to sort when user click on title button but I have to set many things.
   Set Title image list
  Write code for OnTitleButtonClick
  Write cod for OnCalcTitleAttributes

I have to do this for every form that have a grid. I want to write component that speed up the solution.

//procedure TfrmLineGrantList.wwDBGrid2TitleButtonClick(Sender : TObject; AFieldName:String);
procedure OnTitleButtonClick(Sender : TObject; AFieldName:String);
var SortText : String;
    DataSet : TCustomADODataSet;
begin
      if not (Sender is TwwDBGrid) then exit;
      if not (Sender as TwwDBGrid).DataSource.DataSet.Active then exit;
      DataSet := ((Sender as TwwDBGrid).DataSource.DataSet) as TCustomADODataSet);
      SortText :=DataSet.Sort;
      if Pos(AFieldName + ' ASC',SortText)>0 then
             SortText := AFieldName + ' DESC'
      else
             SortText := AFieldName + ' ASC';
      DataSet.Sort
end;

TfrmLineGrantList.wwDBGrid2TitleButtonClick := OnTitleButtonClick;

Above is one of procedure current used for simple sorting (single column).
0
 
bpanaConnect With a Mentor Commented:
then, I would choose
1. Inherited from it and add new features to the new component.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.