Excel-PRIME
5.2606.20
dotnet add package Excel-PRIME --version 5.2606.20
NuGet\Install-Package Excel-PRIME -Version 5.2606.20
<PackageReference Include="Excel-PRIME" Version="5.2606.20" />
<PackageVersion Include="Excel-PRIME" Version="5.2606.20" />
<PackageReference Include="Excel-PRIME" />
paket add Excel-PRIME --version 5.2606.20
#r "nuget: Excel-PRIME, 5.2606.20"
#:package Excel-PRIME@5.2606.20
#addin nuget:?package=Excel-PRIME&version=5.2606.20
#tool nuget:?package=Excel-PRIME&version=5.2606.20
Excel_PRIME 🌟
- Excel_Performant Reader via Interfaces for Memory Efficiency.
- Without using any external libraries.
- Optimised for Range extraction.
What does that mean?
- Yet another Excel reader ?,
- Starting with .Net 8 as the performant Runtime (See Benchmarks)
- .Net9 gives an extra 5% boost,
- .Net10 Another 5% over .Net9 😉
Lets take each of the above elements and explain:
Excel 📈
- Open Large 2007 (Onwards) XLSX file formats and XLSB in V3.##
- Zip Deflate format Only
Performant 🚀
- Try to be as fast as possible, i.e.
- Forward only Lazy loading
- Only "Quick" decipher / convert of the cell(s) types to ease GC pressure
- No attempt at "creating / using" datatables with headers etc.
- Use
IEnumerables with initial offset starts (Row / Column) - Allow
CancellationTokens to be used to allow page transitioning cancellation (More on this later)
- Now the fastest in Real world usage 2025-11-19 onwards
- Strongly-typed accessors (
AsInt32,AsDateTime, etc)
Q & A's
- Q: There are others that are faster
- A: Agreed, but then
- They do not have range extraction.
- Or
optionallyallow the use of the OS's TempFile System to store massive sheets - Or re-use of already extracted (massive) sheets
- Or allow multiple sheets to be read at the same time
- because others use global memory to represent the current row
- Or have a single access into the Zip Excel file
Reader 📋
- Read only
- Therefore no calculations or updates to formula calls
Interfaces 🏗️
- Will use the DotNet core functionality by default
- But, if your target deployment allows for the use of native performant binaries, then via the use of interfaces these will be pluggable
- i.e. Using
Zlib.Netfor getting the data streams out of the compressed Excel file faster. (OrSharpZipLib/PowerPlayZipper) - A faster / slimmer implementation for xml stream reading (i.e. TurboXml)
- i.e. Using
- Allow the implementation of different source files (i.e. XLSB)
Q & A's
- Q: Why?
- A: As mentioned above, this is to allow a developer to replace with external nugets that might perform better XML speed etc.
Memory 🌐
- The reason for this project, is to handle very large XSLX files (i.e. > 500K rows with > 180 columns per sheet, with multiple sheets of this size)
- For
ETLvalidation scenarios, i.e. make sure that the user modified data that has been transferred has interaction rules applied, before moving onto theTandLstages - Try not to hit / store in the LOH
- No internal .Net memory of previously loaded sheets / rows.
Q & A's
- Q: It appears that this uses more memory than other implementations
- A: Currently yes, but it is being optimised for
Range Extraction,- AND for allowing multiple rows (With cell data) to be stored in memory at the same time, (i.e. via
ToList()call); - AND to allow multiple sheets to be read at the same time (Unlike some to of the others that use "a single" global memory to represent a row)
- And it appears that the current benchmarks do not extract unless a
ToStringand a check on the result is used (Otherwise the Jit removes the unassigned dead code) - And, the memory used will actually be used in the ETL pipeline anyway, so it's just being truthful
- AND for allowing multiple rows (With cell data) to be stored in memory at the same time, (i.e. via
Efficiency 📦
- As hinted by the above statements, this is to be targetted at memory restricted environments (i.e. ASP Net VM's)
- Use the OS's
Temp Filecaching, so if the memory is tight then the Owner app will not have to worry about OOM exceptions, or having to use Swap Disk speeds. - Only unzip the sheet(s) when they are asked for
- Only load the shared strings upto the current request number
Q & A's
- Q: Sometimes the
Asyncawait s add too much overhead - A: true, that is why there are also the equivalent base interfaces that perform the same functionality without the need for the
async awaitoverheads, and still withConcellationTokenusage(s).
Etc. 🔧
CancellationTokens
- This is to allow the Large files to be Aborted
- Make "Most" of the "Net Cores'" API's Asynchronous
Tasks
IDisposable
- Got to tidy up those
Temp Files, and release theFileStream's
Caveats ⛔:
Not Be: Same sheet Thread safe 📊
- It will Not be same sheet Instance thread safe, because the xml reader will be locked (Forward only) to the sheet in use.
- but you can Open the sheet more than once, and have different threads running over it,
- And you can have Parallel threads access the Excel file
- Just remember to set
Options{ AccessExcelFileInForwardOnlyMode = false}
Not Do: Dynamic Ranges ⚠️
- i.e. Ones that contain formulas:
<definedName name="Prices">OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),1)</definedName>
Not Do: Poco 🤖
- A POCO / Type populator (Extensions can be written for that later)
Not Be a: Writer / Modifier 📚
- Totally beyond the scope of this project remit
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 5.2606.20 | 95 | 6/20/2026 | |
| 5.2606.7-Beta | 168 | 6/7/2026 | |
| 4.2605.17 | 113 | 5/17/2026 | |
| 4.2605.5 | 137 | 5/5/2026 | |
| 4.2604.28-RC3 | 127 | 4/28/2026 | |
| 4.2604.22-RC2 | 147 | 4/22/2026 | |
| 4.2604.16-RC1 | 146 | 4/16/2026 | |
| 4.2604.10-Beta | 146 | 4/10/2026 | |
| 4.2604.5-Beta | 122 | 4/5/2026 | |
| 4.2604.5-Alpha | 129 | 4/5/2026 | |
| 4.2601.31-Alpha | 251 | 1/31/2026 | |
| 4.2601.18-Alpha | 195 | 1/18/2026 | |
| 3.2601.16 | 152 | 1/16/2026 | |
| 3.2601.11 | 131 | 1/11/2026 | |
| 3.2601.4-XLSB-RC1 | 134 | 1/4/2026 | |
| 3.2601.2-XLSB-Beta | 132 | 1/2/2026 | |
| 3.2512.21-XLSB-Beta | 222 | 12/21/2025 | |
| 2.2512.14 | 189 | 12/14/2025 |
# 2026-06-20 - V5 - Release Notes
- ⛓️💥 **Breaking Change(s)**
- Cell base type will resolve to decimal first before attempting double. #20
- `Cell` and `CellValue` converted from `class` to `readonly struct` to eliminate object-per-cell overhead.
- `IRow`, `ISheet`, and `IExcel_PRIME` interfaces updated to return structs directly, avoiding boxing.
- `GetAllCells` now returns `ArraySegment<Cell>` to provide zero-allocation access to pooled cell arrays.
- **Memory & Allocation Optimizations**
- ✅ Significant reduction in memory allocations (up to 4x) for large files by eliminating object-per-cell overhead.
- ✅ Implemented `ArrayPool<Cell>` for row-level cell storage.
- ✅ Optimized `Cell` struct layout to exactly 32 bytes (half a cache line) for improved performance.
- **Performance Improvements**
- ✅ Optimized numeric parsing: restored custom `TryDecimalParse` priority while maintaining `double` storage for non-integers.
- ✅ Reduced async overhead by using `ValueTask<Cell>` in sheet reading loops.
- ✅ Improved parallel throughput by making `SharedString` loaders thread-safe at the instance level rather than static.
- ✅ Added `AggressiveInlining` and `AggressiveOptimization` to all high-frequency methods.
- ✅ IAsyncEnumerable stream processing
- ✅ Cell object type 📅
- ✅ Store cell _style_ type (see Options enum)
- ✅ Unit Tests
- ✅ Implement reading of the styles to determine the default `DateTime` / `DateOnly` / `TimeOnly` formats #19
- Fixup `Ecma376StandardProvider`
- Fix the `StylesExtractor`'s
- Add more `cellStyles`
- Make the CellVaule default to the lowest type rather than sticking with `decimal`
- **Code-Level Optimizations**
- ✅ Implement `ISpanFormattable` in CellValue
- ✅ Optimisationm in the Xlsb workflow
- ✅ Return to the usage of the FieldOffsets to store the BCL type to prevent boxings in the hot paths
- ✅ Usage of the Fast convertors *i.e.Our ToDecimal is 3 times faster than Convert.ToDecimal* #20
- **Advanced Scenarios**
- ✅ Enable `PublishTrimmed=true` with trim warnings resolved
- ✅ Native AOT compilation testing
- **Bug Fixes**
- Implement reading of the styles to determine the default `DateTime` / `DateOnly` / `TimeOnly` formats #19
- `AsDecimal` method had an issue where it produces incorrect precision, but only with default options #20
- When Attempting to use the "SkipRows" on a a sheet that has null rows to start with, causes infinite loop #27
- When opening the source file, then use "Sharing Mode" to allow it to be opened by other things! (i.e. 2 instances of this !) #28
- Update BugTesting
- Resolved several compiler warnings and potential resource leaks.
- Excel itself treats named ranges in a case-insensitive manner #34