How to Create Excel File in C# Using Dataset
Exporting data from your application into an Excel spreadsheet is a common requirement for giving users a way to analyze, report on, or simply store information. This article walks you through exactly how to create an Excel file in C# using a DataSet, a convenient way to handle structured, in-memory data. We'll use a popular library that simplifies the process, so you can skip the complex parts and get straight to a working solution.
Setting Up Your C# Excel Project
Before you can write any code, you need a way to create and manipulate Excel files without relying on having Microsoft Office installed on the server where your code runs. While there are a few options, the easiest approach is to use a third-party library designed for this purpose.
Choose the Right Tool for the Job
There are three main paths for creating Excel files programmatically in C#:
- Microsoft.Office.Interop.Excel: This is the Microsoft-provided library that directly automates the Excel application.
- Open XML SDK: A lower-level library from Microsoft that lets you work directly with the XML structure that makes up modern Excel files (.xlsx).
- Third-Party Libraries (like ClosedXML): These libraries act as a user-friendly wrapper around the Open XML SDK. They give you the power of Open XML without the complexity.
For this tutorial, we will use ClosedXML. It hits the sweet spot of being powerful, easy to use, and free from external dependencies like a local Office installation.
Installing the ClosedXML Library
The easiest way to add ClosedXML to your project is through the NuGet Package Manager in Visual Studio.
- Right-click on your project in the Solution Explorer.
- Select "Manage NuGet Packages..."
- Click on the "Browse" tab and search for ClosedXML.
- Select it from the list and click "Install."
Alternatively, you can install it using the Package Manager Console:
Install-Package ClosedXML
Free PDF · the crash course
AI Agents for Marketing Crash Course
Learn how to deploy AI marketing agents across your go-to-market — the best tools, prompts, and workflows to turn your data into autonomous execution without writing code.
Populating Your DataSet with Sample Data
A DataSet is an in-memory representation of data that can contain one or more tables, each represented by a DataTable. Think of it as a small, disconnected database living in your application's memory. Before we can export anything, we need some data to work with.
For this example, let's create a DataSet that simulates having customer information in one table and their corresponding orders in another. This will also show how to handle exporting multiple tables into separate tabs (worksheets) in a single Excel file.
Here’s a simple C# method to generate our sample data:
using System,
using System.Data,
public DataSet GetSampleDataSet()
{
// Create a new DataSet
var dataSet = new DataSet("SampleData"),
// Create the Customers DataTable
var customersTable = new DataTable("Customers"),
customersTable.Columns.Add("CustomerID", typeof(int)),
customersTable.Columns.Add("CustomerName", typeof(string)),
customersTable.Columns.Add("Country", typeof(string)),
// Add some sample customer rows
customersTable.Rows.Add(1, "Alfreds Futterkiste", "Germany"),
customersTable.Rows.Add(2, "Ana Trujillo Emparedados y helados", "Mexico"),
customersTable.Rows.Add(3, "Antonio Moreno Taqueria", "Mexico"),
customersTable.Rows.Add(4, "Around the Horn", "UK"),
// Create the Orders DataTable
var ordersTable = new DataTable("Orders"),
ordersTable.Columns.Add("OrderID", typeof(int)),
ordersTable.Columns.Add("CustomerID", typeof(int)), // Foreign key
ordersTable.Columns.Add("OrderDate", typeof(DateTime)),
ordersTable.Columns.Add("Freight", typeof(decimal)),
// Add some sample order rows
ordersTable.Rows.Add(10248, 4, new DateTime(2023, 7, 4), 32.38),
ordersTable.Rows.Add(10249, 1, new DateTime(2023, 7, 5), 11.61),
ordersTable.Rows.Add(10250, 2, new DateTime(2023, 7, 8), 65.83),
ordersTable.Rows.Add(10251, 3, new DateTime(2023, 7, 8), 41.34),
ordersTable.Rows.Add(10252, 4, new DateTime(2023, 7, 9), 51.30),
// Add both tables to the DataSet
dataSet.Tables.Add(customersTable),
dataSet.Tables.Add(ordersTable),
return dataSet,
}This code block sets up everything we need: a DataSet containing two related tables (Customers and Orders), each with columns and several rows of data.
Writing the DataSet to an Excel File with C#
Now for the main event. With your DataSet ready and ClosedXML installed, the actual export process is remarkably simple. The library handles the complex parts of building the .xlsx file structure for you.
The logic follows these basic steps:
- Create a new
XLWorkbookobject, which represents your Excel file. - Loop through each
DataTablein yourDataSet. - For each table, add a new worksheet to the workbook. Happily, ClosedXML can do this in one line, automatically creating columns and populating the data from the
DataTable. - Save the workbook to a file path on your disk.
Here is what that looks like in code. Imagine this is located in your Main method or another function in your application:
using ClosedXML.Excel,
using System.Data,
// Get the sample data
DataSet myDataSet = GetSampleDataSet(),
// Create a new Excel workbook
using (var workbook = new XLWorkbook())
{
// Loop through each DataTable in the DataSet
foreach (DataTable table in myDataSet.Tables)
{
// Add a worksheet for each table in the DataSet.
// The worksheet will be named after the table's `TableName` property.
workbook.Worksheets.Add(table),
}
// Define the file path
string filePath = "C:\\Temp\\MyFirstExport.xlsx",
// Save the workbook
workbook.SaveAs(filePath),
Console.WriteLine($"Excel file created at: {filePath}"),
}That’s it! The real magic is in the workbook.Worksheets.Add(table) line. ClosedXML is smart enough to take a DataTable object, read its TableName property for the sheet name, use the column definitions for headers, and fill the rows with data, all in one simple method call. If you run this code, you'll find an Excel file at C:\Temp\ with two sheets named "Customers" and "Orders," each containing the data we created.
Enhancing Your Excel Export: Styling and Formatting
Just dumping raw data is good, but a little formatting goes a long way toward making your reports professional and readable. ClosedXML provides a straightforward API for applying styles.
Let's update our code to automatically adjust column widths and apply some styling to the header row.
Free PDF · the crash course
AI Agents for Marketing Crash Course
Learn how to deploy AI marketing agents across your go-to-market — the best tools, prompts, and workflows to turn your data into autonomous execution without writing code.
A Complete, Styled Example
This combined example builds on the previous one, adding styles just after a worksheet is created.
using ClosedXML.Excel,
using System.Data,
using System,
// Assume GetSampleDataSet() method exists from the earlier example
DataSet myDataSet = GetSampleDataSet(),
// Create a new Excel workbook
using (var workbook = new XLWorkbook())
{
// Loop through each DataTable
foreach (DataTable table in myDataSet.Tables)
{
// Add a new worksheet to the workbook
var worksheet = workbook.Worksheets.Add(table),
// --- STYLING ---
// 1. Auto-adjust column widths for readability
worksheet.Columns().AdjustToContents(),
// 2. Style the header row
var headerRow = worksheet.FirstRow(),
headerRow.Style.Font.Bold = true,
headerRow.Style.Fill.BackgroundColor = XLColor.LightGray,
headerRow.Style.Font.FontColor = XLColor.DarkBlue,
headerRow.Height = 20,
// 3. (Optional) Put a freeze pane on the header row
worksheet.SheetView.FreezeRows(1),
// 4. (Optional) Example of formatting a specific column as currency
// This is useful when you know a column's name
if (table.TableName == "Orders" && worksheet.Column("Freight") != null)
{
worksheet.Column("Freight").Style.NumberFormat.Format = "\"$\"#,##0.00",
}
}
// Define the file path
string filePath = "C:\\Temp\\StyledExport.xlsx",
// Save the workbook
workbook.SaveAs(filePath),
Console.WriteLine($"Styled Excel file created at: {filePath}"),
}When you run this code, your new Excel file will be much more user-friendly:
- Column widths are perfectly sized to fit the content.
- Header rows stand out with a bold font, a background color, and a high-contrast font color.
- If you scroll down, the header row stays visible because it's frozen.
- The "Freight" column in the "Orders" sheet is now correctly formatted as USD currency.
Final Thoughts
As you can see, creating Excel files from a C# DataSet is straightforward when you use a helpful library like ClosedXML. The process involves preparing your data in one or more DataTables within a DataSet, using the library to create worksheets from those tables, and then adding simple but effective styling to improve readability before saving the final file.
While building custom reports and exports like this is sometimes necessary, we’ve found that most manual reporting is a time sink that keeps teams from focusing on strategy. Rather than writing code to export static files, tools like Graphed let you connect directly to live data sources – like databases, Google Analytics, Shopify, or SaaS platforms – and instantly generate real-time, interactive dashboards. Asking for a new report becomes a simple, natural language question instead of a development ticket, empowering your whole team to get the insights they need in seconds, not days.
Related Articles
How to Create Facebook Ads API for Claude Code
Create a Meta Marketing API access token that never expires, using a system user, so Claude Code can pull Facebook ad reports and manage campaigns.
ClickHouse vs Postgres: When to Switch to Columnar
Comparing ClickHouse vs PostgreSQL means matching storage architecture to workload. Row storage wins for transactions. Columnar wins for scan-heavy analytics.
Google Ads for Orthodontists: Get More Booked Consults
Most orthodontic Google Ads campaigns waste money on low-intent searches. The problem is structure, not the platform.