VCL 기본 Grid 컴포넌트인 TStringGrid는 매우 다양한데 많이 쓰이는데..
아쉽게도 Sorting 기능이 없습니다.
Sorting기능이 있는 Grid 컴포넌트 들이 많이 있지만...
기본 컴포넌트 좋아하는 사람들을 위해..
그리고 Sorting 기능이 있는 Grid라 할찌라도 integer로 판단해서 Sorting해줬으면 하는데
그냥 string으로 판단해 sorting하여 원하는데로 sorting이 안되는 경우도 있더군요
[구현]
TStringList에 보면 QuickSort 소스가 있더군요
그것을 이용하여서 StringGrid에 맞게 변형하여 구현해 보았습니다.
//=================================================================================
TStringList에 QuickSort 소스를 보면 대략 다음과 같다. ( Delphi 소스를 C++Builder로 변환한하여 일반화시킴)
//---------------------------------------------------------------------------
void __fastcall StringListCustomSort(TStringList *lst,TStringListSortCompare Compare )
{
if(lst->Count>1)
{
lst->BeginUpdate();
StringListQuickSort(lst,0,lst->Count-1,Compare);
lst->EndUpdate();
}
}
void __fastcall StringListQuickSort(TStringList *lst,int L,int R,TStringListSortCompare SCompare)
{
int I, J, P;
do
{
I = L;
J = R;
P = (L + R) >> 1;
do
{
P;
while( SCompare(lst, I, P) < 0 ) I++;
while( SCompare(lst, J, P) > 0 ) J--;
if( I <= J )
{
lst->Exchange(I,J);// ExchangeItems(I, J);
if( P == I)P = J;
else if( P == J) P = I;
I++;
J--;
}
}
while(I<=J);// until I > J;
if( L < J ) StringListQuickSort(lst,L, J, SCompare);
L = I;
}
while(I= R;
}
//=====================================================================================
위 TStringList의 QuickSort 소스를 그대로 TStringGrid에 적용하여 본다.
Compare프로시져 타입은 TStringGridSortCompare 로 아래와 같이 정의한다.
typedef int __fastcall (*TStringGridSortCompare)(TStringGrid* grid,int col, int Index1, int Index2);
void __fastcall StringGridQuickSort(TStringGrid *grid,int col,int L,int R, TStringGridSortCompare SCompare);
//Grid QuickSort 소스
void __fastcall StringGridQuickSort(TStringGrid *grid,int col,int L,int R,TStringGridSortCompare SCompare)
{
int I, J, P;
TStringList *TmpRow=new TStringList;
do
{
I = L;
J = R;
P = (L + R) >> 1;
do
{
P;
while( SCompare(grid,col, I, P) < 0 ) I++;
while( SCompare(grid,col, J, P) > 0 ) J--;
if( I <= J )
{
TmpRow->Assign(grid->Rows[I]);
grid->Rows[I]->Assign(grid->Rows[J]);
grid->Rows[J]->Assign(TmpRow);
if( P == I)P = J;
else if( P == J) P = I;
I++;
J--;
}
}
while(I<=J);// until I > J;
if( L < J ) StringGridQuickSort(grid,col,L, J, SCompare);
L = I;
}
while(I= R;
delete TmpRow;
}
//=====================================================================================
TStringGridSortCompare 형의 compare함수를 만든다.
//String일경우 비교
int __fastcall SortGridStringProc(TStringGrid *grid,int col,int r1,int r2) //String오름차순
{
if(grid->Cells[col][r1]>grid->Cells[col][r2])return 1;
else if(grid->Cells[col][r1]Cells[col][r2])return -1;
else return 0;
}
int __fastcall SortGridStringProcDesc(TStringGrid *grid,int col,int r1,int r2)//String 내림차순
{
if(grid->Cells[col][r1]Cells[col][r2])return 1;
else if(grid->Cells[col][r1]>grid->Cells[col][r2])return -1;
else return 0;
}
//Integer인경우 비교
int __fastcall SortGridIntegerProc(TStringGrid *grid,int col,int r1,int r2) //integer 오름차순
{
if(StrToInt(grid->Cells[col][r1])>StrToInt(grid->Cells[col][r2]))return 1;
else if(StrToInt(grid->Cells[col][r1])Cells[col][r2]))return -1;
else return 0;
}
int __fastcall SortGridIntegerProcDesc(TStringGrid *grid,int col,int r1,int r2)//integer내림차순
{
if(StrToInt(grid->Cells[col][r1])Cells[col][r2]))return 1;
else if(StrToInt(grid->Cells[col][r1])>StrToInt(grid->Cells[col][r2]))return -1;
else return 0;
}
compare함수는 float인경우 datetime인경우.. 등 TStringGridSortCompare 에 맞춰 직접 만들면 된다.
//=====================================================================================
//전역으로 현재 Sort한 Colomn정보와 방향(오름차순 or 내림차순)을 기억해둔다.
//----------------------------------------------------------------------------------
int iChkCol=-1; //현재 Sorting한 Col
int iDesc=0; //현재 Sorting한 방향
//----------------------------------------------------------------------------------
void __fastcall SortGrid3(TStringGrid *SGrid,int ACol,int ARow)
{
//Sorting하는 구간은 SGrid->FixedRows부터 SGrid->RowCount-1 번째(즉 끝까지) 한다.
if((grid->RowCount-SGrid->FixedRows)<2)return; //compare한 row가 2보다 작으면 return
if( iChkCol==ACol )
{
if(iDesc)
{
if( ACol>0)
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridStringProc);
else
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridIntegerProc);
iDesc=0;
}
else
{
iDesc=1;
if( ACol>0)
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridStringProcDesc);
else
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridIntegerProcDesc);
}
}
else
{
iChkCol=ACol;
iDesc=0;
if( ACol>0)
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridStringProc);
else
StringGridQuickSort(SGrid,ACol,SGrid->FixedRows,SGrid->RowCount-1,SortGridIntegerProc);
}
}
//=====================================================================================
void __fastcall TForm1::StringGrid1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
int ACol ,ARow;
TStringGrid *SGrid=(TStringGrid *)Sender;
SGrid->MouseToCell(X,Y,ACol,ARow);
if(ARow>0)return;
if(ACol<0)return;
SortGrid3(SGrid,ACol ,ARow);
return;
}
//---------------------------------------------------------------------------
완벽하진 않습니다.
TStringGridSortCompare 프로시져 안에서 error가 발생하는 경우 에러처리가 제대로 되어있지 않죠
특히 Integer를 비교하는 프로시져에서...
보완에서 쓰세요
그럼..
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=429