跳過到頁腳內容
使用 IRONXL

如何使用 C# 中的 Interop 而非 IronXL 將資料表匯出到 Excel

對 .NET 開發人員而言,將 DataTable 匯出至 Excel 為何如此重要?

將資料從資料庫或應用程式匯出至 Excel 檔案,是組織高效分析、視覺化及分享資訊的基本需求。 Excel 檔案以其使用者友善的介面廣受認可,讓終端使用者能夠輕鬆地與資料互動並解讀資料。 透過將資料集轉換為 .xlsx 格式,開發人員可以確保無論接收者的技術背景如何,資料都能保持可存取性和良好的結構。

對於 .NET 開發人員而言,有兩種常見的方法:Microsoft Office Interop 以及專用的 Excel 程式庫(例如 IronXL)。 本指南將透過可運作的 C# 程式碼範例,逐步說明這兩種方法,比較其優缺點,並解釋何時適合在生產環境中採用每種方法。

Interop 與 IronXL 之間的主要差異為何?

在深入研究程式碼之前,了解這兩種方法之間的根本差異,有助於為任何專案做出正確的選擇。 此比較涵蓋技術架構、部署需求,以及在處理 DataTable 轉 Excel 匯出情境時的實際開發經驗。

C# 中 Microsoft Office Interop 與 IronXL 用於 Excel 匯出的比較
特點 Microsoft Office Interop IronXL
需安裝 Office 是的 -- 必須安裝 Microsoft Excel 否 -- 獨立函式庫
伺服器端支援 不建議使用(Microsoft) 全面支援
平台支援 僅限 Windows Windows、Linux、macOS、Azure
支援 .NET Core / .NET 5+ 限額 全面支援 (.NET 6、7、8、9、10)
資源管理 需要執行 COM 物件清理 標準 .NET 資源釋放
安裝方法 COM 參考資料 + Office 安裝 NuGet 包
執行緒模型 單執行緒公寓 (STA) 線程安全操作
大型資料集 記憶體密集型處理 高效的檔案導向方法
支援的檔案格式 XLSX、XLS、CSV XLSX、XLS、CSV、JSON、XML
許可證 需具備 Office 授權 提供商業授權

兩者的架構差異至關重要:Excel Interop 透過 COM 自動化 Microsoft Excel 應用程式本身,而 IronXL 則直接讀寫 Excel 檔案格式,無需啟動任何外部程序。 這項差異影響的範圍涵蓋從記憶體使用量到部署複雜性等各個層面。

如何安裝 IronXL 進行 Excel 匯出?

透過 NuGet 安裝 IronXL 僅需數秒鐘。 無需安裝任何額外軟體、Office 套件或進行系統設定。 此函式庫在 Windows、Linux 和 macOS 上安裝後即可立即執行,包括 Azure App Services、Azure Functions 以及容器執行個體。

開啟 NuGet 套件管理員控制台並執行:

Install-Package IronXL
dotnet add package IronXL
Install-Package IronXL
dotnet add package IronXL
SHELL

IronXL 支援.NET Framework 4.6.2+以及所有現代 .NET 版本,直到 .NET 10。安裝完成後,在文件頂部新增 using IronXL;,即可匯出。

如何在 C# 中使用 Interop 將 DataTable 匯出至 Excel?

傳統方法使用 Microsoft.Office.Interop.Excel 命名空間直接自動化 Excel。 此方法要求在執行程式碼的電腦上已安裝 Microsoft Excel。

Interop 的先決條件

在使用 Interop 之前,請確認:

  1. 開發與部署機器上已安裝 Microsoft Excel。
  2. Visual Studio 中新增了對"Microsoft Excel Object Library"的 COM 參考。
  3. 您的專案中已包含 Microsoft.Office.Interop.Excel 命名空間。

Interop 匯出程式碼

以下程式碼示範如何使用 C# 中的 Microsoft Office Interop 和頂級語句將 DataTable 匯出到 Excel 檔案:

using Microsoft.Office.Interop.Excel;
using System.Data;
using System.Runtime.InteropServices;

// Create a sample DataTable with employee data
DataTable dt = new DataTable("Employees");
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));

