C# 將 DataGridView 匯出到 Excel 並帶列標題
如何在 C# 中將帶有列標題的 DataGridView 匯出到 Excel?
將 Windows Forms DataGridView 控制項中的資料匯出為 Excel 格式是一個常見的需求,但開發人員經常會遇到一個令人沮喪的問題:匯出的文件缺少列標題。 當您需要將 DataGridView 匯出到 Excel 並保留列標題時,解決方案必須能夠可靠地保留所有資料和格式。 使用 Microsoft Office Interop 的傳統方法可能速度慢、不穩定,並且需要在執行程式碼的每台電腦上安裝 MS Excel。
IronXL可以完美地解決這個問題。 這是一個 .NET Excel 程式庫,可以讀取、建立和寫入 Excel 文件,而無需任何 Office 依賴項。 本教學將引導您完成完整的匯出解決方案—只需幾行程式碼即可處理列標題、資料類型、空白儲存格和使用者友好的檔案保存。
最後,您將擁有一個可用的 Windows Forms 按鈕處理程序,該處理程序可以將 DataGridView 匯出到 XLSX 文件,並保留所有列標題。
開始之前你需要準備什麼
在編寫任何程式碼之前,請確保以下事項已就緒:
- Visual Studio 2022 或更高版本(任何版本) 已安裝 .NET 10 SDK
- 一個面向 .NET 10 的 Windows 窗體應用程式項目
- 透過 NuGet 存取來安裝 IronXL
以下範例通篇使用頂級語句和現代 .NET 10 專案結構。
如何在 .NET 專案中安裝程式庫?
在 Visual Studio 中開啟 NuGet 套件管理器控制台,並執行下列任一命令。 該軟體包已在NuGet Gallery上列出,面向 .NET Standard 2.0 及更高版本,因此可與任何現代 .NET 專案配合使用。
Install-Package IronXL
Install-Package IronXL
dotnet add package IronXL
dotnet add package IronXL
安裝完成後,請在表單檔案頂部新增所需的命名空間:
using IronXL;
using System;
using System.Data;
using System.Windows.Forms;
using IronXL;
using System;
using System.Data;
using System.Windows.Forms;
Imports IronXL
Imports System
Imports System.Data
Imports System.Windows.Forms
這些匯入功能可以存取IronXL 的 Excel 功能、資料表操作以及匯出過程所需的 Windows 窗體控制項。
如何使用範例資料設定 DataGridView?
首先在 Visual Studio 中建立一個 Windows 窗體應用程式。 透過設計器向主窗體新增名為 dataGridView1 的 DataGridView 和名為 btnExport 的 Button。 然後在表單載入時填充表格:
using System;
using System.Data;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
// Define columns -- these names become Excel headers
dt.Columns.Add("Product ID", typeof(int));
dt.Columns.Add("Product Name", typeof(string));
dt.Columns.Add("Price", typeof(decimal));
dt.Columns.Add("Stock Quantity", typeof(int));
// Add sample rows
dt.Rows.Add(1001, "Laptop", 999.99m, 15);
dt.Rows.Add(1002, "Mouse", 29.99m, 50);
dt.Rows.Add(1003, "Keyboard", 79.99m, 30);
dt.Rows.Add(1004, "Monitor", 299.99m, 12);
dt.Rows.Add(1005, "Headphones", 89.99m, 25);
// Bind data to the grid
dataGridView1.DataSource = dt;
}
}
using System;
using System.Data;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DataTable dt = new DataTable();
// Define columns -- these names become Excel headers
dt.Columns.Add("Product ID", typeof(int));
dt.Columns.Add("Product Name", typeof(string));
dt.Columns.Add("Price", typeof(decimal));
dt.Columns.Add("Stock Quantity", typeof(int));
// Add sample rows
dt.Rows.Add(1001, "Laptop", 999.99m, 15);
dt.Rows.Add(1002, "Mouse", 29.99m, 50);
dt.Rows.Add(1003, "Keyboard", 79.99m, 30);
dt.Rows.Add(1004, "Monitor", 299.99m, 12);
dt.Rows.Add(1005, "Headphones", 89.99m, 25);
// Bind data to the grid
dataGridView1.DataSource = dt;
}
}
Imports System
Imports System.Data
Imports System.Windows.Forms
Public Partial Class Form1
Inherits Form
Public Sub New()
InitializeComponent()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable()
' Define columns -- these names become Excel headers
dt.Columns.Add("Product ID", GetType(Integer))
dt.Columns.Add("Product Name", GetType(String))
dt.Columns.Add("Price", GetType(Decimal))
dt.Columns.Add("Stock Quantity", GetType(Integer))
' Add sample rows
dt.Rows.Add(1001, "Laptop", 999.99D, 15)
dt.Rows.Add(1002, "Mouse", 29.99D, 50)
dt.Rows.Add(1003, "Keyboard", 79.99D, 30)
dt.Rows.Add(1004, "Monitor", 299.99D, 12)
dt.Rows.Add(1005, "Headphones", 89.99D, 25)
' Bind data to the grid
dataGridView1.DataSource = dt
End Sub
End Class
在 dt.Columns.Add(...) 呼叫中定義的列名將成為匯出 Excel 檔案中的標題行。您可以替換此處的任何資料來源——資料庫查詢結果、CSV 匯入或儲存為 DataTable 的 API 回應,所有這些都與後面所示的匯出程式碼的工作方式相同。 DataTable 方法特別方便,因為 DataGridView 公開了一個 DataSource 屬性,該屬性接受任何 IList 或 IBindingList,這意味著相同的匯出程式碼無需修改即可推廣到每個綁定場景。
如果您的 DataGridView 是透過 SqlDataAdapter 從資料庫填入的,則 DataTable 已經包含類型化的列。 將這些鍵入的值傳遞給 SetCellValue 而不是對它們呼叫 ToString(),可以使 Excel 輸出中的數值列保持為數值,這對於任何下游報告或資料透視表的使用都很重要。
這將創建一個包含所有資料的 DataGridView:
! 使用 IronXL 將 C# DataGridView 匯出到 Excel 並帶有列標題:圖 1 - DataGridView 中的範例資料
對於更進階的資料綁定場景,微軟關於DataGridView 資料綁定的文件提供了更多範例。
如何在將 DataGridView 匯出到 Excel 時保留列標題?
匯出方法從每個 DataGridView 列的 HeaderText 屬性讀取列標題,並將它們寫入工作表的第 0 行。 資料行從第 1 行開始。 將此方法連接到 btnExport 點擊事件:
private void btnExport_Click(object sender, EventArgs e)
{
try
{
// Create a new Excel workbook in XLSX format
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet worksheet = workbook.CreateWorkSheet("Exported Data");
// Write column headers to row 0
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
worksheet.SetCellValue(0, col, dataGridView1.Columns[col].HeaderText);
}
// Write data rows starting at row 1
for (int row = 0; row < dataGridView1.Rows.Count; row++)
{
// Skip the placeholder new-row at the bottom of the grid
if (dataGridView1.AllowUserToAddRows && row == dataGridView1.Rows.Count - 1)
continue;
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
var cellValue = dataGridView1.Rows[row].Cells[col].Value;
if (cellValue != null)
{
worksheet.SetCellValue(row + 1, col, cellValue.ToString());
}
}
}
// Prompt the user to choose a save location
using SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
FileName = "DataGridView_Export.xlsx"
};
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
workbook.SaveAs(saveFileDialog.FileName);
MessageBox.Show("Export completed successfully!", "Success",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show($"Export failed: {ex.Message}", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnExport_Click(object sender, EventArgs e)
{
try
{
// Create a new Excel workbook in XLSX format
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet worksheet = workbook.CreateWorkSheet("Exported Data");
// Write column headers to row 0
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
worksheet.SetCellValue(0, col, dataGridView1.Columns[col].HeaderText);
}
// Write data rows starting at row 1
for (int row = 0; row < dataGridView1.Rows.Count; row++)
{
// Skip the placeholder new-row at the bottom of the grid
if (dataGridView1.AllowUserToAddRows && row == dataGridView1.Rows.Count - 1)
continue;
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
var cellValue = dataGridView1.Rows[row].Cells[col].Value;
if (cellValue != null)
{
worksheet.SetCellValue(row + 1, col, cellValue.ToString());
}
}
}
// Prompt the user to choose a save location
using SaveFileDialog saveFileDialog = new SaveFileDialog
{
Filter = "Excel Files|*.xlsx",
FileName = "DataGridView_Export.xlsx"
};
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
workbook.SaveAs(saveFileDialog.FileName);
MessageBox.Show("Export completed successfully!", "Success",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show($"Export failed: {ex.Message}", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Private Sub btnExport_Click(sender As Object, e As EventArgs)
Try
' Create a new Excel workbook in XLSX format
Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
Dim worksheet As WorkSheet = workbook.CreateWorkSheet("Exported Data")
' Write column headers to row 0
For col As Integer = 0 To dataGridView1.Columns.Count - 1
worksheet.SetCellValue(0, col, dataGridView1.Columns(col).HeaderText)
Next
' Write data rows starting at row 1
For row As Integer = 0 To dataGridView1.Rows.Count - 1
' Skip the placeholder new-row at the bottom of the grid
If dataGridView1.AllowUserToAddRows AndAlso row = dataGridView1.Rows.Count - 1 Then
Continue For
End If
For col As Integer = 0 To dataGridView1.Columns.Count - 1
Dim cellValue = dataGridView1.Rows(row).Cells(col).Value
If cellValue IsNot Nothing Then
worksheet.SetCellValue(row + 1, col, cellValue.ToString())
End If
Next
Next
' Prompt the user to choose a save location
Using saveFileDialog As New SaveFileDialog With {
.Filter = "Excel Files|*.xlsx",
.FileName = "DataGridView_Export.xlsx"
}
If saveFileDialog.ShowDialog() = DialogResult.OK Then
workbook.SaveAs(saveFileDialog.FileName)
MessageBox.Show("Export completed successfully!", "Success",
MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
End Using
Catch ex As Exception
MessageBox.Show($"Export failed: {ex.Message}", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
分解導出步驟
該方法的每個步驟都有其特定目的:
- WorkBook.Create :使用 XLSX 格式在記憶體中初始化一個新的 Excel 檔案。 在呼叫
SaveAs之前,不會將任何檔案寫入磁碟。 - CreateWorkSheet :新增一個命名的工作表來儲存匯出的資料。 在 Excel 中,"匯出資料"會顯示為標籤頁名稱。
-列標題循環:讀取每一列的
dataGridView1.Columns[col].HeaderText並將其寫入行索引 0。這是保留標題的關鍵步驟。 -資料行循環:巢狀循環遍歷每一行和每一列,使用row + 1作為 Excel 行索引,因此資料始終從標題行下方開始。 -空值檢查:防止儲存格不包含值時出現異常,這在實際資料中很常見。 - SaveFileDialog :允許使用者在執行時選擇檔案名稱和目標位置,而不是硬編碼路徑。
匯出的文件如下所示:
使用 IronXL 將 C# DataGridView 匯出到 Excel 並帶有列標題:圖 2 - 包含匯出範例資料的輸出 Excel 文件
匯出過程中如何處理常見極端情況?
現實世界的數據很少像樣本資料集那樣乾淨。 以下是您最有可能遇到的情況以及應對方法。
空白單元格
資料循環中的空值檢查(if (cellValue != null))可以處理空單元格,而不會拋出異常。 在 Excel 輸出中,空白儲存格將保持空白,從而保留網格結構。
混合資料類型
IronXL 可以自動處理不同的資料格式。 當您透過 ToString() 將數字作為字串傳遞時,Excel 仍可能根據其值將其識別為數值。 為了精確控制資料類型,請在寫入之前將單元格值強制轉換為正確的類型:
if (cellValue is int intVal)
worksheet.SetCellValue(row + 1, col, intVal);
else if (cellValue is decimal decVal)
worksheet.SetCellValue(row + 1, col, (double)decVal);
else
worksheet.SetCellValue(row + 1, col, cellValue?.ToString() ?? string.Empty);
if (cellValue is int intVal)
worksheet.SetCellValue(row + 1, col, intVal);
else if (cellValue is decimal decVal)
worksheet.SetCellValue(row + 1, col, (double)decVal);
else
worksheet.SetCellValue(row + 1, col, cellValue?.ToString() ?? string.Empty);
If TypeOf cellValue Is Integer Then
Dim intVal As Integer = CType(cellValue, Integer)
worksheet.SetCellValue(row + 1, col, intVal)
ElseIf TypeOf cellValue Is Decimal Then
Dim decVal As Decimal = CType(cellValue, Decimal)
worksheet.SetCellValue(row + 1, col, CDbl(decVal))
Else
worksheet.SetCellValue(row + 1, col, If(cellValue?.ToString(), String.Empty))
End If
這種方法可以保持 Excel 中的數值列為數值型,以便後續的公式和排序功能能夠正常運作。
標題中的特殊字符
包含特殊字元(例如 &、<、>)和重音符號的字母的列標題可以正確匯出。 IronXL 會自動處理編碼,無需您進行任何轉義操作。
大型資料集
對於包含數萬行的表格,請考慮將匯出邏輯移至後台執行緒以保持 UI 的回應速度。將 WorkBook.Create 和循環邏輯封裝在 Task.Run 呼叫中,並在完成的回呼函數中更新 UI。 微軟關於 使用 Task 進行非同步程式設計的文件詳細解釋了這種模式。
主要出口方式有何異同?
在決定使用某個函式庫之前,了解最常用方法之間的優缺點會很有幫助。
| 方法 | 辦公室要求 | 列標題 | 表現 | 伺服器安全 |
|---|---|---|---|---|
| Microsoft Office Interop | 是 | 手冊 | 慢的 | 無 |
| OpenXml SDK | 無 | 手冊 | 快速地 | 是 |
| ClosedXML | 無 | 手冊 | 好的 | 是 |
| IronXL | 無 | 自動化 | 快速地 | 是 |
基於互通性的解決方案需要在伺服器上安裝 Excel,這既是授權問題,也是部署複雜性問題。 OpenXml SDK 功能強大但底層-編寫標題行需要手動建立 XML 結構。 IronXL 和 ClosedXML 都提供了更高層級的 API,但 IronXL 的WorkBook 和 WorkSheet 模型與開發人員對電子表格的現有思維方式非常接近。
如何匯出為 CSV 而不是 XLSX?
當您需要CSV 檔案而不是 Excel 工作簿時,也適用相同的匯出模式。 更改檔案格式和副檔名:
WorkBook csvWorkbook = WorkBook.Create(ExcelFileFormat.CSV);
WorkSheet csvSheet = csvWorkbook.CreateWorkSheet("Data");
// Headers and data loops remain identical
using SaveFileDialog dialog = new SaveFileDialog
{
Filter = "CSV Files|*.csv",
FileName = "DataGridView_Export.csv"
};
if (dialog.ShowDialog() == DialogResult.OK)
csvWorkbook.SaveAs(dialog.FileName);
WorkBook csvWorkbook = WorkBook.Create(ExcelFileFormat.CSV);
WorkSheet csvSheet = csvWorkbook.CreateWorkSheet("Data");
// Headers and data loops remain identical
using SaveFileDialog dialog = new SaveFileDialog
{
Filter = "CSV Files|*.csv",
FileName = "DataGridView_Export.csv"
};
if (dialog.ShowDialog() == DialogResult.OK)
csvWorkbook.SaveAs(dialog.FileName);
Imports System.Windows.Forms
Dim csvWorkbook As WorkBook = WorkBook.Create(ExcelFileFormat.CSV)
Dim csvSheet As WorkSheet = csvWorkbook.CreateWorkSheet("Data")
' Headers and data loops remain identical
Using dialog As New SaveFileDialog With {
.Filter = "CSV Files|*.csv",
.FileName = "DataGridView_Export.csv"
}
If dialog.ShowDialog() = DialogResult.OK Then
csvWorkbook.SaveAs(dialog.FileName)
End If
End Using
當使用系統不支援 XLSX 格式,或者對於非常大的資料集來說檔案大小是一個問題時,CSV 匯出非常有用。
如何在匯出的文件中設定標題行的樣式?
匯出的資料如果標題行在視覺上清晰可見,則更易於閱讀。 IronXL 提供儲存格樣式選項,讓您在寫入標題值後套用粗體文字、背景顏色和字體大小:
// Write headers and apply bold styling
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
string cellAddress = worksheet.GetCellAddress(0, col);
worksheet[cellAddress].Value = dataGridView1.Columns[col].HeaderText;
worksheet[cellAddress].Style.Font.Bold = true;
worksheet[cellAddress].Style.SetBackgroundColor("#4472C4");
worksheet[cellAddress].Style.Font.FontColor = "#FFFFFF";
}
// Write headers and apply bold styling
for (int col = 0; col < dataGridView1.Columns.Count; col++)
{
string cellAddress = worksheet.GetCellAddress(0, col);
worksheet[cellAddress].Value = dataGridView1.Columns[col].HeaderText;
worksheet[cellAddress].Style.Font.Bold = true;
worksheet[cellAddress].Style.SetBackgroundColor("#4472C4");
worksheet[cellAddress].Style.Font.FontColor = "#FFFFFF";
}
' Write headers and apply bold styling
For col As Integer = 0 To dataGridView1.Columns.Count - 1
Dim cellAddress As String = worksheet.GetCellAddress(0, col)
worksheet(cellAddress).Value = dataGridView1.Columns(col).HeaderText
worksheet(cellAddress).Style.Font.Bold = True
worksheet(cellAddress).Style.SetBackgroundColor("#4472C4")
worksheet(cellAddress).Style.Font.FontColor = "#FFFFFF"
Next col
帶有樣式的標題行使匯出的文件可以直接用於報告,而無需收件人手動套用格式。 有關樣式屬性的完整列表,請參閱IronXL 單元格樣式參考。
如何開始免費試用?
IronXL提供免費試用版,讓您可以測試所有功能,包括本文所示的匯出工作流程。 使用上面顯示的任一 NuGet 命令安裝該軟體包,在IronXL 許可頁面上產生試用密鑰,並在首次調用庫之前將其設定到您的應用程式中:
IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";
IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE";
Imports IronXL
IronXL.License.LicenseKey = "YOUR-LICENSE-KEY-HERE"
該試用版會產生功能齊全的 Excel 文件,並且不會限制哪些功能可用。 對於生產部署,授權選項涵蓋單一開發人員、團隊和免版稅再分發。
對於相關的匯出場景,請探索 IronXL 如何處理將 DataTables 直接匯出到 Excel 、將 Excel 檔案讀取到 DataGridViews以及從匯出的資料建立圖表。
為您的用例選擇合適的出口策略
本教學中所展示的逐單元格匯出方法簡單直接,適用於大多數 Windows Forms 應用程式。 如果您的 DataGridView 綁定到 DataTable,您也可以將 DataTable 直接傳遞給 IronXL 的DataTable 到工作表轉換器,該轉換器會自動處理標題行。 如果列佈局固定,且您希望程式碼路徑最短,請選擇直接使用 DataTable 的方法。 當您需要對每個單元格套用條件邏輯時,請選擇逐單元格手動操作的方法—例如,突出顯示值超出可接受範圍的單元格,或在寫入之前明確映射可空類型。
對於產生可下載 Excel 報表的伺服器端場景(例如 ASP.NET Core 控制器),同樣的 IronXL API 也適用。 唯一的區別在於保存目標:不是呼叫 SaveAs(filePath),而是呼叫 workbook.ToByteArray(),並將位元組寫入內容類型為 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 的 HTTP 回應。 無論輸出到檔案或流,列標題的傳輸方式都完全相同。
常見問題解答
如何在 C# 中將 DataGridView 數據匯出到 Excel?
使用IronXL程式庫創建Excel工作簿,迭代DataGridView列將標頭寫入第0行,然後迭代資料列並從第一行開始寫入儲存格值。使用SaveAs保存工作簿。
使用 IronXL 匯出資料有什麼好處?
IronXL提供了一個高層API進行Excel操作,不需要安裝Microsoft Office。它管理標頭、資料類型和檔案格式,無需手動XML操作。
從 DataGridView 匯出到 Excel 時,是否可以保留列標題?
是的。在寫入任何資料列之前,讀取每個DataGridView列的HeaderText屬性並將其寫入IronXL工作表的第0行。
我需要試用版才能開始使用 IronXL 將檔案匯出到 Excel 嗎?
提供免費試用,可以訪問所有功能。安裝NuGet套件,生成一個試用金鑰,並在進行任何程式庫調用之前設置IronXL.License.LicenseKey。
IronXL在匯出到Excel時能否處理大型DataGridView資料集?
是的。對於非常大的網格,在背景執行緒上使用Task.Run進行匯出,以在IronXL寫入資料時保持UI響應。
使用 IronXL 將 DataGridView 匯出到 Excel 的步驟是什麼?
安裝IronXL,創建一個WorkBook和WorkSheet,循環遍歷DataGridView列以在第0行寫入標頭,循環遍歷列以從第1行開始寫入資料,然後調用SaveAs來寫入檔案。
為什麼選擇 IronXL 而不是其他匯出到 Excel 的庫?
IronXL不需安裝Office,在伺服器上運行,提供一個乾淨的工作簿/工作表API,自然地映射到開發人員對電子表格的思考方式--具有強大的文檔和積極的支持。
IronXL 是否有故障排除方面的支援?
是的。IronXL為授權的客戶提供詳細的API文檔、程式碼範例和直接的工程支援。
我可以使用 IronXL 自訂 Excel 匯出流程嗎?
是的。在寫入資料之後,您可以使用IronXL的Style API對任何儲存格範圍應用粗體字體、背景顏色、邊框和數字格式。
IronXL除了Excel格式外,是否支援將資料匯出為其他格式?
是的。IronXL支援XLSX、XLS、CSV和TSV格式。切換格式只需要更改傳遞給WorkBook.Create的ExcelFileFormat枚舉值。


