[gelöst]Stringgridspalte numerisch sortieren

Rund um die LCL und andere Komponenten
Antworten
kirchfritz
Beiträge: 248
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 4.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

[gelöst]Stringgridspalte numerisch sortieren

Beitrag von kirchfritz »

Hallo,
ich stehe irgendwie auf dem Schlauch.
Gegeben ist ein StringGrid mit drei Spalten.
Die erste Spalte enthält nur integer Werte.
die zweite und dritte Spalte nur Text
Ich möchte nun auf die Spaltenheader klicken und so die zeilen im grid sortieren.

Das funktioniert grundsätzlich korrekt, wenn ich

Code: Alles auswählen

StringGrid1.ColumnClickSorts:=true;

setze
Alle drei Spalten lassen sich sortieren.

Da die erste Spalte numerisch sortiert werden soll, habe ich eine OnCompareCells Methode geschrieben, die die erste Spalte numerisch sortieren soll, und die anderen beiden alphabetisch sortieren soll.

Code: Alles auswählen

 
 procedure TForm1.StringGrid1CompareCells(Sender: TObject; ACol, ARow, BCol,
  BRow: Integer; var Result: integer);
var
  v1, v2: Integer;
  s1, s2: string;
begin
  if ACol = 0 then  // Spalte 0 numerisch
  begin
    v1 := StrToIntDef(StringGrid1.Cells[ACol, ARow], 0);
    v2 := StrToIntDef(StringGrid1.Cells[BCol, BRow], 0);
    if v1 < v2 then Result := -1
    else if v1 > v2 then Result := 1
    else Result := 0;
  end
  else  // Alle anderen Spalten alphabetisch, ohne Berücksichtigung von Groß/Klein
  begin
    s1 := StringGrid1.Cells[ACol, ARow];
    s2 := StringGrid1.Cells[BCol, BRow];
    Result := CompareText(s1, s2);  // Case-insensitive
  end;
end; 
Irgendwas läuft schief mit dieser StringGrid1CompareCells Methode.
Jede Spalte lässt sich genau einmal sortieren. Also mehrmals auf den gleichen Spaltenheader klicken und damit rauf- bzw. runter zu sortieren, funktioniert nicht.
Screenshot 2025-12-02 182009.png
Screenshot 2025-12-02 182009.png (11.62 KiB) 132 mal betrachtet
Kann mir jemand weiterhelfen?
Demo-Programm im Anhang.

Fritz
Lazarus 4.2
Windows 11
Dateianhänge
StringGridDemo.zip
(96.29 KiB) 84-mal heruntergeladen
Zuletzt geändert von kirchfritz am Mi 3. Dez 2025, 06:53, insgesamt 1-mal geändert.

Benutzeravatar
theo
Beiträge: 11089
Registriert: Mo 11. Sep 2006, 19:01

Re: Stringgridspalte numerisch sortieren

Beitrag von theo »

Du musst halt auf die SortOrder reagieren.
Schnelles Bsp. zur Demo:

Code: Alles auswählen

procedure TForm1.StringGrid1CompareCells(Sender: TObject; ACol, ARow, BCol,
  BRow: Integer; var Result: integer);
var
  v1, v2: Integer;
  s1, s2: string;
begin
  if ACol = 0 then  // Spalte 0 numerisch
  begin
    v1 := StrToIntDef(StringGrid1.Cells[ACol, ARow], 0);
    v2 := StrToIntDef(StringGrid1.Cells[BCol, BRow], 0);
    if v1 < v2 then Result := -1
    else if v1 > v2 then Result := 1
    else Result := 0;
    if TStringGrid(Sender).SortOrder=soAscending then Result:=-Result; //<-----------------
  end
  else  // Alle anderen Spalten alphabetisch, ohne Berücksichtigung von Groß/Klein
  begin
    s1 := StringGrid1.Cells[ACol, ARow];
    s2 := StringGrid1.Cells[BCol, BRow];
    Result := CompareText(s1, s2);  // Case-insensitive
    if TStringGrid(Sender).SortOrder=soAscending then Result:=-Result; //<-----------------
  end;
end;   

kirchfritz
Beiträge: 248
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win11 (L 4.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Stringgridspalte numerisch sortieren

Beitrag von kirchfritz »

@theo:
Danke für den Hinweis.
Jetzt ist das Sortierverhalten wie gewünscht.

Sieben
Beiträge: 297
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.2.0, FPC 3.2.2
CPU-Target: i386

Re: [gelöst]Stringgridspalte numerisch sortieren

Beitrag von Sieben »

Die Unit Math stellt übrigens die vielfach überladene Funktion CompareValue zur Verfügung, die wie CompareText und CompareString -1, 0 oder 1 zurückgibt:

Code: Alles auswählen

function CompareValue ( const A, B  : Integer) : TValueRelationship; inline;
function CompareValue ( const A, B  : Int64) : TValueRelationship; inline;
function CompareValue ( const A, B  : QWord) : TValueRelationship; inline;

{$ifdef FPC_HAS_TYPE_SINGLE}
function CompareValue ( const A, B : Single; delta : Single = 0.0 ) : TValueRelationship; inline;
{$endif}
{$ifdef FPC_HAS_TYPE_DOUBLE}
function CompareValue ( const A, B : Double; delta : Double = 0.0) : TValueRelationship; inline;
{$endif}
{$ifdef FPC_HAS_TYPE_EXTENDED}
function CompareValue ( const A, B : Extended; delta : Extended = 0.0 ) : TValueRelationship; inline;
{$endif}    
Und die Unit DateUtils stellt ebenfalls Vergleichsfunktionen nach dem selben Schema zur Verfügung:

Code: Alles auswählen

Function CompareDateTime(const A, B: TDateTime): TValueRelationship;
Function CompareDate(const A, B: TDateTime): TValueRelationship;
Function CompareTime(const A, B: TDateTime): TValueRelationship;     

Antworten