Package Split Architecture

dotnet-poi uses a multi-package architecture with clear separation of concerns. This was designed to let OOXML stability advance independently of legacy binary format development.

The Packages

PackageNuGet IDContentsStability
OoxmlDotnetPoi.OoxmlXSSF (xlsx/xlsm), XWPF (docx/docm), XSLF (pptx/pptm) + OPC/openxml + POIFS + CommonStable — ready for v1.0
LegacyDotnetPoi.LegacyHSSF (xls), HWPF (doc), HSLF (ppt) + POIFS + CommonIn development
FormulaDotnetPoi.FormulaLimited formula evaluator (IFormulaEvaluator, FormulaEvaluator, CellValue)Experimental — intentionally small subset
CommonDotnetPoi.CommonSS interfaces, shared enums, common exceptions, XML writer foundationStable (transitive)
POIFSDotnetPoi.POIFSOLE2/CFB compound file container, encryption helpersStable (transitive)
AllDotnetPoi.AllMeta-package referencing all of the aboveSmoke-tested

Design Rules

1. Format packages have zero knowledge of Formula. No compile-time dependency. Ooxml and Legacy work perfectly without Formula. 2. Formula references Ooxml (or Legacy). It consumes types like ICell, IWorkbook. 3. Auto-discovery at runtime. Formula registers itself via a static constructor. When you call createFormulaEvaluator(), the format package uses lazy assembly discovery (Type.GetType + RuntimeHelpers.RunClassConstructor) to find and activate Formula automatically. 4. Graceful fallback. If Formula is not installed, createFormulaEvaluator() throws a clear NotSupportedException.

What Goes Where

FeaturePackageReason
Read/write xlsx, docx, pptxOoxmlOOXML format operations
Read/write xls, doc, pptLegacyLegacy binary format operations
Cell values, styles, layoutOoxml (xlsx) / Legacy (xls)No evaluation needed
Formula text read/writeOoxml (xlsx) / Legacy (xls)Preserving formula text + cached values
setCellFormula / getCellFormulaOoxml (xlsx) / Legacy (xls)Text operations
calcPr fullCalcOnLoadOoxmlTell Excel to recalculate on open
createFormulaEvaluator()Ooxml/Legacy (factory), Formula (impl)Factory in format package, evaluator in Formula
evaluate() / evaluateAll() for supported simple expressionsFormulaLimited calculation subset
evaluateFormulaCell() for supported simple expressionsFormulaRefresh cached result when the formula is in scope

Why This Split

Installation Examples

<!-- OOXML only: xlsx / docx / pptx -->
<PackageReference Include="DotnetPoi.Ooxml" Version="..." />

<!-- OOXML + formula evaluation -->
<PackageReference Include="DotnetPoi.Ooxml" Version="..." />
<PackageReference Include="DotnetPoi.Formula" Version="..." />

<!-- Legacy binary only: xls / doc / ppt -->
<PackageReference Include="DotnetPoi.Legacy" Version="..." />

<!-- Legacy + formula evaluation -->
<PackageReference Include="DotnetPoi.Legacy" Version="..." />
<PackageReference Include="DotnetPoi.Formula" Version="..." />

<!-- Everything with one dependency -->
<PackageReference Include="DotnetPoi.All" Version="..." />