Stringgrid sortieren

Für Fragen von Einsteigern und Programmieranfängern...
Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Stringgrid sortieren

Beitrag von Adenos »

gibt es eine einfache Möglichkeit, die Reihen im Stringgrid nach dem Inhalt einer Spalte auf- bzw. absteigend zu sortieren? Komplizierte Lösungen sind mir schon eingefallen, wie z.B. das Exportieren des Inhalts in eine Excel-Datei, dort sortieren und dann wieder importieren.

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

Re: Stringgrid sortieren

Beitrag von theo »

Code: Alles auswählen

  StringGrid1.SortColRow(true,1);     
Schaust du nie in Code Insight rein? Dort sieht man das sofort und kann es ja mal ausprobieren um zu sehen, was es tut.

laz_sg_sort.png
laz_sg_sort.png (35.33 KiB) 1226 mal betrachtet

Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Re: Stringgrid sortieren

Beitrag von Adenos »

ok, vielen Dank. Dass es so einfach geht, hätte ich nicht gedacht. In Zukunft werde ich mir die Möglichkeiten genauer anschauen.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringgrid sortieren

Beitrag von Winni »

Hi!

Du kannst sogar numerisch sortieren.

1. StringGrid1.SortColRow(true,1);
So wird nach der ersten Spalte neben den "Fixed" sortiert.

2. Numerisch sortieren:

Dafür gibt es das event OnCompareCells. Dort hängt man diese Procedure ein:

Code: Alles auswählen

procedure TForm1.GridCompareCells(Sender: TObject; ACol, ARow, BCol, BRow: Integer; var Result: integer);
begin
  result := StrToIntDef(Grid.Cells[ACol,ARow],0)       -StrToIntDef (Grid.Cells[BCol,BRow],0);
  if StringGrid1.SortOrder = soDescending then
    result := -result;
end;

Winni

Sieben
Beiträge: 202
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: Stringgrid sortieren

Beitrag von Sieben »

...und dann kann man auch noch einfach ColumnClickSorts im ObjektInspektor auf True setzen...

Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Re: Stringgrid sortieren

Beitrag von Adenos »

es tut mir leid, wenn ich jetzt nochmal frage, aber bei mir wird die Spalte nicht richtig sortiert. Wenn ich die Sortierreihenfolge umkehre, steht die Spalte auf dem Kopf, aber genauso falsch sortiert wie vorher. In der Spalte stehen Werte, wie z.B. "107,45 USD", in der nächsten Zeile steht z.B. "508.386,25 USD" und dann "311,60 US". Die Lazarushilfe hat für mich keinen Wert, weil ich englisch nicht verstehe. Ich kann mir das nicht erklären. Die Reihen werden zwar anders angeordnet, aber nicht nach der Größe der Zahlen. ColumnClickSorts steht auf true und ob ich die Sortorder auf soDescending oder soAscending stelle, bewirkt nur eine Umkehr der falschen Reihenfolge. Was könnte ich wohl falsch machen?

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

Re: Stringgrid sortieren

Beitrag von theo »

Adenos hat geschrieben:
Mi 19. Jan 2022, 16:48
Was könnte ich wohl falsch machen?
Eigentlich hat dir Winni schon die Antwort gegeben.
Standardmässig wird nach Alphabet und nicht nach Zahlen sortiert.
Du musst also für deine gemischten Werte (Fliesskommazahl plus Text) deine eigene Vergleichsprozedur (was ist grösser/kleiner) basteln in OnCompareCells

Alphabetisch kommt halt immer "1" vor "2" und "3"
Also 1000 kommt vor 20 und 30000.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringgrid sortieren

Beitrag von Winni »

Hallo!

Also mal Grundsätzliches zur Arbeit mit Zahlen und Tabellen in Pascal:

* Der Dezimal-Separator ist der Punkt und nicht das deutsche Komma
* Tausender-Trenner sind nicht erlaubt, wenn man mit den Zahlen rechnen - also auch vergleichen - möchte.
* Buchstaben wie die Währungsangaben haben in dem Feld schon mal garnix zu suchen, sondern gehören in die nächste Spalte.

Aber um dich nicht völlig zu enttäuschen hab ich ne Routine geschrieben, die Deinen Verhau auf das richtige Fließkomma-Format bringt und dann die Zellen vergleicht.

Code: Alles auswählen

procedure TForm1.StringGrid1CompareCells(Sender: TObject; ACol, ARow, BCol,
		BRow: Integer; var Result: integer);

	   function correctFloat (s : string): string;
	   var i : integer;
	   begin
	   result := '';
	   for i := 1 to length(s) do
	      if s[i] in ['0'..'9'] then result := result + s[i] else
	        if s[i]=',' then result := result +'.';
	    end; // correctFloat

begin
  result := round(
      StrToFloatDef(correctFloat(StringGrid1.Cells[ACol,ARow]),0) -
        StrToFloatDef(correctFloat(StringGrid1.Cells[BCol,BRow]),0)
            );
  if StringGrid1.SortOrder = soDescending then
    result := -result;
end;


Grüße
Winni

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringgrid sortieren

Beitrag von wp_xyz »

Winni hat geschrieben:
Mi 19. Jan 2022, 18:02
* Der Dezimal-Separator ist der Punkt und nicht das deutsche Komma
* Tausender-Trenner sind nicht erlaubt, wenn man mit den Zahlen rechnen - also auch vergleichen - möchte.
* Buchstaben wie die Währungsangaben haben in dem Feld schon mal garnix zu suchen, sondern gehören in die nächste Spalte.
In den Zellen stehen Strings, die z.B. ein Datenbank-Export da reingeschrieben hat, und da ist alles erlaubt und möglich. Wenn der Programmierer damit rechnen will (z.B. sortieren), muss er sich die Zellen ansehen und gegebenenfalls so umformatieren, dass man damit rechnen kann. So wie du es in deinem Beispiel getan hast (das allerdings den Tausender-Trenner ignoriert).

Aber zu fordern, dass in einem Zahlenstring ein Dezimalpunkt verwendet werden muss, kein Komma, und dass kein Tausendertrenner und kein Währungssymbol vorhanden sein darf, ist Unsinn.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringgrid sortieren

Beitrag von Winni »

wp_xyz hat geschrieben:
Mi 19. Jan 2022, 20:03
So wie du es in deinem Beispiel getan hast (das allerdings den Tausender-Trenner ignoriert).
Natürlich ignoriere ich die Tausender-Trenner. Sonst gibt es eine Exception in StrToFloatDef.
Aber zu fordern, dass in einem Zahlenstring ein Dezimalpunkt verwendet werden muss, kein Komma, und dass kein Tausendertrenner und kein Währungssymbol vorhanden sein darf, ist Unsinn.
Sehr hochqualifizierte Aussage: "Unsinn"

Winni

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringgrid sortieren

Beitrag von wp_xyz »

Winni hat geschrieben:
Mi 19. Jan 2022, 20:34
wp_xyz hat geschrieben:
Mi 19. Jan 2022, 20:03
So wie du es in deinem Beispiel getan hast (das allerdings den Tausender-Trenner ignoriert).
Natürlich ignoriere ich die Tausender-Trenner. Sonst gibt es eine Exception in StrToFloatDef.
Sorry - da habe ich nicht so genau hingesehen... Aber das Minus-Zeichen ignorierst du. Ein Pluszeichen könnte auch drinnen stehen. Und wenn die Zahl in Exponentialdarstellung ist, fällt das 'E' oder 'e' unter den Tisch - obwohl das bei kaufmännischen Zahlen weniger das Problem sein sollte. Aber apropros kaufmännisch: die schreiben manchmal das Minuszeichen hinter die Zahl, oder setzen negative Zahlen in Klammern... Schließlich noch: StrToFloatDef braucht den in den Formatsettings festgelegten Dezimalseparator, das ist bei den meisten hier das Komma.
Winni hat geschrieben:
Mi 19. Jan 2022, 20:34
Sehr hochqualifizierte Aussage: "Unsinn"
Trotzdem.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringgrid sortieren

Beitrag von Winni »

Hi!

Du trotziges Kind ....

Es gibt mehrere Versionen von StrToFloatDef. Mit und ohne FormatSettings. Die ohne nimmt den Punkt an.

Bei Minus gebe ich Dir recht. Plus darf man getrost ignorieren darf.

Wissenschaftliche Darstellung bei irgendwelchen Wechselkursen, Indizes oder Rechnungsbeträgen habe ich noch nie gesehen. Wer schreibt denn auch schon Rechnungen über 1E9 €. Außer Rüstungskonzernen .....

Winni

wp_xyz
Beiträge: 4892
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringgrid sortieren

Beitrag von wp_xyz »

Winni hat geschrieben:
Mi 19. Jan 2022, 21:07
Es gibt mehrere Versionen von StrToFloatDef. Mit und ohne FormatSettings. Die ohne nimmt den Punkt an.
Nur wenn deine Formatsettings den Punkt als Dezimaltrenner verwenden.

Code: Alles auswählen

program Project1;

uses
  SysUtils;

var
  s: String;
  x: Double;
begin
  WriteLn('DecimalSeparator: ', FormatSettings.DecimalSeparator);
  s := '1,234';
  x := StrToFloatDef(s, 0.0);
  WriteLn('"', s, '" ---> x = ', x:0:3);

  s := '1.234';
  x := StrToFloatDef(s, 0.0);
  WriteLn('"', s, '" ---> x = ', x:0:3);
  
  ReadLn;
end.
Output bei mir:

Code: Alles auswählen

DecimalSeparator: ,
"1,234" ---> x = 1.234
"1.234" ---> x = 0.000

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6215
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Stringgrid sortieren

Beitrag von af0815 »

Das die Tausendertrennzeichen nicht richtig ausgewertet werden, habe ich Erfahren, ist der Delphi-Kompatibilität geschuldet. Also meinen Lieblingssatz: Its not a bug, its per design.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringgrid sortieren

Beitrag von Winni »

Hi!

Ich hab als System Suse Tumbleweed mit deutscher localisation.

Bei mir wird anstandslos bei StrToFloatDef ohne FormatSettings der Punkt angenommen.

Aber die Lokalisierung der Fortmatsettings ist einer der größten Mist-Bolzen, die Delphi je eingeführt hat. Ich erinnere mich noch gut: Hatte man das Zeugs auf dem einen Rechner am Laufen, versagte der gleiche Code auf dem nächsten Rechner. Das hat Unmengen von Stunden gekostet. U nd war voller Bugs.

Seitdem gehe ich dem Zeugs aus dem Weg und formatiere das in die gute alte Pascal-Schreibweise um. Und arbeite am Liebsten mit val.


Winni

PS.: Nachgeguckt:

function StrToFloatDef(const S: string; const Default: Extended): Extended;

ruft

StrToFloatDef(S,Default,DefaultFormatSettings);

und in denen steht:

DefaultFormatSettings : TFormatSettings = (
...
DecimalSeparator: '.';
...

Also geht das mit dem Punkt als DecimalSeparator höchst offiziell seinen korrekten Gang

Antworten