Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Stringgrid inkl. Umlaute richtig sortieren (https://www.delphipraxis.net/95852-stringgrid-inkl-umlaute-richtig-sortieren.html)

Steven2 14. Jul 2007 08:59


Stringgrid inkl. Umlaute richtig sortieren
 
Hallo...

wie kann ich ein Stringgrid alphabetisch sortieren,
so dass auch die Umlaute ordnungsgemäß sortiert werden?

Grüße
Steven

Bernhard Geyer 14. Jul 2007 10:54

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Zitat:

Zitat von Steven2
so dass auch die Umlaute ordnungsgemäß sortiert werden?

Ordnungsgemäße Sortierung ist definitionssache. Welche Definition hast du dafür?

Steven2 14. Jul 2007 18:32

Re: Stringgrid inkl. Umlaute richtig sortieren
 
So dachte ich mir das...
Umlaut:
Ä bei AE einsortieren
Ü bei UE einsortieren
Ö bei OE einsortieren

Beste Grüße
Steven

Christian Seehase 14. Jul 2007 18:47

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Moin Steven,

ohne Berücksichtigung der Gross-/Kleinschreibung kommt hier Delphi-Referenz durchsuchenAnsiCompareText in Frage.
Da ich mal davon ausgehe, dass das StringGrid mehrere Spalten umfasst, müsstest Du allerdings die Sortierroutine selber schreiben, damit alle Zeilen erhalten bleiben.
Bei einem ListView wäre das etwas einfacher.

Reinhard Kern 14. Jul 2007 19:02

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Zitat:

Zitat von Steven2
Hallo...

wie kann ich ein Stringgrid alphabetisch sortieren,
so dass auch die Umlaute ordnungsgemäß sortiert werden?

Grüße
Steven

Hallo,

soweit ich weiss, ist sowas nur in Datenbanksoftware standardmässig verfügbar. Um selbst nach DIN zu sortieren, musst du Kopien der Strings anlegen, weil du vor dem Vergleich ä durch ae ... ß durch ss usw. ersetzen musst und der Ausgangsstring dabei theoretisch doppelt so lang werden kann.

Darüber hinaus sind in der DIN glaube ich noch ein paar Feinheiten definiert wie die genaue Sortierreihenfolge von AE,Ae,aE,ae, aber man kann es ja auch übertreiben. In der EDV ist es üblich, Gross/Klein überhaupt nicht zu beachten.

Gruss Reinhard

Steven2 15. Jul 2007 00:31

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Irgendwie müsste es sowas wie hier sein, arbeite auch mit den TMS Kompos TadvStringgrid:
Natürlich muss der Code anders aussehen, evt. wäre das aber eine Möglichkeit.
Hab selber keinen Plan, ist nur mal so geraten.

Delphi-Quellcode:
procedure TForm1.AdvStringGrid1CustomCompare(Sender: TObject; str1,
  str2: String; var res: Integer);
var
  i1,i2,code:integer;

begin
  if (pos('Kb',str1)>0) then
  begin
    Delete(str1,Pos('Kb',str1),2);
    Val(str1,i1,code);
    i1 := i1 * 1024;
  end
  else
    Val(str1,i1,code);

  if (pos('Kb',str2)>0) then
  begin
    Delete(str2,Pos('Kb',str2),2);
    Val(str2,i2,code);
    i2:=i2*1024;
  end
  else
    Val(str2,i2,code);

  if i1 = i2 then
    res := 0
  else
  begin
    if i1 > i2 then
      res := 1
    else
      res := -1;
  end;
end;
Hätte ich doch besser eine Listview nehmen sollen, mißt nun ist das Programm fertig.
^^

Christian Seehase 15. Jul 2007 00:56

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Moin Steven,

ich kenne TadvStringgrid nicht, aber so wie die Sort-Routine aussieht dürfte sich das recht leicht einbauen lassen.
So müsste das genügen:

Delphi-Quellcode:
procedure TForm1.AdvStringGrid1CustomCompare(Sender: TObject; str1,
  str2: String; var res: Integer);
begin
  res := AnsiCompareText(str1,str2);
  if res < 0 then begin
    res := -1;
  end else begin
    if res > 0 then begin
      res := 1;
    end;
  end;
end;
Ich weiss jetzt nicht, ob AnsiCompareText evtl. garantiert auch -1,0 und 1 zurückgibt.
Für den Fall könnte man dann auch die ganze if/then/else-Konstruktion auch weglassen.

marabu 15. Jul 2007 08:47

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Guten Morgen Steven.

Das Ereignis OnCustomCompare() wird nicht unbedingt benötigt.

Wenn du beim Ereignis OnGetFormat() die richtigen Angaben zu den einzelnen Spalten machst, dann sortiert das AdvStringGrid wie von selbst. Ich gehe von nicht-virtualisierten Zellinhalten aus:

Delphi-Quellcode:
const // edit
  SIZE_SUFFIX = ' Kb'; // Anpassen!
  SIZE_COLINDEX = 3;   // Anpassen!

procedure TDemoForm.AdvStringGridGetFormat(Sender: TObject; ACol: Integer;
  var AStyle: TSortStyle; var aPrefix, aSuffix: String);
begin
  with Sender as TAdvStringGrid do
    case ACol of // edit
      SIZE_COLINDEX: // edit
      begin
        AStyle := ssNumeric;
        aSuffix := SIZE_SUFFIX;
      end;
    else
      AStyle := ssAnsiAlphaNoCase; // edit
    end;
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
begin
  with AdvStringGrid do
    SortByColumn(SIZE_COLINDEX);
end;
Getippt und nicht getestet.

EDIT:

(1) resourcestring durch const ersetzt: wegen SIZE_COLINDEX
(2) case selector vereinfacht
(3) erstes case label korrigiert: Konstante statt Literal
(4) sort mode umgestellt: ssAlphabetic kennt keine lokalisierten strings

Grüße vom marabu

Steven2 15. Jul 2007 16:50

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Dankeschön für eure Hilfe.

Gilt das dann für alle Spalten?

Delphi-Quellcode:
procedure TDemoForm.AdvStringGridGetFormat(Sender: TObject; ACol: Integer;
  var AStyle: TSortStyle; var aPrefix, aSuffix: String);
begin
  with Sender as TAdvStringGrid do
    case ACol - FixedCols of
      1:
      begin
        AStyle := ssNumeric;
        aSuffix := SIZE_SUFFIX;
      end;
    else
      AStyle := ssAlphabetic;
    end;
end;
...oder muss ich
Delphi-Quellcode:
  with AdvStringGrid do
    SortByColumn(SIZE_COLINDEX);
für jede Spalte extra anlegen?

marabu 15. Jul 2007 18:11

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

jetzt habe ich meinen Code-Vorschlag mal getestet. Achte bitte auf meine Änderungen im Beitrag #8.

Beim Ereignis OnGetFormat() habe ich nur für eine Spalte spezielle Vorkehrungen getroffen. Wenn du mehrere solche Spalten hast, dann musst du weitere case label einfügen.

Die Sortierung habe ich der Einfachheit halber nur für eine Spalte und per Button gezeigt. Du wirst in deinem Code sicher auf das Klicken auf einen Spaltenkopf reagieren um die Sortierung zu wechseln. Oder du hast sogar mehr als eine Spalte als Sortierkriterium.

Freundliche Grüße

Steven2 16. Jul 2007 13:38

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo marabu,
kann ich mehrere Umlaute so einfügen?

const
SIZE_SUFFIX = 'Ä,Ü,Ö';
SIZE_COLINDEX = 3;

Freundliche Grüße
Steven

Steven2 16. Jul 2007 14:02

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo marabu,
magst du dir mal bitte mein Beispiel ansehen.
Irgendwie krieg ich das nicht hin

Es gibt auch noch, evtl. ist das auch was?
Delphi-Quellcode:
aStyle:=ssAnsiAlphaNoCase;
Grüße Steven

marabu 16. Jul 2007 15:14

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

ich habe mir dein Projekt angeschaut.

Mein Code-Beispiel war in erster Linie als Reaktion auf die Beiträge #6 und #7 entstanden. Du hattest dort eine Spalte mit Größenangaben und nachfolgendem ' Kb' eingeführt. Jetzt habe ich deinen ganzen Thread gelesen und erkenne ein ganz anderes Problem. Du möchtest nicht die Standardordnung (Ä nach A) für deine Strings, sondern die Telefonbuch-Ordnung (Ä wie AE). Windows unterstützt diese Ordnung grundsätzlich über den Sort Identifier SORT_GERMAN_PHONE_BOOK, den du über SetThreadLocale() für dein Programm wählen kannst.

Ich habe das soeben einmal ausprobiert. Da das Ergebnis nicht beeinflusst wird, vermute ich, dass die Compare-Funktionen in AdvStringGrid diese Einstellung ignorieren. Hier wäre sicher eine Anfrage an den Support von TMS angebracht.

EDIT: Getestet habe ich mit deinem Projekt.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  locale: LCID;
begin
  locale := GetThreadLocale;
  SetThreadLocale(locale or SORT_GERMAN_PHONE_BOOK shl 16);
  with AdvStringGrid1 do
    SortByColumn(2);
  SetThreadLocale(locale);
end;
Freundliche Grüße

Steven2 16. Jul 2007 16:47

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Vielen Dank für deine SUPERHILFE.
Habe TMS schon damals mal angemailt, das ist die Antwort:
Zitat:

It is the Windows locale that determines the sort order of characters with accent, umlaut, etc..
We cannot change this rule.
See:
http://msdn2.microsoft.com/en-us/library/ms647476.aspx
for the compare method that is used in TAdvStringGrid.

If you want to use a different compare routine, you can do this by setting
sort style to ssCustom and providing it via OnCustomCompare.
verstanden habe ich es ehrlich gesagt nicht.

Ich schick denen jetzt mal deinen Beispielcode.
Grüße
Steven

marabu 16. Jul 2007 17:28

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

wenn du meinen Code an TMS schickst, dann sollte TMS erkennen, dass sich die Flexibilität ihrer Komponente erhöht, wenn beim internen Aufruf von CompareString() GetThreadLocale() statt GetSystemDefaultLCID() verwendet wird. Nur so können alternative Sort Modi aktiviert werden ohne andere Anwendungen zu beeinflussen. Alle NT-basierten Windows-Versionen würden davon profitieren.

Freundliche Grüße

Steven2 17. Jul 2007 08:12

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo marabu...

Zitat:

If you want to use a different compare routine, you can do this by setting
sort style to ssCustom and providing it via OnCustomCompare.
das war die Antwort von TMS.

Freundliche Grüße
Steven

marabu 17. Jul 2007 16:37

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

ich habe meinen Code aus deinem Test-Projekt jetzt so angepasst, dass abgesehen von der vierten Spalte (3 wegen nullbasiertem Index) mit den Kilobyte-Angaben alle anderen Spalten nach Art der deutschen Telefonbücher sortiert werden. Diese Anpassungen wären überflüssig, wenn TMS mit der ThreadLocale arbeiten würde.

Delphi-Quellcode:
const // edit
  SIZE_SUFFIX = ' Kb'; // so werden Angaben wie '123 Kb' numerisch korrrekt sortiert
  SIZE_COLINDEX = 3;   // nur in der vierten Spalte, der Rest sind Strings

procedure TForm1.Button1Click(Sender: TObject);
begin
  AdvStringGrid1.LoadFromCSV(ExtractFilePath(Application.ExeName)+'test.CSV');
end;

procedure TForm1.AdvStringGrid1GetFormat(Sender: TObject; ACol: Integer;
  var AStyle: TSortStyle; var aPrefix, aSuffix: String);

begin
  with Sender as TAdvStringGrid do
    case ACol of // edit
      SIZE_COLINDEX: // edit
      begin
        AStyle := ssNumeric;
        aSuffix := SIZE_SUFFIX;
      end;
    else
      AStyle := ssCustom; // edit
    end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  with AdvStringGrid1 do
    SortByColumn(2);
end;

// Event Handler für OnCustomCompare() im OI erzeugen:
procedure TForm1.AdvStringGrid1CustomCompare(Sender: TObject; str1,
  str2: String; var Res: Integer);
begin
  // die Locale solltest du in deinem Programm an zentraler Stelle
  // gleich zu Beginn zwischenspeichern, damit der ständige Aufruf
  // von GetThreadLocale hier unterbleiben kann.
  Res := CompareString(GetThreadLocale or SORT_GERMAN_PHONE_BOOK shl 16,
      NORM_IGNORECASE, PChar(str1), Length(str1), Pchar(str2), Length(str2)) - 2;
end;
Freundliche Grüße

Steven2 17. Jul 2007 20:57

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo marabu,
es funktioniert...du hast mir sehr damit geholfen.
Danke!

Freundliche Grüße
Steven

Steven2 21. Jul 2007 17:53

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo..
zwei Fragen habe ich nun doch noch dazu.

Wie kann ich mehrere Umlaute überprüfen?
So kann ich nur einen Umlaut angeben.
Delphi-Quellcode:
  SIZE_SUFFIX = 'Ä'
Wie kann ich in allen Spalten des Stringgrids
So kann ich nur in einer bestimmten Spalte sortieren.
Delphi-Quellcode:
  SIZE_COLINDEX = 3;
Ich hoffe die Fragen gehören noch zu diesem Thread.

Freundliche Grüße
Steven

marabu 21. Jul 2007 19:58

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

leider verstehe ich nicht was du vorhast. Kannst du das etwas ausführlicher erklären - eventuell mit Beispieldaten?

Freundliche Grüße

Steven2 23. Jul 2007 21:51

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo marabu, komme leider erst jetzt zum antworten.
Das mit den KB war ja nur ein Beispiel, mir geht es um die Umlaute.

Ich will ja nach diesen Umlauten sortieren.
Zur Zeit kann ich mit deinem Beispiel nur einen Umlaut überprüfen, wollte halt nach allen in einer Spalte sortieren.
Delphi-Quellcode:
SIZE_SUFFIX = 'Ä'
so, gehts aber nicht :coder2:
Delphi-Quellcode:
SIZE_SUFFIX = 'Ä','Ü','Ö','ä','ü','ö'
Auch will ich nicht nur eine Spalte prüfen sondern auch in allen anderen des Stringgrid's bei denen auf den Spaltenkopf geklickt wird.

Habe ich mich nun verständlicher ausgedrückt?
Wenn nicht mache ich so schnell wie ich kann ein Beispiel fertig.

Freundliche Grüße
Steven

marabu 25. Jul 2007 09:24

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

ich fürchte du hast den Suffix aus meinem Code-Beispiel nicht richtig verstanden. Ausgelöst von deinem Beispiel mit den KByte-Werten wollte ich dir zeigen, dass über das Ereignis OnGetFormat() Spaltenwerte sogar dann numerisch korrekt sortiert werden können, wenn sie eingebettet in einem String mit definiertem Prefix oder Suffix stehen. Mit deinen Umlauten und deren Einsortierung nach Telefonbuch-Manier hat das überhaupt nichts zu tun.

Wenn da noch irgendwas sein sollte, was ich übersehe, dann musst du wirklich mal ein illustrierendes Beispiel bringen.

Freundliche Grüße

Steven2 26. Jul 2007 00:18

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Zitat:

Mit deinen Umlauten und deren Einsortierung nach Telefonbuch-Manier hat das überhaupt nichts zu tun.
Hallo marabu...
oh mann, ich hab wohl alles falsch beschrieben.
Ich bin jetzt eine Woche unterwegs, ich mache danach ein Beispiel fertig.
Vielen Dank für deine Hilfe schon mal vorab.

Freundlichen Gruß
Steven

Steven2 8. Aug 2007 00:15

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Endlich habe ich nun das Beispiel fertig.
Es geht mir darum nach wie ich noch nach anderen Umlauten sortieren kann
und wie ich das Sortieren mit einem klick auf die Caption der jeweiligen Spalte machen kann.
Ich hoffe mein Beipiel ist eindeutig.

Freundliche Grüße
Steven

Steven2 16. Aug 2007 12:51

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Mag sich jemand mein Beispiel doch noch ansehen? (evt. auch marabu? :)

LG
Steven

Steven2 4. Sep 2007 21:35

Re: Stringgrid inkl. Umlaute richtig sortieren
 
SORRY **PUSH**

marabu 4. Sep 2007 21:57

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hi Steven,

auch sorry, aber ich habe deinen Thread erst jetzt wieder gesehen. Ich schaue mir das an, sobald ich kann. Versprochen.

Gute Nacht

marabu 5. Sep 2007 22:02

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

du kannst das Event OnClickSort() deines Grids zum Sortieren der Spalten verwenden:

Delphi-Quellcode:
procedure TForm1.AdvStringGrid1ClickSort(Sender: TObject; ACol: Integer);
begin
   with Sender as TAdvStringGrid do
     SortByColumn(ACol);
end;
Du musst vorher noch im Object Inspector die SortSettings ändern: Show und NormalCellsOnly müssen auf True gesetzt werden. Das Ergebnis mit deinen Testdaten sieht für mich vernünftig aus.

Gute Nacht

Mackhack 5. Sep 2007 22:11

Re: Stringgrid inkl. Umlaute richtig sortieren
 
marabu,

fuer was ist denn das shl 16 in deinem Codebeispiel?

marabu 6. Sep 2007 05:56

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hi Tobias,

SHL - logical shift left? Damit schiebe ich die SORTID an die richtige Stelle:

Code:
+-------------+---------+-------------------------+
|   Reserved | Sort ID |      Language ID       |
+-------------+---------+-------------------------+
31         20 19     16 15                      0   bit
Freundliche Grüße

Mackhack 6. Sep 2007 06:58

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Marabu,

schiebst du dabei die Bits um 16 stellen nach Links oder wie muss ich mir das vorstellen? Und warum funktioniert das ueberhaupt mit dem schieben?

marabu 6. Sep 2007 08:00

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Ja richtig, alle Bits werden um 16 Positionen nach links verschoben - das ist eine Multiplikation mit 2 hoch 16. Das funktioniert so, weil die Multiplikation, wie jede andere Rechenoperation auch, auf Registerebene per Shift realisiert wird. Manchmal musst du aufpassen, dass du den richtigen Basistyp verwendest. Ein Byte und SHL 8 löscht effektiv das Byte, da die Bits "am linken Rand" verloren gehen und "von rechts her" mit Nullen aufgefüllt wird.

Hier ein paar Stichworte für eine Suche: Technische Informatik Schieberegister ALU.

PS: Hast du Schlafstörungen? Bei dir muss es doch zappenduster sein...

Steven2 6. Sep 2007 10:45

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Danke Marabu, das müßte nun wirklich funktionieren...sieht hier auch gut aus.
Danke !!!

Viele Grüße
Steven

Mackhack 6. Sep 2007 14:52

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Zitat:

Zitat von marabu
PS: Hast du Schlafstörungen? Bei dir muss es doch zappenduster sein...

Hallo Marabu,

nein hab ich keine, Schlaf is doch sowas von ueberbewertet, findest du nicht auch :???: Vielen Dank fuer die Erklaerungen!

Steven2 8. Sep 2007 19:57

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo

wie funktioniert das jetzt hiermit?
Delphi-Quellcode:
  SIZE_SUFFIX = 'Ä'; // Wie kann ich auch die anderen Umlaute sortieren (angeben)
  SIZE_COLINDEX = 3;
kann ich das weglassen oder muss ich die anderen umlaute integrieren?
wenn ja...magst du mir noch zeigen wie?

grüße steven

marabu 8. Sep 2007 20:19

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Hallo Steven,

die beiden Konstanten sind doch nur Relikte aus deinem anfangs geschilderten Problem, der Sortierung von Zeichenketten, die eine Zahl und ordinären Text enthalten. Sie haben nichts mit dem allgemeinen Sortierproblem (Telefonbuchordnung) zu tun.

Gute Nacht

Steven2 8. Sep 2007 20:30

Re: Stringgrid inkl. Umlaute richtig sortieren
 
AHA...achso, also brauche ich nur folgendes?
Irgendwie bin ich grad etwas verwirrt:

Delphi-Quellcode:
// Event Handler für OnCustomCompare() im OI erzeugen:
procedure TForm.AdvStringGrid1ClickSort(Sender: TObject; ACol: Integer);

begin
   with Sender as TAdvStringGrid do
     SortByColumn(ACol);
end;

Delphi-Quellcode:
procedure TForm.AdvStringGrid1CustomCompare(Sender: TObject; str1,
  str2: String; var Res: Integer);
begin
  // die Locale solltest du in deinem Programm an zentraler Stelle
  // gleich zu Beginn zwischenspeichern, damit der ständige Aufruf
  // von GetThreadLocale hier unterbleiben kann.
  Res := CompareString(GetThreadLocale or SORT_GERMAN_PHONE_BOOK shl 16,
  NORM_IGNORECASE, PChar(str1), Length(str1), Pchar(str2), Length(str2)) - 2;
end;

marabu 8. Sep 2007 20:39

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Richtig.

Der Code für das Event OnGetFormat() bezog sich auf Spaltenwerte der Form '150 Kb'.

Weg damit.

Steven2 8. Sep 2007 21:08

Re: Stringgrid inkl. Umlaute richtig sortieren
 
Okay
Danke :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:48 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz