Skip to footer content
USING IRONXL

Build an Excel API for .NET Core: Create, Read, and Export XLSX Files

Building an Excel API for .NET Core is straightforward with IronXL. Install the package, create a WorkBook, populate cells, and return the stream directly -- no Microsoft Office required.

Install-Package IronXL.Excel

IronXL handles XLSX creation, data import, multi-format exports, and cell styling entirely in managed .NET code. It runs on Windows, Linux, and macOS, making it a practical choice for any ASP.NET Core API that needs programmatic Excel support.

How Do You Install IronXL in a .NET Core Project?

Add IronXL to any .NET 10 project through the NuGet Package Manager Console:

Install-Package IronXL.Excel

Or install via the Visual Studio NuGet UI by searching for IronXl. The package name on NuGet is IronXL.Excel.

After installation, add using IronXL; to any file that creates or reads workbooks. No Office interop libraries, no COM registration, and no Microsoft Excel installation is required on the host machine -- IronXL is entirely self-contained.

IronXL targets .NET Standard 2.0 and above, which means the same library works for .NET Core, .NET 5/6/7/8/9/10, and .NET Framework projects. The IronXL documentation covers all supported environments in detail.

How Do You Create Excel Files Programmatically in .NET Core?

Creating Excel documents from scratch requires just a few lines of code with IronXL's intuitive API. The library provides full control over workbooks, worksheets, cell styles, and formulas through a clean object model.

Here is a controller action that creates a new Excel workbook with formatted data, demonstrates worksheet management, and applies cell styles:

using IronXL;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ExcelController : ControllerBase
{
    [HttpGet("create-report")]
    public IActionResult CreateSalesReport()
    {
        // Create a new Excel workbook in XLSX format
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Sales Data");

        // Set header labels in the first row
        worksheet["A1"].Value = "Product";
        worksheet["B1"].Value = "Q1 Sales";
        worksheet["C1"].Value = "Q2 Sales";
        worksheet["D1"].Value = "Total";

        // Bold headers and apply a blue background with white text
        worksheet["A1:D1"].Style.Font.Bold = true;
        worksheet["A1:D1"].Style.SetBackgroundColor("#4472C4");
        worksheet["A1:D1"].Style.Font.SetColor("#FFFFFF");

        // Add data rows
        worksheet["A2"].Value = "Widget Pro";
        worksheet["B2"].Value = 15000;
        worksheet["C2"].Value = 18500;
        worksheet["D2"].Formula = "=B2+C2";

        worksheet["A3"].Value = "Gadget Plus";
        worksheet["B3"].Value = 22000;
        worksheet["C3"].Value = 24000;
        worksheet["D3"].Formula = "=B3+C3";

        // Apply currency number format to sales columns
        worksheet["B2:D3"].Style.Format = "$#,##0";

        // Stream the XLSX file back to the caller
        var stream = workbook.ToStream();
        return File(
            stream,
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "SalesReport.xlsx");
    }
}
using IronXL;
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ExcelController : ControllerBase
{
    [HttpGet("create-report")]
    public IActionResult CreateSalesReport()
    {
        // Create a new Excel workbook in XLSX format
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Sales Data");

        // Set header labels in the first row
        worksheet["A1"].Value = "Product";
        worksheet["B1"].Value = "Q1 Sales";
        worksheet["C1"].Value = "Q2 Sales";
        worksheet["D1"].Value = "Total";

        // Bold headers and apply a blue background with white text
        worksheet["A1:D1"].Style.Font.Bold = true;
        worksheet["A1:D1"].Style.SetBackgroundColor("#4472C4");
        worksheet["A1:D1"].Style.Font.SetColor("#FFFFFF");

        // Add data rows
        worksheet["A2"].Value = "Widget Pro";
        worksheet["B2"].Value = 15000;
        worksheet["C2"].Value = 18500;
        worksheet["D2"].Formula = "=B2+C2";

        worksheet["A3"].Value = "Gadget Plus";
        worksheet["B3"].Value = 22000;
        worksheet["C3"].Value = 24000;
        worksheet["D3"].Formula = "=B3+C3";

        // Apply currency number format to sales columns
        worksheet["B2:D3"].Style.Format = "$#,##0";

        // Stream the XLSX file back to the caller
        var stream = workbook.ToStream();
        return File(
            stream,
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "SalesReport.xlsx");
    }
}
Imports IronXL
Imports Microsoft.AspNetCore.Mvc

