Bin demletzt (fast) daran verzweifelt ein StringGrid, nach einer Spalte zu sortiern, die nur Zahlen enthält. Jetzt habe ich es geschafft und mache es hiermit anderen zugängliuch.
Als erstes der Code (ganzer Brocken...):
Delphi-Quellcode:
procedure SortStringGrid(var GenStrGrid: TStringGrid; ThatCol: Integer; const number: Boolean);
const
// Define the Separator
TheSeparator = '@';
var
CountItem, I, J, K, ThePosition: integer;
MyList: TStringList;
MyString, TempString: string;
begin
// Give the number of rows in the StringGrid
CountItem := GenStrGrid.RowCount;
//Create the List
MyList := TStringList.Create;
MyList.Sorted := False;
try
begin
for I := 1 to (CountItem - 1) do MyList.Add(GenStrGrid.Rows[I].Strings[ThatCol] + TheSeparator + GenStrGrid.Rows[I].Text);
//Sort the List
if not number then Mylist.Sort
else BubbleSort(MyList);
for K := 1 to Mylist.Count do
begin
//Take the String of the line (K – 1)
MyString := MyList.Strings[(K - 1)];
//Find the position of the Separator in the String
ThePosition := Pos(TheSeparator, MyString);
TempString := '';
{Eliminate the Text of the column on which we have sorted the StringGrid}
TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
MyList.Strings[(K - 1)] := '';
MyList.Strings[(K - 1)] := TempString;
end;
// Refill the StringGrid
for J := 1 to (CountItem - 1) do GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];
end;
finally
//Free the List
MyList.Free;
end;
end;
procedure BubbleSort(var items: TStringList);
var
done: boolean;
i, n,valtest,t: integer;
Dummy,s0,s1: string;
begin
n := Items.Count;
repeat
done := true;
for i := 0 to n - 3 do
begin
s0 :=copy(Items.Strings[i], 0, pos('@', Items.Strings[i])-1);
s1 :=copy(Items.Strings[i+1], 0, pos('@', Items.Strings[i+1])-1);
//Hier wurde was geändert
if (StrToInt(s0) > StrToInt(s1)) then
begin
Dummy := s0 + copy(Items.Strings[i], pos('@', Items.Strings[i]), length(Items.Strings[i]));
Items.Strings[i] := s1 + copy(Items.Strings[i+1], pos('@', Items.Strings[i+1]), length(Items.Strings[i+1]));
Items[i + 1] := Dummy;
done := false
end;
end;
until done;
end;
Die obere procedure werden einige schnell wiedererkennen. Es ist die procedure von Delphiswiss. Aber etwas abgeändert, so, dass es auch nummern sortieren kann. Hierfür wird der procedure ein weiterer Wert übergeben: number. Wenn number true ist, wird nach Zahlen sortiert, sonst nach Strings. In dieser procedure wurde nur eine Kleinigkeit geändert:
Delphi-Quellcode:
{vorher:} Mylist.Sort
{nachher:}if not number then Mylist.Sort
else BubbleSort(MyList);
Wenn number false ist (also, wenn es sich ganz normal um Strings handelt, dann wird wie vorher die StringList sortiert. Wenn dies nicht der Fall ist (wenn es sich um eine Spalte mit Zahlen handelt) dann wird die Liste nach bubblesort sortiert. Und jetzt wird es interessant, denn jetzt kommen wir zur modifizierten bubblesort-procedure. Bevor wir dahin kommen, erkläre ich aber noch mal ganz kurz, wie die schweizer sortierlösung funktioniert:
Als erstes holen wir alle Zeilen in eine StringList. Dann tun wir vor denentsprechenden Eintrag in der StringList die zu sortierende Zeile und trennen sie mit einem @ vom Rest der Zeile ab. Nun wird die StringList sortiert. Dann wird der erste Teil (das war die zu sortierende Spalte) mit dem @ wieder entfernt und schlussendlich zurück ins StringGrid getan.
Aber jetzt zur modifizierten BubbleSort procedure:
Mit einer for-Schleife gehen wir alle Eintrage in der StringList durch:
Im ersten Teil kopieren wir die zu sortierende Spalte (der Teil vor dem @) der aktuellen Zeile und der darauffolgenden Zeile in eine tempörere Stringvariable (s0,s1). Wenn s0 jetzt größer ist als s1, dann werden die beiden Werte in der StringList vertauscht und done auf false gesetzt. (In diesem Fall ahbe ich StringToInt verwendet. Wenn ihr StringToFloat verwendet geht das nat. auch mit kommazahlen). Und jetzt geht die for-Schleife wieder von vorne los und die nächsten zwei Zeilen werden verglichen udn gegebenenfalls vertauscht.
Wenn jetzt alle Zeilen durch sind (die for-Schleife durch ist) dann wird überprüft, ob noch etwas verändert wurde. (wenn nichts verändert wurde, sit done immernoch auf true) sollte das nicht der Fall sein, fängt der Algo wieder von vorne and und geht nochmal alle Zeilen durch, bis alles sortiert ist.
Dann wird noch die normale Sortierprocedure zuende ausgeführt und die Spalte ist sortiert.
Aufruf:
SortStringGrid(MyStringGrid, 2, true);
--> sortier im "MyStringGrid" die 3. Zeile von links und die Zeile enthält nur nummern.
!!ACHTUNG!!: Wenn number true ist, die entsprechende Zeile wirklich NUR Zahlen enthalten. Ein einziger String führt zur exeption und damit zum scheitern...
Letzter Tipp: Drogen. Machen zwar nicht glücklich, geben einem aber wenigstens das Gefühl glücklich zu sein.
Have a lot of fun!