Skip to content

gustafl/ExcelLibrary

Repository files navigation

ExcelLibrary

A lightweight, dependency-free .NET library for reading Excel workbooks (.xlsx).

using var workbook = Workbook.Open("data.xlsx");
var value = workbook.Sheet("Sheet1")?.Cell("B2")?.Value;

Quick Start

Reading cells

using var workbook = Workbook.Open("Book1.xlsx");
var sheet = workbook.Sheet("Sheet1");

// Access by cell address
var cell = sheet?.Cell("A1");
Console.WriteLine(cell?.Value);

// Or by row and column index (1-based)
var value = sheet?.Cell(2, 3)?.Value;

// Get a specific row or column
var row = sheet?.Row(5);
var column = sheet?.Column(2);

// Access cells from a row or column
var cellsInRow = row?.Cells;
var cellsInColumn = column?.Cells;

// Navigate up the hierarchy
var parentSheet = row?.Sheet;
var parentWorkbook = cell?.Row.Sheet.Workbook;

Iterating rows and cells

using var workbook = Workbook.Open("report.xlsx");

foreach (var sheet in workbook.Sheets)
{
    Console.WriteLine($"Sheet: {sheet.Name}");

    foreach (var row in sheet.Rows)
    {
        foreach (var cell in row.Cells)
        {
            Console.Write($"{cell.Value}\t");
        }
        Console.WriteLine();
    }
}

All collections (Sheets, Rows, Columns, Cells) are IEnumerable<T>, so you can use LINQ:

// Find non-empty cells
var nonEmpty = sheet.Rows
    .SelectMany(r => r.Cells)
    .Where(c => !string.IsNullOrEmpty(c.Value));

// Get unique values from a column
var uniqueValues = sheet.Column(1)?.Cells
    .Select(c => c.Value)
    .Distinct();

Exception handling

Handle common exceptions when opening workbooks:

try
{
    using var workbook = Workbook.Open("data.xlsx");
    // Work with the workbook
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"File not found: {ex.FileName}");
}
catch (IOException ex)
{
    Console.WriteLine($"Error reading file: {ex.Message}");
}

Including hidden elements

By default, hidden sheets, rows, and columns are excluded. Use WorkbookOptions to include them:

using var workbook = Workbook.Open("data.xlsx", new WorkbookOptions { IncludeHidden = true });

// Now hidden sheets, rows, and columns are accessible
var hiddenSheet = workbook.Sheet("HiddenSheet");

Lazy loading sheets

For large workbooks, you can defer loading sheet data until needed:

using var workbook = Workbook.Open("large-file.xlsx", new WorkbookOptions { LoadSheets = false });

// Sheet metadata is available, but rows/cells are not yet loaded
var sheet = workbook.Sheet("Sheet1");

// Load the sheet data when needed
sheet?.Open();

Parallel sheet loading

For workbooks with many sheets, enable parallel loading for better performance:

using var workbook = Workbook.Open("many-sheets.xlsx", new WorkbookOptions { ParallelLoadSheets = true });

// All sheets are loaded concurrently
foreach (var sheet in workbook.Sheets)
{
    Console.WriteLine($"{sheet.Name}: {sheet.Rows.Count()} rows");
}

Loading from streams

Load workbooks directly from any stream (useful for web uploads, embedded resources, etc.):

// From a file stream
using var stream = File.OpenRead("data.xlsx");
using var workbook = Workbook.Open(stream);

// From a memory stream (e.g., downloaded content)
var bytes = await httpClient.GetByteArrayAsync(url);
using var memoryStream = new MemoryStream(bytes);
using var workbook = Workbook.Open(memoryStream);

Cell formats and dates

Dates and times are automatically converted from Excel's internal numeric format to ISO format strings:

var cell = sheet?.Cell("A1");
Console.WriteLine(cell?.Value);  // Output: 2025-12-31

The Cell.Format property indicates the number format category, which is useful for custom parsing of other formats:

var cell = sheet?.Cell("B2");

var value = cell?.Format switch
{
    NumberFormat.Percentage => double.Parse(cell.Value.TrimEnd('%')) / 100,
    NumberFormat.Currency => decimal.Parse(cell.Value, NumberStyles.Currency),
    NumberFormat.Number => double.Parse(cell.Value),
    _ => null as double?
};

Format categories include General, Number, Currency, Accounting, Date, Time, Percentage, Fraction, Scientific, Text, Special, Custom, and Unsupported.

Features

  • Zero dependencies — Uses only built-in .NET APIs
  • Stream support — Load from files, memory streams, or any readable stream
  • LINQ-friendly — Collections like Sheets, Rows, and Cells are IEnumerable<T>
  • Visibility-aware — Respects hidden sheets, rows, and columns by default
  • Lazy loading — Optionally defer sheet loading for better performance
  • Parallel loading — Load multiple sheets concurrently for large workbooks
  • Well-tested — Comprehensive test suite with 99 unit tests

API Reference

Class Description
Workbook Represents an Excel file; provides access to sheets and metadata
Sheet A worksheet containing rows, columns, and cells
Row A row with access to its cells
Column A column with access to its cells
Cell A single cell with its value and format
WorkbookOptions Configuration for loading workbooks

Limitations

This library focuses on reading Excel files. The following are out of scope:

  • File formats other than .xlsx
  • Writing/modifying workbooks
  • Formula evaluation
  • Cell formatting/styles

Requirements

  • .NET 8.0 or later

License

MIT

NuGet notice

An older version of this library has been published on NuGet without my authorization. I am currently working on publishing this new much improved version as an official NuGet package. Any NuGet package not explicitly linked or mentioned in this repository should be considered unofficial. Further updates regarding an official package will be announced here.

About

An intuitive C# library for reading data from Excel documents (.xlsx). No dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages