Read and write Excel files in C# without Excel
WorkbookEditor reads and writes XLSX files from .NET with no Excel installed. This guide covers values, an unknown upload, formulas and formatting, and where the formatting stops.
byte[] xlsx = WorkbookEditor.Create("Sales", new object?[][]
{
new object?[] { "Region", "Total" },
new object?[] { "North", 1200 },
new object?[] { "South", 950 },
});
string before = WorkbookEditor.ReadCell(xlsx, "Sales", "B2");
byte[] updated = WorkbookEditor.SetCell(xlsx, "Sales", "B2", 1500);
string after = WorkbookEditor.ReadCell(updated, "Sales", "B2");Numbers stay numbers
WorkbookEditorcovers XLSX. No Excel is needed.- Cell values are
object?. Numbers are written as numbers and strings as strings, so a column of totals can be summed in Excel. ReadCellreturns the cell's value as text, not as Excel displays it.- A cell holding
1200under a#,##0.00number format reads back as1200, not1,200.00.
Read a file you were handed
- You do not need to know the shape of the workbook in advance.
SheetNamestells you what is in the file, andReadSheetreturns the used range as rows of strings.- Together they are enough to walk an upload you have never seen.
Formulas
- A cell holding an
XlsxFormulais written as a formula, not as text that starts with=. - Write it without the leading
=, as inXlsxFormula.From("SUM(Q1!B2:B4)"). The writer adds the=. - Read back through DocToolkit, the formula gives its computed value.
- A reader that only reads cached values sees an empty cell until Excel has opened and saved the file.
Make a sheet look like a report
XlsxFormat.Reportis the usual preset: bold header, frozen header and auto-fit.Formatis a separate call that takes a workbook and a sheet name, so it works on a sheet that already exists.- Auto-fit fits the column to its content. Against short values that is narrower than Excel's 8.43-character default.
What it will not do
- The formatting vocabulary is closed: six rule conditions, five validation kinds and four highlights. For arbitrary fonts, borders or color scales, use ClosedXML directly.
WithTableandWithAutoFiltercannot target overlapping ranges. Applying both over the same cells throwsDocumentConversionException.WithTabledoes not makeAppendRowskeep the table current. The new row lands next to the table, not inside it.
Install
dotnet add package Ank.DocToolkitRead it in the DocToolkit docsNuGetGitHub