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

C# 操作 Excel 完整指南:COM 互操作、資料匯出、部署與避坑指南

     編輯:關於C語言

前言

Excel 作為最通用的試算表格式,是企業報表、資料匯出、列印客製化的首選。本文完整說明 C# 透過 COM 互操作操作 Excel 的架構、核心物件模型、實作範例、記憶體管理與部署注意事項。

Excel 物件模型核心層級

層級物件說明
1ApplicationExcel 應用程式本身,進入點
2Workbook活頁簿(.xlsx 檔案),含多個工作表
3Worksheet工作表(分頁),含儲存格
4Range儲存格區塊,核心操作單位

環境建置

  1. Visual Studio 專案 → 加入參考 → COM → Microsoft Excel 16.0 Object Library(版本依安裝 Office 而定)
  2. 自動產生 Interop 組件(Microsoft.Office.Interop.Excel.dll)
  3. 引用命名空間:using Excel = Microsoft.Office.Interop.Excel;

基礎操作:建立、寫入、顯示

using Excel = Microsoft.Office.Interop.Excel;

var app = new Excel.Application();
app.Visible = true; // 可見模式方便除錯,生產環境建議 false

var workbook = app.Workbooks.Add(Type.Missing);
var worksheet = (Excel.Worksheet)workbook.ActiveSheet;

// 寫入單一儲存格
worksheet.Cells[1, 1] = "標題";
worksheet.Cells[1, 2] = "數值";

// 批次寫入 Range(效能較好)
var range = worksheet.Range["A2", "B10"];
range.Value2 = new object[,] 
{
    { "項目1", 100 },
    { "項目2", 200 },
    { "項目3", 300 }
};

// 儲存
workbook.SaveAs(@"C:\Temp\Report.xlsx");
workbook.Close();
app.Quit();

實戰範例:資料庫查詢匯出 Excel

public void ExportToExcel(string connectionString, string query, string outputPath)
{
    Excel.Application app = null;
    Excel.Workbook wb = null;
    Excel.Worksheet ws = null;

    try
    {
        app = new Excel.Application();
        app.DisplayAlerts = false; // 關閉覆蓋確認對話框
        wb = app.Workbooks.Add();
        ws = (Excel.Worksheet)wb.ActiveSheet;

        using (var conn = new System.Data.OleDb.OleDbConnection(connectionString))
        using (var cmd = new System.Data.OleDb.OleDbCommand(query, conn))
        {
            conn.Open();
            using (var reader = cmd.ExecuteReader())
            {
                // 寫入欄位名
                for (int i = 0; i < reader.FieldCount; i++)
                    ws.Cells[1, i + 1] = reader.GetName(i);

                // 寫入資料
                int row = 2;
                while (reader.Read())
                {
                    for (int i = 0; i < reader.FieldCount; i++)
                        ws.Cells[row, i + 1] = reader.GetValue(i)?.ToString();
                    row++;
                }
            }
        }

        // 自動調整欄寬
        ws.Columns.AutoFit();
        wb.SaveAs(outputPath);
    }
    finally
    {
        // 關鍵:正確釋放 COM 物件
        ReleaseComObject(ws);
        ReleaseComObject(wb);
        if (app != null)
        {
            app.Quit();
            ReleaseComObject(app);
        }
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

private void ReleaseComObject(object obj)
{
    if (obj != null && System.Runtime.InteropServices.Marshal.IsComObject(obj))
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
    }
}

記憶體管理:受控 vs 非受控

Excel Interop 屬於 非受控 COM 物件,GC 不會自動釋放。必須:

  • 明確呼叫 Marshal.ReleaseComObject()
  • 避免「雙重點號」:app.Workbooks.Add() 會產生中間 RCW 物件洩漏
  • 正確寫法:
// 錯誤:產生無法釋放的中間物件
var ws = app.Workbooks.Add().ActiveSheet;

// 正確:每層存變數再釋放
var wb = app.Workbooks.Add();
var ws = (Excel.Worksheet)wb.ActiveSheet;
// ... 使用 ...
ReleaseComObject(ws);
ReleaseComObject(wb);

效能優化技巧

技巧說明
關閉螢幕更新app.ScreenUpdating = false;
關閉自動計算app.Calculation = Excel.XlCalculation.xlCalculationManual;
批次寫入 Range.Value2一次寫入二維陣列 object[,],避免逐格寫入
避免在迴圈中存取 Cells每次存取都是跨程序呼叫,極慢
使用 UsedRange僅處理有資料區域

部署注意事項

  1. 目標機器必須安裝 Excel:Interop 只是包裝層,需實際 Excel 執行引擎
  2. 位元數一致:應用程式、Office、Interop 組件需同為 32-bit 或 64-bit
  3. 註冊表/權限:DCOM 設定可能需調整「Microsoft Excel Application」啟動權限(特別是 IIS/服務帳號)
  4. 無 Office 環境替代方案:
  • EPPlus:純 .NET、支援 .xlsx、無 Office 依賴、LGPL/商業授權
  • ClosedXML:API 友善、MIT 授權
  • NPOI:支援 .xls/.xlsx、Apache 授權
  • OpenXML SDK:微軟官方、底層、效能最強、學習曲線較陡

常見問題排查

現象原因解決
Excel 程序殘留不關閉COM 物件未釋放完整 ReleaseComObject + GC.Collect
存取被拒絕 (0x800A03EC)檔案被佔用/唯讀/路徑錯誤檢查路徑、關閉 Excel、檢查權限
中文亂碼編碼不匹配確保 .NET 字串正確傳遞,Range.Value2 接受 Unicode
大量資料極慢逐格跨程序呼叫改用 Range.Value2 = object[,]

現代化建議

新專案優先考慮 EPPlus 或 ClosedXML,僅在需操作巨集、列印、圖表、樞紐分析等 Excel 獨有功能時,才使用 Interop。Interop 適合「自動化既有 Excel 檔案」,不適合「高效能產生報表」。

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