DotnetPoi.Core
0.5.0
dotnet add package DotnetPoi.Core --version 0.5.0
NuGet\Install-Package DotnetPoi.Core -Version 0.5.0
<PackageReference Include="DotnetPoi.Core" Version="0.5.0" />
<PackageVersion Include="DotnetPoi.Core" Version="0.5.0" />
<PackageReference Include="DotnetPoi.Core" />
paket add DotnetPoi.Core --version 0.5.0
#r "nuget: DotnetPoi.Core, 0.5.0"
#:package DotnetPoi.Core@0.5.0
#addin nuget:?package=DotnetPoi.Core&version=0.5.0
#tool nuget:?package=DotnetPoi.Core&version=0.5.0
DotnetPoi.Core
Faithful .NET port of Apache POI — read/write xlsx, docx, pptx, xls, doc, ppt with zero dependencies.
⚠️ This is an unofficial port and is not affiliated with the Apache Software Foundation. Apache POI is a registered trademark of the Apache Software Foundation.
Install
dotnet add package DotnetPoi.Core
<PackageReference Include="DotnetPoi.Core" Version="0.5.0" />
Compatible with .NET 5+, .NET Core 3.1+, .NET Framework 4.7.2+, Mono 5.4+, Unity 2018.1+.
Documentation
Full documentation is available at the dotnet-poi documentation site
| Section | Contents |
|---|---|
| Getting Started | Installation, first workbook, first document, first presentation |
| Compatibility | Format coverage, limitations, package split |
| xlsx Guides | Cell types, styles, layout, images, formulas, data validation, conditional formatting, auto filter, pivot tables, protection, rich text, macros |
| docx Guides | Paragraphs, tables, images, headers/footers, hyperlinks, fields, sections |
| pptx Guides | Slides, images, tables, formatting |
| Examples | Runnable example projects index |
Package architecture
| Package | Contents | Dependencies |
|---|---|---|
DotnetPoi.Core (this package) |
XSSF (xlsx), HSSF (xls), XWPF (docx), XSLF (pptx), HWPF (doc), HSLF (ppt), POIFS OLE2 container, common SS interfaces, PoiXmlWriter, OOXML Agile Encryption |
Zero |
DotnetPoi.Formula |
Formula evaluator — add when you need createFormulaEvaluator() |
References Core |
DotnetPoi.Core contains everything except formula evaluation. Formulas are preserved as text and cached values are read/written, but the evaluator engine lives in the separate DotnetPoi.Formula package. When DotnetPoi.Formula is referenced, createFormulaEvaluator() is automatically enabled via lazy assembly discovery at runtime.
Quick start
xlsx — write
using DotnetPoi.XSSF.UserModel;
using var wb = new XSSFWorkbook();
var sheet = wb.createSheet("Sheet1");
var row = sheet.createRow(0);
row.createCell(0).setCellValue("Hello");
row.createCell(1).setCellValue(42);
using var fs = new FileStream("output.xlsx", FileMode.Create);
wb.write(fs);
xlsx — read
using var fs = new FileStream("input.xlsx", FileMode.Open);
using var wb = new XSSFWorkbook(fs);
var cell = wb.getSheetAt(0).getRow(0).getCell(0);
Console.WriteLine(cell.getStringCellValue());
xlsx — styling
using DotnetPoi.SS.UserModel;
var style = wb.createCellStyle();
style.setFillForegroundColor(IndexedColors.Green.getIndex());
style.setFillPattern(FillPatternType.SolidForeground);
style.setBorderTop(BorderStyle.Thin);
var cell = sheet.createRow(0).createCell(0);
cell.setCellValue("Styled");
cell.setCellStyle(style);
docx — write
using DotnetPoi.XWPF.UserModel;
using var doc = new XWPFDocument();
var run = doc.createParagraph().createRun();
run.setText("Hello from dotnet-poi");
run.setBold(true);
using var fs = new FileStream("output.docx", FileMode.Create);
doc.write(fs);
pptx — write
using DotnetPoi.XSLF.UserModel;
using var prs = new XMLSlideShow();
var slide = prs.createSlide();
var picIdx = prs.addPicture(File.ReadAllBytes("photo.jpeg"), XSLFPictureData.PICTURE_TYPE_JPEG);
var shape = prs.createPicture(slide, picIdx);
shape.setAnchor(0, 0, XMLSlideShow.DefaultSlideCx, XMLSlideShow.DefaultSlideCy);
shape.setRotation(45.0);
using var fs = new FileStream("output.pptx", FileMode.Create);
prs.write(fs);
Encrypted xlsx
using var wb = new XSSFWorkbook();
wb.createSheet("Sheet1").createRow(0).createCell(0).setCellValue("Secret");
using var fs = new FileStream("secret.xlsx", FileMode.Create);
wb.writeEncrypted(fs, "password123");
Format coverage
Legend: ✅ complete / ⚠️ partial / 🔵 preserved as unknown parts, not editable / ❌ not implemented.
xlsx / XSSF (~78%)
| Category | Feature | Status | |
|---|---|---|---|
| Cell values | string, numeric, date, boolean, error | ✅ | |
| Formulas | formula text write/read + cached value read | ✅ | |
| Formulas | programmatic formula evaluation | ❌ — see DotnetPoi.Formula | |
| Styles | fonts (name, size, bold, italic, color, underline, strikethrough) | ✅ | |
| Styles | fill (pattern + foreground colour) | ✅ | |
| Styles | borders (4 sides, each with style+colour) | ✅ | |
| Styles | number/date format codes | ✅ | |
| Styles | alignment (horizontal, vertical, wrap, indent, rotation) | ✅ | |
| Layout | merged cells, column width, row height | ✅ | |
| Layout | hidden rows/columns | ✅ | |
| Layout | freeze panes (pane splits) | ✅ | |
| Layout | active sheet index, active cell API | ✅ | |
| Layout | print settings (margins, page size, orientation, header/footer) | ✅ | |
| Drawings | images (multiple, anchor, rotation) | ✅ | |
| Drawings | hyperlinks | ✅ | |
| Drawings | charts | 🔵 preserved, not creatable | |
| Drawings | comments | 🔵 preserved, not creatable | |
| Drawings | auto-shapes | 🔵 | Unknown xdr:twoCellAnchor children preserved via raw XML capture/re-emission |
| Data | data validation (input rules) | ✅ | |
| Data | conditional formatting | ✅ | |
| Data | auto filter | ✅ | |
| Data | pivot tables | ⚠️ creation only, editing not modelled | |
| Strings | shared strings (plain) | ✅ | |
| Strings | rich text (per-character formatting) | ✅ | |
| Other | workbook/sheet protection | ✅ | |
| Other | macro-enabled (xlsm) | ✅ VBA bytes preserved | |
| Other | sparklines | ❌ | |
| Other | external data connections | 🔵 | xl/connections.xml / xl/externalLinks/* round-trip via _preservedEntries |
docx / XWPF (~65%)
| Category | Feature | Status | |
|---|---|---|---|
| Paragraphs/runs | text, font name/size/color, bold, italic, underline, strikethrough | ✅ | |
| Paragraphs | alignment, indents, spacing, bullet/numbered lists | ✅ | |
| Tables | create/read tables, rows, cells | ✅ | |
| Tables | cell merging, borders | 🔵 | Round-trip preserved via raw XML capture/re-emission; API-level creation not modeled |
| Sections | page setup, headers, footers | ✅ | |
| Sections | columns | ✅ | setColumns() API, round-trip verified |
| Links | external hyperlinks | ✅ | |
| Images | inline images + rotation | ✅ | |
| Images | text boxes (w:txbxContent) |
❌ | |
| Review | comments, footnotes, endnotes | 🔵 | Existing parts round-trip via _preservedEntries |
| Fields | TOC, page numbers, mail merge fields | ✅ | |
| Styles | paragraph style reference (pStyle) | ✅ | setStyle()/getStyleID() API, round-trip verified. Character/table styles ❌. word/styles.xml 🔵 preserved + default styles auto-generated. |
| Other | macro-enabled (docm) | ✅ | |
| Other | content controls (SDT) | 🔵 | Block-level and inline SDT preserved via raw XML capture/re-emission |
| 〃 | tracked changes (ins/del/move) | ❌ | |
| 〃 | OLE embeddings | 🔵 | word/embeddings/* round-trip via _preservedEntries |
pptx / XSLF (~40%)
| Category | Feature | Status | |
|---|---|---|---|
| Slides | create/read, slide size | ✅ | |
| Slides | notes slides | 🔵 | ppt/notesSlides/* round-trip via _preservedEntries |
| Text | text boxes, multiple paragraphs, run formatting | ✅ | |
| Shapes | pictures (anchor, size, rotation) | ✅ | |
| Shapes | tables (p:graphicFrame / a:tbl) |
✅ | |
| Shapes | group shapes, connectors, lines | 🔵 | Unknown p:spTree children preserved via raw XML capture/re-emission |
| Shapes | SmartArt, charts | 🔵 preserved, not modelled | |
| Media | video/audio embedding | 🔵 | Non-image ppt/media/* round-trip via _preservedEntries |
| Animation | animations, transitions | 🔵 preserved, not modelled | |
| Theme | layouts, masters, themes | 🔵 preserved, not editable | |
| Other | macro-enabled (pptm) | ✅ |
xls / HSSF (~10%)
| Category | Feature | Status |
|---|---|---|
| Basic | read/write cell values | ⚠️ in progress |
| Everything else | BIFF records, styles, formulas, images, filters, pivots | ❌ |
Legacy binary
| Format | Status |
|---|---|
| doc (HWPF) | ~5% read-only MVP |
| ppt (HSLF) | ~5% read-only MVP |
Practical gaps (priority order)
| # | Gap | Why it matters |
|---|---|---|
| 1 | Formula evaluation | Template fill → save → open in Excel works, but programmatic access to freshly calculated values needs DotnetPoi.Formula |
| 2 | Chart creation | Reports and presentations commonly need charts from data |
| 3 | docx styles | Word documents rely on named styles (Normal, Heading1…) for formatting |
| 4 | HSSF .xls depth |
Legacy format support is still minimal |
| 5 | docx text boxes | Word text inside w:txbxContent elements is not read |
Test coverage
| Project | Tests | Notes |
|---|---|---|
| Core.Tests | 244 | xlsx round-trip coverage, active sheet, auto filter, protection, fields, docx table/rPr preservation |
| Formula.Tests | 10 | Minimal — evaluator is early stage |
| Interop.Tests (C#) | 55 | Bidirectional Java/.NET fixtures + preservation tests |
| Total (C#) | 309 | |
| Java POI side (Maven) | 44 | Fixture generation / readback |
Testing strategy
Quality and fidelity to Apache POI are ensured through a multi-layered testing strategy:
- Unit tests (xUnit): Ported alongside each class from the original Apache POI test suite. Ensures internal logic and edge-case handling are consistent with Java.
- XML Parity tests: Captures raw XML output from Apache POI (via XMLBeans) and verifies that
PoiXmlWriterproduces byte-equivalent output in C#. This prevents interoperability issues caused by subtle XML formatting differences. - Bidirectional Interop tests:
- Direction A: Java POI writes a file →
DotnetPoi.Corereads it. - Direction B:
DotnetPoi.Corewrites a file → Java POI reads it.
- Direction A: Java POI writes a file →
- Preservation tests: Verifies that unmodeled features (macros, charts, comments, pivot tables) survive a read-modify-write cycle (round-trip) without data loss.
- Manual Verification: Periodic verification using real Office applications (Excel, Word, PowerPoint) and LibreOffice on macOS, Windows, and Linux to ensure no "repair" dialogs or visual regressions.
Philosophy
- 🔱 Maximum fidelity to upstream Apache POI — we follow, not reinvent
- 🤖 Ported class-by-class with LLM assistance
- 💸 Free forever. No EULA. No maintenance fee. No exceptions.
- 📖 Apache POI is the source of truth — included as a git submodule
License
Apache License 2.0 — same as upstream Apache POI.
Disclaimer
This project is not affiliated with the Apache Software Foundation or the Apache POI project. Apache POI is a registered trademark of the Apache Software Foundation.
| 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 was computed. 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 was computed. 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 was computed. 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. |
-
.NETStandard 2.0
- System.Memory (>= 4.5.5)
- System.Text.Encoding.CodePages (>= 8.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on DotnetPoi.Core:
| Package | Downloads |
|---|---|
|
DotnetPoi.Formula
Formula evaluator for DotnetPoi.Core — evaluate spreadsheet formulas in xlsx workbooks. Requires DotnetPoi.Core. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|