DEV Community

IronSoftware
IronSoftware

Posted on

ExcelDataReader in 2026: The Half of the Job It Can't Do

An old ERP drops a legacy .xls on a share every night. A .NET service picks it up, validates the numbers, and needs to write a corrected copy back. ExcelDataReader handles the first step and cannot do the last one, because it has no write API at all.

No save method, no cell setter, nothing in the public surface. The moment a requirement grows from importing a file to importing it and sending a corrected copy back, you are adding a second library, and IronXL is where both halves live in one object model.

Full disclosure. We build IronXL at Iron Software, and this read looks at where ExcelDataReader's read-only boundary costs a team and where IronXL covers both halves.

What Does It Read, and Where Is That Enough?

Reading is the half ExcelDataReader is built for. It streams a file forward, one row at a time, so memory stays flat on a 200 MB export, and it opens the legacy .xls that many .NET libraries refuse. Its current line, 3.9.0 from 2026, is still read-only by design. If a pipeline only needs to read, that is the ceiling of what ExcelDataReader covers. IronXL reads the same formats, including that legacy .xls, so nothing about the reading half is given up by choosing the library that also writes.

Where Does It Hit a Wall at Export?

Then the export requirement lands, and ExcelDataReader has no path through it. There is no partial write, no limited setter to work around, the calculation engine is absent so formulas come back as whatever value Excel last cached rather than a recomputed result, and access is forward-only, so cross-referencing a total on the last row against a header on the first means buffering the file into your own structures first. Cell formatting is only half-exposed on top of that, because a number-format string comes back but applying it is left to the caller, so a date or a currency renders the way the source workbook showed it only if you write that code yourself. Each of those is a job the caller now writes by hand. IronXL writes any of those formats, recalculates formulas with its own engine, applies the number formats rather than handing back a string, and addresses cells at random, so none of that hand-written work exists.

What Does a Second Library Cost?

Bridge the gap in place and the shape of the cost is a second dependency. Because ExcelDataReader cannot write a single cell, a project ends up with it for reading and a separate library for writing, two object models, and hand-written translation code between them for what a developer reasonably assumed was one task. That translation code tends to stay in the codebase permanently, and the encoding provider ExcelDataReader makes you register by hand on .NET 5 and later is the kind of setup step that surfaces as a production bug the first time a real .xls arrives. IronXL removes the bridge, because reading and writing are the same object model with no translation layer between them, and the whole gap lines up in one table.

Aspect ExcelDataReader IronXL
Write or modify a workbook Not supported at all Supported, WorkBook.SaveAs
Access model Forward-only, row by row Random access by cell address
Formula calculation Not supported, returns cached values WorkBook.EvaluateAll, 150+ functions
Applied cell styling Format string only, not applied Applied styling and formatting
Legacy .xls on .NET 5+ Throws until you register an encoding provider Loads with no extra setup, WorkBook.Load
Charts and pivot tables Not supported Supported

Table 1. ExcelDataReader and IronXL across the read-and-write questions, from each project's own README and documentation.

One Model Instead of Two

IronXL loads the file that came in and writes the file that goes out from a single API, with no second library and no translation code.

using IronXL;

// Same legacy .xls file, but now the workbook is editable
WorkBook workBook = WorkBook.Load("legacy-export.xls");
WorkSheet workSheet = workBook.DefaultWorkSheet;

// Random access, not forward-only, and formulas the library computes
decimal total = workSheet["B2:B500"].Sum();
workSheet["D1"].Value = "Validated";
workSheet["D2"].Formula = "=SUM(B2:B500)";
workBook.EvaluateAll();

workBook.SaveAs("validated-export.xlsx");
Enter fullscreen mode Exit fullscreen mode

The file that came in as legacy .xls goes back out as .xlsx from the same API, formulas are calculated by the library rather than inherited from whatever Excel last cached, and cells are addressable rather than streamed past once. You can pull IronXL from NuGet and run this in a couple of minutes, and the reading guide shows the same file loaded and written back end to end.

Which side are you on, is your pipeline read-only, or are you already running a reader and a separate writer? Tell us in the comments, we read every one.

IronXL has a free trial if you want to run your own import-and-export path through it before deciding.

ExcelDataReader is an open-source project distributed under the MIT licence, and is not affiliated with Iron Software. The details above are drawn from the project's own README, NuGet metadata, and documentation. If something has changed since, correct us in the comments.

Top comments (0)