首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 將 DataTable 導出 Excel 完整方案:COM 互操作與開源庫對比

     編輯:C# 入門

將 DataTable 導出 Excel 是企業級應用的高頻需求。本文提供基於 Microsoft.Office.Interop.Excel (COM) 的經典方案,並分析其優缺點,推薦現代無依賴的開源庫替代方案。

方案一:COM 互操作 (傳統方案,需安裝 Office)

適用於服務器/客戶端均安裝 Office 且對格式控制要求極高 (如合併儲存格、樣式、圖表) 的場景。


using System;
using System.Data;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;

public class ExcelExporterCom
{
    public void ExportToExcel(DataTable dtSource, string filePath)
    {
        if (dtSource == null || dtSource.Rows.Count == 0) return;

        Excel.Application xlApp = null;
        Excel.Workbook xlBook = null;
        Excel.Worksheet xlSheet = null;

        try
        {
            xlApp = new Excel.Application();
            xlApp.DisplayAlerts = false; // 關閉覆蓋提示
            xlApp.ScreenUpdating = false; // 關閉屏幕刷新,提速

            xlBook = xlApp.Workbooks.Add(Type.Missing);
            xlSheet = (Excel.Worksheet)xlBook.ActiveSheet;
            xlSheet.Name = "數據導出";

            // 1. 寫入表頭
            for (int col = 0; col < dtSource.Columns.Count; col++)
            {
                xlSheet.Cells[1, col + 1] = dtSource.Columns[col].ColumnName;
                // 可選:設置表頭樣式
                // ((Excel.Range)xlSheet.Cells[1, col + 1]).Font.Bold = true;
            }

            // 2. 批量寫入數據 (陣列賦值比逐單元格快 100 倍以上)
            object[,] dataArray = new object[dtSource.Rows.Count, dtSource.Columns.Count];
            for (int row = 0; row < dtSource.Rows.Count; row++)
            {
                for (int col = 0; col < dtSource.Columns.Count; col++)
                {
                    dataArray[row, col] = dtSource.Rows[row][col];
                }
            }
            // 定義目標範圍並一次性賦值
            Excel.Range targetRange = xlSheet.Range[
                xlSheet.Cells[2, 1], 
                xlSheet.Cells[dtSource.Rows.Count + 1, dtSource.Columns.Count]
            ];
            targetRange.Value2 = dataArray;

            // 3. 自動調整列寬
            targetRange.EntireColumn.AutoFit();

            // 4. 保存
            xlBook.SaveAs(filePath, Excel.XlFileFormat.xlWorkbookDefault);
        }
        catch (Exception ex)
        {
            throw new Exception($"Excel 導出失敗: {ex.Message}", ex);
        }
        finally
        {
            // 關鍵:正確釋放 COM 對象,避免 Excel 進程殘留
            ReleaseComObject(xlSheet);
            ReleaseComObject(xlBook);
            if (xlApp != null)
            {
                xlApp.Quit();
                ReleaseComObject(xlApp);
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }

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

COM 方案調用示例


private void btnExport_Click(object sender, EventArgs e)
{
    using (SaveFileDialog sfd = new SaveFileDialog 
    { 
        Filter = "Excel 文件 (*.xlsx)|*.xlsx|Excel 97-2003 (*.xls)|*.xls",
        DefaultExt = "xlsx"
    })
    {
        if (sfd.ShowDialog() == DialogResult.OK)
        {
            try 
            {
                new ExcelExporterCom().ExportToExcel(dtFindCharge, sfd.FileName);
                MessageBox.Show("導出成功!");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"導出失敗: {ex.Message}");
            }
        }
    }
}

⚠️ COM 方案核心痛點

  • 強依賴 Office:服務器部署需安裝 Office,授權成本高,容器化部署極其困難。
  • 進程殘留風險:釋放不徹底導致後台殘留 EXCEL.EXE 進程,需定時清理。
  • 併發性能差:單線程 COM 組件,高併發導出極易卡死。
  • 32/64 位兼容性:需項目目標平台與 Office 位數一致。

方案二:開源庫 — 推薦用於生產環境

無需安裝 Office,純托管代碼,高性能,支援 .NET Core / .NET 5+ / Linux 容器部署。

庫特點適用場景
EPPlus (v5+ 商業授權)功能最全,支援樣式、圖表、樞紐分析表、數據驗證複雜報表、商業項目
NPOIApache POI 移植,支援 .xls/.xlsx,免費開源通用導出、舊版 .xls 支援
ClosedXMLAPI 簡潔優雅,基於 OpenXML SDK,免費現代 .NET 項目、簡潔代碼風格
MiniExcel輕量、流式讀寫、低內存、高性能大數據量導出 (百萬行)、WebAPI 導出

MiniExcel 導出示例 (高性能、低內存、推薦)


// NuGet: Install-Package MiniExcel
using MiniExcelLibs;
using System.Data;

public void ExportWithMiniExcel(DataTable dt, string path)
{
    // 一行代碼完成導出,自動處理類型、流式寫入,內存佔用極低
    MiniExcel.SaveAs(path, dt, sheetName: "數據導出");
    
    // 進階:自定義列類型、樣式
    // var config = new MiniExcelLibs.OpenXml.Configuration() { ... };
    // MiniExcel.SaveAs(path, dt, configuration: config);
}

ClosedXML 導出示例 (API 友好)


// NuGet: Install-Package ClosedXML
using ClosedXML.Excel;

public void ExportWithClosedXML(DataTable dt, string path)
{
    using (var workbook = new XLWorkbook())
    {
        // DataTable 直接轉 Worksheet,自動處理表頭、類型
        var worksheet = workbook.Worksheets.Add(dt, "數據導出");
        worksheet.Columns().AdjustToContents(); // 自動列寬
        workbook.SaveAs(path);
    }
}

總結建議

  1. 新項目 / 服務端 / 容器化部署:首選 MiniExcel (大數據) 或 ClosedXML (功能均衡)。
  2. 需複雜樣式/圖表/樞紐表且預算允許:EPPlus (商業授權)。
  3. 維護舊系統、必須用 .xls 格式:NPOI。
  4. 客戶端工具、用戶機器確裝 Office、需啟動 Excel 讓用戶二次編輯:可用 COM 方案,但務必做好 COM 釋放與異常處理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved