| C++ Builder Snippets |
|
Daten im TStringGrid numerisch, alphanumerisch oder nach Datum sortieren: |
|
Oft müssen die Inhalte einer Tabelle nach bestimmten Kriterien sortiert werden. Woodym postete
am 16.03.2002 im Forum der RAD-Seiten einen Beitrag über die
Sortierung der TStringGrid-Inhalte nach Datum. Die nachfolgend beschriebene Funktion
StringGridBubbleSort() ist einer Weiterführung seines Vorschlags. Sie ermöglicht sowohl
auf- als auch absteigende Sortierung von StringGrid-Zeilen. Es kann nach Strings, Zahlen
oder Datumsangaben sortiert werden. Die Funktion StringGridBubbleSort() verwendet langsames BubbleSort-Verfahren und führt ggf. zeitaufwendige Konvertierungen durch. Bei grösseren Datenmengen ist es daher sinnvoller, mit TList oder STL-Containern zu arbeiten und deren Sortierfunktionen (in der Regel Quicksort) zu verwenden. TStringGrid sollte ohnehin nur für die Visualisierung der Daten und nicht als "Datenarray" zur Verwaltung der Variablen vewendet werden. Nachtrag vom 29.12.2002: Peter Tuschik hat die Sortierroutine auf ShellSort-Verfahren umgestellt, wodurch die Ausführungsgeschwindigkeit sich bereits bei 250 Elementen im Beispielprogramm um Faktor 30 (!) erhöht hat. Seine Implementierung der Sortierfunktion befindet sich in der Routine StringGridShellSort(). ![]() //--------------------------------------------------------------------------- // Art der zu sortierenden Daten: enum GRIDSORT_TYPE { SORT_NUMERIC, SORT_DATETIME, SORT_STRINGS }; //---------------------------------------------------------------------------- // StringGridBubbleSort() sortiert den Inhalt eines TStringGrid // (BubbleSort-Verfahren wird verwendet) //---------------------------------------------------------------------------- // Übergabeparameter: // // TStringGrid* pGrid - Zeiger auf die zu sortierende Tabelle // int iCol - Index der Spalte, nach der sortiert werden soll // int ilSortType - Art der Daten in der Spalte, folgende Werte möglich: // SORT_NUMERIC : Zelleninhalt numerisch // SORT_DATETIME : Zellen mit Datumswerten // SORT_STRINGS : Zellen mit Strings // bool blAsccending - true für aufsteigende Sortierung, anderenfalls false //---------------------------------------------------------------------------- void StringGridBubbleSort(TStringGrid* pGrid, int iCol, int iSortType, bool blAsccending) { TCursor crOldCursor = Screen->Cursor; Screen->Cursor = crHourGlass; AnsiString sBuf; bool blSwap = false; bool blSwapped = false; try { for (int ilRow = 1; ilRow < pGrid->RowCount; ilRow++) { blSwapped = false; for (int iRow = 1; iRow < pGrid->RowCount-1; iRow++) { if (iSortType == SORT_NUMERIC) { if ((blAsccending && ConvertToDoubleDef(pGrid->Cells[iCol][iRow], MaxDouble) > ConvertToDoubleDef(pGrid->Cells[iCol][iRow+1], MaxDouble)) || (!blAsccending && ConvertToDoubleDef(pGrid->Cells[iCol][iRow], MaxDouble) < ConvertToDoubleDef(pGrid->Cells[iCol][iRow+1], MaxDouble))) blSwap = true; } else if (iSortType == SORT_DATETIME) { try { if ((blAsccending && (TDateTime)pGrid->Cells[iCol][iRow] > (TDateTime)pGrid->Cells[iCol][iRow+1]) || (!blAsccending && (TDateTime)pGrid->Cells[iCol][iRow] < (TDateTime)pGrid->Cells[iCol][iRow+1])) blSwap = true; } catch(...) {;} } else if (iSortType == SORT_STRINGS) { if ((blAsccending && pGrid->Cells[iCol][iRow].AnsiCompare( pGrid->Cells[iCol][iRow+1]) > 0 )|| (!blAsccending && pGrid->Cells[iCol][iRow].AnsiCompare( pGrid->Cells[iCol][iRow+1]) < 0)) blSwap = true; } if (blSwap) { sBuf = pGrid->Rows[iRow]->Text; pGrid->Rows[iRow]->Text = pGrid->Rows[iRow+1]->Text; pGrid->Rows[iRow+1]->Text = sBuf; blSwapped = true; blSwap = false; } } if (!blSwapped) break; } } __finally { Screen->Cursor = crOldCursor; } } //---------------------------------------------------------------------------- // StringGridShellSort() sortiert den Inhalt eines TStringGrid // (ShellSort-Verfahren wird verwendet) by Peter Tuschik //---------------------------------------------------------------------------- // Übergabeparameter: // // TStringGrid* pGrid - Zeiger auf die zu sortierende Tabelle // int iCol - Index der Spalte, nach der sortiert werden soll // int ilSortType - Art der Daten in der Spalte, folgende Werte möglich: // SORT_NUMERIC : Zelleninhalt numerisch // SORT_DATETIME : Zellen mit Datumswerten // SORT_STRINGS : Zellen mit Strings // bool blAsccending - true für aufsteigende Sortierung, anderenfalls false //---------------------------------------------------------------------------- void StringGridShellSort(TStringGrid *pGrid, int iCol, int iSortType, bool blAsccending) { int iOffset, iLimit, iRow, iSwitch; int anz = pGrid->RowCount; AnsiString sBuf; // Vergleichsoffset auf Mitte der iOffset = anz / 2; // Datenmenge initialisieren while (iOffset) // Loop bis Offset == 0 { bool blSwap = false; iLimit = anz - iOffset; do { iSwitch = 0; // Assume no switches at this offset /* Compare elements and switch ones out of order. */ for (iRow = 1; iRow < iLimit; iRow++) { if (iSortType == SORT_NUMERIC) { if ((blAsccending && ConvertToDoubleDef(pGrid->Cells[iCol][iRow], MaxDouble) > ConvertToDoubleDef(pGrid->Cells[iCol][iRow+iOffset], MaxDouble)) || (!blAsccending && ConvertToDoubleDef(pGrid->Cells[iCol][iRow], MaxDouble) < ConvertToDoubleDef(pGrid->Cells[iCol][iRow+iOffset], MaxDouble))) blSwap = true; } else if (iSortType == SORT_DATETIME) { try { if ((blAsccending && (TDateTime)pGrid->Cells[iCol][iRow] > (TDateTime)pGrid->Cells[iCol][iRow+iOffset]) || (!blAsccending && (TDateTime)pGrid->Cells[iCol][iRow] < (TDateTime)pGrid->Cells[iCol][iRow+iOffset])) blSwap = true; } catch(...) {;} } else if (iSortType == SORT_STRINGS) { if ((blAsccending && pGrid->Cells[iCol][iRow].AnsiCompare( pGrid->Cells[iCol][iRow+iOffset]) > 0 )|| (!blAsccending && pGrid->Cells[iCol][iRow].AnsiCompare( pGrid->Cells[iCol][iRow+iOffset]) < 0)) blSwap = true; } if (blSwap) { sBuf = pGrid->Rows[iRow]->Text; pGrid->Rows[iRow]->Text = pGrid->Rows[iRow+iOffset]->Text; pGrid->Rows[iRow+iOffset]->Text = sBuf; iSwitch = iRow+1; blSwap = false; } } /* For */ /* Sort on next pass only to where last switch was made. */ iLimit = iSwitch - iOffset; } while(iSwitch); /* No switches at last offset, try one half as big. */ iOffset = iOffset / 2; } /*while */ } //--------------------------------------------------------------------------- // Beschreibung: Konvertiert einen AnsiString zu double // (gibt dlDefValue zurück, falls nicht konvertiert werden kann) //--------------------------------------------------------------------------- double ConvertToDoubleDef(AnsiString sValueString, double dlDefValue) { double dResultValue = 0.0; sValueString = sValueString.Trim(); if(sValueString == EmptyStr) return dResultValue; if(DecimalSeparator == ',' && sValueString.Pos(".") > 0) sValueString[sValueString.Pos(".")] = DecimalSeparator; else if(DecimalSeparator == '.' && sValueString.Pos(",") > 0) sValueString[sValueString.Pos(",")] = DecimalSeparator; try { dResultValue = sValueString.ToDouble(); } catch(...) { return dlDefValue; } return dResultValue; } Original-Beitrag von Woodym im Forum der RAD-Seiten vom 16.03.02: StringGrid sortierung nach Datum ich will einen kleinen beitrag zu den snippets leisten. das problem: ein StringGrid soll nach datum sortiert werden. das datum steht hier in der form TT.MM.JJJJ in einer zelle (wird direkt erzeugt durch ein DateTimePicker). durch aufruf von DateStringGridSort(StringGrid1,0);wird nun das StringGrid sortiert nach Datum. das Datum ist in spalte 0. void changeStringGridRow(TStringGrid* strg,int source,int dest) { int i=0; AnsiString buf; for(i=0;i<strg->ColCount;i++) { buf=strg->Cells[i][source]; strg->Cells[i][source]=strg->Cells[i][dest]; strg->Cells[i][dest]=buf; } } void DateStringGridSort(TStringGrid* slStrings,int zelle) { int i, j, k,l,m; for(i = 1; i < slStrings->RowCount - 1; i++) { k = i; for(j=i+1; j < slStrings->RowCount; j++) { if(slStrings->Cells[zelle][j]=="" || slStrings->Cells[zelle][k]=="") continue; l=(TDate)slStrings->Cells[zelle][j]; m=(TDate)slStrings->Cells[zelle][k]; if(l < m) k = j; } changeStringGridRow(slStrings,k,i); } } |
|
Download BCB6 Projekt-Quellcode |
|
Download Demo-Exe |
| © '99-2002 by S. Kreutzmann |