OfficeIMO.Excel
2.0.0
Prefix Reserved
See the version list below for details.
dotnet add package OfficeIMO.Excel --version 2.0.0
NuGet\Install-Package OfficeIMO.Excel -Version 2.0.0
<PackageReference Include="OfficeIMO.Excel" Version="2.0.0" />
<PackageVersion Include="OfficeIMO.Excel" Version="2.0.0" />
<PackageReference Include="OfficeIMO.Excel" />
paket add OfficeIMO.Excel --version 2.0.0
#r "nuget: OfficeIMO.Excel, 2.0.0"
#:package OfficeIMO.Excel@2.0.0
#addin nuget:?package=OfficeIMO.Excel&version=2.0.0
#tool nuget:?package=OfficeIMO.Excel&version=2.0.0
OfficeIMO.Excel - Excel workbooks for .NET
OfficeIMO.Excel is the main Excel package in the OfficeIMO family. It creates, edits, reads, converts, and saves .xlsx workbooks without COM automation and without Microsoft Excel installed. It can also open BIFF8 legacy binary .xls workbooks, project supported content into the normal OfficeIMO Excel model, and save a native .xls subset through the first-party BIFF writer.
If OfficeIMO saves you time, please consider supporting the work through GitHub Sponsors or PayPal. PowerShell users should use PSWriteOffice for the PowerShell-facing experience.
Install
dotnet add package OfficeIMO.Excel
Quick start
using OfficeIMO.Excel;
using var document = ExcelDocument.Create("report.xlsx");
var sheet = document.AddWorksheet("Data");
sheet.CellValue(1, 1, "Name");
sheet.CellValue(1, 2, "Value");
sheet.CellValue(2, 1, "Alpha");
sheet.CellValue(2, 2, 42);
sheet.AddTable("A1:B2", hasHeader: true, name: "DataTable", style: TableStyle.TableStyleMedium9);
sheet.AutoFitColumns();
document.Save();
What it does
- Creates and edits workbooks, worksheets, cells, ranges, tables, styles, hyperlinks, formulas, names, comments, images, charts, filters, and page setup.
- Reads values through worksheet, range, row, dictionary, stream, and typed object helpers.
- Supports editable row workflows where rows can be read, changed, and saved back.
- Handles practical workbook hygiene such as table/filter conflicts, safe table names, deterministic save order, and feature inspection.
- Includes parallel execution controls for heavy export and autofit workloads while serializing the Open XML mutation phase safely.
Competitive performance with workbook features
OfficeIMO.Excel is optimized for fast tabular reads and writes, but it is not
only a streaming data pipe. The same first-party model authors and edits styles,
tables, formulas, charts, pivots, conditional formatting, validation, images,
templates, protection, print settings, headers and footers, and both .xlsx
and the supported legacy .xls subset.
The compact table deliberately mixes raw data paths with feature-bearing work:
typed-object reads, plain and styled DataReader exports, and a report containing
normal workbook features. Each row only includes libraries with a directly
comparable public API. Lower is faster.
Differences below 5% are treated as ties rather than ranking claims.
| Scenario | Variables | Host | Operation | OfficeIMO.Excel | ClosedXML | EPPlus | LargeXlsx | SpreadCheetah | Sylvan.Data.Excel | Result |
|---|---|---|---|---|---|---|---|---|---|---|
| Compact DataReader to XLSX | Format=.xlsx, MeasuredIterations=9, Rows=25,000, Runner=rotated local, Snapshot=2026-07-14, Warmups=20 | .NET 8 | Write | 1.00x (23ms) | n/a | n/a | 1.11x (26ms) | 1.00x (23ms) | 1.11x (26ms) | OfficeIMO.Excel tied with SpreadCheetah |
| Feature-rich report to XLSX | Format=.xlsx, MeasuredIterations=9, Rows=25,000, Runner=rotated local, Snapshot=2026-07-14, Warmups=20 | .NET 8 | Create | 1.00x (37ms) | n/a | 11.12x (409ms) | n/a | n/a | n/a | OfficeIMO.Excel fastest |
| Styled DataReader table to XLSX | Format=.xlsx, MeasuredIterations=9, Rows=25,000, Runner=rotated local, Snapshot=2026-07-14, Warmups=20 | .NET 8 | Write | 1.00x (34ms) | 9.50x (320ms) | 9.76x (329ms) | n/a | n/a | n/a | OfficeIMO.Excel fastest |
| Typed objects streamed from XLSX | Format=.xlsx, MeasuredIterations=9, Rows=25,000, Runner=rotated local, Snapshot=2026-07-14, Warmups=20 | .NET 8 | Read | 1.00x (25ms) | 11.13x (278ms) | 10.08x (252ms) | n/a | n/a | 1.56x (39ms) | OfficeIMO.Excel fastest |
These are local direction-finding results, not guarantees. Hardware, runtime,
workload shape, package versions, warm-up, and library options change outcomes;
results will vary. OfficeIMO wins some lanes and not others. The
benchmark harness publishes the full
comparison suite against ClosedXML, EPPlus, MiniExcel, LargeXlsx,
SpreadCheetah, ExcelDataReader, and Sylvan.Data.Excel. The opt-in
NPOI comparison separately covers
.xlsx row/cell work and legacy .xls values, formulas, metadata, formatting,
filters, styles, and pictures.
Examples
The quick start covers the smallest workbook. These examples show common read, write, reporting, and automation workflows that belong in OfficeIMO.Excel.
Read rows by header
using var document = ExcelDocument.Load("input.xlsx");
var sheet = document["Data"];
foreach (var row in sheet.Rows()) {
Console.WriteLine(row["Name"]);
}
Work with legacy XLS workbooks
using var document = ExcelDocument.Load("legacy.xls");
ExcelFeatureReport report = document.InspectFeatures();
document.Save("converted.xlsx");
document.Save("native-copy.xls");
ExcelDocument.Convert("legacy.xls", "converted.xlsx");
ExcelDocument.Convert("openxml.xlsx", "native-copy.xls");
BIFF8 .xls files load through the normal ExcelDocument.Load entry point.
Supported cells, formulas, styles, names, comments, filters, validations,
conditional formatting, layout, protection metadata, document properties,
images, drawings, tables, and chart sheets project into the normal OfficeIMO
model. Unsupported sheet kinds, VBA, embedded OLE content, signatures, and
unprojected BIFF records are reported through the legacy import diagnostics
instead of being silently dropped.
Native .xls save uses the same Save("*.xls") path as other OfficeIMO saves.
When a workbook contains a feature outside the supported BIFF8 writer subset,
OfficeIMO throws a preflight error with the unsupported feature name so the
caller can save as .xlsx, remove the feature, or choose a different workflow.
ExcelDocument.Convert(...) uses those same load and save paths and blocks
legacy sources with unsupported or preserve-only content by default. Set
LossPolicy to ExcelConversionLossPolicy.Allow on conversion or save options
only after reviewing that loss. See
XLS and XLSX compatibility for
the current capability matrix, safety contract, and breaking API migration.
Map rows to objects
using var document = ExcelDocument.Load("input.xlsx");
List<Person> people = document["Data"].RowsAs<Person>("A1:C100").ToList();
public sealed class Person {
public string Name { get; set; } = "";
public int Value { get; set; }
public string Status { get; set; } = "";
}
Append to an existing table
using var document = ExcelDocument.Load("sales.xlsx");
var rows = new DataTable();
rows.Columns.Add("Revenue", typeof(decimal));
rows.Columns.Add("Region", typeof(string));
rows.Rows.Add(150m, "APAC");
document["Sales"].AppendDataTableToTable(rows, "SalesTable");
document.Save();
Validation lists and typed reads
using var document = ExcelDocument.Load("input.xlsx");
var sheet = document["Data"];
sheet.ValidationList("C2:C100", new[] { "New", "Processed", "Hold" });
sheet.Range("D2:D100").Validate.WholeNumberBetween(1, 10, errorMessage: "Use 1 through 10");
List<RowModel> rows = document.Read()
.Sheet("Data")
.Range("A1:C100")
.AsObjects<RowModel>()
.ToList();
public sealed class RowModel {
public string Name { get; set; } = "";
public string Status { get; set; } = "";
}
Charts and dashboard recipes
using OfficeIMO.Excel;
using var document = ExcelDocument.Create("dashboard.xlsx");
var sheet = document.AddWorksheet("Summary");
sheet.CellValue(1, 1, "Quarter");
sheet.CellValue(1, 2, "Revenue");
sheet.CellValue(2, 1, "Q1");
sheet.CellValue(2, 2, 10);
sheet.CellValue(3, 1, "Q2");
sheet.CellValue(3, 2, 18);
sheet.CellValue(4, 1, "Q3");
sheet.CellValue(4, 2, 24);
sheet.CellValue(5, 1, "Q4");
sheet.CellValue(5, 2, 30);
sheet.AddTable("A1:B5", hasHeader: true, name: "RevenueTable", style: TableStyle.TableStyleMedium2);
sheet.ChartFromTable("RevenueTable")
.RevenueTrend("Revenue trend")
.Size(640, 320)
.At(row: 1, column: 5);
document.Save();
Pivot tables and pivot-backed charts
using OfficeIMO.Excel;
using System.Linq;
using var document = ExcelDocument.Create("pivot-report.xlsx");
var sheet = document.AddWorksheet("Sales");
sheet.CellValue(1, 1, "Region");
sheet.CellValue(1, 2, "Product");
sheet.CellValue(1, 3, "Quarter");
sheet.CellValue(1, 4, "Revenue");
sheet.CellValue(2, 1, "EMEA");
sheet.CellValue(2, 2, "Alpha");
sheet.CellValue(2, 3, "Q1");
sheet.CellValue(2, 4, 125000);
sheet.CellValue(3, 1, "EMEA");
sheet.CellValue(3, 2, "Beta");
sheet.CellValue(3, 3, "Q1");
sheet.CellValue(3, 4, 94000);
sheet.CellValue(4, 1, "APAC");
sheet.CellValue(4, 2, "Alpha");
sheet.CellValue(4, 3, "Q2");
sheet.CellValue(4, 4, 141000);
sheet.AddTable("A1:D4", hasHeader: true, name: "SalesTable", style: TableStyle.TableStyleMedium4);
sheet.Pivot("A1:D4")
.Rows("Region")
.Columns("Quarter")
.Filters("Product")
.Sum("Revenue", "Total revenue", "#,##0")
.Layout(ExcelPivotLayout.Tabular)
.Style("PivotStyleMedium9")
.Captions(rowHeader: "Region", columnHeader: "Quarter", grandTotal: "Total")
.At("F2", "SalesPivot");
var pivot = sheet.GetPivotTables().Single(p => p.Name == "SalesPivot");
Console.WriteLine($"{pivot.Name}: {string.Join(", ", pivot.RowFields)}");
var chart = sheet.ChartFromTable("SalesTable")
.VarianceColumns("Revenue by region")
.At(row: 12, column: 1);
chart.SetPivotSource("SalesPivot");
document.Save();
Pivot support is useful but still marked partial in the compatibility matrix. It covers source-range pivots, row/column/page/data fields, styles, layouts, filters, calculated fields, grouping metadata, and readback. Slicers, timelines, external connections, and query-table authoring are still preserve-oriented or roadmap areas.
Formula inspection and calculation policy
using var document = ExcelDocument.Load("report.xlsx");
var formulas = document.InspectFormulas();
Console.WriteLine(formulas.ToMarkdown());
foreach (var formula in formulas.Formulas.Where(f => !f.IsSupportedByOfficeIMO)) {
Console.WriteLine($"{formula.SheetName}!{formula.CellReference}: {formula.UnsupportedReason}");
}
int calculated = document.Calculate();
document.Save("report.xlsx", new ExcelSaveOptions {
EvaluateFormulasBeforeSave = true,
ForceFullCalculationOnOpen = true
});
Preflight a workbook before choosing a workflow
using var document = ExcelDocument.Load("incoming.xlsx", readOnly: true);
ExcelFeatureReport report = document.InspectFeatures();
try {
report.EnsureCan(ExcelPreflightCapability.EditWorkbookStructure);
} catch (InvalidOperationException ex) {
Console.WriteLine(ex.Message);
}
if (!report.Can(ExcelPreflightCapability.ExportPdfReport)) {
Console.WriteLine(report.ToMarkdown());
}
Use workflow preflight when an application needs to decide whether a workbook is safe for readback, cell-value edits, structure-changing edits, cached-formula reads, OfficeIMO formula calculation, template binding, or first-party PDF report export. Preserve-only features such as macros, slicers, timelines, threaded comments, external links, custom XML, OLE objects, and form controls are reported with package details instead of being silently ignored.
DataTable and JSON exchange
using System.Data;
using var document = ExcelDocument.Load("data.xlsx");
var sheet = document["Data"];
DataTable table = sheet.ToDataTable("A1:C100");
string json = sheet.ToJson("A1:C100");
sheet.FromJson("[{\"Name\":\"Gamma\",\"Amount\":30}]", startRow: 8, startColumn: 1);
Template markers
using var document = ExcelDocument.Load("invoice-template.xlsx");
int replacements = document.ApplyTemplate(new Dictionary<string, object?> {
["Invoice.Number"] = "INV-001",
["Customer.Name"] = "Adatum",
["Total"] = 123.45m
});
var template = document.InspectTemplate(new {
Invoice = new { Number = "INV-001" },
Customer = new { Name = "Adatum" },
Total = 123.45m
});
template.EnsureAllMarkersBound();
document.Save("invoice.xlsx");
Comments and conditional formatting
using var document = ExcelDocument.Load("review.xlsx");
var sheet = document["Data"];
sheet.SetComment("A1", "Review total", author: "Alice", initials: "AA");
sheet.UpdateComments(new ExcelCommentFilter { TextContains = "total" }, "Total reviewed", author: "Carol", initials: "CC");
sheet.AddConditionalColorScale("C2:C100", "#FFF0F0", "#70AD47");
sheet.Range("D2:D100").ConditionalFormat.DataBar("#5B9BD5");
document.Save();
Tune larger exports
using var document = ExcelDocument.Create("large-report.xlsx");
document.Execution.Mode = ExecutionMode.Automatic;
document.Execution.MaxDegreeOfParallelism = Environment.ProcessorCount;
document.Execution.SaveWorksheetAfterAutoFit = false;
For a new workbook that only contains tabular data, write the XLSX package directly without building an editable workbook model:
using var output = File.Create("large-export.xlsx");
ExcelDocument.WriteRows(
output,
rows,
new[] { "Id", "Name", "Created", "Active" },
static (writer, row) => writer
.Write(row.Id)
.Write(row.Name)
.Write(row.Created)
.Write(row.Active),
new ExcelTabularWriteOptions {
SheetName = "Data",
IncludeCellReferences = false,
UseSharedStrings = false
});
Fluent compose
using var document = ExcelDocument.Create("composed-report.xlsx");
document.Compose("Report", composer => {
composer.Title("Demo Report", "Generated with OfficeIMO.Excel");
composer.Callout("info", "Heads up", "Generated via the fluent API");
composer.Section("Summary");
composer.PropertiesGrid(new (string, object?)[] {
("Author", "OfficeIMO"),
("Date", DateTime.Today.ToString("yyyy-MM-dd"))
});
var items = new[] {
new { Name = "Alice", Score = 90, Status = "OK" },
new { Name = "Bob", Score = 80, Status = "Warning" }
};
composer.TableFrom(items, title: "Scores", visuals: visuals => {
visuals.NumericColumnDecimals["Score"] = 0;
visuals.TextBackgrounds["Status"] = new Dictionary<string, string> {
["Warning"] = "#FFF3CD"
};
});
composer.HeaderFooter(header => header.Center("Demo Report").FooterRight("Page &P of &N"));
composer.Finish(autoFitColumns: true);
});
document.Save();
Adjacent packages
| Package | Use it for |
|---|---|
| OfficeIMO.Excel.Pdf | Excel to PDF export through OfficeIMO.Pdf, plus PDF table import to Excel. |
| OfficeIMO.Excel.GoogleSheets | Planning and exporting Excel content to Google Sheets. |
| OfficeIMO.Excel.Benchmarks | Benchmark harness for Excel workloads. |
Deeper docs
Targets and license
- Targets:
netstandard2.0,net8.0,net10.0;net472is included when building on Windows. - License: MIT.
- Repository: EvotecIT/OfficeIMO
Dependency footprint
- External: Open XML SDK for
.xlsxpackage mechanics. Microsoft BCL/JSON compatibility packages are used on older targets. - OfficeIMO:
OfficeIMO.Drawing. The workbook API, BIFF8.xlsreader/writer, large-data paths, validation, and PNG/SVG export are first-party.
See the complete OfficeIMO package map for related formats and conversion paths.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- DocumentFormat.OpenXml (>= 3.5.1 && < 4.0.0)
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.9)
- OfficeIMO.Drawing (>= 2.0.0)
- System.Text.Json (>= 10.0.7 && < 11.0.0)
-
.NETStandard 2.0
- DocumentFormat.OpenXml (>= 3.5.1 && < 4.0.0)
- Microsoft.Bcl.AsyncInterfaces (>= 10.0.9)
- OfficeIMO.Drawing (>= 2.0.0)
- System.Text.Json (>= 10.0.7 && < 11.0.0)
-
net10.0
- DocumentFormat.OpenXml (>= 3.5.1 && < 4.0.0)
- OfficeIMO.Drawing (>= 2.0.0)
-
net8.0
- DocumentFormat.OpenXml (>= 3.5.1 && < 4.0.0)
- OfficeIMO.Drawing (>= 2.0.0)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on OfficeIMO.Excel:
| Package | Downloads |
|---|---|
|
OfficeIMO.Reader
Unified, read-only document extraction facade for OfficeIMO (Word/Excel/PowerPoint/Markdown/PDF) intended for AI ingestion. |
|
|
OfficeIMO.Excel.Pdf
PDF converter for OfficeIMO.Excel - Export Excel workbooks to PDF using the first-party OfficeIMO.Pdf engine. |
|
|
OfficeIMO.Excel.GoogleSheets
Google Sheets planning and export scaffolding for OfficeIMO.Excel. |
|
|
OfficeIMO.Excel.Html
HTML converter for OfficeIMO.Excel - Export Excel workbooks and worksheets to semantic or visual review HTML. |
|
|
OfficeIMO.Excel.OpenDocument
Explicit ODS and Excel conversion adapter with feature-mapping reports. |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on OfficeIMO.Excel:
| Repository | Stars |
|---|---|
|
EvotecIT/PSWriteOffice
PowerShell Module to create and edit Microsoft Word, Microsoft Excel, and Microsoft PowerPoint documents without having Microsoft Office installed.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.1 | 509 | 7/14/2026 |
| 2.0.0 | 321 | 7/14/2026 |
| 0.6.55 | 909 | 7/9/2026 |
| 0.6.54 | 902 | 7/8/2026 |
| 0.6.53 | 1,139 | 7/5/2026 |
| 0.6.52 | 834 | 7/4/2026 |
| 0.6.51 | 867 | 6/27/2026 |
| 0.6.50 | 719 | 6/27/2026 |
| 0.6.49 | 954 | 6/24/2026 |
| 0.6.48 | 811 | 6/23/2026 |
| 0.6.47 | 865 | 6/21/2026 |
| 0.6.46 | 902 | 6/16/2026 |
| 0.6.45 | 883 | 6/16/2026 |
| 0.6.44 | 1,583 | 6/15/2026 |
| 0.6.43 | 744 | 6/13/2026 |
| 0.6.42 | 729 | 6/12/2026 |
| 0.6.41 | 634 | 6/9/2026 |
| 0.6.40 | 706 | 6/5/2026 |
| 0.6.39 | 2,141 | 5/27/2026 |
| 0.6.38 | 542 | 5/26/2026 |