SharpCell

Getting started

Install SharpCell, read an .xlsx file, recalculate it and read the results, step by step through the console sample.

Requirements

.NET 8 or .NET 10.

Install

dotnet add package SharpCell.Xlsx

SharpCell.Xlsx brings SharpCell with it. Use dotnet add package SharpCell alone if you build workbooks in code and never read files. Versions before 1.0 may change the API between minor versions.

The sample

samples/SharpCell.Sample is a console app built around budget.xlsx, one sheet named Budget:

Cell Content
A2:B5 Rent 1200, Food 450, Transport 120, Internet 40 (monthly)
C2:C5 Yearly amounts, =B2*12 and so on
B6 =SUM(B2:B5), the monthly total
F1 Income, 3000
F2 =F1-B6, what is left

Namespaces

using SharpCell;
using SharpCell.Xlsx;

Load and recalculate

XlsxReader.Load reads sheets, values and formulas. Cells with formulas start out holding the results Excel saved in the file, if any. Recalculate calculates every formula with SharpCell and replaces those results.

// Read the workbook: sheets, values, formulas and any results Excel saved with them.
Workbook workbook = XlsxReader.Load(path);
Worksheet budget = workbook["Budget"];

// Calculate every formula now instead of relying on saved results.
workbook.Recalculate();

Read values

A cell's Value is a CellValue. Check its Kind before calling AsNumber, AsText or another As method: each one throws InvalidOperationException when the value is of another kind. Excel errors such as #DIV/0! are values of kind Error, not exceptions.

CellValue total = budget["B6"].Value;   // =SUM(B2:B5)
output.WriteLine($"Total per month: {Format(total)}");
output.WriteLine($"Left after expenses: {Format(budget["F2"].Value)}");

The sample formats values with this helper:

// A CellValue can be a number, text, logical, error, array or empty; check Kind before As*.
private static string Format(CellValue value) => value.Kind switch
{
    CellValueKind.Number => value.AsNumber().ToString(CultureInfo.InvariantCulture),
    CellValueKind.Error => value.AsError().ToText(),   // "#DIV/0!", "#N/A", ...
    _ => value.ToString(),
};

Change an input

Assigning a value does not update the formulas that depend on it. Call Recalculate after a batch of changes: it calculates only the cells that are out of date.

// Change an input. Dependent formulas are updated by the next Recalculate, not before.
budget["B2"].Value = 1350;
workbook.Recalculate();
output.WriteLine("After rent change to 1350:");
output.WriteLine($"Total per month: {Format(budget["B6"].Value)}");
output.WriteLine($"Left after expenses: {Format(budget["F2"].Value)}");

Formulas without a cell

Workbook.Evaluate calculates a formula that lives in no cell. It can read the workbook's sheets. A formula that returns several values gives a CellValue of kind Array; its text form is {1;2;3}.

// Evaluate formulas that live in no cell. They can read the workbook's sheets.
CellValue food = workbook.Evaluate("=XLOOKUP(\"Food\", Budget!A2:A5, Budget!B2:B5)");
CellValue average = workbook.Evaluate("=LET(items, Budget!B2:B5, SUM(items) / COUNT(items))");
CellValue sequence = workbook.Evaluate("=SEQUENCE(3)");   // a dynamic array: {1;2;3}
output.WriteLine($"Food per month: {Format(food)}");
output.WriteLine($"Average expense: {Format(average)}");
output.WriteLine($"Sequence: {sequence}");

Run it

dotnet run --project samples/SharpCell.Sample -f net10.0
Total per month: 1810
Left after expenses: 1190
After rent change to 1350:
Total per month: 1960
Left after expenses: 1040
Food per month: 450
Average expense: 490
Sequence: {1;2;3}

Next