如何使用 IronXL 在 C# 中將 DataGridView 匯出到 Excel
從DataGridView導出資料到Excel文件,只需使用IronXL編寫幾行C#程式碼即可實現。 建立一個.xlsx文件 - 無需安裝Microsoft Office。
如何設置Windows Forms專案以實現Excel導出?
Windows Forms是在.NET生態系統中廣泛用於構建桌面應用程式的基礎GUI程式庫。 DataTable、資料庫查詢結果或記憶體列表。
將該網格資料導出到Excel滿足了多種日常需求——將報告發送給利益相關者,存檔以便審計,或將資料餵入下游分析工具。 傳統的兩種方法是使用Microsoft Office Interop和第三方程式庫。 Interop要求每台運行應用程式的機器上均安裝Excel副本,會產生COM物件生命週期問題,並且在伺服器或雲部署中表現不佳。 如IronXL、ClosedXML和Syncfusion等程式庫通過直接寫入Open XML文件格式而不依賴Office來避免這些問題。
本指南演示了針對.NET 10的IronXL方法,儘管IronXL支持.NET Framework 4.6.2及所有現代.NET版本。
前提條件
在編寫任何導出程式碼前,請確認以下條件已滿足:
- Visual Studio 2022或更高版本
- .NET 10 SDK已安裝
- 一個包含
DataGridView控制項的Windows Forms App專案 - NuGet存取以安裝IronXL
如何安裝IronXL?
在Visual Studio中打開程式包管理器控制台,運行以下任何一個命令:
Install-Package IronXL.Excel
或者,在解決方案資源管理器中右鍵點擊專案,選擇管理NuGet封裝,搜索IronXL.Excel,然後點擊安裝。

安裝完成後,在任何使用Excel功能的文件頂部新增IronXL的using指令:
using IronXL;
using System.Data;
using IronXL;
using System.Data;
Imports IronXL
Imports System.Data
IronXL支持每個常見的試算表格式:XLSX、XLS、CSV和TSV。 本指南全程使用XLSX,因為它是現代Excel版本的預設格式。
如何用樣本資料填充DataGridView?
在本演練中,窗體包含一個名為btnExport的按鈕。 網格在窗體的DataTable中的員工記錄進行填充:
void Form1_Load(object sender, EventArgs e)
{
var dt = new DataTable();
// Define columns with the appropriate .NET type
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));
// Add sample rows
dt.Rows.Add(101, "Sarah Johnson", "Engineering", 85000m);
dt.Rows.Add(102, "Michael Chen", "Marketing", 72000m);
dt.Rows.Add(103, "Emily Davis", "Finance", 91000m);
dt.Rows.Add(104, "James Wilson", "Engineering", 78000m);
DataGridView1.DataSource = dt;
}
void Form1_Load(object sender, EventArgs e)
{
var dt = new DataTable();
// Define columns with the appropriate .NET type
dt.Columns.Add("EmployeeID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Department", typeof(string));
dt.Columns.Add("Salary", typeof(decimal));
// Add sample rows
dt.Rows.Add(101, "Sarah Johnson", "Engineering", 85000m);
dt.Rows.Add(102, "Michael Chen", "Marketing", 72000m);
dt.Rows.Add(103, "Emily Davis", "Finance", 91000m);
dt.Rows.Add(104, "James Wilson", "Engineering", 78000m);
DataGridView1.DataSource = dt;
}
Option Strict On
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable()
' Define columns with the appropriate .NET type
dt.Columns.Add("EmployeeID", GetType(Integer))
dt.Columns.Add("Name", GetType(String))
dt.Columns.Add("Department", GetType(String))
dt.Columns.Add("Salary", GetType(Decimal))
' Add sample rows
dt.Rows.Add(101, "Sarah Johnson", "Engineering", 85000D)
dt.Rows.Add(102, "Michael Chen", "Marketing", 72000D)
dt.Rows.Add(103, "Emily Davis", "Finance", 91000D)
dt.Rows.Add(104, "James Wilson", "Engineering", 78000D)
DataGridView1.DataSource = dt
End Sub
每個列都定義了特定的.NET型別,以便後續的數字比較和格式化正確運作。 DataGridView,並且網格在窗體打開時自動呈現所有行。 在生產中,這些資料通常來自資料庫查詢、ORM結果集,或REST API回應,而非硬編碼值。

理解DataGridView資料模型
一個Rows(用於實際的資料單元)。 每個Cells集合。 每個單元格的Value屬性返回一個需要轉型或轉換才能寫入Excel單元格的裝箱物件。 理解這種層次結構對於編寫可靠的導出迴圈至關重要。
幕後的DataTable儲存型別化的值,因此小數工資不需要在寫入IronXL工作表之前進行字串轉換。 IronXL的DateTime重載,允許您在輸出文件中保留原始資料型別。
如何將DataGridView資料導出到包含列標題的Excel文件?
導出邏輯位於按鈕的點擊處理器內。 程式碼建立一個新的WorkBook,檢索預設工作表,將列標題寫入第一行,然後將每個資料行寫在其下方:
void btnExport_Click(object sender, EventArgs e)
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
// Write column headers to row index 0
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
// Write data rows starting at row index 1
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cellValue = DataGridView1.Rows[row].Cells[col].Value;
if (cellValue is not null)
{
sheet.SetCellValue(row + 1, col, cellValue.ToString()!);
}
}
}
string outputPath = "EmployeeData.xlsx";
workbook.SaveAs(outputPath);
MessageBox.Show("Export complete. File saved to: " + outputPath, "Success");
}
void btnExport_Click(object sender, EventArgs e)
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
// Write column headers to row index 0
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
// Write data rows starting at row index 1
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cellValue = DataGridView1.Rows[row].Cells[col].Value;
if (cellValue is not null)
{
sheet.SetCellValue(row + 1, col, cellValue.ToString()!);
}
}
}
string outputPath = "EmployeeData.xlsx";
workbook.SaveAs(outputPath);
MessageBox.Show("Export complete. File saved to: " + outputPath, "Success");
}
Private Sub btnExport_Click(sender As Object, e As EventArgs)
Dim workbook = WorkBook.Create()
Dim sheet = workbook.DefaultWorkSheet
' Write column headers to row index 0
For col As Integer = 0 To DataGridView1.Columns.Count - 1
sheet.SetCellValue(0, col, DataGridView1.Columns(col).HeaderText)
Next
' Write data rows starting at row index 1
For row As Integer = 0 To DataGridView1.Rows.Count - 1
For col As Integer = 0 To DataGridView1.Columns.Count - 1
Dim cellValue As Object = DataGridView1.Rows(row).Cells(col).Value
If cellValue IsNot Nothing Then
sheet.SetCellValue(row + 1, col, cellValue.ToString())
End If
Next
Next
Dim outputPath As String = "EmployeeData.xlsx"
workbook.SaveAs(outputPath)
MessageBox.Show("Export complete. File saved to: " & outputPath, "Success")
End Sub
WorkBook物件表示記憶體中整個Excel文件。 DefaultWorkSheet回傳第一個工作表,而無需顯式建立。 外迴圈將HeaderText中的標題文字寫入零行。 巢狀迴圈隨後迭代每個資料行,檢查是否為null,然後將單元格值轉換為字串。 row + 1偏移量將資料下移至標題行以下。 SaveAs將完成的工作簿作為Open XML XLSX文件寫入指定路徑。

生成的文件可以在Excel、Google試算表或任何能讀取XLSX格式的應用程式中打開。 列標題出現在第一行,並且所有資料行按在DataGridView中出現的順序跟隨。
如何將單元格格式應用于導出的Excel文件?
單純的資料轉儲是功能性的,但還未準備好展示。 IronXL的樣式API允許您在保存前應用粗體字體、背景顏色、文字顏色和數字格式到任何單元格範圍:
void ExportWithFormatting()
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
// Write column headers
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
// Style the header row: bold white text on blue background
var headerRange = sheet.GetRange("A1:D1");
headerRange.Style.Font.Bold = true;
headerRange.Style.SetBackgroundColor("#4472C4");
headerRange.Style.Font.SetColor("#FFFFFF");
// Locate the Salary column index
int salaryColIndex = -1;
for (int i = 0; i < DataGridView1.Columns.Count; i++)
{
if (string.Equals(DataGridView1.Columns[i].HeaderText, "Salary",
StringComparison.OrdinalIgnoreCase))
{
salaryColIndex = i;
break;
}
}
// Write data rows, preserving numeric types
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
if (DataGridView1.Rows[row].IsNewRow) continue;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cellValue = DataGridView1.Rows[row].Cells[col].Value;
if (cellValue is null) continue;
int targetRow = row + 1;
if (col == salaryColIndex)
{
// Write salary as a true numeric decimal
if (decimal.TryParse(cellValue.ToString(),
System.Globalization.NumberStyles.Number,
System.Globalization.CultureInfo.InvariantCulture,
out decimal decValue))
{
sheet.SetCellValue(targetRow, col, decValue);
}
else
{
sheet.SetCellValue(targetRow, col, cellValue.ToString()!);
}
}
else
{
sheet.SetCellValue(targetRow, col, cellValue.ToString()!);
}
}
}
// Apply currency format to the salary column data range
var salaryRange = sheet.GetRange("D2:D5");
salaryRange.FormatString = "$#,##0";
workbook.SaveAs("FormattedEmployeeData.xlsx");
}
void ExportWithFormatting()
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
// Write column headers
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
// Style the header row: bold white text on blue background
var headerRange = sheet.GetRange("A1:D1");
headerRange.Style.Font.Bold = true;
headerRange.Style.SetBackgroundColor("#4472C4");
headerRange.Style.Font.SetColor("#FFFFFF");
// Locate the Salary column index
int salaryColIndex = -1;
for (int i = 0; i < DataGridView1.Columns.Count; i++)
{
if (string.Equals(DataGridView1.Columns[i].HeaderText, "Salary",
StringComparison.OrdinalIgnoreCase))
{
salaryColIndex = i;
break;
}
}
// Write data rows, preserving numeric types
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
if (DataGridView1.Rows[row].IsNewRow) continue;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cellValue = DataGridView1.Rows[row].Cells[col].Value;
if (cellValue is null) continue;
int targetRow = row + 1;
if (col == salaryColIndex)
{
// Write salary as a true numeric decimal
if (decimal.TryParse(cellValue.ToString(),
System.Globalization.NumberStyles.Number,
System.Globalization.CultureInfo.InvariantCulture,
out decimal decValue))
{
sheet.SetCellValue(targetRow, col, decValue);
}
else
{
sheet.SetCellValue(targetRow, col, cellValue.ToString()!);
}
}
else
{
sheet.SetCellValue(targetRow, col, cellValue.ToString()!);
}
}
}
// Apply currency format to the salary column data range
var salaryRange = sheet.GetRange("D2:D5");
salaryRange.FormatString = "$#,##0";
workbook.SaveAs("FormattedEmployeeData.xlsx");
}
Option Strict On
Sub ExportWithFormatting()
Dim workbook = WorkBook.Create()
Dim sheet = workbook.DefaultWorkSheet
' Write column headers
For col As Integer = 0 To DataGridView1.Columns.Count - 1
sheet.SetCellValue(0, col, DataGridView1.Columns(col).HeaderText)
Next
' Style the header row: bold white text on blue background
Dim headerRange = sheet.GetRange("A1:D1")
headerRange.Style.Font.Bold = True
headerRange.Style.SetBackgroundColor("#4472C4")
headerRange.Style.Font.SetColor("#FFFFFF")
' Locate the Salary column index
Dim salaryColIndex As Integer = -1
For i As Integer = 0 To DataGridView1.Columns.Count - 1
If String.Equals(DataGridView1.Columns(i).HeaderText, "Salary", StringComparison.OrdinalIgnoreCase) Then
salaryColIndex = i
Exit For
End If
Next
' Write data rows, preserving numeric types
For row As Integer = 0 To DataGridView1.Rows.Count - 1
If DataGridView1.Rows(row).IsNewRow Then Continue For
For col As Integer = 0 To DataGridView1.Columns.Count - 1
Dim cellValue As Object = DataGridView1.Rows(row).Cells(col).Value
If cellValue Is Nothing Then Continue For
Dim targetRow As Integer = row + 1
If col = salaryColIndex Then
' Write salary as a true numeric decimal
Dim decValue As Decimal
If Decimal.TryParse(cellValue.ToString(), Globalization.NumberStyles.Number, Globalization.CultureInfo.InvariantCulture, decValue) Then
sheet.SetCellValue(targetRow, col, decValue)
Else
sheet.SetCellValue(targetRow, col, cellValue.ToString())
End If
Else
sheet.SetCellValue(targetRow, col, cellValue.ToString())
End If
Next
Next
' Apply currency format to the salary column data range
Dim salaryRange = sheet.GetRange("D2:D5")
salaryRange.FormatString = "$#,##0"
workbook.SaveAs("FormattedEmployeeData.xlsx")
End Sub
A1:D1)來選擇一個連續的單元格區塊。 設置Style.Font.SetColor將這些格式應用于所選範圍內的每個單元格。 對於數字列,將值寫入$#,##0的數字格式。 以字串保存的單元格不會響應數字格式程式碼。

您可以擴展此模式以應用交替行著色、列寬自動調整或凍結窗格,具體可參考<IronXL樣式文件>。
如何將DataGridView資料導出為CSV而非XLSX?
某些工作流程需要CSV輸出,以便與舊系統或輕量級資料管道相容。 IronXL處理CSV導出時,不需要對主程式碼進行額外的配置更改:
void ExportToCsv()
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
if (DataGridView1.Rows[row].IsNewRow) continue;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cell = DataGridView1.Rows[row].Cells[col].Value;
if (cell is not null)
sheet.SetCellValue(row + 1, col, cell.ToString()!);
}
}
// Saving with a .csv extension produces a comma-separated file
workbook.SaveAs("EmployeeData.csv");
}
void ExportToCsv()
{
var workbook = WorkBook.Create();
var sheet = workbook.DefaultWorkSheet;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
sheet.SetCellValue(0, col, DataGridView1.Columns[col].HeaderText);
}
for (int row = 0; row < DataGridView1.Rows.Count; row++)
{
if (DataGridView1.Rows[row].IsNewRow) continue;
for (int col = 0; col < DataGridView1.Columns.Count; col++)
{
object? cell = DataGridView1.Rows[row].Cells[col].Value;
if (cell is not null)
sheet.SetCellValue(row + 1, col, cell.ToString()!);
}
}
// Saving with a .csv extension produces a comma-separated file
workbook.SaveAs("EmployeeData.csv");
}
Sub ExportToCsv()
Dim workbook = WorkBook.Create()
Dim sheet = workbook.DefaultWorkSheet
For col As Integer = 0 To DataGridView1.Columns.Count - 1
sheet.SetCellValue(0, col, DataGridView1.Columns(col).HeaderText)
Next
For row As Integer = 0 To DataGridView1.Rows.Count - 1
If DataGridView1.Rows(row).IsNewRow Then Continue For
For col As Integer = 0 To DataGridView1.Columns.Count - 1
Dim cell As Object = DataGridView1.Rows(row).Cells(col).Value
If cell IsNot Nothing Then
sheet.SetCellValue(row + 1, col, cell.ToString())
End If
Next
Next
' Saving with a .csv extension produces a comma-separated file
workbook.SaveAs("EmployeeData.csv")
End Sub
唯一的變化是將文件擴展名傳遞給SaveAs,與XLSX導出的變化。 IronXL檢測擴展名並自動以正確的格式序列化工作簿。 這種一致性意味著無論輸出格式如何,您的資料寫入邏輯始終保持一致 - 這是相對於需要為每種格式提供單獨程式碼路徑之程式庫的一大優勢。
當下游消費者是Python pandas腳本、資料庫批量導入工具或無法讀取二進制XLSX文件的分析平台時,CSV導出尤其有用。
如何有效地處理大型DataGridView資料集?
對於包含數萬行的網格,性能將成為需要考慮的問題。 以下模式通過一次性構造整個資料集來減少記憶體壓力:
| 方法 | 處理的行數 | 需要安裝Office | 型別保留 |
|---|---|---|---|
| Microsoft.Office.Interop.Excel | 最多約65k(緩慢) | 是 | 部分 |
| IronXL(字串單元格) | 1M+行 | 否 | 否(全文字) |
| IronXL(型別化單元格) | 1M+行 | 否 | 是 |
| IronXL從DataTable | 1M+行 | 否 | 是(自動) |
當DataTable時,可以使用WorkSheet.LoadDataTable方法直接將表載入到IronXL中,完全避免逐個單元格迭代。 這種方法更快,並能自動保留所有列型別。
對於非由DataTable支援的網格,先前顯示的逐個單元格模式仍然是標準方法。 如果您需要異步導出以使介面在大型導出過程中保持響應,請將導出邏輯包裝在await結果。 請參閱異步文件操作文件,以了解將結果調回UI執行緒的模式。
爲什麼IronXL比Office Interop導出DataGridView資料更好?
傳統的.NET解決方案使用Microsoft.Office.Interop.Excel來驅動運行中的Excel進程。 這種方法帶來了幾個部署和穩定性問題:
- 每台運行應用程式的機器都需安裝一個已授權的Microsoft Excel副本
- 伺服器環境和雲容器通常無法安裝Office
- COM Interop需要顯式釋放每個物件以避免記憶體洩漏和僵尸Excel進程
- 跨COM邊界的錯誤處理冗長且脆弱
- 隨著行數的增加,性能迅速下降
IronXL直接寫入OOXML文件格式,而無需啟動任何外部進程。 應用程式以自包含單元方式部署。 該程式庫的API是完全托管的.NET,因此垃圾回收自動處理記憶體,而無需Marshal.ReleaseComObject調用。 速度明顯更快,因為沒有進程間通信。
對於評估替代方案的團隊,ClosedXML是一個受歡迎的開源選項。 IronXL提供了更廣泛的功能集,包括PDF轉換、圖表生成和商業支援,這可能是企業採購決策中的考慮因素。 查看IronXL的許可選項,以匹配您團隊規模和部署情況的合適級別。
| 功能 | IronXL | Office Interop |
|---|---|---|
| 需要安裝Office | 否 | 是 |
| 伺服器/雲部署 | 是 | 否(不支持) |
| 托管記憶體模型 | 是 | 否(需要COM清理) |
| XLSX / CSV / XLS格式 | 所有三者 | 取決於安裝的Excel |
| 從試算表中導出PDF | 是 | 需要額外的程式庫 |
IronXL教程介紹了讀取現有Excel文件、修改模板、生成圖表和應用條件格式——所有這些能力自然地從這裡展示的DataGridView導出模式中擴展出來。
您接下來的步驟是什麼?
您現在已擁有使用IronXL將DataGridView導出為格式化Excel文件的有效C#程式碼。 從這裡,考慮以下方向:
- 新增錯誤處理:將導出程式碼包裹在
try/catch塊中,如果文件被鎖定或路徑無效,則顯示一條使用者友好的消息 - 支持文件路徑選擇:使用
SaveFileDialog,讓使用者在運行時選擇輸出位置和文件名 - 載入真實資料:將樣本
DataTable替換為使用ADO.NET或Entity Framework的資料庫查詢 - 讀取現有文件:使用WorkBook.Load打開現有試算表並更新它,而不是總是建立一個新的
- 導出到多個工作表:在相同的
WorkSheet物件以組織相關的資料集 - 應用條件格式:使用IronXL的條件格式API突出顯示超過閾值的單元格
- 查看許可選項:提供免費試用 許可層級涵蓋從個人開發者到企業部署
- 瀏覽完整API參考:IronXL物件參考記錄了每個類和可用的方法
常見問題
在C#中匯出DataGridView資料到Excel的最簡方式是什麼?
使用IronXL,您可以使用簡短的迴圈將DataGridView資料匯出到Excel,將列標題和資料行寫入WorkBook物件,然後調用SaveAs生成XLSX文件。不需要安裝Microsoft Office。
如何在C# Windows Forms應用程式中使用IronXL處理Excel文件?
通過NuGet安裝IronXL,新增using IronXL指令,建立WorkBook與WorkBook.Create(),使用SetCellValue撰寫資料,並使用SaveAs保存。 IronXL 支持XLSX、XLS和CSV格式。
IronXL 是否支持將大量的DataGridView資料集匯出到Excel?
是的,IronXL 可以有效處理大型資料集。對於由DataTable支持的DataGridView,您可以使用LoadDataTable 方法繞過逐個單元格的迴圈,以獲得更佳的性能。
使用IronXL是否需要安裝Microsoft Excel?
不需要。IronXL直接寫入Open XML文件格式,不需要啟動Excel或任何COM自動化。利用IronXL構建的應用程式可部署到沒有Office的伺服器和雲端環境。
使用IronXL進行Excel匯出的好處,相比Office Interop有哪些?
IronXL 不需要Office安裝,避免了COM記憶體洩漏問題,支持伺服器和雲端部署,並提供一個乾淨的管理 .NET API 用於讀取和寫入XLSX、XLS 和CSV文件。
IronXL 可以將DataGridView資料匯出為CSV,以及XLSX嗎?
是的。將.csv文件路徑傳遞給WorkBook.SaveAs會生成逗號分隔文件。資料寫入程式碼對兩種格式都是一致的--僅文件擴展名不同。
如何使用IronXL對匯出的Excel單元格進行格式化?
使用WorkSheet.GetRange來選取單元格範圍,然後存取Style屬性來設置Font.Bold,SetBackgroundColor,Font.SetColor,和FormatString以設置數字格式。
如何在C#專案中開始使用IronXL?
在您的專案中運行 Install-Package IronXL 或 dotnet add package IronXL,新增using IronXL置於文件頂部,並參考IronXL文件的範例,可在ironsoftware.com/csharp/excel/找到。




