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

ListView 資料匯出 Word/Excel 完整函式庫(OLE 自動化)

     編輯:關於C++

功能概覽

提供兩個即拿即用的函式:ListView2Word、ListView2Excel,將 TListView 內容(含欄標、子項目)完整匯出為 Word 文件或 Excel 試算表,支援欄寬保留、標題列樣式、字體同步。

核心技術:OLE Variant 自動化

  • 透過 Variant::CreateObject("Word.Application") / "Excel.Application" 啟動應用程式
  • 使用 OlePropertyGet/Set、OleFunction/Procedure 操作物件模型
  • 全程隱藏介面 (Visible = false),背景完成後自動儲存關閉

ListView2Word 完整程式碼

void __fastcall ListView2Word(TListView* lv, String strDocFile) {
    Variant vWordApp, vTable, vCell;
    try {
        vWordApp = Variant::CreateObject("Word.Application");
    } catch (...) {
        MessageBox(0, "啟動 Word 失敗,請確認已安裝。", "ListView2Doc", MB_OK|MB_ICONERROR);
        return;
    }

    vWordApp.OlePropertySet("Visible", false);
    vWordApp.OlePropertyGet("Documents").OleFunction("Add");

    Variant vSelect = vWordApp.OlePropertyGet("Selection");
    vSelect.OlePropertyGet("Font").OlePropertySet("Size", lv->Font->Size);
    vSelect.OlePropertyGet("Font").OlePropertySet("Name", lv->Font->Name.c_str());

    int nRowCount = lv->Items->Count + 1; // +1 標題列
    nRowCount = nRowCount < 2 ? 2 : nRowCount;
    int nColCount = lv->Columns->Count;
    nColCount = nColCount < 1 ? 1 : nColCount;

    // 插入表格
    vWordApp.OlePropertyGet("ActiveDocument").OlePropertyGet("Tables")
        .OleProcedure("Add", vSelect.OlePropertyGet("Range"), nRowCount, nColCount, 1, 0);

    vTable = vWordApp.OlePropertyGet("ActiveDocument")
        .OleFunction("Range").OlePropertyGet("Tables").OleFunction("Item", 1);

    // 設定欄寬(Word 以 Points 為單位,約 1 px = 2 pt)
    for (int i = 0; i < nColCount; ++i) {
        int w = (i < lv->Columns->Count) ? lv->Columns->Items[i]->Width : 100;
        vTable.OlePropertyGet("Columns").OleFunction("Item", i+1)
            .OlePropertySet("PreferredWidthType", 3); // wdPreferredWidthPoints
        vTable.OlePropertyGet("Columns").OleFunction("Item", i+1)
            .OlePropertySet("PreferredWidth", w * 2);
    }

    // 寫入欄標
    for (int i = 0; i < lv->Columns->Count; ++i) {
        vCell = vTable.OleFunction("Cell", 1, i+1);
        vCell.OlePropertySet("Range", lv->Columns->Items[i]->Caption.c_str());
        vCell.OlePropertyGet("Shading")
            .OlePropertySet("BackgroundPatternColor", 14737632); // 灰底
    }

    // 寫入資料
    for (int i = 0; i < nRowCount - 1; ++i) {
        vCell = vTable.OleFunction("Cell", i+2, 1);
        vCell.OlePropertySet("Range", lv->Items->Item[i]->Caption.c_str());
        for (int j = 0; j < lv->Items->Item[i]->SubItems->Count; ++j) {
            if (lv->Columns->Count > j) {
                vCell = vTable.OleFunction("Cell", i+2, j+2);
                vCell.OlePropertySet("Range",
                    lv->Items->Item[i]->SubItems->Strings[j].c_str());
            }
        }
    }

    // 儲存並結束
    vWordApp.OlePropertyGet("ActiveDocument").OleProcedure("SaveAs", strDocFile.c_str());
    vWordApp.OlePropertyGet("ActiveDocument").OleProcedure("Close");
    Application->ProcessMessages();
    vWordApp.OleProcedure("Quit");
    Application->ProcessMessages();
    vWordApp = Unassigned;

    MessageBox(0, "ListView2Doc 轉換完成!", "ListView2Doc", MB_OK|MB_ICONINFORMATION);
}

ListView2Excel 完整程式碼