dt.Rows.Add(1, "John Smith", "Engineering", 75000);
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
dt.Rows.Add(3, "Michael Chen", "Finance", 70000);
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000);

// Initialize Excel Application object
Application excelApp = new Application
{
    Visible = false,
    DisplayAlerts = false
};

Workbook workbook = excelApp.Workbooks.Add();
Worksheet worksheet = (Worksheet)workbook.ActiveSheet;

try
{
    // Write column headers to the first row
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;
    }

    // Write data rows starting from row 2
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            worksheet.Cells[i + 2, j + 1] = dt.Rows[i][j].ToString();
        }
    }

    string filePath = @"C:\Reports\EmployeeReport_Interop.xlsx";
    workbook.SaveAs(filePath);
    Console.WriteLine("Excel file created using Interop.");
}
catch (Exception ex)
{
    Console.WriteLine("Error: " + ex.Message);
}
finally
{
    // Always release COM objects to prevent orphaned Excel processes
    workbook.Close();
    excelApp.Quit();
    Marshal.ReleaseComObject(worksheet);
    Marshal.ReleaseComObject(workbook);
    Marshal.ReleaseComObject(excelApp);
}
using Microsoft.Office.Interop.Excel;
using System.Data;
using System.Runtime.InteropServices;

// Create a sample DataTable with employee data
DataTable dt = new DataTable("Employees");
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));

dt.Rows.Add(1, "John Smith", "Engineering", 75000);
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
dt.Rows.Add(3, "Michael Chen", "Finance", 70000);
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000);

// Initialize Excel Application object
Application excelApp = new Application
{
    Visible = false,
    DisplayAlerts = false
};

Workbook workbook = excelApp.Workbooks.Add();
Worksheet worksheet = (Worksheet)workbook.ActiveSheet;

try
{
    // Write column headers to the first row
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;
    }

    // Write data rows starting from row 2
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        for (int j = 0; j < dt.Columns.Count; j++)
        {
            worksheet.Cells[i + 2, j + 1] = dt.Rows[i][j].ToString();
        }
    }

    string filePath = @"C:\Reports\EmployeeReport_Interop.xlsx";
    workbook.SaveAs(filePath);
    Console.WriteLine("Excel file created using Interop.");
}
catch (Exception ex)
{
    Console.WriteLine("Error: " + ex.Message);
}
finally
{
    // Always release COM objects to prevent orphaned Excel processes
    workbook.Close();
    excelApp.Quit();
    Marshal.ReleaseComObject(worksheet);
    Marshal.ReleaseComObject(workbook);
    Marshal.ReleaseComObject(excelApp);
}
Imports Microsoft.Office.Interop.Excel
Imports System.Data
Imports System.Runtime.InteropServices

' Create a sample DataTable with employee data
Dim dt As New DataTable("Employees")
dt.Columns.Add("EmployeeID", GetType(Integer))
dt.Columns.Add("Name", GetType(String))
dt.Columns.Add("Department", GetType(String))
dt.Columns.Add("Salary", GetType(Decimal))

dt.Rows.Add(1, "John Smith", "Engineering", 75000)
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000)
dt.Rows.Add(3, "Michael Chen", "Finance", 70000)
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000)

' Initialize Excel Application object
Dim excelApp As New Application With {
    .Visible = False,
    .DisplayAlerts = False
}

Dim workbook As Workbook = excelApp.Workbooks.Add()
Dim worksheet As Worksheet = CType(workbook.ActiveSheet, Worksheet)

Try
    ' Write column headers to the first row
    For i As Integer = 0 To dt.Columns.Count - 1
        worksheet.Cells(1, i + 1) = dt.Columns(i).ColumnName
    Next

    ' Write data rows starting from row 2
    For i As Integer = 0 To dt.Rows.Count - 1
        For j As Integer = 0 To dt.Columns.Count - 1
            worksheet.Cells(i + 2, j + 1) = dt.Rows(i)(j).ToString()
        Next
    Next

    Dim filePath As String = "C:\Reports\EmployeeReport_Interop.xlsx"
    workbook.SaveAs(filePath)
    Console.WriteLine("Excel file created using Interop.")
Catch ex As Exception
    Console.WriteLine("Error: " & ex.Message)
Finally
    ' Always release COM objects to prevent orphaned Excel processes
    workbook.Close()
    excelApp.Quit()
    Marshal.ReleaseComObject(worksheet)
    Marshal.ReleaseComObject(workbook)
    Marshal.ReleaseComObject(excelApp)
End Try
$vbLabelText   $csharpLabel

Application 物件代表 Excel 流程本身。 設定 Visible = false 可防止 Excel 在處理過程中開啟螢幕,這對於背景操作至關重要。 DisplayAlerts = false 設定會抑制原本會中斷自動化工作流程的對話方塊。

finally 區塊不是可選的-它必須使用 Marshal.ReleaseComObject 明確釋放每個 COM 物件。 若省略此步驟,將導致"工作管理員"中殘留孤立的 Excel 程序,這些程序會消耗記憶體,並最終導致伺服器運作不穩定。 這種清理模式是眾所周知的痛點,導致 Interop 不適合用於 Web 應用程式和服務。

如何使用 IronXL 將 DataTable 匯出至 Excel?

IronXL 提供了一種現代化的替代方案,無需安裝任何 Office 軟體即可運作。 此函式庫可直接讀寫 Excel 檔案,使其非常適合用於伺服器環境、雲端部署及跨平台應用程式。 請參閱完整的 IronXL 文件以獲取更多 API 詳情。

IronXL 匯出程式碼

以下程式碼顯示如何使用 IronXL 函式庫和頂級語句將 DataTable 檔案轉換為 Excel 檔案:

using IronXL;
using System.Data;

// Create a sample DataTable
DataTable dt = new DataTable("Employees");
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));

dt.Rows.Add(1, "John Smith", "Engineering", 75000);
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
dt.Rows.Add(3, "Michael Chen", "Finance", 70000);
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000);

// Create a new Excel workbook
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Employees");

// Write column headers to row 0
for (int i = 0; i < dt.Columns.Count; i++)
{
    sheet.SetCellValue(0, i, dt.Columns[i].ColumnName);
}

// Export DataTable rows to Excel cells
for (int i = 0; i < dt.Rows.Count; i++)
{
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        sheet.SetCellValue(i + 1, j, dt.Rows[i][j]);
    }
}

string filePath = @"C:\Reports\EmployeeReport_IronXL.xlsx";
workbook.SaveAs(filePath);
Console.WriteLine("Excel file created using IronXL.");
using IronXL;
using System.Data;

// Create a sample DataTable
DataTable dt = new DataTable("Employees");
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));

dt.Rows.Add(1, "John Smith", "Engineering", 75000);
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
dt.Rows.Add(3, "Michael Chen", "Finance", 70000);
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000);

// Create a new Excel workbook
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Employees");

// Write column headers to row 0
for (int i = 0; i < dt.Columns.Count; i++)
{
    sheet.SetCellValue(0, i, dt.Columns[i].ColumnName);
}

// Export DataTable rows to Excel cells
for (int i = 0; i < dt.Rows.Count; i++)
{
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        sheet.SetCellValue(i + 1, j, dt.Rows[i][j]);
    }
}

string filePath = @"C:\Reports\EmployeeReport_IronXL.xlsx";
workbook.SaveAs(filePath);
Console.WriteLine("Excel file created using IronXL.");
Imports IronXL
Imports System.Data

' Create a sample DataTable
Dim dt As New DataTable("Employees")
dt.Columns.Add("EmployeeID", GetType(Integer))
dt.Columns.Add("Name", GetType(String))
dt.Columns.Add("Department", GetType(String))
dt.Columns.Add("Salary", GetType(Decimal))

dt.Rows.Add(1, "John Smith", "Engineering", 75000)
dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000)
dt.Rows.Add(3, "Michael Chen", "Finance", 70000)
dt.Rows.Add(4, "Emily Davis", "Engineering", 80000)

' Create a new Excel workbook
Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim sheet As WorkSheet = workbook.CreateWorkSheet("Employees")

' Write column headers to row 0
For i As Integer = 0 To dt.Columns.Count - 1
    sheet.SetCellValue(0, i, dt.Columns(i).ColumnName)
Next

