1

Delphi used: 2007

Hello,

I have a Listview with several columns. I want to sort one specific column. Items can be numbers or letters.

Example

Basically, the order should be the following: 1->99, A->Z, AA->ZZ, AAA->ZZZ. I found some CustomSort code on the Internet and I modified it. Here's the result (well, the code is bigger, but I'm only putting what's important):

function CustomSortProc(Item1, Item2: TListItem; SortColumn: Integer): Integer; stdcall;
var
 s1, s2: string;
 i1, i2: Integer;
 r1, r2: Boolean;

 function IsValidNumber(AString : string; var AInteger : Integer): Boolean;
 var
  Code: Integer;
 begin
  Val(AString, AInteger, Code);
  Result := (Code = 0);
 end;

 function CompareNumeric(AInt1, AInt2: Integer): Integer;
 begin
  if AInt1 > AInt2 then Result := 1 else
  if AInt1 = AInt2 then Result := 0 else Result := -1;
 end;

begin
 Result := 0;

 if (Item1 = nil) or (Item2 = nil) then Exit;

 r1 := IsValidNumber(s1, i1);
 r2 := IsValidNumber(s2, i2);
 Result := ord(r1 or r2);
 if Result <> 0 then Result := CompareNumeric(i1, i2) else
 begin
  Result := Length(s1) - Length(s2);
  if Result = 0 then Result := lstrcmp(PChar(s1), PChar(s2));
 end;
end;

And here's how the column is sorted:

Example

In other words, the letters and the numbers are correctly sorted. However, I am unable to put all the numbers before the letters. I'm sure it's something simple, but I cannot for the life of me figure it out.

Thank you very much.

Community
  • 1
  • 1
Pascal Bergeron
  • 761
  • 3
  • 12
  • 27
  • Too localized. Please debug your own code. Since it's obviously not arranging numbers and letters properly, pretend it's comparing one of each. Walk through the code with a pencil and paper and see where your function goes wrong. Consider using the debugger. – Rob Kennedy Mar 10 '13 at 03:08
  • possible duplicate of [custom sort method in Delphi to sort list of strings](http://stackoverflow.com/questions/15257746/custom-sort-method-in-delphi-to-sort-list-of-strings) – jachguate Mar 10 '13 at 06:12
  • The only thing you need to fix is Result := ord(r1 or r2); which can never evaluate to -1 – David Heffernan Mar 10 '13 at 07:59
  • Never seen that value in that sort of clever myself. I've been doing Delphi since version 1 and I had to think about what it was doing versus your intent. Spell it out in the code, compiler will deal with it being Verbose. – Tony Hopkinson Mar 10 '13 at 14:04

1 Answers1

1

If one is a string and one is an int, the value of the string from val is 0 so it will before.

if (Item1 = nil) or (Item2 = nil) then Exit;

 r1 := IsValidNumber(s1, i1);
 r2 := IsValidNumber(s2, i2);
 if (r1 and r2) then
   Result := CompareNumeric(i1, i2)
 else
   if r1 then 
     result := -1
   else
    if r2 then
      result := 1
    else
    begin
     Result := Length(s1) - Length(s2);
     if Result = 0 then 
       Result := lstrcmp(PChar(s1), PChar(s2));
    end;
end;

I think, no Dephi on the machine to check.

Tony Hopkinson
  • 20,172
  • 3
  • 31
  • 39