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



Comments

  • Lots of bugs....

    Posted by Legacy on 11/08/2000 12:00am

    Originally 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
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

  • Live Event Date: August 20, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT When you look at natural user interfaces as a developer, it isn't just fun and games. There are some very serious, real-world usage models of how things can help make the world a better place – things like Intel® RealSense™ technology. Check out this upcoming eSeminar and join the panel of experts, both from inside and outside of Intel, as they discuss how natural user interfaces will likely be getting adopted in a wide variety …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds