Skip to footer content
USING IRONXL

C# DataGridView Export to Excel: Complete Guide with Formatting | IronXL

C# DataGridView Export to Excel with Formatting: The Complete Guide: Image 1 - C# DataGridView Export to Excel with Formatting

Exporting DataGridView data to an Excel file is one of the most common tasks in Windows Forms development. When building business applications that display tabular data -- whether sales reports, inventory records, or customer lists -- users expect to click a button and receive a properly formatted Excel file they can share or analyze further. The challenge is doing this cleanly, without depending on a Microsoft Excel installation on every end-user machine, and without wrestling with COM interop cleanup code that leaks memory or breaks silently. This guide walks you through the complete process of exporting DataGridView to Excel in C# using IronXL, covering everything from project setup through advanced cell formatting, so you end up with production-ready code.

Get stated with IronXL now.
green arrow pointer

How Do You Set Up a Windows Forms Project for DataGridView Export?

Traditional approaches to exporting DataGridView data relied on Microsoft Interop -- you would open Add Reference, navigate to the COM tab, select the Microsoft Excel Object Library, and write fragile code that called Marshal.ReleaseComObject to avoid memory leaks. That pattern requires Microsoft Excel installed on every machine where the application runs, performs slowly with large datasets, and often produces COMException errors in deployment environments that lack Office licenses. Microsoft's own guidance on Office Automation explicitly recommends third-party libraries for server-side and automated scenarios.

IronXL removes all of those dependencies. It is a pure .NET library that reads and writes .xlsx, .xls, .csv, and .ods files without Microsoft Office or any COM registration. You install it through NuGet and start writing code immediately.

Installing IronXL via NuGet

Start by creating a new Windows Forms App project in Visual Studio targeting .NET 10. Add a DataGridView control and a Button to the form surface. Name the button btnExport and give it the label "Export to Excel". Then open the NuGet Package Manager Console and run:

Install-Package IronXL.Excel
Install-Package IronXL.Excel
SHELL

Add the required namespaces to the top of your form file:

using IronXL;
using System.Data;
using IronXL;
using System.Data;
$vbLabelText   $csharpLabel

These two namespaces cover all the IronXL types you need for reading and writing Excel workbooks, and the standard System.Data types for working with DataTable objects that bridge your DataGridView to the export pipeline.

How Do You Load Sample Data into a DataGridView Control?

Before building the export logic, populate your DataGridView with representative data. The Form1_Load event is the right place to bind a DataTable as the data source. In a real application you would query a database or call a service; here a hard-coded DataTable illustrates the structure clearly. The DataGridView control overview on Microsoft Docs provides additional context on how the control manages data sources.

Binding a DataTable to DataGridView

void Form1_Load(object sender, EventArgs e)
{
    DataTable dt = new DataTable();
    dt.Columns.Add("ProductID", typeof(int));
    dt.Columns.Add("ProductName", typeof(string));
    dt.Columns.Add("Price", typeof(decimal));
    dt.Columns.Add("Stock", typeof(int));

    dt.Rows.Add(1, "Laptop", 999.99m, 50);
    dt.Rows.Add(2, "Mouse", 29.99m, 200);
    dt.Rows.Add(3, "Keyboard", 79.99m, 150);
    dt.Rows.Add(4, "Monitor", 349.99m, 75);
    dt.Rows.Add(5, "Webcam", 89.99m, 120);

    dataGridView1.DataSource = dt;
}
void Form1_Load(object sender, EventArgs e)
{
    DataTable dt = new DataTable();
    dt.Columns.Add("ProductID", typeof(int));
    dt.Columns.Add("ProductName", typeof(string));
    dt.Columns.Add("Price", typeof(decimal));
    dt.Columns.Add("Stock", typeof(int));

    dt.Rows.Add(1, "Laptop", 999.99m, 50);
    dt.Rows.Add(2, "Mouse", 29.99m, 200);
    dt.Rows.Add(3, "Keyboard", 79.99m, 150);
    dt.Rows.Add(4, "Monitor", 349.99m, 75);
    dt.Rows.Add(5, "Webcam", 89.99m, 120);

    dataGridView1.DataSource = dt;
}
$vbLabelText   $csharpLabel

This code uses top-level statement style for the event handler signature. The DataTable has four typed columns -- integer, string, decimal, and integer -- which IronXL will preserve when writing to the Excel workbook. Typed columns matter because IronXL writes numeric columns as numeric cells rather than text, which lets users sort and sum values in Excel without reformatting.

C# DataGridView Export to Excel with Formatting: The Complete Guide: Image 2 - UI for the form

The DataGridView renders a column header row automatically from the DataTable column names. When you export, you want that header row preserved in the Excel file, which means your export code must handle headers separately from data rows -- the next section covers exactly that.

For production use, the same pattern applies whether the DataTable comes from Entity Framework, Dapper, ADO.NET, or any other data access layer. The DataGridView binding is decoupled from the export code, so you can swap the data source without touching the export logic.

How Do You Export DataGridView Data to an Excel File?

The core export logic runs inside the button click handler. IronXL provides a LoadFromDataTable method on WorkSheet that handles the column-to-cell mapping automatically. The cleanest approach extracts a DataTable from the DataGridView and passes it directly. The Open XML SDK, which underlies the .xlsx format, is documented by Microsoft and confirms why pure .NET solutions like IronXL outperform Interop for programmatic generation.

Button Click Export Handler

void btnExport_Click(object sender, EventArgs e)
{
    try
    {
        DataTable dt = new DataTable();

        foreach (DataGridViewColumn column in dataGridView1.Columns)
            dt.Columns.Add(column.HeaderText);

        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            if (row.IsNewRow) continue;

            DataRow dataRow = dt.NewRow();
            for (int i = 0; i < dataGridView1.Columns.Count; i++)
                dataRow[i] = row.Cells[i].Value ?? DBNull.Value;

            dt.Rows.Add(dataRow);
        }

        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.DefaultWorkSheet;
        worksheet.Name = "Product Data";

        worksheet.LoadFromDataTable(dt, true);

        string outputPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
            "DataGridViewExport.xlsx"
        );

        workbook.SaveAs(outputPath);
        MessageBox.Show($"Exported successfully to:\n{outputPath}", "Export Complete",
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Export failed: {ex.Message}", "Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
void btnExport_Click(object sender, EventArgs e)
{
    try
    {
        DataTable dt = new DataTable();

        foreach (DataGridViewColumn column in dataGridView1.Columns)
            dt.Columns.Add(column.HeaderText);

        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            if (row.IsNewRow) continue;

            DataRow dataRow = dt.NewRow();
            for (int i = 0; i < dataGridView1.Columns.Count; i++)
                dataRow[i] = row.Cells[i].Value ?? DBNull.Value;

            dt.Rows.Add(dataRow);
        }

        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.DefaultWorkSheet;
        worksheet.Name = "Product Data";

        worksheet.LoadFromDataTable(dt, true);

        string outputPath = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
            "DataGridViewExport.xlsx"
        );

        workbook.SaveAs(outputPath);
        MessageBox.Show($"Exported successfully to:\n{outputPath}", "Export Complete",
            MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Export failed: {ex.Message}", "Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}
$vbLabelText   $csharpLabel

C# DataGridView Export to Excel with Formatting: The Complete Guide: Image 3 - Generated Excel file

The LoadFromDataTable(dt, true) call takes the DataTable and a boolean flag that tells IronXL to write the column names as the first Excel row -- those become your header cells. The workbook is saved to the user's Desktop using Environment.SpecialFolder.Desktop rather than a hard-coded path, which makes the code portable across user accounts.

The null check (?? DBNull.Value) prevents a NullReferenceException when a cell contains no value. This is important for real-world data where optional fields may be empty. IronXL writes DBNull as an empty cell rather than the string "DBNull", so the output stays clean.

For more details on reading data back from Excel files into a DataGridView, see the IronXL DataTable documentation, which covers the reverse operation and how to convert Excel to DataSet for multi-sheet workbooks.

How Do You Apply Professional Formatting to the Exported Excel File?

Plain data in an Excel file is functional, but professionally formatted output -- bold headers, column widths fitted to content, alternating row background colors -- makes the difference between a tool users trust and one they export and immediately reformat by hand. IronXL exposes a rich cell styling API that covers fonts, colors, borders, number formats, and alignment. The OOXML specification for spreadsheet styles defines the underlying format that IronXL writes, giving you confidence the output opens correctly in any compliant application.

Applying Header Styles and Alternating Row Colors

void ExportWithFormatting(object sender, EventArgs e)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.DefaultWorkSheet;
    worksheet.Name = "Formatted Export";

    string[] headers = { "ID", "Product Name", "Price", "Stock" };

    // Write and style header row
    for (int col = 0; col < headers.Length; col++)
    {
        char colLetter = (char)('A' + col);
        string cellAddress = $"{colLetter}1";

        worksheet.SetCellValue(0, col, headers[col]);
        worksheet[cellAddress].Style.Font.Bold = true;
        worksheet[cellAddress].Style.Font.Height = 12;
        worksheet[cellAddress].Style.SetBackgroundColor("#4472C4");
        worksheet[cellAddress].Style.Font.Color = "#FFFFFF";
        worksheet[cellAddress].Style.HorizontalAlignment =
            IronXL.Styles.HorizontalAlignment.Center;
    }

    // Write data rows with alternating background colors
    int rowIndex = 1;
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (row.IsNewRow) continue;

        for (int col = 0; col < dataGridView1.Columns.Count; col++)
        {
            worksheet.SetCellValue(rowIndex, col,
                row.Cells[col].Value?.ToString() ?? string.Empty);
        }

        if (rowIndex % 2 == 0)
        {
            string rangeAddress = $"A{rowIndex + 1}:D{rowIndex + 1}";
            worksheet[rangeAddress].Style.SetBackgroundColor("#D6DCE5");
        }

        rowIndex++;
    }

    // Format the Price column as currency
    worksheet["C2:C100"].Style.Format = "$#,##0.00";

    // Auto-fit column widths
    worksheet.AutoSizeColumn(0);
    worksheet.AutoSizeColumn(1);
    worksheet.AutoSizeColumn(2);
    worksheet.AutoSizeColumn(3);

    string outputPath = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
        "FormattedExport.xlsx"
    );

    workbook.SaveAs(outputPath);
    MessageBox.Show("Formatted export complete.", "Done",
        MessageBoxButtons.OK, MessageBoxIcon.Information);
}
void ExportWithFormatting(object sender, EventArgs e)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.DefaultWorkSheet;
    worksheet.Name = "Formatted Export";

    string[] headers = { "ID", "Product Name", "Price", "Stock" };

    // Write and style header row
    for (int col = 0; col < headers.Length; col++)
    {
        char colLetter = (char)('A' + col);
        string cellAddress = $"{colLetter}1";

        worksheet.SetCellValue(0, col, headers[col]);
        worksheet[cellAddress].Style.Font.Bold = true;
        worksheet[cellAddress].Style.Font.Height = 12;
        worksheet[cellAddress].Style.SetBackgroundColor("#4472C4");
        worksheet[cellAddress].Style.Font.Color = "#FFFFFF";
        worksheet[cellAddress].Style.HorizontalAlignment =
            IronXL.Styles.HorizontalAlignment.Center;
    }

    // Write data rows with alternating background colors
    int rowIndex = 1;
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (row.IsNewRow) continue;

        for (int col = 0; col < dataGridView1.Columns.Count; col++)
        {
            worksheet.SetCellValue(rowIndex, col,
                row.Cells[col].Value?.ToString() ?? string.Empty);
        }

        if (rowIndex % 2 == 0)
        {
            string rangeAddress = $"A{rowIndex + 1}:D{rowIndex + 1}";
            worksheet[rangeAddress].Style.SetBackgroundColor("#D6DCE5");
        }

        rowIndex++;
    }

    // Format the Price column as currency
    worksheet["C2:C100"].Style.Format = "$#,##0.00";

    // Auto-fit column widths
    worksheet.AutoSizeColumn(0);
    worksheet.AutoSizeColumn(1);
    worksheet.AutoSizeColumn(2);
    worksheet.AutoSizeColumn(3);

    string outputPath = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
        "FormattedExport.xlsx"
    );

    workbook.SaveAs(outputPath);
    MessageBox.Show("Formatted export complete.", "Done",
        MessageBoxButtons.OK, MessageBoxIcon.Information);
}
$vbLabelText   $csharpLabel

