Library / SDK
nissl-lab/npoi avatar
nissl-lab/npoi

NPOI: Reading and Writing xls, xlsx and docx in .NET Without Office Installed

a .NET library that can read/write Office formats without Microsoft Office installed. No COM+, no interop.

6,195 stars1,492 forksC#Apache-2.0

At a glance

What is it?
NPOI is the .NET port of Apache POI. It handles BIFF8 .xls, OOXML .xlsx and .docx on Windows and Linux, with no COM interop and no Office install. The catch is the maintenance fee EULA attached to binary releases since 2.8.0.
Who is it for?
NPOI fits teams that must parse or generate legacy .xls alongside .xlsx, run on Linux build agents, and avoid a COM dependency on Office. It does not fit revenue-generating organizations unwilling to pay the maintenance fee, or anyone who only needs xlsx and prefers an MIT-licensed library.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What NPOI solves, and who actually needs it

The README states this project is the .NET version of Apache POI, and that with NPOI you can read and write Office 2003 and 2007 files very easily. The phrase that matters is the one in the repository description: no COM+, no interop. That is the whole point. If your service runs on a Linux container or a headless build agent, there is no Microsoft Office to automate and no COM registration to fake. NPOI parses and writes the file formats itself.

The format coverage is the second half of the pitch. The README lists xls, xlsx and docx as supported formats, and the repository topics add biff, openxml and word. BIFF is the binary format behind .xls, which is the older Office 2003 format. Many libraries in this space dropped .xls years ago and only handle the zipped OOXML container. NPOI still carries both code paths, and the top-level OpenXmlFormats and ooxml directories reflect that split.

The audience follows from that. You are importing spreadsheets that arrive from customers, government portals or accounting systems that still emit .xls. You are generating reports on a server that has never had Office installed. You are reading .docx to extract text. If you are writing a desktop add-in that talks to a running Excel instance, NPOI is not what you want, because it never talks to Excel at all.

How the library is put together: BIFF, OOXML and the NPOI.SS abstraction

The README describes the design as interface-oriented and points at the NPOI.SS namespace. That namespace is the spreadsheet abstraction, and it is the same shape Apache POI uses: Workbook, Sheet, Row, Cell, with concrete implementations behind them for each file format. The practical consequence is that code written against the interfaces can be pointed at either an HSSF-style .xls workbook or an XSSF-style .xlsx workbook, and the cell-level logic does not change.

That is also where the friction lives. The abstraction covers the common surface, not everything. Features that exist only in the newer format cannot be expressed through a shared interface, so the moment you need a pivot table or a chart you are back in format-specific types. The interface-oriented design buys portability at the cost of a lowest-common-denominator API.

The repository layout shows how the work is divided. The main directory holds the core library, openxml4Net handles the OPC package layer that both .xlsx and .docx sit on, ooxml and OpenXmlFormats hold the generated schema bindings, and testcases and benchmarks sit alongside them. The build is driven by build.cmd, build.ps1 and build.sh, with .nuke indicating the NUKE build system. The presence of a separate benchmarks project is worth noting, but the README publishes no numbers from it, so treat it as infrastructure rather than evidence of speed.

Installing NPOI and writing your first xlsx

The README does not spell out an install command, but it links to the NuGet package page through its badge and the related searches confirm NuGet is how people get it. The package id is NPOI.

System requirements are listed explicitly in the README: .NET 8, .NET Standard 2.1 for .NET Core 3.x, .NET 5 and .NET 6, .NET Standard 2.0 for .NET Core 2.x, and .NET Framework 4.0 and above. Note that .NET 8 is the only modern target named, so a project pinned to .NET 7 should expect to resolve through the .NET Standard 2.1 asset.

The README points to the wiki page Getting Started with NPOI for a first walkthrough rather than embedding code, and it links the How to use NPOI on Linux page for Linux deployments. Read the wiki before you assume a font or graphics dependency will resolve itself.

One thing the README does state plainly is the format list: xls, xlsx and docx. It also states the library supports not only export but also import, and that it works on both Windows and Linux. Those three sentences are the acceptance criteria to check against your own workload before you commit to the dependency.

The maintenance fee EULA is the real adoption decision

The most consequential thing in this README is not a format or an API. It is the boxed notice at the top. A monthly maintenance fee has been introduced, and the README says it is required to be paid by all organizations or users of any library from this project who generate revenue. To enact it, an EULA on binary releases was added to the repository and to NuGet packages since 2.8.0.

The README also states the free tier: the library is totally free to startups, freelancers and hobbyists whose annual revenue is less than $10,000 USD. The repository carries OSMFEULA.txt at the top level, and the README links the Open Source Maintenance Fee organization page for the details of who must pay. The releases confirm the version boundary: 2.8.0-rc3 was published on 2026-04-03 and 2.8.1-rc2 on 2026-09-22, both after the 2.8.0 line where the EULA took effect.

