• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 522
  • Last Modified:

Sort a Listview by Numbers and Text

Hi I'd like to be able to sort the listview columns

like for the numbers.
0
1
2
3
4
5
6
7
8
9
10
11
12

in that order. because I know sometimes 2 could be placed with 20 and thats not what I want, I want it to be natrual like above.

and for the text, the simple a to z

and how would I sort it back and forth? so the last becomes the first and the first becomes the last etc.
0
eNarc
Asked:
eNarc
  • 4
  • 3
1 Solution
 
twinsoftCommented:
Hi, take a look at the example below:

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;
0
 
twinsoftCommented:
Hi again, to sort text values instead of

  val(Item1.SubItems.Strings[0], R1, code);
  val(Item2.SubItems.Strings[0], R2, code);
  if R1 > R2 then
    result := ParamSort
  else if R1 < R2 then
    result := -ParamSort
  else
    result := 0;

use

Result := AnsiCompareText(Item1.Caption, Item2.Caption);
0
 
eNarcAuthor Commented:
E2003 Undeclared identifier: 'SizeSortOrder'
I've tried it with integer.

it moves the items around though doesn't sort them correctly

like I'm needing
4.23
403.29
403.30
403.31
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
twinsoftCommented:
Try the code below...
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
    procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
  private
    LastSortedColumn: Integer;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Ascending : Boolean;

implementation

uses Math;

{$R *.dfm}

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;

function SortByColumn(Item1, Item2: TListItem; Data: integer):
  integer; stdcall;
begin
  if Data = 0 then
    Result := AnsiCompareText(Item1.Caption, Item2.Caption)
  else
    Result := AnsiCompareText(Item1.SubItems[Data - 1],
      Item2.SubItems[Data - 1]);
  if not Ascending then
    Result := -Result;
end;

procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
begin
  if Column.Index = LastSortedColumn then
    Ascending := not Ascending
  else
    LastSortedColumn := Column.Index;
  TListView(Sender).CustomSort(@SortByColumn, Column.Index);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  ListItem: TListItem;
begin
  Randomize;
  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('%3d', [RandomRange(1, 20)]));
      end;
    end;
  end;
end;

end.

Open in new window

0
 
Geert GruwezOracle dbaCommented:
you changed your question from numbers to a other format ...
this is a completely different issue

you need to format your code with leading zeros to work correctly
adding a sort column with leading zero formatted code should do the trick
you could set the with to 0 to not show the column

for your code with nnn.mmm value

sortvalue := Format('%.6d.%.6d', [StrToInt(Copy(Code, 1, Pos('.', Code)-1)),StrToInt(Copy(Code, Pos('.', Code)+1, Length(Code)))]);

then use AnsiCompareText in CustomSort  

columnSort := 0;
Result := AnisCompareText(Item1.SubItems.Strings[columnSort],  Item2.SubItems.Strings[columnSort]);
0
 
eNarcAuthor Commented:
this is the best sorting function ever!! it works every time! on text and numbers!!
0
 
eNarcAuthor Commented:
Hi I've put another question here about this function that I'm needing the first click to be always ascending.

http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_25029529.html
0
 
eNarcAuthor Commented:
Hi Geert_Gruwez, I didn't know what to do with your code or where I should put it. twinsoft did the full monty with showing me where everything went and how it all slotted together.

though Geert_Gruwez, I'm still curious as to how ur code fits together? cos I couldn't find CustomSort, where is that?
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now