C# 將 DataGridView 匯出到 Excel 並帶列標題
如何在C#中將DataGridView的資料匯出到Excel並保留欄位標題?
從Windows Forms的DataGridView控制項將資料匯出到Excel格式是一個常見的需求,但開發人員經常會遇到一個令人沮喪的問題:匯出的檔案丟失了欄位標題。 當您需要將DataGridView匯出到Excel並保留欄位標題時,解決方案必須可靠地保留所有的資料和格式。 使用Microsoft Office Interop的傳統方法可能很慢,容易崩潰,並且需要在每台運行此程式碼的機器上安裝MS Excel。
IronXL乾淨地解決了這個問題。 它是一個.NET Excel程式庫,無需任何Office依賴性即可讀取、建立和寫入Excel檔案。 這個教程將引導您完成一個完整的匯出解決方案——一個可以處理欄位標題、資料型別、空單元格和使用者友好檔案保存的解決方案,只需幾行程式碼。
最後,您將擁有一個正常運作的Windows Forms按鈕處理器,將DataGridView匯出到一個帶有所有欄位標題的XLSX檔案中。
在開始之前您需要什麼
在編寫程式碼之前,請確保以下內容已經就緒:
- Visual Studio 2022或更高版本(任何版本)
- 安裝.NET 10 SDK
- 針對.NET 10的Windows Forms應用程式專案
- 可以存取NuGet以安裝IronXL
下面的例子使用頂層語句和現代的.NET 10專案結構。
如何在.NET專案中安裝程式庫?
在Visual Studio中打開NuGet包管理器控制台並運行以下任何一條命令。 該包列在NuGet畫廊中,並針對.NET Standard 2.0及以上,因此它適用於任何現代的.NET專案。
Install-Package IronXL.Excel
dotnet add package IronXL.Excel
安裝後,在您的表單檔案的頂部新增所需的命名空間:
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功能、DataTable操作以及匯出過程所需的Windows Forms控制項的存取權限。
如何設置帶有範例資料的DataGridView?
首先在Visual Studio中建立一個Windows Forms應用程式。 通過設計器在主窗體中新增一個名為btnExport的按鈕。 然後填充窗體載入上的表格:
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公開了一個IBindingList,這意味著相同的匯出程式碼可以在每個綁定場景中通用而不需修改。
如果您的DataGridView是由資料庫使用SqlDataAdapter填充的,則DataTable已經包含型別化的列。 將這些型別化的值傳遞給ToString()可以讓數字列在Excel的輸出中保持數字格式,這對於下游報告或資料透視表的使用很重要。
這將建立一個填充了所有資料的DataGridView:

如需更多高級資料綁定場景,請參閱Microsoft關於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:允許使用者在運行時選擇文件名和目的地,而不是硬編碼路徑。
匯出的文件看起來如下:

如何在匯出過程中處理常見的邊界案例?
實際世界的数据很少像範例数據集那樣整潔。 以下是您最有可能遇到的場景以及如何解決它們。
空單元格
資料迴圈中的空檢查(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響應。將Task.Run調用中,並在完成回調時更新UI。 Microsoft關於使用任務的異步編程的文件詳細說明了這個模式。
主要匯出方法如何比較?
在承諾使用程式庫之前,了解最常見方法之間的取捨是有幫助的。
| 方法 | 需要Office | 欄位標題 | 性能 | 伺服器安全 |
|---|---|---|---|---|
| Microsoft Office Interop | 是 | 手動 | 緩慢 | 否 |
| OpenXml SDK | 否 | 手動 | 快速 | 是 |
| ClosedXML | 否 | 手動 | 好 | 是 |
| IronXL | 否 | 自動 | 快速 | 是 |
基於Interop的解決方案需要在伺服器上安裝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
CSV匯出在消費系統不支持XLSX或文件大小對於非常大的数据集是個問題時很有用。
如何在匯出的文件中樣式化標題行?
當標題行在視覺上有別於其他行時,匯出的資料更具可讀性。 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提供免費試用,允許您測試所有功能,包括本文中顯示的匯出工作流程。 使用上面顯示的任何一個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適用。 唯一不同的是保存目標:而不是application/vnd.openxmlformats-officedocument.spreadsheetml.sheet的內容型別將字節寫到HTTP響應中。 無論輸出是到文件還是到流,欄位標題傳輸方式相同。
常見問題
如何在 C# 中將 DataGridView 資料匯出到 Excel?
using IronXL 程式庫建立一個 Excel 工作簿,遍歷 DataGridView 欄位並將標題寫入第0行,然後遍歷資料行並從第1行開始寫入單元格值。使用 SaveAs 保存工作簿。
using IronXL 匯出資料的好處是什麼?
IronXL 提供了一個高階API進行 Excel 操作,無需安裝 Microsoft Office。它在無需手動 XML 操作的情況下處理標題、資料型別和文件格式。
從 DataGridView 匯出到 Excel 時是否可以保留欄位標題?
可以。讀取每個 DataGridView 欄位的 HeaderText 屬性,並在寫入任何資料行之前將其寫入 IronXL 工作表的第0行。
我需要試用版才能開始使用 IronXL 進行 Excel 匯出嗎?
提供免費試用版,可存取所有功能。安裝 NuGet 套件,生成試用金鑰,並在進行任何程式庫調用之前設置 IronXL.License.LicenseKey。
IronXL 可以在匯出到 Excel 時處理大型 DataGridView 資料集嗎?
可以。對於非常大的網格,使用 Task.Run 在後台執行匯出,以保持 UI 響應,同時 IronXL 寫入資料。
using IronXL 將 DataGridView 匯出到 Excel 的步驟是什麼?
安裝 IronXL,建立一個 WorkBook 和 WorkSheet,遍歷 DataGridView 欄位將標題寫入第0行,遍歷行將資料從第1行寫入,然後調用 SaveAs 寫入文件。
為什麼選擇 IronXL 而不是其他程式庫進行 Excel 匯出?
IronXL 不需要 Office 安裝,可以在伺服器上運行,並提供一個乾淨的 WorkBook/WorkSheet API,這符合開發者對電子表格的自然思考方式——同時具有強大的文件和主動的支持。
有可用的支持來解決 IronXL 的問題嗎?
有的。IronXL 提供詳細的 API 文件、程式碼範例和針對授權客戶的直接工程支持。
我可以使用 IronXL 自訂 Excel 匯出過程嗎?
可以。在寫入資料之後,您可以使用 IronXL 的 Style API 對任何單元格範圍應用加粗字體、背景顏色、邊框和數字格式。
IronXL 是否支持除 Excel 之外的其他格式匯出資料?
支持。IronXL 支持 XLSX、XLS、CSV 和 TSV 格式。更改格式僅需更改傳遞給 WorkBook.Create 的 ExcelFileFormat 枚舉值。