This is not a licensing technicality you can route around by reading the source. The EULA attaches to the binaries, and the binaries are what NuGet delivers. The project is still Apache-2.0 at the repository level, but the two layers now say different things, and the README is explicit that the fee applies to organizations generating revenue. If your legal or procurement process treats any added binary EULA as a blocker, that determination happens before any code is written. I am not giving legal advice here; the point is that the decision is a licensing one, not an engineering one, and it should be made early rather than discovered during a release audit.

The last push to the default branch was on 2026-09-22, and the most recent release is 2.8.1-rc2 from the same day. The release train is running, but note the version suffixes: the recent releases listed are all release candidates, not final builds.

Where NPOI is the wrong tool

If all you produce is .xlsx and you want a permissive licence with no fee attached, NPOI is carrying weight you do not need. The BIFF code path for .xls, the interface layer, and the maintenance fee all exist because the project serves a broad format surface. A team that only writes modern spreadsheets is paying for that breadth in both dependencies and licence review.

The abstraction is the second limitation. Because the API is deliberately format-agnostic, it exposes the intersection of what .xls and .xlsx can do. When you need something that only OOXML supports, you leave the interfaces and work with format-specific types, which means the portability the design promises is not unconditional.

Memory behaviour is the third thing to watch, and the README says nothing about it. Nothing in the documentation describes a streaming or event-based read mode. The documented model is a workbook object that you create, populate and write, which implies the document is materialized in memory. For a 50 MB export that is fine. For a multi-hundred-megabyte file, the README gives you no guidance, and the benchmarks directory it ships contains no published figures. Do not assume a streaming path exists just because the directory is there.

Finally, the documentation surface is thin in places. The README is largely a link list: wiki pages, YouTube tutorials, a Medium article. It does not document rollback, concurrency behaviour, or thread safety, and none of those gaps are filled by the repository files listed at the top level.

NPOI or ClosedXML: the difference is the format surface and the licence

ClosedXML vs NPOI is a comparison people search for, and the distinction is not subtle. ClosedXML is an OpenXML wrapper: it targets the modern .xlsx container and builds a friendlier API on top of it. NPOI is a port of Apache POI, and the README is explicit that it covers Office 2003 and 2007 files, which means BIFF .xls is in scope alongside .xlsx and .docx.

If your input pipeline receives .xls files, that difference decides the choice on its own. A wrapper around OpenXML has no path to a binary BIFF stream, so the legacy format is simply out of reach. If everything in your world is .xlsx, the extra format machinery in NPOI is cost without benefit, and you are also taking on the maintenance fee EULA that the README attaches to revenue-generating users.

The second axis is API philosophy. NPOI's NPOI.SS interfaces mirror POI's spreadsheet model, which is familiar to anyone who has worked with the Java library and is stable across formats. ClosedXML optimizes for ergonomics on one format. Neither is wrong; they are answers to different questions. Pick by which formats actually arrive at your door, then check the licence terms, in that order.

Editorial conclusion

NPOI fits teams that must parse or generate legacy .xls alongside .xlsx, run on Linux build agents, and avoid a COM dependency on Office. It does not fit revenue-generating organizations unwilling to pay the maintenance fee, or anyone who only needs xlsx and prefers an MIT-licensed library. Before adopting, read OSMFEULA.txt in the repository and confirm which licence terms apply to the exact NuGet version you pin, because the EULA attaches to binaries from 2.8.0 onward.

Frequently asked questions

What is NPOI?

NPOI is the .NET version of the Apache POI project, according to its README. It reads and writes Office 2003 and 2007 files, specifically xls, xlsx and docx, without Microsoft Office installed and without COM+ or interop.

What is the latest version of NPOI?

The most recent release listed is 2.8.1-rc2, published on 2026-09-22. Note the rc suffix: the recent releases shown are release candidates rather than final builds.

Which .NET versions does NPOI support?

The README lists .NET 8, .NET Standard 2.1 for .NET Core 3.x, .NET 5 and .NET 6, .NET Standard 2.0 for .NET Core 2.x, and .NET Framework 4.0 and above. It also states the library works on both Windows and Linux.

Does NPOI require Microsoft Office to be installed?

No. The repository description states it reads and writes Office formats without Microsoft Office installed, and adds no COM+ and no interop. The library parses and writes the file formats itself.

What licence does NPOI use, and is there a fee?

The repository is Apache-2.0, but the README states that an EULA requiring a monthly maintenance fee was added to binary releases and NuGet packages since 2.8.0, payable by organizations or users who generate revenue. It also states the library is free to startups, freelancers and hobbyists with annual revenue under $10,000 USD.

Official sources

  1. License: Apache-2.0
  2. nissl-lab/npoi on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nissl-lab-npoi.svg)](https://hysenlabs.com/projects/nissl-lab-npoi)