C# DataGridView Export to Excel with Formatting: The Complete Guide: Image 4 - Output for the generated formatted Excel file

The formatting code applies several techniques. The header row gets a blue background (#4472C4) with white text, 12-point bold font, and centered alignment -- a standard business spreadsheet style. Data rows alternate between white and light gray (#D6DCE5) every even row, which makes it easier for users to read across wide tables without losing their place. The Price column uses Excel's built-in currency format ($#,##0.00), so values display with dollar signs and two decimal places in the spreadsheet without changing the underlying numeric data. AutoSizeColumn fits each column to its longest value so no content is truncated.

You can extend this pattern further with cell border styling, conditional formatting, and data validation rules. For reports that must match a corporate template, you can also set the page layout and print area so the exported file is ready to print without adjustment.

How Do You Handle Large Datasets and Performance Tuning?

When a DataGridView is bound to thousands of rows, iterating cell by cell becomes noticeably slow. Two optimizations improve performance significantly. First, use LoadFromDataTable instead of per-cell SetCellValue calls. Second, if your data source is a DataTable, pass it directly to IronXL rather than extracting values through the DataGridView rows:

void ExportLargeDataset(DataTable sourceTable)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.DefaultWorkSheet;

    // Direct DataTable load -- fastest path for large data
    worksheet.LoadFromDataTable(sourceTable, true);

    // Apply header styling after load
    int colCount = sourceTable.Columns.Count;
    for (int col = 0; col < colCount; col++)
    {
        char colLetter = (char)('A' + col);
        worksheet[$"{colLetter}1"].Style.Font.Bold = true;
        worksheet[$"{colLetter}1"].Style.SetBackgroundColor("#4472C4");
        worksheet[$"{colLetter}1"].Style.Font.Color = "#FFFFFF";
    }

    workbook.SaveAs(Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
        "LargeExport.xlsx"
    ));
}
void ExportLargeDataset(DataTable sourceTable)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.DefaultWorkSheet;

    // Direct DataTable load -- fastest path for large data
    worksheet.LoadFromDataTable(sourceTable, true);

    // Apply header styling after load
    int colCount = sourceTable.Columns.Count;
    for (int col = 0; col < colCount; col++)
    {
        char colLetter = (char)('A' + col);
        worksheet[$"{colLetter}1"].Style.Font.Bold = true;
        worksheet[$"{colLetter}1"].Style.SetBackgroundColor("#4472C4");
        worksheet[$"{colLetter}1"].Style.Font.Color = "#FFFFFF";
    }

    workbook.SaveAs(Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
        "LargeExport.xlsx"
    ));
}
$vbLabelText   $csharpLabel

For datasets with more than 10,000 rows, running the export on a background thread keeps the UI responsive. Wrap the export logic in Task.Run and marshal the MessageBox.Show call back to the UI thread using Invoke. IronXL is thread-safe for write operations on separate WorkBook instances, so you can run multiple exports concurrently if needed.

Additional performance resources:

How Do You Compare IronXL to Microsoft Interop for DataGridView Export?

Many developers start with Microsoft Excel Interop because it ships with Office and requires no additional packages. However, Interop has real-world costs that show up quickly in production environments. The following table summarizes the key differences:

IronXL vs. Microsoft Excel Interop for DataGridView Export
Capability IronXL Microsoft Interop
Requires Microsoft Excel installed No Yes
Works in server / cloud environments Yes No (unsupported by Microsoft)
COM object cleanup required No Yes (Marshal.ReleaseComObject)
Performance with large datasets Fast (pure .NET) Slow (COM marshalling overhead)
Install method NuGet COM reference / Office installation
Supported .NET versions .NET 4.6.2 -- .NET 10 .NET Framework only (limited)
XLSX, CSV, ODS support Yes XLSX/XLS only via Excel

Microsoft's own documentation warns against using Office Interop on servers or in service accounts, citing stability and licensing concerns. IronXL works correctly in Azure App Service, Windows Service hosts, Docker containers, and any other headless environment where running a desktop application like Excel is not feasible.

For teams already using Interop who want to migrate, IronXL's API maps closely enough that most WorkBook and WorkSheet operations translate directly. The IronXL migration guide covers common Interop patterns and their IronXL equivalents.

What Are Your Next Steps?

Exporting DataGridView data to Excel using IronXL requires only a NuGet package install and a few lines of code, replacing the fragile COM interop approach with a clean, maintainable solution that works in any deployment environment. The techniques covered here -- basic export, formatted output, large-dataset optimization, and a comparison table -- give you everything needed to ship this feature in a production Windows Forms application.

From here, explore these related capabilities:

Start a free IronXL trial to test the full feature set in your project, or review the IronXL licensing options when you are ready for production deployment.

Frequently Asked Questions

How can I export DataGridView data to Excel in C#?

Install IronXL via NuGet, extract a DataTable from your DataGridView, create a WorkBook and WorkSheet, call worksheet.LoadFromDataTable(dt, true), then save with workbook.SaveAs.

What formatting options are available when exporting DataGridView to Excel?

IronXL supports bold fonts, background colors, font colors, horizontal alignment, number formats (such as currency), auto-size columns, border styles, and conditional formatting.

Do I need Microsoft Excel installed to export DataGridView data?

No. IronXL is a pure .NET library that generates Excel files without requiring Microsoft Office or any COM registration on the machine.

Can I style headers when exporting DataGridView to Excel?

Yes. After writing the header row, access each header cell by address and set Style.Font.Bold, Style.SetBackgroundColor, and Style.Font.Color properties.

How do I apply alternating row colors in Excel when exporting from DataGridView?

Track the row index as you iterate DataGridView rows, and for even rows apply a range style using worksheet[rangeAddress].Style.SetBackgroundColor with your chosen hex color.

How do I handle large datasets when exporting DataGridView to Excel?

Pass the underlying DataTable directly to worksheet.LoadFromDataTable rather than iterating cells one by one. For very large sets, run the export on a background thread using Task.Run.

How does IronXL compare to Microsoft Excel Interop for DataGridView export?

IronXL does not require Microsoft Excel, works in server and cloud environments, needs no COM cleanup code, and performs significantly faster with large datasets.

Jordi Bardia
Software Engineer
Jordi is most proficient in Python, C# and C++, when he isn’t leveraging his skills at Iron Software; he’s game programming. Sharing responsibilities for product testing, product development and research, Jordi adds immense value to continual product improvement. The varied experience keeps him challenged and engaged, and he ...
Read More

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me