C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[733] [Controls] TStringGrid Sort
장성호 [nasilso] 10122 읽음    2008-01-10 01:56
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를 비교하는 프로시져에서...

보완에서 쓰세요

그럼..
장성호 [nasilso]   2008-01-10 04:21 X
예전에 박영목님이 올린 팁입니다. 참조하세요
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=429

+ -

관련 글 리스트
733 [Controls] TStringGrid Sort 장성호 10122 2008/01/10
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.