MiniExcel
Fast, Low-Memory, Easy Excel .NET helper to import/export/template spreadsheet (support Linux, Mac)
Install / Use
/learn @mini-software/MiniExcelREADME
<div align="center"> <p>This project is part of the <a href="https://www.dotnetfoundation.org/">.NET Foundation</a> and operates under their <a href="https://www.dotnetfoundation.org/code-of-conduct">code of conduct</a>. </p> </div>
<div align="center"> <p><strong><a href="README.md">English</a> | <a href="README.zh-CN.md">简体中文</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=zh-TW">繁體中文</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=ja">日本語</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=ko">한국어</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=hi">हिन्दी</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=th">ไทย</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=fr">Français</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=de">Deutsch</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=es">Español</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=it">Italiano</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=ru">Русский</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=pt">Português</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=nl">Nederlands</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=pl">Polski</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=ar">العربية</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=fa">فارسی</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=tr">Türkçe</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=vi">Tiếng Việt</a> | <a href="https://openaitx.github.io/view.html?user=mini-software&project=MiniExcel&lang=id">Bahasa Indonesia</a><p></p> </strong></p> </div>
<div align="center"> Your <a href="https://github.com/mini-software/MiniExcel">Stars</a> or <a href="https://miniexcel.github.io">Donations</a> can make MiniExcel better </div>
Introduction
MiniExcel is a simple and efficient Excel processing tool for .NET, specifically designed to minimize memory usage.
At present, most popular frameworks need to load all the data from an Excel document into memory to facilitate operations, but this may cause memory consumption problems. MiniExcel's approach is different: the data is processed row by row in a streaming manner, reducing the original consumption from potentially hundreds of megabytes to just a few megabytes, effectively preventing out-of-memory(OOM) issues.
flowchart LR
A1(["Excel analysis<br>process"]) --> A2{{"Unzipping<br>XLSX file"}} --> A3{{"Parsing<br>OpenXML"}} --> A4{{"Model<br>conversion"}} --> A5(["Output"])
B1(["Other Excel<br>Frameworks"]) --> B2{{"Memory"}} --> B3{{"Memory"}} --> B4{{"Workbooks &<br>Worksheets"}} --> B5(["All rows at<br>the same time"])
C1(["MiniExcel"]) --> C2{{"Stream"}} --> C3{{"Stream"}} --> C4{{"POCO or dynamic"}} --> C5(["Deferred execution<br>row by row"])
classDef analysis fill:#D0E8FF,stroke:#1E88E5,color:#0D47A1,font-weight:bold;
classDef others fill:#FCE4EC,stroke:#EC407A,color:#880E4F,font-weight:bold;
classDef miniexcel fill:#E8F5E9,stroke:#388E3C,color:#1B5E20,font-weight:bold;
class A1,A2,A3,A4,A5 analysis;
class B1,B2,B3,B4,B5 others;
class C1,C2,C3,C4,C5 miniexcel;
Features
- Minimizes memory consumption, preventing out-of-memory (OOM) errors and avoiding full garbage collections
- Enables real-time, row-level data operations for better performance on large datasets
- Supports LINQ with deferred execution, allowing for fast, memory-efficient paging and complex queries
- Lightweight, without the need for Microsoft Office or COM+ components, and a DLL size under 500KB
- Simple and intuitive API style to read/write/fill excel
Version 2.0 preview
We are working on a future MiniExcel version, with a new modular and focused API,
separate nuget packages for Core and Csv funcionalities, full support for asynchronously streamed queries through IAsyncEnumerable,
and more to come soon! The packages are gonna be available in pre-release, so feel free to check them out and give us some feedback!
If you do, make sure to also check out the new docs and the upgrade notes.
Get Started
Installation
You can install the package from NuGet
Release Notes
Please Check Release Notes
TODO
Please Check TODO
Performance
The code for the benchmarks can be found in MiniExcel.Benchmarks.
The file used to test performance is Test1,000,000x10.xlsx, a 32MB document containing 1,000,000 rows * 10 columns whose cells are filled with the string "HelloWorld".
To run all the benchmarks use:
dotnet run -project .\benchmarks\MiniExcel.Benchmarks -c Release -f net9.0 -filter * --join
You can find the benchmarks' results for the latest release here.
Excel Query/Import <a name="getstart1"></a>
1. Execute a query and map the results to a strongly typed IEnumerable [Try it]
Recommand to use Stream.Query because of better efficiency.
public class UserAccount
{
public Guid ID { get; set; }
public string Name { get; set; }
public DateTime BoD { get; set; }
public int Age { get; set; }
public bool VIP { get; set; }
public decimal Points { get; set; }
}
var rows = MiniExcel.Query<UserAccount>(path);
// or
using (var stream = File.OpenRead(path))
var rows = stream.Query<UserAccount>();

2. Execute a query and map it to a list of dynamic objects without using head [Try it]
- dynamic key is
A.B.C.D..
| MiniExcel | 1 | |-----------|---| | Github | 2 |
var rows = MiniExcel.Query(path).ToList();
// or
using (var stream = File.OpenRead(path))
{
var rows = stream.Query().ToList();
Assert.Equal("MiniExcel", rows[0].A);
Assert.Equal(1, rows[0].B);
Assert.Equal("Github", rows[1].A);
Assert.Equal(2, rows[1].B);
}
3. Execute a query with first header row [Try it]
note : same column name use last right one
Input Excel :
| Column1 | Column2 | |-----------|---------| | MiniExcel | 1 | | Github | 2 |
var rows = MiniExcel.Query(useHeaderRow:true).ToList();
// or
using (var stream = File.OpenRead(path))
{
var rows = stream.Query(useHeaderRow:true).ToList();
Assert.Equal("MiniExcel", rows[0].Column1);
Assert.Equal(1, rows[0].Column2);
Assert.Equal("Github", rows[1].Column1);
Assert.Equal(2, rows[1].Column2);
}
4. Query Support LINQ Extension First/Take/Skip ...etc
Query First
var row = MiniExcel.Query(path).First();
Assert.Equal("HelloWorld", row.A);
// or
using (var stream = File.OpenRead(path))
{
var row = stream.Query().First();
Assert.Equal("HelloWorld", row.A);
}
Performance between MiniExcel/ExcelDataReader/ClosedXML/EPPlus

5. Query by sheet name
MiniExcel.Query(path, sheetName: "SheetName");
//or
stream.Query(sheetName: "SheetName");
6. Query all sheet name and rows
var sheetNames = MiniExcel.GetSheetNames(path);
foreach (var sheetName in sheetNames)
{
var rows = MiniExcel.Query(path, sheetName: sheetName);
}
7. Get Columns
var columns = MiniExcel.GetColumns(path); // e.g result : ["A","B"...]
var