' Export DataTable rows to Excel cells
For i As Integer = 0 To dt.Rows.Count - 1
    For j As Integer = 0 To dt.Columns.Count - 1
        sheet.SetCellValue(i + 1, j, dt.Rows(i)(j))
    Next
Next

Dim filePath As String = "C:\Reports\EmployeeReport_IronXL.xlsx"
workbook.SaveAs(filePath)
Console.WriteLine("Excel file created using IronXL.")
$vbLabelText   $csharpLabel

IronXL 的方法採用類似的邏輯結構,但語法更簡潔,且無需處理 COM 的複雜性。 WorkBook.Create 方法以指定的格式初始化一個新的工作簿 -- ExcelFileFormat.XLSX 產生與 Excel 2007 及更高版本相容的現代 Office Open XML 檔案。 此函式庫亦支援 XLS 格式,以相容於舊式系統。

SetCellValue 使用符合標準 .NET 約定的從 0 開始的索引,從而減少了在索引系統之間轉換時經常發生的差一錯誤。 此方法會自動處理類型轉換:整數、字串、十進位和 DateTime 值將以適當的 Excel 儲存格類型寫入。

請注意,此處完全沒有清理程式碼。 IronXL 物件是標準的 .NET 受管物件,由垃圾回收器自動處理。 無需擔心孤立程序或 COM 參考計數的管理問題。

如何使用 Interop 或 IronXL 將資料表匯出至 Excel(C#):圖 1 - Excel 輸出

如何使用 Interop 或 IronXL 將資料表匯出至 Excel(C#):圖 2 - 控制台輸出

有關工作簿建立的更多詳細資訊,請參閱 IronXL 建立試算表指南

如何建立可重複使用的匯出方法?

生產應用通常需要一個可重複使用的方法,將任何 DataTable 匯出到 Excel 檔案。以下範例示範了一個輔助函數,它封裝了導出邏輯,處理空值,並在輸出目錄不存在時自動建立該目錄。更多範例請參閱IronXL 範例頁面

可重複使用的 IronXL 匯出輔助程式

using IronXL;
using IronXL.Styles;
using System;
using System.Data;
using System.IO;

// --- ExcelExporter helper ---

bool ExportToExcel(DataTable dt, string filePath)
{
    if (dt == null || dt.Rows.Count == 0)
        return false;

    try
    {
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet sheet = workbook.CreateWorkSheet(dt.TableName ?? "Sheet1");

        // Bold headers in the first row
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            var cell = sheet.GetCellAt(0, i);
            cell.Value = dt.Columns[i].ColumnName;
            cell.Style.Font.Bold = true;
        }

        // Data rows
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                var value = dt.Rows[i][j];
                sheet.SetCellValue(
                    i + 1, j,
                    (value == DBNull.Value || value == null) ? "" : value
                );
            }
        }

        FileInfo fileInfo = new FileInfo(filePath);
        if (!fileInfo.Directory!.Exists)
            fileInfo.Directory.Create();

        workbook.SaveAs(filePath);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Export failed: " + ex.Message);
        return false;
    }
}

// --- Usage ---

DataTable employees = new DataTable("Employees");
employees.Columns.Add("EmployeeID", typeof(int));
employees.Columns.Add("Name", typeof(string));
employees.Columns.Add("Department", typeof(string));
employees.Rows.Add(1, "John Smith", "Engineering");
employees.Rows.Add(2, "Sarah Johnson", "Marketing");

bool success = ExportToExcel(employees, @"C:\Reports\Export.xlsx");
Console.WriteLine(success ? "Export completed." : "Export failed.");
using IronXL;
using IronXL.Styles;
using System;
using System.Data;
using System.IO;

// --- ExcelExporter helper ---

bool ExportToExcel(DataTable dt, string filePath)
{
    if (dt == null || dt.Rows.Count == 0)
        return false;

    try
    {
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet sheet = workbook.CreateWorkSheet(dt.TableName ?? "Sheet1");

        // Bold headers in the first row
        for (int i = 0; i < dt.Columns.Count; i++)
        {
            var cell = sheet.GetCellAt(0, i);
            cell.Value = dt.Columns[i].ColumnName;
            cell.Style.Font.Bold = true;
        }

        // Data rows
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            for (int j = 0; j < dt.Columns.Count; j++)
            {
                var value = dt.Rows[i][j];
                sheet.SetCellValue(
                    i + 1, j,
                    (value == DBNull.Value || value == null) ? "" : value
                );
            }
        }

        FileInfo fileInfo = new FileInfo(filePath);
        if (!fileInfo.Directory!.Exists)
            fileInfo.Directory.Create();

        workbook.SaveAs(filePath);
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine("Export failed: " + ex.Message);
        return false;
    }
}

// --- Usage ---

DataTable employees = new DataTable("Employees");
employees.Columns.Add("EmployeeID", typeof(int));
employees.Columns.Add("Name", typeof(string));
employees.Columns.Add("Department", typeof(string));
employees.Rows.Add(1, "John Smith", "Engineering");
employees.Rows.Add(2, "Sarah Johnson", "Marketing");

bool success = ExportToExcel(employees, @"C:\Reports\Export.xlsx");
Console.WriteLine(success ? "Export completed." : "Export failed.");
Imports IronXL
Imports IronXL.Styles
Imports System
Imports System.Data
Imports System.IO

' --- ExcelExporter helper ---

Function ExportToExcel(dt As DataTable, filePath As String) As Boolean
    If dt Is Nothing OrElse dt.Rows.Count = 0 Then
        Return False
    End If

    Try
        Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
        Dim sheet As WorkSheet = workbook.CreateWorkSheet(If(dt.TableName, "Sheet1"))

        ' Bold headers in the first row
        For i As Integer = 0 To dt.Columns.Count - 1
            Dim cell = sheet.GetCellAt(0, i)
            cell.Value = dt.Columns(i).ColumnName
            cell.Style.Font.Bold = True
        Next

        ' Data rows
        For i As Integer = 0 To dt.Rows.Count - 1
            For j As Integer = 0 To dt.Columns.Count - 1
                Dim value = dt.Rows(i)(j)
                sheet.SetCellValue(i + 1, j, If(value Is DBNull.Value OrElse value Is Nothing, "", value))
            Next
        Next

        Dim fileInfo As New FileInfo(filePath)
        If Not fileInfo.Directory.Exists Then
            fileInfo.Directory.Create()
        End If

        workbook.SaveAs(filePath)
        Return True
    Catch ex As Exception
        Console.WriteLine("Export failed: " & ex.Message)
        Return False
    End Try
End Function

' --- Usage ---

Dim employees As New DataTable("Employees")
employees.Columns.Add("EmployeeID", GetType(Integer))
employees.Columns.Add("Name", GetType(String))
employees.Columns.Add("Department", GetType(String))
employees.Rows.Add(1, "John Smith", "Engineering")
employees.Rows.Add(2, "Sarah Johnson", "Marketing")

Dim success As Boolean = ExportToExcel(employees, "C:\Reports\Export.xlsx")
Console.WriteLine(If(success, "Export completed.", "Export failed."))
$vbLabelText   $csharpLabel

ExportToExcel 輔助函數接受任何 DataTable 和一個檔案路徑字串,如果匯出失敗或表為空,則傳回 false。 它會在寫入單元格之前檢查 DBNull.Value,從而優雅地處理缺失值。 建立目錄的步驟可以防止 DirectoryNotFoundException 中斷計畫匯出到新資料夾路徑的操作-這是部署到新環境時常見的生產問題。

使用 cell.Style.Font.Bold = true 套用粗體標題,無需額外配置即可產生專業外觀的輸出。 此範本易於擴充:可新增背景顏色、邊框或列寬自動調整功能,以符合貴組織的報表標準。

針對大型資料集的處理,IronXL 效能指南涵蓋了可將記憶體分配降至最低的批次寫入策略。 該庫還支援將一組相關的物件匯出到單一工作簿中的多個工作表中,這對於多工作表報表非常有用。

這兩種方法如何處理儲存格格式?

Professional Excel 匯出檔案通常需要格式設定:例如加粗標題、彩色儲存格、邊框以及數字格式。 這兩套函式庫均支援樣式設定,但在實現方式上,其冗長程度與可靠性存在顯著差異。

使用 IronXL 進行格式設定

using IronXL;
using IronXL.Styles;
using System.Data;

