Solved

# Sort a Listview by Numbers and Text

Posted on 2010-01-06
428 Views
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
Question by:eNarc

LVL 7

Expert Comment

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

LVL 7

Expert Comment

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

LVL 5

Author Comment

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

LVL 7

Accepted Solution

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;
begin
Caption := 'Column 1';
width := 90;
end;
begin
Caption := 'Column 2';
width := 90;
Alignment := taRightJustify;
end;
for i := 1 to 20 do
begin
with ListItem do
begin
caption := format('FileName %2d', [i]);
end;
end;
end;
end;

end.
``````
0

LVL 36

Expert Comment

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

LVL 5

Author Closing Comment

this is the best sorting function ever!! it works every time! on text and numbers!!
0

LVL 5

Author Comment

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

LVL 5

Author Comment

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

### Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…