Sort list based on text/numeric/date-time in any column
Posted
by Tal J. Rosen
on August 6th, 1998
"Sorting the list based on text in any column" &
"Sorting list on Numeric Column".
The follwing code combines both articals and adds a new sort type Date/Time sort.
#include// MFC Ole #include // Ole TimeData something...
Add function
// Compare two string by their column types
//
// returns:
// Zero if the strings are identical,
// < 0 if cstL is less than cstR,
// > 0 if cstL is greater than cstR.
//
int CMyListCtrl::CmpItems(CString cstL, CString cstR, int nCol)
{
switch (nCol) {
//Date time column(s)
//***********************
case 0:
COleDateTime odtL;
COleDateTime odtR;
odtL.ParseDateTime(cstL);
odtR.ParseDateTime(cstR);
COleDateTimeSpan spanElapsed = odtL - odtR;
if (spanElapsed.GetStatus() == COleDateTimeSpan::invalid ) {
// Invalid Date time.
ASSERT(FALSE);
return(0);
}
return((int)spanElapsed.GetTotalSeconds());
}
//Numbers column(s)
//***********************
case 1:
case 4:
return(atoi(cstL) - atoi(cstR));
// Strings column(s)
//***********************
//***********************
default:
return (cstL.Compare(cstR));
}
}
Modified lines ==> /*!!!*/
bool CMyListCtrl::SortNumericItems( int nCol, BOOL bAscending,int low/*=0*, int high/*=-1* )
{
if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1;
int lo = low;
int hi = high;
CString midItem;
if( hi <= lo )
return FALSE;
midItem = GetItemText( (lo+hi)/2, nCol );
// loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
CStringArray rowText;
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
//while( ( lo < high ) && (atoi(GetItemText(lo, nCol)) < midItem ) )
/*!!!* while( ( lo < high ) && ( CmpItems( GetItemText(lo, nCol) , midItem, nCol) < 0 ) )
++lo;
else
//while( ( lo < high ) && (atoi(GetItemText(lo, nCol)) > midItem ) )
/*!!!* while( ( lo < high ) && ( CmpItems( GetItemText(lo, nCol) , midItem, nCol) > 0 ) )
++lo;
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
//while( ( hi > low ) && (atoi(GetItemText(hi, nCol)) > midItem ) )
/*!!!* while( ( hi > low ) && ( CmpItems(GetItemText(hi, nCol) , midItem, nCol ) > 0 ) )
--hi;
else
//while( ( hi > low ) && (atoi(GetItemText(hi, nCol)) < midItem ) )
/*!!!* while( ( hi > low ) && ( CmpItems(GetItemText(hi, nCol) , midItem, nCol ) < 0 ) )
--hi;
// if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
//if(atoi(GetItemText(lo, nCol)) != atoi(GetItemText(hi, nCol)) )
/*!!!* if( CmpItems (GetItemText(lo, nCol) , GetItemText(hi, nCol), Col ) != 0) {
// swap the rows
LV_ITEM lvitemlo, lvitemhi;
int nColCount = ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
int i;
for( i=0; i < nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
lvitemhi = lvitemlo;
lvitemhi.iItem = hi;
GetItem( &lvitemlo );
GetItem( &lvitemhi );
for( i=0; i< nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i) );
lvitemhi.iItem = lo;
SetItem( &lvitemhi );
for( i=0; i< nColCount; i++)
SetItemText(hi, i, rowText[i]);
lvitemlo.iItem = hi;
SetItem( &lvitemlo );
}
++lo;
--hi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortNumericItems( nCol, bAscending , low, hi);
// If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortNumericItems( nCol, bAscending , lo, high );
return TRUE;
}

Comments
Lots of bugs....
Posted by Legacy on 11/08/2000 12:00amOriginally posted by: Goetz Hasselberg
I was looking for a clue to solve my problems with sorting of ListCtrls.
Your code seemed to do exactly what I needed, so I copied it and put it into my application but it's full of bugs!
There are some struggles with variable-names that are written with underscores here and without underscores there aswell as brackets right in the middle of the case-construct.
Ok, all in all it helped my to solve my problems, but please(!): Releasing correct code would have been much more helpful!
Reply