void __fastcall ListView2Excel(TListView* lv, String strXlsFile) {
    Variant vExcelApp, vSheet;
    try {
        vExcelApp = Variant::CreateObject("Excel.Application");
    } catch (...) {
        MessageBox(0, "啟動 Excel 失敗,請確認已安裝。", "ListView2Excel", MB_OK|MB_ICONERROR);
        return;
    }

    vExcelApp.OlePropertySet("Visible", false); // 背景執行
    vExcelApp.OlePropertyGet("Workbooks").OleFunction("Add", 1);

    vSheet = vExcelApp.OlePropertyGet("ActiveWorkbook").OlePropertyGet("Sheets", 1);

    // 字體同步
    vSheet.OleProcedure("Select");
    vSheet.OlePropertyGet("Cells").OleProcedure("Select");
    vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
        .OlePropertySet("Size", lv->Font->Size);
    vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
        .OlePropertySet("Name", lv->Font->Name.c_str());
    vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
        .OlePropertySet("FontStyle", "常規");
    vSheet.OlePropertyGet("Cells", 1, 1).OleProcedure("Select");

    int nRowCount = lv->Items->Count + 1;
    nRowCount = nRowCount < 2 ? 2 : nRowCount;
    int nColCount = lv->Columns->Count;
    nColCount = nColCount < 1 ? 1 : nColCount;

    // 欄寬(Excel 寬度單位約 1 px = 1/2.6)
    for (int i = 0; i < nColCount; ++i) {
        int w = (i < lv->Columns->Count) ? lv->Columns->Items[i]->Width : 100;
        vExcelApp.OlePropertyGet("Columns", i+1)
            .OlePropertySet("ColumnWidth", w / 2.6);
    }

    // 寫入欄標(灰底)
    for (int j = 0; j < lv->Columns->Count; ++j) {
        vExcelApp.OlePropertyGet("Rows", 1).OlePropertySet("RowHeight", 20);
        vSheet.OlePropertyGet("Cells", 1, j+1)
            .OlePropertySet("Value", lv->Columns->Items[j]->Caption.c_str());
        Variant vInter = vSheet.OlePropertyGet("Cells", 1, j+1).OlePropertyGet("Interior");
        vInter.OlePropertySet("ColorIndex", 15);
        vInter.OlePropertySet("Pattern", 1); // xlSolid
        vInter.OlePropertySet("PatternColorIndex", -4105); // xlAutomatic
    }

    // 寫入資料
    for (int i = 0; i < nRowCount - 1; ++i) {
        vExcelApp.OlePropertyGet("Rows", i+2).OlePropertySet("RowHeight", 16);
        vSheet.OlePropertyGet("Cells", i+2, 1)
            .OlePropertySet("Value", lv->Items->Item[i]->Caption.c_str());
        for (int j = 0; j < lv->Items->Item[i]->SubItems->Count; ++j) {
            vSheet.OlePropertyGet("Cells", i+2, j+2)
                .OlePropertySet("Value",
                    lv->Items->Item[i]->SubItems->Strings[j].c_str());
        }
    }

    vExcelApp.OlePropertyGet("ActiveWorkbook").OleFunction("SaveAs", strXlsFile.c_str());
    vExcelApp.OleFunction("Quit");
    vSheet = Unassigned; vExcelApp = Unassigned;

    MessageBox(0, "ListView2Excel 轉換完成!", "ListView2Excel", MB_OK|MB_ICONINFORMATION);
}

呼叫範例

ListView2Word(ListView1, "C:\\Export\\Report.doc");
ListView2Excel(ListView1, "C:\\Export\\Report.xls");

注意事項與優化建議

  • 需安裝 Office:目標機器必須安裝相應版本 Word/Excel
  • 大量資料效能:逐儲存格寫入較慢,大量資料建議改用陣列一次寫入 Range.Value = SafeArray
  • 版本相容:不同 Office 版本物件模型細節可能差異,建議測試目標環境
  • 例外處理:生產環境請加強 try-catch 並記錄錯誤日誌
  • 無 Office 環境:可改用第三方函式庫(如 LibreOffice UNO、ClosedXML、NPOI)或直接產生 XML/CSV

版本歷程

  • v0.1 (2005.10.12) 初版發布
  • v0.2 (2005.10.13) 新增標題列匯出、欄寬自適應、字體同步
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved