Sort list based on text/numeric/date-time in any column

This code is based on the articls

“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;
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read