Export Data from MFC List Control into CSV File

In this post, I provide the reusable and extendable C++ source code to export data from MFC list control into CSV file. The source code could be easily integrated into your windows application and it applies to any MFC List Control (as long as you inherit CListCtrl class) with arbitrary number of rows and columns.

Furthermore, the code is designed for different options, you can choose
(1) whether or not to include the header names from the MFC list control
(2) specify the delimiter in the CSV file, and the default one is comma (‘,’)

The following code involves using CListCtrl, CFile, CArchive, CFileDialog, and the source code should explain itself quite well, please do not hesitate to leave any comments or question you have.

And note to use the code, you need to customize the declaration of your own window classes a bit (i.e., CYourWindowClass in the code) which I consider won’t be a problem for you! :)

/**
 * Author: sigmainfy 烟客旅人
 * Date:   Aug 14, 2014
 * Wesite: http://tech-wonderland.net/
 */
CString CYourWindowClass::GetColumnName(const CListCtrl * listctrl, int iCol)
{
    CString strName(_T(""));
    CHeaderCtrl* pHeaderCtrl = listctrl->GetHeaderCtrl();
    if (NULL != pHeaderCtrl && iCol < pHeaderCtrl->GetItemCount())
    {
	    HDITEM hditem;
	    hditem.mask = HDI_TEXT;
	    hditem.pszText = strName.GetBuffer(256);
	    hditem.cchTextMax = 256;
	    pHeaderCtrl->GetItem(iCol, &hditem);
	    strName.ReleaseBuffer();
    }
    return strName;
}

/**
 * Author: sigmainfy 烟客旅人
 * Date:   Aug 14, 2014
 * Wesite: http://tech-wonderland.net/
 */
void CYourWindowClass::ExportToCSVFile(
				     const CListCtrl *plistctrlContent,
				     BOOL bIncludeHeaderNames,
				     char cDelimiter) // default to ',' and declared in the header file
{
	CFile filePersistent;
	CString strFilter = _T("CSV Files (*.csv)|*.csv|All Files (*.*)|*.*||");
	CFileDialog dlgSaveFile(
				FALSE,	     // Save As, not File Open
				_T(".csv"),  // default file name extentsion
				NULL,        // initial file name in the dialgo
				0,           // DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
				strFilter,   // filter
				this);       // parent window, i.e., Your own window class

	// copyright @ sigmainfy :
	// http://tech-wonderland.net/
	if (dlgSaveFile.DoModal() == IDOK)
	{
	    // 1. file
	    CString strFileName = dlgSaveFile.GetPathName(); // full path
	    filePersistent.Open(
			strFileName,
			CFile::modeCreate | CFile::modeWrite); // write and create user rights

	    // 2. archive
	    // Constructs a CArchive object and specifies
	    // whether it will be used for loading or storing objects.
	    CArchive archiveContent(
			    &filePersistent,
			    CArchive::store); // just storing obj

	    // 3. optional: header names
	    CHeaderCtrl *pheaderctrl = plistctrlContent->GetHeaderCtrl();
	    int iHeaderNameCount = pheaderctrl->GetItemCount();
	    CString strRightHaffSeparator(_T(""));
	    strRightHaffSeparator.Format(_T("\"%c "), cDelimiter);
	    if (TRUE == bIncludeHeaderNames)
	    {
		    CHeaderCtrl *pheaderctrl = plistctrlContent->GetHeaderCtrl();
		    CString strOneRecord(_T(""));
		    for (int i = 0; i < iHeaderNameCount - 1; ++i)
		    {
		            strOneRecord += _T("\"");
		            strOneRecord += this->GetColumnName(plistctrlContent, i);
		            strOneRecord += strRightHaffSeparator;
		    }
		    strOneRecord += _T("\"");
		    strOneRecord += this->GetColumnName(plistctrlContent, iHeaderNameCount - 1);
		    strOneRecord += _T("\"\r\n"); // windows change a line
		    archiveContent.Write(strOneRecord, strOneRecord.GetLength() * sizeof(_TCHAR));
	    }

	    int iItemCount = plistctrlContent->GetItemCount();
	    for (int i = 0; i < iItemCount; ++i)
	    {
		    CString strOneRecord(_T(""));
		    for (int j = 0; j < iHeaderNameCount - 1; ++j)
		    {
		            strOneRecord += _T("\"");
		            strOneRecord += plistctrlContent->GetItemText(i, j);
		            strOneRecord += strRightHaffSeparator;
		    }
		    strOneRecord += _T("\"");
		    strOneRecord += plistctrlContent->GetItemText(i, iHeaderNameCount - 1);
		    strOneRecord += _T("\"\r\n");

		    archiveContent.Write(strOneRecord, strOneRecord.GetLength() * sizeof(_TCHAR));
	    }

	    archiveContent.Close();
	    filePersistent.Close();
	}
	return;
}

To summarize the post, I just wrote some C++ code to export data from MFC list control into CSV file. I consider my code here to be quite reusable and extendable which applies to list control with any number of columns and row. And it supports different options with whether or not the header names should be included into the CSV file and the delimiter in the CSV file could be customized as well.

Written on August 15, 2014