<ApiController>
<Route("api/[controller]")>
Public Class ExcelController
    Inherits ControllerBase

    <HttpGet("create-report")>
    Public Function CreateSalesReport() As IActionResult
        ' Create a new Excel workbook in XLSX format
        Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLSX)
        Dim worksheet As WorkSheet = workbook.CreateWorkSheet("Sales Data")

        ' Set header labels in the first row
        worksheet("A1").Value = "Product"
        worksheet("B1").Value = "Q1 Sales"
        worksheet("C1").Value = "Q2 Sales"
        worksheet("D1").Value = "Total"

        ' Bold headers and apply a blue background with white text
        worksheet("A1:D1").Style.Font.Bold = True
        worksheet("A1:D1").Style.SetBackgroundColor("#4472C4")
        worksheet("A1:D1").Style.Font.SetColor("#FFFFFF")

        ' Add data rows
        worksheet("A2").Value = "Widget Pro"
        worksheet("B2").Value = 15000
        worksheet("C2").Value = 18500
        worksheet("D2").Formula = "=B2+C2"

        worksheet("A3").Value = "Gadget Plus"
        worksheet("B3").Value = 22000
        worksheet("C3").Value = 24000
        worksheet("D3").Formula = "=B3+C3"

        ' Apply currency number format to sales columns
        worksheet("B2:D3").Style.Format = "$#,##0"

        ' Stream the XLSX file back to the caller
        Dim stream = workbook.ToStream()
        Return File(
            stream,
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "SalesReport.xlsx")
    End Function
End Class
$vbLabelText   $csharpLabel

Output Excel File

Build an Excel API for .NET Core: Create, Read, and Export XLSX Files: Image 1 - Excel file generated by the .NET Core API

WorkBook.Create() supports both XLSX and XLS formats. The CreateWorkSheet() method adds a named sheet where you populate cells with values, apply Excel formulas for calculations, and control layout through cell ranges. IronXL's calculation engine evaluates formulas automatically when workbook data changes, including support for array formulas used in more complex data analysis scenarios.

Cell styles go well beyond bold and color. The cell formatting API lets you set number formats, borders, alignment, font sizes, and more -- all without touching the COM layer. This makes it safe to run inside containerized Linux environments where no display context exists.

How Do You Add Multiple Worksheets to a Workbook?

A single workbook can hold any number of worksheets. Call workbook.CreateWorkSheet("SheetName") for each tab needed. Worksheets are accessible later by name through workbook.GetWorkSheet("SheetName") or by index through workbook.WorkSheets[0].

This pattern is useful when generating summary-plus-detail reports: one sheet holds aggregated totals while child sheets hold the raw transaction rows. The worksheet management docs walk through renaming, reordering, and removing sheets at runtime.

What Is the Best Way to Read Excel Data in Web APIs?

Importing data from user-uploaded Excel files is essential for any web application that processes spreadsheet content. IronXL makes reading Excel spreadsheets direct -- load from a stream, iterate rows, and pull typed values out of each cell.