DataTable dt = new DataTable("Sales");
dt.Columns.Add("Product", typeof(string));
dt.Columns.Add("Revenue", typeof(decimal));
dt.Rows.Add("Widget A", 15000.50m);
dt.Rows.Add("Widget B", 22500.75m);

WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Sales");

// Write headers with light blue background and bold font
for (int i = 0; i < dt.Columns.Count; i++)
{
    var cell = sheet.GetCellAt(0, i);
    cell.Value = dt.Columns[i].ColumnName;
    cell.Style.Font.Bold = true;
    cell.Style.SetBackgroundColor("#ADD8E6");
    cell.Style.BottomBorder.SetColor("#000000");
    cell.Style.BottomBorder.Type = BorderType.Thin;
}

// Write data rows
for (int i = 0; i < dt.Rows.Count; i++)
{
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        sheet.SetCellValue(i + 1, j, dt.Rows[i][j]);
    }
}

workbook.SaveAs(@"C:\Reports\FormattedReport_IronXL.xlsx");
Console.WriteLine("Formatted Excel file created.");
using IronXL;
using IronXL.Styles;
using System.Data;

DataTable dt = new DataTable("Sales");
dt.Columns.Add("Product", typeof(string));
dt.Columns.Add("Revenue", typeof(decimal));
dt.Rows.Add("Widget A", 15000.50m);
dt.Rows.Add("Widget B", 22500.75m);

WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet sheet = workbook.CreateWorkSheet("Sales");

// Write headers with light blue background and bold font
for (int i = 0; i < dt.Columns.Count; i++)
{
    var cell = sheet.GetCellAt(0, i);
    cell.Value = dt.Columns[i].ColumnName;
    cell.Style.Font.Bold = true;
    cell.Style.SetBackgroundColor("#ADD8E6");
    cell.Style.BottomBorder.SetColor("#000000");
    cell.Style.BottomBorder.Type = BorderType.Thin;
}

// Write data rows
for (int i = 0; i < dt.Rows.Count; i++)
{
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        sheet.SetCellValue(i + 1, j, dt.Rows[i][j]);
    }
}

workbook.SaveAs(@"C:\Reports\FormattedReport_IronXL.xlsx");
Console.WriteLine("Formatted Excel file created.");
Imports IronXL
Imports IronXL.Styles
Imports System.Data

Dim dt As New DataTable("Sales")
dt.Columns.Add("Product", GetType(String))
dt.Columns.Add("Revenue", GetType(Decimal))
dt.Rows.Add("Widget A", 15000.50D)
dt.Rows.Add("Widget B", 22500.75D)

Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim sheet As WorkSheet = workbook.CreateWorkSheet("Sales")

' Write headers with light blue background and bold font
For i As Integer = 0 To dt.Columns.Count - 1
    Dim cell = sheet.GetCellAt(0, i)
    cell.Value = dt.Columns(i).ColumnName
    cell.Style.Font.Bold = True
    cell.Style.SetBackgroundColor("#ADD8E6")
    cell.Style.BottomBorder.SetColor("#000000")
    cell.Style.BottomBorder.Type = BorderType.Thin
Next

' Write data rows
For i As Integer = 0 To dt.Rows.Count - 1
    For j As Integer = 0 To dt.Columns.Count - 1
        sheet.SetCellValue(i + 1, j, dt.Rows(i)(j))
    Next
Next

workbook.SaveAs("C:\Reports\FormattedReport_IronXL.xlsx")
Console.WriteLine("Formatted Excel file created.")
$vbLabelText   $csharpLabel

IronXL 的樣式 API 採用簡潔的物件模型。 顏色值接受標準十六進位代碼,例如 #ADD8E6(淺藍色),無需在顏色系統之間轉換即可輕鬆匹配企業品牌。 BorderType.ThinBorderType.Thick 涵蓋了標準邊界場景,無需枚舉查找。

如何使用 Interop 或 IronXL 將資料表匯出至 Excel C#:圖 3 - 使用 IronXL 輸出格式

有關所有樣式設定選項(包括數字格式、條件格式化及儲存格合併),請參閱 IronXL 儲存格樣式指南以及邊框與對齊方式的文件

互通性格式設定的複雜性

