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

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 […]

Written By
CodeGuru Staff
CodeGuru Staff
Aug 6, 1998
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

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

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.