[HttpPost("import")]
public IActionResult ImportExcelData(IFormFile file)
{
    if (file == null || file.Length == 0)
        return BadRequest("No file uploaded");

    using var stream = file.OpenReadStream();

    // Load the workbook directly from the upload stream
    WorkBook workbook = WorkBook.Load(stream);
    WorkSheet worksheet = workbook.DefaultWorkSheet;

    var records = new List<Dictionary<string, object>>();

    // Start at row 2 to skip the header row
    for (int row = 2; row <= worksheet.RowCount; row++)
    {
        var record = new Dictionary<string, object>
        {
            ["Product"] = worksheet[$"A{row}"].StringValue,
            ["Sales"]   = worksheet[$"B{row}"].DecimalValue,
            ["Date"]    = worksheet[$"C{row}"].DateTimeValue
        };
        records.Add(record);
    }

    return Ok(new {
        message     = "Import successful",
        recordCount = records.Count,
        data        = records
    });
}
[HttpPost("import")]
public IActionResult ImportExcelData(IFormFile file)
{
    if (file == null || file.Length == 0)
        return BadRequest("No file uploaded");

    using var stream = file.OpenReadStream();

    // Load the workbook directly from the upload stream
    WorkBook workbook = WorkBook.Load(stream);
    WorkSheet worksheet = workbook.DefaultWorkSheet;

    var records = new List<Dictionary<string, object>>();

    // Start at row 2 to skip the header row
    for (int row = 2; row <= worksheet.RowCount; row++)
    {
        var record = new Dictionary<string, object>
        {
            ["Product"] = worksheet[$"A{row}"].StringValue,
            ["Sales"]   = worksheet[$"B{row}"].DecimalValue,
            ["Date"]    = worksheet[$"C{row}"].DateTimeValue
        };
        records.Add(record);
    }

    return Ok(new {
        message     = "Import successful",
        recordCount = records.Count,
        data        = records
    });
}
Imports Microsoft.AspNetCore.Mvc
Imports System.Collections.Generic
Imports IronXL

<HttpPost("import")>
Public Function ImportExcelData(file As IFormFile) As IActionResult
    If file Is Nothing OrElse file.Length = 0 Then
        Return BadRequest("No file uploaded")
    End If

    Using stream = file.OpenReadStream()
        ' Load the workbook directly from the upload stream
        Dim workbook As WorkBook = WorkBook.Load(stream)
        Dim worksheet As WorkSheet = workbook.DefaultWorkSheet

        Dim records As New List(Of Dictionary(Of String, Object))()

        ' Start at row 2 to skip the header row
        For row As Integer = 2 To worksheet.RowCount
            Dim record As New Dictionary(Of String, Object) From {
                {"Product", worksheet($"A{row}").StringValue},
                {"Sales", worksheet($"B{row}").DecimalValue},
                {"Date", worksheet($"C{row}").DateTimeValue}
            }
            records.Add(record)
        Next

        Return Ok(New With {
            .message = "Import successful",
            .recordCount = records.Count,
            .data = records
        })
    End Using
End Function
$vbLabelText   $csharpLabel

Output

Build an Excel API for .NET Core: Create, Read, and Export XLSX Files: Image 2 - Output showing the successfully imported Excel data

WorkBook.Load() opens Excel files from streams, file paths, or byte arrays. Cells are accessed through the worksheet["A1"] indexer syntax or by iterating a named cell range. IronXL handles data validation automatically and exposes type-safe accessors -- IntValue, DecimalValue, DateTimeValue, StringValue -- so the consuming code stays clean and predictable.

How Do You Filter and Sort Imported Data?

After loading a workbook, call .SortAscending() or .SortDescending() on any Range object to sort rows. For filtering, iterate cells and evaluate conditions inline or transfer data into a LINQ collection for further processing. The sorting and filtering guide demonstrates both approaches with practical examples.

Working with large uploads? IronXL reads only the cells accessed, so there is no need to load an entire multi-megabyte file into memory before querying a specific column. This lazy-access approach keeps memory consumption stable even when processing workbooks with tens of thousands of rows.

How Can You Export Excel Data to Different Formats?

Applications often need to offer spreadsheets in multiple output formats. IronXL supports exporting to XLSX, XLS, CSV, JSON, and HTML in a single method call, with no external conversion tools required.

