Mirror

Sort a TListView by numerical values (Views: 100)


Problem/Question/Abstract:

My TListView is populated with file names in the first column and their sizes in the second column. To sort the data in the columns I use certain code. Now I would like the second column sorted not by Ansi values, where 822 is greater than 1000, but by numerical values. The second column must behave like the first, which means that the first click sorts the values ascending and the next click sorts them descending. Can anyone help me?

Answer:

Start a new project, and drop a ListView on the form. Replace all of the unit's code with code listed below. Set the ListView1's OnColumnClick Event to point to the ListView1ColumnClick in the code and link the form's OnCreate to the FormCreate. Run the program. Every time you click on the "Column 2" header, the column will sort in the opposite order. Note, if you click too quick, it'll be considered a double click, and it's not set up for that. Also, if you click on Column 1's header, it'll sort alphabetically.

unit Unit1;

{$O-}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls,
    StdCtrls;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
    procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
  private
    NameSortOrder, SizeSortOrder: integer;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  ListItem: TListItem;
begin
  Randomize;
  NameSortOrder := -1;
  SizeSortOrder := -1;
  with ListView1 do
  begin
    Align := alClient;
    ViewStyle := vsReport;
    with Columns.Add do
    begin
      Caption := 'Column 1';
      width := 90;
    end;
    with Columns.Add do
    begin
      Caption := 'Column 2';
      width := 90;
      Alignment := taRightJustify;
    end;
    for i := 1 to 20 do
    begin
      ListItem := ListView1.Items.Add;
      with ListItem do
      begin
        caption := format('FileName %2d', [i]);
        SubItems.add(Format('%3.6n', [random]));
      end;
    end;
  end;
end;

function SizeCustomSort(Item1, Item2: TListItem; ParamSort: integer): integer;
  stdcall;
var
  R1, R2: real;
  code: Integer;
begin
  val(Item1.SubItems.Strings[0], R1, code); {ignore code}
  val(Item2.SubItems.Strings[0], R2, code);
  if R1 > R2 then
    result := ParamSort
  else if R1 < R2 then
    result := -ParamSort
  else
    result := 0;
end;

procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
begin
  if Column.Index = 1 then
  begin
    ListView1.CustomSort(@SizeCustomSort, SizeSortOrder);
    SizeSortOrder := SizeSortOrder * -1; {reverse the next sort order}
  end
  else
  begin
    ListView1.SortType := stText;
    ListView1.AlphaSort;
  end;
end;

end.

<< Back to main page