Excel-PRIME
4.2605.17
dotnet add package Excel-PRIME --version 4.2605.17
NuGet\Install-Package Excel-PRIME -Version 4.2605.17
<PackageReference Include="Excel-PRIME" Version="4.2605.17" />
<PackageVersion Include="Excel-PRIME" Version="4.2605.17" />
<PackageReference Include="Excel-PRIME" />
paket add Excel-PRIME --version 4.2605.17
#r "nuget: Excel-PRIME, 4.2605.17"
#:package Excel-PRIME@4.2605.17
#addin nuget:?package=Excel-PRIME&version=4.2605.17
#tool nuget:?package=Excel-PRIME&version=4.2605.17
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 | |
|---|---|---|---|
| 4.2605.17 | 101 | 5/17/2026 | |
| 4.2605.5 | 129 | 5/5/2026 | |
| 4.2604.28-RC3 | 109 | 4/28/2026 | |
| 4.2604.22-RC2 | 130 | 4/22/2026 | |
| 4.2604.16-RC1 | 125 | 4/16/2026 | |
| 4.2604.10-Beta | 132 | 4/10/2026 | |
| 4.2604.5-Beta | 106 | 4/5/2026 | |
| 4.2604.5-Alpha | 115 | 4/5/2026 | |
| 4.2601.31-Alpha | 235 | 1/31/2026 | |
| 4.2601.18-Alpha | 181 | 1/18/2026 | |
| 3.2601.16 | 149 | 1/16/2026 | |
| 3.2601.11 | 127 | 1/11/2026 | |
| 3.2601.4-XLSB-RC1 | 116 | 1/4/2026 | |
| 3.2601.2-XLSB-Beta | 119 | 1/2/2026 | |
| 3.2512.21-XLSB-Beta | 205 | 12/21/2025 | |
| 2.2512.14 | 184 | 12/14/2025 | |
| 2.2512.10 | 516 | 12/10/2025 | |
| 2.2512.7-Beta | 262 | 12/7/2025 |
# 2026-05-12 - V4 - Bug fixes
- Return null when `EndValue` is potted in the xml #22
- Return null for not found SheetId #23
- Changed CellValue to an abstract base class and removed all [FieldOffset(0)] fields.
- Introduced internal sealed class CellValue<T> : CellValue to store values of type T without boxing for value types.
# 2026-05-05 - V4
- ⛓️💥 **Breaking Change(s)**
- Removal of `GetSheetFileName(int offsetSheetId);`
- Removal of `GetDefinedRange` via `int sheetId`
- Removal of `Index` property from `ISheet`
- Internal Creation of WorkBooks
- Internal implementation of `IOpenXmlWorkBookReader::GetSheetNames` now returns the relative path to the sheetName
- `CellValue` is now a `class`, therefore no need to use `.Value`
- `ICell.CellValue` is now nullable
- `ArrayPool` support has been added to ThreadStringBuilderPool using ArrayPool<char>.
- Release-specific optimizations added
- EnableTrimAnalyzer: true
- TieredCompilation: true
- TieredCompilationQuickJit: true
- TieredCompilationQuickJitForLoops: true
- Implement `System.DBNull` return option, for empty cells
- Implement `INullRow` return option, for empty rows
- Update tests to use `INullRow` detection
- Implement `GetCell###(string columnLetters, ...)` #8
- Implement `System.DBNull` return option, for empty cells
- Mark up usage of userdefined cells styles for V5
- Remove `in` usages (Supposed to not benefit !)
- Make use of ThreadStatic in XlsbRow
- Remove secoundary usage of a struct
- Re-introduce the CellConversion for the XLSX cell types
- Use `ValueTask` and reduce memory allocations in some hot paths
- Cell object type 📅
- "Best Effort" `Operator` based conversion
- TryGet`Type` will return `out type`, if stored as that type.
- Add `Ecma376StandardProvider`
- Add `StylesExtractor`
- Attempt to make use of the Cell types
- Tinker with some `MethodImpl`
- Add `_iStyleRef` and start to add formatting based on it
- Fix fallout from making `CellValue` is now a `class`
- 🚀 [2026-05-05](https://github.com/Smurf-IV/Excel_PRIME/blob/main/Performance.md#2026-05-05---v4)