Interop 等效項存取各個 Range 對象,並設定屬性,如 Font.BoldInterior.ColorBorders.LineStyle。 每次屬性存取都是一次 COM 進程間調用,這會增加開銷,並且如果 Excel 無回應,則會增加出現異常的機率。顏色值需要進行 System.Drawing.ColorTranslator.ToOle 轉換,並且每個樣式塊之後都必須跟上標準的 COM 清理鏈——至少需要三次 Marshal.ReleaseComObject 呼叫。

當在大型試算表中套用條件格式、欄位寬度或數字格式時,這種冗長性便會成為問題。 IronXL 能以更少的程式碼行數處理相同的情境,且無須擔心系統當機後 Excel 程序仍持續執行。

在 .NET 中進行 Excel 匯出的最佳實務有哪些?

在所有輸出例程中遵循一致的實作規範,可減少錯誤、提升可維護性,並使您的程式碼更易於測試與部署。

命名與路徑規範

匯出檔案應使用一致的命名約定:{ReportName}_{Timestamp}.xlsx。 可預測的檔案名稱能讓自動清理與歸檔作業變得簡單明瞭。 將輸出目錄儲存在應用程式配置中,而不是硬編碼路徑——這樣可以防止在部署到新環境時出現 DirectoryNotFoundException 錯誤。

錯誤處理

請將所有輸出邏輯封裝在 try-catch 區塊中,並在記錄例外狀況時提供足夠的上下文以利診斷失敗原因。 針對排程匯出作業,建議返回結果物件而非拋出例外狀況,以便呼叫服務能在不導致系統當機的情況下進行重試或通知操作人員。 上面的 ExportToExcel 輔助函數示範了這個模式,傳回值為 bool

大型資料集處理

對於超過 50,000 行的資料集,請分批串流資料以避免記憶體壓力。 IronXL 支援漸進式寫入,而 OpenXML SDK 則為超大檔案提供低階串流功能。 請完全避免在大型資料集上使用 Interop —— 其記憶體內模型會在規模擴大時導致顯著的效能下降。

跨平台部署

若應用程式運行於 Linux 或 macOS 環境(例如 Docker 容器或 Azure Linux App Services),IronXL 是唯一可行的選擇。由於 Interop 依賴 Excel COM 伺服器,因此無法在 Windows 以外的環境中運作。 請使用 .NET 跨平台部署指南,確認目標執行環境中所有依賴項皆可取得。

測試

針對匯出邏輯的單元測試應驗證:輸出檔案確實存在、包含預期的列數,且使用正確的欄位名稱。 IronXL 的 WorkBook.Load 方法使得在測試中無需啟動 Excel 即可輕鬆讀取匯出的檔案。 請參閱 IronXL 閱讀指南以獲取範例。

何時該選擇哪種方法?

正確的選擇取決於專案的具體需求、部署環境以及長期維護的考量。

在以下情況下選擇 Microsoft Office Excel Interop:

  • 現有系統已依賴 Interop,且無法進行遷移。
  • 進階的 Excel 功能(如巨集、樞紐分析表或圖表自動化)需要完整的 Excel 應用程式物件模型。
  • 開發桌面應用程式,使用者需安裝 Microsoft Excel,且應用程式以互動方式運行。
  • 部署環境完全受控,僅限 Windows 系統,且已具備 Office 授權。
  • 自動化現有 Excel 範本,其中包含複雜的內嵌公式或 VBA 程式碼。

選擇 IronXL 的情況:

  • 建置能產生 Excel 檔案匯出的網頁應用程式、REST API 或背景服務。
  • 部署至 Azure App Services、AWS Lambda 或 Docker 容器等雲端環境。
  • 需支援跨平台部署,適用於 Windows、Linux 或 macOS 環境。
  • 適用於 .NET Framework 4.6.2 以上版本,或支援 Interop 功能受限的現代 .NET 版本。
  • 需要可靠的資源管理,且無須擔心 COM 清理問題。
  • 避免在生產伺服器上依賴 Office 授權。
  • 建置需要生成獨立 Excel 檔案的多租戶應用程式。
  • 高效處理大型資料集,無需承受 COM 進程間通訊的額外負擔。
  • 需能匯出至多種格式,包括 XLSX、XLS、CSV、JSON 及 XML。

請參閱 IronXL 教學指南,了解更多應用情境,包括讀取現有 Excel 檔案、處理公式以及管理多個工作表

下一步計劃是什麼?

DataTable 匯出到 Excel 檔案是處理業務資料的 .NET 應用程式的基本要求。 無論是資料庫查詢、具有多個相關資料表的 DataSet,或是動態建置的記憶體集合,選擇合適的函式庫都能決定部署的彈性和長期的可維護性。

Microsoft Office Excel Interop 多年來一直為開發人員提供服務,但其對 Office 安裝的依賴、COM 的複雜性、未受支援的伺服器情境,以及資源管理方面的挑戰,使其在現代應用程式開發中變得越來越不切實際。

IronXL 提供了一種更簡潔的替代方案,可解決這些限制。 透過簡單的 NuGet 安裝、橫跨 Windows、Linux 和 macOS 的跨平台支援,以及遵循 .NET 規範的直觀 API,它消除了 Excel 互操作解決方案常有的部署困擾與資源管理陷阱。

首先,從 NuGet 安裝 IronXL,複製上面的一個程式碼範例,然後從測試中快速匯出 DataTableIronXL 快速入門指南能在短短幾分鐘內涵蓋最常見的使用情境。 當您準備投入生產環境時,請參閱 IronXL 授權頁面,選擇符合您團隊規模與部署模式的方案。 如需進一步了解,請瀏覽完整的 IronXL API 參考文件,並查閱 IronXL GitHub 儲存庫中的社群範例。

常見問題解答

在 C# 中匯出 DataTables 時,使用 IronXL 相較於 Excel Interop 的主要優勢為何?

IronXL 提供了一種更簡單、更有效率的方式,讓您能在 C# 中將 DataTables 匯出至 Excel,且無需在伺服器上安裝 Excel。

IronXL 在匯出至 Excel 時能否處理大型 DataTables?

是的,IronXL 經過效能優化,能夠處理大型 DataTables,確保快速且可靠地匯出至 Excel 檔案。

使用 IronXL 匯出資料時,是否需要安裝 Microsoft Excel?

不,IronXL 無需安裝 Microsoft Excel,因此非常適合用於伺服器端應用程式。

相較於 Interop,IronXL 如何簡化 DataTables 的匯出流程?

IronXL 透過消除與 Interop 相關的複雜設定和依賴項,提供直觀的 API 來匯出 DataTables,從而簡化了此流程。

IronXL 是否相容於 .NET Core,以便將 DataTables 匯出至 Excel?

是的,IronXL 完全相容於 .NET Core,讓您能在跨平台應用程式中將 DataTables 匯出至 Excel。

IronXL 可以將 DataTables 匯出為哪些檔案格式?

IronXL 可將 DataTables 匯出為多種 Excel 檔案格式,包括 XLSX、XLS 和 CSV。

IronXL 是否支援 Excel 試算表的樣式與格式設定?

是的,IronXL 支援進階樣式與格式設定選項,讓您能夠從 DataTables 建立精美的 Excel 試算表。

我可以使用 IronXL 在 C# 中自動化執行 Excel 相關任務嗎?

是的,IronXL 可用於自動化各種與 Excel 相關的任務,從匯出 DataTables 到複雜的資料分析操作皆可。

對於初次接觸 IronXL 的開發者來說,是否需要一段學習曲線?

IronXL 設計直觀且易於學習,並提供詳盡的文件與範例,協助開發者快速上手。

在商業專案中使用 IronXL 有哪些授權選項?

IronXL 提供多種授權方案以滿足不同專案需求,包括供商業用途的永久授權與訂閱授權。

Jordi Bardia
軟體工程師
Jordi 在 Python、C# 和 C++ 上最得心應手,當他不在 Iron Software 展現技術時,便在做遊戲編程。在分担產品测测试,產品開發和研究的责任時,Jordi 為持续的產品改進增值。他说这种多样化的经验使他受到挑战并保持参与, 而这也是他与 Iron Software 中工作一大乐趣。Jordi 在佛罗里达州迈阿密长大,曾在佛罗里达大学学习计算机科学和统计学。

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我