![]() |
VOOZH | about |
dotnet add package ClosedXML --version 0.100.1
NuGet\Install-Package ClosedXML -Version 0.100.1
<PackageReference Include="ClosedXML" Version="0.100.1" />
<PackageVersion Include="ClosedXML" Version="0.100.1" />Directory.Packages.props
<PackageReference Include="ClosedXML" />Project file
paket add ClosedXML --version 0.100.1
#r "nuget: ClosedXML, 0.100.1"
#:package ClosedXML@0.100.1
#addin nuget:?package=ClosedXML&version=0.100.1Install as a Cake Addin
#tool nuget:?package=ClosedXML&version=0.100.1Install as a Cake Tool
ClosedXML is a .NET library for reading, manipulating and writing Excel 2007+ (.xlsx, .xlsm) files. It aims to provide an intuitive and user-friendly interface to dealing with the underlying OpenXML API.
using (var workbook = new XLWorkbook())
{
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell("A1").Value = "Hello World!";
worksheet.Cell("A2").FormulaA1 = "=MID(A1, 7, 5)";
workbook.SaveAs("HelloWorld.xlsx");
}
For more information see the documentation or the wiki.
Added implicit conversion from decimal to XLCellValue, so it is not necessary to cast decimal to double explicitly.
Basically this now works, as it did pre-0.100:
decimal number = 15.5m;
ws.Cell(1,1).Value = number;
These are release notes for a version 0.100. We skipped a few version since the last release (0.97), because 0.100 should denote a major change at the very heart of ClosedXML. Not as clean break as I hoped, but close enough.
The list of all things that were changed from 0.97 to 0.100 is at the migration guide at the https://closedxml.readthedocs.io/en/latest/migrations/migrate-to-0.100.html
This is more like list of you should upgrade despite breaking changes 😃
Memory consumption during saving of large data workbooks was significantly improved. Originally, ClosedXML workbook representation was converted to DocumentFomrat.OpenXML DOM representation and the DOM was then saved. Instead of creating whole DOM, sheet data (=cell values) are now directly streamed to the output file and aren't included in the DOM.
To demonstrate difference, see the before and after memory consumption of a report that generated 30 000 rows, 45 columns. Memory consumption has decreased from 2.08 GiB 🡆 0.8 GiB.
Save cells and strings through DOM: 2.08 GiB
👁 1874-dtoMemory-save-30k-text-DOM
Save cell and strings through streaming: 0.8 GiB
👁 1874-dtoMemory-save-30k-text-streaming
The purple area are bytes of uncompressed package zip stream.
IXLCell.Value and IXLCellValue.CachedValue have now type XLCellValue. At the core, xlsx consists of addressable cells with a functions that transform a set of values in source cells to different values in target cells. Is is really important to represent potential values of cells by a sane type. All other things, pivot tables, auto filter, graphs rely on this premise.
Cell value has been represented as string text and a value. The string depended on the value, e.g. 0/1 for boolean. That has been the case since the beginning of the ClosedXML project (see the original XLCell). The value was also returned as an Object.
This approach has several drawbacks
Object is not suitable representation of cell value. User had no idea what kind of values could be returned as a cell value. Everything could also break down, if a new type would be returned (e.g. XLError).IXLColumn.Value of a cell is not represented by a XLCellValue structure. It is basically a union of one of possible types that can be value of a cell:
Since datetime and duration are basically masqaraded number, you can use XLCellValue.GetUnifiedNumber() to get a backing number, no matter if the type is number, datetime and duration.
The structure contains implicit operators, as well as other methods to make transaction as seamless as possible
// Will use an implicit cast operator to convert string to XLCellValue and pass it to the Value setter
ws.Cell("A1").Value = "Text";
There is also a new singleton Blank.Value that represent a blank value of a cell. Null is not blank. Empty string is not a blank value of a cell. Null instead of blank was considered and everything is just so much easier to work with, if blank is represented as a custom singleton type and not as a null.
XLCellValue will be able to represent all values of a cell and won't be boxed/unboxed all the time.
ClosedXML used to guess a data type from a value. It caused all sort of unexpected behaviors (e.g. text value Z12.31 has been converted to date time 12/30/2022 19:00). Date caused most problems, but other sometimes too (e.g. text "Infinity" was detected as a number).
This behavior was likely intended to emulate how user interacts with an Excel. Excel guesses type, but only if the cell Number Format is set to "General" (e.g. if NumberFormat is set to Text, there is no conversion even in Excel). Application is not human and doesn't have to interact with xlsx in the same way.
This behavior was removed. Type that is set is the type that will be returned. Note that although XLCellValue can represent date and time as a different types, in reality that is only presentation logic for user. They are both just serial date time numbers.
Cell value now can accurately represent error or a blank value.
ClosedXML used to throw on error value and cell couldn't contain an error. That was a significant problem, especially for formula calculation where formula referenced a cell that should contain an error value.
ClosedXML used to represent blank cell as an empty string, but no longer. It uses Blank.Value singleton, wrapped in XLCellValue. Also brings significant improvement in accuracy for CalcEngine evaluation.
Excel has a pretty complicated undocumented coercion process from text to number. It can convert fraction text (="1 1/2"*2 is 3), dates (e.g. ="1900-01-05"*2 is 10, though date format is culture specific), percent (e.g. ="100%"*2), braces imply negative value (="(100%)"*2 = -2) and many more. That causes a significant problems for formula evaluation, especially if the source cell contains a date as a text, not as a date.
ClosedXml used to only convert test that looked like double, it now coerces nearly everything Excel does. Coercion from dates should mostly work, but Excel has it's own database of acceptable formats and it's own format, while we rely on .NET Core infrastructure.
Thanks to incorporation of XLError to core of CalcEngine, the exceptions are no longer necessary and have been removed. Error is a normal value type that is used during formula evaluation (e.g. ISNA accepts it and VLOOKUP returns it).
Technically speaking CalcEngine can still throw MissingContextException, but only if evaluation is not called from a cell, but from method like XLWorkbook.Evaluate. Functions like ROW just can't work without the context of the cell.
If you ever tried to use CalcEngine, you have encountered a dreaded The function *SomeFunctionwas not recognised. exception.
ClosedXML will no longer throw an exception on unimplemented function, but will return #NAME? error instead. It has several reasons
=SOME.UNKNOWN.FUN(4), why should it throw on =LARGE(A1:A5,1)?Basically, the exception doesn't bring any benefit and only imposes costs. User can report missing function on #NAME? error just like on exception.
CalcEngine now can evaluate array literal expressions, so formulas like VLOOKUP(4, {1,2; 3,2; 5,3; 7,4}, 2) now actually work.
Array processing is limited to argument parsing across formulas and CalcEngine still needs some love to process it work correctly. Array formulas are still not implemented.
Information and lookup functions were reimplemented to take advantage of other improvements. They should now be compliant with Excel (with exception of wildcard search for VLOOKUP).
Documentation is being moved from wiki to the ReadTheDocs. It has been there for since 2019, but we didn't actually had any documentation. Documentation is super important and ClosedXML lacks in that area. It is of course WIP, but it should improve over the time (see https://closedxml.readthedocs.io/en/latest/features/protect.html, https://closedxml.readthedocs.io/en/latest/features/cell-format.html#number-format or infamous https://closedxml.readthedocs.io/en/latest/tips/missing-font.html).
The move to ReadTheDocs has significant advantages:
We are not breaking the compatibility just because. Break imposes heavy penalty on users of the library. That makes it less likely to use it and that is definitely not the goal. Even the ClosedXML.Report must be fixed after every release.
That is not desirable situation. Version 1.0 and semantic versioning is certainly the goal. But it must be with an clear API that can endure some development between minor version. That is just not the case at the moment.
API will be reviewed along with the documentation and will be adjusted as necessary. ClosedXML will practice release early, release often. If breaking changes are not acceptable, stay on version that works and wait for 1.0 (though that will likely take at least a year, likely more... we are on a second decade).
Technically we do semver since forever, since Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable. ). Initial development for a decade /sigh.
Similar to current release, the general plan is to work on neglected foundational things and bug fixes.
It is likely there will be 0.100.x to fix whatever bugs XLCellValue caused that weren't convered by tests.
Pivot tables won't get any love in 0.101, but hopefully in the next one. It is one of distinguishing features of ClosedXML and it has a lot of reported issues.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on ClosedXML:
| Package | Downloads |
|---|---|
|
ClosedXML.Report
ClosedXML.Report is a tool for report generation and data analysis in .NET applications through the use of Microsoft Excel. ClosedXML.Report is a .NET-library for report generation Microsoft Excel without requiring Excel to be installed on the machine that's running the code. |
|
|
OO.Data
Data Entity base types and declarations for EasyDataCore infrastructure |
|
|
CsvHelper.Excel.Core
An implementation of ICsvParser and ICsvSerializer from CsvHelper that reads and writes using the ClosedXml library. |
|
|
ClosedXML.Extensions.Mvc
MVC extensions for ClosedXML |
|
|
Microsoft.KernelMemory.Core
The package contains the core logic and abstractions of Kernel Memory, not including extensions. |
Showing the top 20 popular GitHub repositories that depend on ClosedXML:
| Repository | Stars |
|---|---|
|
nopSolutions/nopCommerce
ASP.NET Core eCommerce software. nopCommerce is a free and open-source shopping cart.
|
|
|
rmcrackan/Libation
Libation: Liberate your Library
|
|
|
mini-software/MiniExcel
Lightweight, fast and simple cross-platform .NET processing tool for importing and exporting spreadsheet documents
|
|
|
open-rpa/openrpa
Free Open Source Enterprise Grade RPA
|
|
|
serenity-is/Serenity
Business Apps Made Simple with Asp.Net Core MVC / TypeScript
|
|
|
phongnguyend/Practical.CleanArchitecture
Full-stack .Net 10 Clean Architecture (Microservices, Modular Monolith, Monolith), Blazor, Angular 22, React 19, Vue 3.5, BFF with YARP, NextJs 16, Domain-Driven Design, CQRS, SOLID, Asp.Net Core Identity Custom Storage, OpenID Connect, EF Core, OpenTelemetry, SignalR, Background Services, Health Checks, Rate Limiting, Clouds (Azure, AWS, GCP), ...
|
|
|
microsoft/kernel-memory
Research project. A Memory solution for users, teams, and applications.
|
|
|
Yu-Core/SwashbucklerDiary
侠客日记是一个开源、跨平台的本地日记app,使用Blazor开发,支持Android,Windows,macOS,Web,Linux。"SwashbucklerDiary" is an open source cross-platform local diary app using Blazor , support Android,Windows,macOS,Web,Linux.
|
|
|
abpframework/abp-samples
Sample solutions built with the ABP Framework
|
|
|
UiPath/CoreWF
WF runtime ported to work on .NET 6
|
|
|
VladislavAntonyuk/MauiSamples
.NET MAUI Samples
|
|
|
DotNetNext/WebFirst
.NET CORE 代码生成器 ,Web中使用CodeFirst模式, 实体 生成器,UI代码 生成器,在线建表,PostgresSql生成器,达梦生成器,金仓生成器MySql生成器,SQLServere生成器、Oracle生成器、Sqlite生成器、导出文档,模版配置, WEB代码生成器 ,API代码生成器
|
|
|
cmu-sei/GHOSTS
GHOSTS (General Human-Oriented Synthetic Teammates and Systems) is a realistic user simulation framework for cyber experimentation, simulation, training, and exercise
|
|
|
sveinungf/spreadcheetah
SpreadCheetah is a high-performance .NET library for generating spreadsheet (Microsoft Excel XLSX) files.
|
|
|
Implem/Implem.Pleasanter
Pleasanter is a no-code/low-code development platform that runs on .NET. You can quickly create business applications with simple operations.
|
|
|
ClosedXML/ClosedXML.Report
ClosedXML.Report is a tool for report generation with which you can easily export any data from your .NET classes to Excel using a XLSX-template.
|
|
|
TabBlazor/TabBlazor
Blazor admin template based on Tabler UI
|
|
|
EvotecIT/OfficeIMO
Fast and easy to use cross-platform .NET library that creates or modifies Microsoft Word (DocX) and later also Excel (XLSX) files without installing any software. Library is based on Open XML SDK
|
|
|
ShapeCrawler/ShapeCrawler
PowerPoint .NET library for reading, modifying, and generating PPTX presentations without Microsoft Office
|
|
|
pearlxcore/PS4-PKG-Tool
Manage and perform various operations on PS4 PKG.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 0.105.0 | 29,074,679 | 5/14/2025 |
| 0.105.0-rc | 562,510 | 1/22/2025 |
| 0.104.2 | 24,899,101 | 11/15/2024 |
| 0.104.1 | 5,912,045 | 9/30/2024 |
| 0.104.0-rc1 | 83,584 | 9/17/2024 |
| 0.104.0-preview2 | 539,559 | 10/26/2023 |
| 0.103.0-beta | 50,763 | 9/28/2023 |
| 0.102.3 | 6,246,475 | 7/18/2024 |
| 0.102.2 | 16,514,123 | 1/5/2024 |
| 0.102.1 | 7,902,140 | 8/18/2023 |
| 0.102.0 | 2,978,151 | 6/24/2023 |
| 0.102.0-rc | 9,707 | 6/18/2023 |
| 0.101.0 | 4,103,083 | 4/9/2023 |
| 0.101.0-rc | 5,793 | 4/1/2023 |
| 0.100.3 | 5,589,206 | 1/12/2023 |
| 0.100.2 | 170,898 | 1/10/2023 |
| 0.100.1 | 163,577 | 1/9/2023 |
| 0.100.0 | 316,847 | 1/9/2023 |