[HttpGet("export/{format}")]
public IActionResult ExportData(string format)
{
    // Load a pre-designed template workbook
    WorkBook workbook = WorkBook.Load("template.xlsx");

    return format.ToLower() switch
    {
        "xlsx" => File(
            workbook.ToStream(),
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "export.xlsx"),

        "csv"  => File(
            workbook.ToStream(FileFormat.CSV),
            "text/csv",
            "export.csv"),

        "json" => Ok(workbook.ToJson()),

        _      => BadRequest("Unsupported format")
    };
}
[HttpGet("export/{format}")]
public IActionResult ExportData(string format)
{
    // Load a pre-designed template workbook
    WorkBook workbook = WorkBook.Load("template.xlsx");

    return format.ToLower() switch
    {
        "xlsx" => File(
            workbook.ToStream(),
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "export.xlsx"),

        "csv"  => File(
            workbook.ToStream(FileFormat.CSV),
            "text/csv",
            "export.csv"),

        "json" => Ok(workbook.ToJson()),

        _      => BadRequest("Unsupported format")
    };
}
Imports Microsoft.AspNetCore.Mvc

<HttpGet("export/{format}")>
Public Function ExportData(format As String) As IActionResult
    ' Load a pre-designed template workbook
    Dim workbook As WorkBook = WorkBook.Load("template.xlsx")

    Select Case format.ToLower()
        Case "xlsx"
            Return File(workbook.ToStream(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "export.xlsx")
        Case "csv"
            Return File(workbook.ToStream(FileFormat.CSV), "text/csv", "export.csv")
        Case "json"
            Return Ok(workbook.ToJson())
        Case Else
            Return BadRequest("Unsupported format")
    End Select
End Function
$vbLabelText   $csharpLabel

Using Excel templates with predefined layouts accelerates report generation. Load a pre-designed workbook, populate dynamic data into named cells or ranges, then stream the result. This approach suits sales reports, invoices, and compliance documents where consistent formatting matters more than flexibility.

IronXL's cross-platform support means these file operations work identically on Windows, Linux, and macOS, making it suitable for .NET Core containerized deployments. Read more in the IronXL cross-platform guide.

How Do You Export to CSV from a .NET Core API?

Call workbook.ToStream(FileFormat.CSV) and return it with the text/csv content type, as shown above. For multi-sheet workbooks, each sheet can be exported independently by accessing workbook.WorkSheets[index] and calling .ToStream(FileFormat.CSV) on the sheet object. The CSV export documentation covers handling of delimiters, encoding, and date format options.

How Do You Apply Conditional Formatting and Data Bars?

Beyond basic cell styles, IronXL supports conditional formatting rules -- highlight cells above a threshold in green, flag negatives in red, or apply gradient data bars to make trends immediately visible in the spreadsheet without any post-processing in a separate tool.

Conditional formatting is particularly valuable in financial dashboards and KPI reports where readers need to spot outliers at a glance. Rather than relying on the recipient to apply their own formatting after download, the rules travel embedded in the XLSX file and are evaluated automatically when the file opens in any version of Microsoft Excel or compatible viewer.

Conditional formatting is set through the worksheet's ConditionalFormatting property. Rules are applied to a named cell range and support multiple condition types: cell value comparisons, formula-based rules, color scales that grade values from low to high, and data bar overlays that function like in-cell bar charts. The Open XML specification defines the underlying rule structure that IronXL writes into the XLSX file.

For a complete reference on applying color scales, icon sets, and data bars, see the conditional formatting tutorial in the IronXL docs.

How Do You Protect Excel Files and Worksheets?

Distributing reports that contain sensitive data requires a layer of access control. IronXL supports both workbook-level password protection and worksheet-level protection:

  • Workbook password: Set workbook.Password = "secret" before calling .SaveAs() to encrypt the XLSX file. Recipients must enter the password to open it in Excel.
  • Worksheet protection: Call worksheet.ProtectSheet("password") to lock cell editing while still allowing the sheet to be viewed. Specific ranges can be unlocked for data entry using the AllowEditRange API.
  • Read-only distribution: For documents that should never be edited, combine worksheet protection with file-level encryption.

Password-protected XLSX files use AES-128 encryption by default, the same standard that native Excel applies. This means a file protected through IronXL is fully compatible with Excel's built-in open-file prompt -- no special viewer is required on the recipient's end.

These security features complement the standard .NET Core security model and are especially useful when building finance or HR reporting endpoints. The file protection documentation provides the full API reference.

How Do You Work with Excel Formulas in .NET?

IronXL's built-in calculation engine evaluates standard Excel formulas at runtime, so the API can return computed values without saving to disk and reopening in Excel first. Assign a formula string to any cell's .Formula property:

// Sum a column and place the result in a footer row
worksheet[$"B{lastRow}"].Formula = $"=SUM(B2:B{lastRow - 1})";

// Calculate an average across a range
worksheet[$"C{lastRow}"].Formula = $"=AVERAGE(C2:C{lastRow - 1})";

// Retrieve the computed value immediately
decimal total = worksheet[$"B{lastRow}"].DecimalValue;
// Sum a column and place the result in a footer row
worksheet[$"B{lastRow}"].Formula = $"=SUM(B2:B{lastRow - 1})";

// Calculate an average across a range
worksheet[$"C{lastRow}"].Formula = $"=AVERAGE(C2:C{lastRow - 1})";

// Retrieve the computed value immediately
decimal total = worksheet[$"B{lastRow}"].DecimalValue;
' Sum a column and place the result in a footer row
worksheet($"B{lastRow}").Formula = $"=SUM(B2:B{lastRow - 1})"

' Calculate an average across a range
worksheet($"C{lastRow}").Formula = $"=AVERAGE(C2:C{lastRow - 1})"

' Retrieve the computed value immediately
Dim total As Decimal = worksheet($"B{lastRow}").DecimalValue
$vbLabelText   $csharpLabel

IronXL supports most standard Excel functions including mathematical, statistical, text, date, and lookup categories. Array formulas (Ctrl+Shift+Enter semantics) are also supported for advanced scenarios. Because formula evaluation happens inside the .NET process, there is no round-trip to an external calculation service -- results are available immediately after the formula is assigned, which keeps API response times predictable even when calculating across thousands of rows. The formula support reference lists all supported functions.

What Are Your Next Steps?

Building an Excel API with IronXL gives .NET Core applications solid capabilities for working with spreadsheets. From creating XLSX files with formatted data and calculated formulas to importing user uploads and exporting data in multiple formats, IronXL handles every aspect of programmatic spreadsheet manipulation in a cross-platform, Office-free way.

Explore these resources to go further:

Start a free trial to test IronXL in a live project, or review licensing options to find the right plan for production deployment.

Frequently Asked Questions

What is IronXL?

IronXL is a .NET Excel library that lets developers create, read, and export Excel files programmatically in C# without requiring Microsoft Office or COM interop.

How do you create an Excel file in .NET Core without Office?

Call WorkBook.Create(ExcelFileFormat.XLSX) to create a new workbook, add sheets with CreateWorkSheet(), populate cells with the worksheet['A1'].Value syntax, and stream the result with workbook.ToStream().

How do you read an uploaded Excel file in ASP.NET Core?

Pass the IFormFile stream to WorkBook.Load(stream), access the DefaultWorkSheet, and iterate rows using worksheet.RowCount. Typed accessors such as DecimalValue and DateTimeValue extract strongly-typed data from each cell.

Can IronXL export Excel data to CSV or JSON?

Yes. Call workbook.ToStream(FileFormat.CSV) for CSV output or workbook.ToJson() for a JSON representation of the workbook data.

Does IronXL run on Linux and macOS?

Yes. IronXL targets .NET Standard 2.0 and above and runs on Windows, Linux, and macOS without any Microsoft Office installation or COM layer.

How do you password-protect an Excel file with IronXL?

Set workbook.Password to a string before calling SaveAs(). For worksheet-level protection, call worksheet.ProtectSheet('password') to prevent cell editing while allowing the sheet to be read.

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