首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC CListCtrl 數據導出 Excel 完整方案 (ODBC 直連)

     編輯:關於VC++

方案概述

利用 MFC CDatabase + ODBC Excel 驅動,將 CListCtrl 所有數據 (含列標題) 直接寫入 `.xls` 文件,無需 Excel COM 自動化,無需安裝 Office,速度快、部署輕量。

關鍵技術點

1. 獲取列信息避坑

LVCOLUMN columnData;
columnData.mask = LVCF_TEXT;
columnData.cchTextMax = 100;  // 必須設置!否則 GetColumn 不返回文本
columnData.pszText = columnName.GetBuffer(100);

for (int i = 0; pList->GetColumn(i, &columnData); i++) {
    // columnData.pszText 即列標題
}
columnName.ReleaseBuffer();

常見錯誤:只設置 `mask = LVCF_TEXT` 卻忘記 `cchTextMax` 和 `pszText` 緩衝區,導致列名為空。

2. 計算列數

無直接 API,需從 0 開始遞增 `nCol` 直到 `GetColumn` 返回 FALSE。

3. ODBC 連接字符串構建

CString sSql;
sSql.Format(_T("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s"),
            sDriver, sExcelFile, sExcelFile);
  • `FIRSTROWHASNAMES=1`:第一行作為列名
  • `CREATE_DB`:自動創建文件
  • `DBQ`:文件路徑

完整導出函數

void ExportListToExcel(CListCtrl* pList, CString strTitle) {
    if (pList->GetItemCount() == 0) return;

    CDatabase database;
    CString sDriver = GetExcelDriver();  // 註冊表查找 "Microsoft Excel Driver (*.xls)"
    if (sDriver.IsEmpty()) {
        AfxMessageBox(_T("未安裝 Excel 驅動!"));
        return;
    }

    CString sExcelFile;
    if (!GetDefaultXlsFileName(sExcelFile)) return;  // "另存為" 對話框

    CString sSql = _T("");
    CString tableName = strTitle;
    CString strH, strV;

    // 1. 打開/創建數據庫 (即 .xls 文件)
    if (database.OpenEx(sSql, CDatabase::noOdbcDialog)) {
        // 2. 構建 CREATE TABLE 語句
        LVCOLUMN columnData;
        CString columnName;
        columnData.mask = LVCF_TEXT;
        columnData.cchTextMax = 100;
        columnData.pszText = columnName.GetBuffer(100);

        int columnNum = 0;
        for (int i = 0; pList->GetColumn(i, &columnData); i++) {
            if (i != 0) { sSql += _T(", "); strH += _T(", "); }
            sSql += _T(" ") + columnData.pszText + _T(" TEXT");
            strH += _T(" ") + columnData.pszText + _T(" ");
            columnNum = i + 1;
        }
        columnName.ReleaseBuffer();

        sSql = _T("CREATE TABLE ") + tableName + _T(" (") + sSql + _T(" )");
        database.ExecuteSQL(sSql);

        // 3. 插入數據行
        for (int nItemIndex = 0; nItemIndex < pList->GetItemCount(); nItemIndex++) {
            strV = _T("");
            for (int i = 0; i < columnNum; i++) {
                if (i != 0) strV += _T(", ");
                CString cellText = pList->GetItemText(nItemIndex, i);
                cellText.Replace(_T("'"), _T("''"));  // 轉義單引號
                strV += _T("'") + cellText + _T("'");
            }
            sSql = _T("INSERT INTO ") + tableName + _T(" (") + strH + _T(") VALUES (") + strV + _T(")");
            database.ExecuteSQL(sSql);
        }

        database.Close();
        AfxMessageBox(_T("導出成功:") + sExcelFile);
    }
}

輔助函數

獲取 Excel 驅動名稱

CString GetExcelDriver() {
    CString strDriver;
    // 遍歷 ODBC 驅動註冊表項
    // HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers
    // 查找包含 "Excel" 的驅動名稱
    return strDriver;  // 如 "Microsoft Excel Driver (*.xls)"
}

默認文件名 (另存為對話框)

BOOL GetDefaultXlsFileName(CString& sFile) {
    CFileDialog dlg(FALSE, _T("xls"), _T("Export.xls"),
                    OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
                    _T("Excel 文件 (*.xls)|*.xls||"));
    if (dlg.DoModal() == IDOK) {
        sFile = dlg.GetPathName();
        return TRUE;
    }
    return FALSE;
}

優缺點分析

優點缺點
無需安裝 Office/Excel僅支持 .xls (Excel 97-2003),不支持 .xlsx
純數據導出,速度極快無法設置單元格格式 (顏色、字體、寬度、公式)
部署簡單,只需 ODBC 驅動 (Windows 內建)大數據量時 INSERT 逐條執行較慢,可批次優化
代碼純 C++/MFC,無 COM 依賴64 位程序需 64 位 Excel 驅動 (Office 64位或 Access Database Engine)

進階優化建議

  1. 批次插入:拼接多行 `VALUES (...), (...), ...` 減少 `ExecuteSQL` 調用
  2. 支持 .xlsx:改用 `Microsoft.ACE.OLEDB.12.0` Provider 或 OpenXML SDK
  3. 格式保留:需求複雜時改用 Excel COM 自動化 (`_Application`, `Workbook`, `Worksheet`)
  4. 導出進度條:大數據量時在線程中導出,UI 顯示進度
  5. 內容轉義:除單引號外,處理換行符、制表符等特殊字符

總結

此方案適合「純數據導出、無 Office 環境、追求簡單部署」的場景。代碼結構清晰,封裝為通用函數即可在專案中複用。若需專業報表功能,建議遷移至 COM 自動化或第三方庫 (如 libxl, OpenXLSX)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved