FormulaEngineer 1.0.1
dotnet add package FormulaEngineer --version 1.0.1
NuGet\Install-Package FormulaEngineer -Version 1.0.1
<PackageReference Include="FormulaEngineer" Version="1.0.1" />
<PackageVersion Include="FormulaEngineer" Version="1.0.1" />
<PackageReference Include="FormulaEngineer" />
paket add FormulaEngineer --version 1.0.1
#r "nuget: FormulaEngineer, 1.0.1"
#:package FormulaEngineer@1.0.1
#addin nuget:?package=FormulaEngineer&version=1.0.1
#tool nuget:?package=FormulaEngineer&version=1.0.1
FormulaEngineer
A high-performance .NET library that reads, writes, and accurately evaluates Excel formulas — without Excel installed.
What FormulaEngineer does
Most .NET Excel libraries can open and create .xlsx files. Very few can evaluate the formulas inside them correctly. FormulaEngineer is built around that gap: a from-scratch formula engine that matches Excel's output to last-bit floating-point precision.
- Accurate formula evaluation — verified against hundreds of real-world formulas; where Excel's cached values exist in the source workbooks, results match bit-for-bit
- 250+ Excel functions — lookup, financial, statistical, math, text, date/time, logical, information, and database families
- Handles the hard cases — dynamic arrays, structured table references, cross-sheet
INDIRECT, spill semantics (#SPILL!/#CALC!), full error propagation - Reads and writes formulas — write formulas into cells, then read them back and evaluate them with no Excel involved
- Ultra-fast streaming reader and writer — forward-only, single-enumeration, flat memory profile regardless of file size
- Cross-platform — pure managed code for .NET 6 and later; Windows, Linux, macOS. No Excel installation, no COM interop.
Install
dotnet add package FormulaEngineer
Targets net6.0 and later.
A note on formula strings
When you create a formula with ExcelFormula.From(...), pass the formula without a leading =. Write SUM(A1:A3), not =SUM(A1:A3).
Activating a license
During the 7-day trial period, there is no need to call LicenseManager.ActivateFromFile("license.lic");.
For paid Pro or Enterprise licenses, activate your .lic file like this:
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
Writing formulas
Pass an ExcelFormula into WriteRow to write a formula cell. Each example below writes a workbook; the matching example in the next section reads it back and evaluates it.
Example 1 — SUM
Writes three numbers and a SUM formula over them.
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("sum.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Data"))
{
sheet.WriteRow(10); // A1
sheet.WriteRow(20); // A2
sheet.WriteRow(30); // A3
sheet.WriteRow(ExcelFormula.From("SUM(A1:A3)")); // A4 — the formula
}
writer.Close();
}
The formula cell is in row 4, column 1. It sums 10 + 20 + 30.
Example 2 — Cell arithmetic
Writes two numbers and a formula that multiplies them.
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("multiply.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Data"))
{
// A1 = 7, B1 = 6, C1 = the formula
sheet.WriteRow(7, 6, ExcelFormula.From("A1*B1"));
}
writer.Close();
}
The formula cell is in row 1, column 3. It multiplies 7 * 6.
Example 3 — Conditional logic (medium)
Writes a header row, a score, and an IF formula that returns text.
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("conditional.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Scores"))
{
sheet.WriteRow("Score", "Result"); // A1, B1
sheet.WriteRow(135, ExcelFormula.From("IF(A2>100, \"High\", \"Low\")")); // A2 = 135, B2 = formula
}
writer.Close();
}
The formula cell is in row 2, column 2. Since 135 > 100, it returns the text "High".
Example 4 — VLOOKUP over a table (difficult)
Writes a three-row lookup table and a VLOOKUP formula against it.
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("lookup.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Regions"))
{
sheet.WriteRow("EMEA", 1_240_000); // A1, B1
sheet.WriteRow("APAC", 2_180_000); // A2, B2
sheet.WriteRow("AMER", 3_950_000); // A3, B3
sheet.WriteRow(ExcelFormula.From("VLOOKUP(\"APAC\", A1:B3, 2, FALSE)")); // A4 — the formula
}
writer.Close();
}
The formula cell is in row 4, column 1. It looks up "APAC" in the table and returns the value from the second column.
Example 5 — Multiple formulas in one sheet (advanced)
Writes an invoice sheet where formulas work together — line totals feed a subtotal, which feeds the tax and total, which the status formula tests.
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("invoice.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Invoice"))
{
sheet.WriteRow("Item", "Qty", "Unit Price", "Line Total"); // row 1 — header
sheet.WriteRow("Widget", 4, 25.00, ExcelFormula.From("B2*C2")); // row 2
sheet.WriteRow("Gadget", 2, 80.00, ExcelFormula.From("B3*C3")); // row 3
sheet.WriteRow("Cable", 10, 3.50, ExcelFormula.From("B4*C4")); // row 4
sheet.WriteRow("Subtotal", "", "", ExcelFormula.From("SUM(D2:D4)")); // row 5
sheet.WriteRow("Tax (8%)", "", "", ExcelFormula.From("D5*0.08")); // row 6
sheet.WriteRow("Total", "", "", ExcelFormula.From("D5+D6")); // row 7
sheet.WriteRow("Status", "", "", ExcelFormula.From("IF(D7>200,\"Large order\",\"Standard\")")); // row 8
}
writer.Close();
}
The line totals (B*C) feed the subtotal (SUM), which feeds the tax line and the total, which the status formula then tests. The formula cells are all in column 4, rows 2 through 8.
Reading and evaluating formulas
Each example opens the workbook written above, reads the formula cell to get its formula text, then evaluates it — printing both. The formula text is read first with one worksheet reader; the evaluation uses a separate reader afterwards.
Example 1 — SUM
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("sum.xlsx");
using var evaluator = new ExcelFormulaEvaluator();
// Read the formula text (row 4, column 1)
string formulaText;
using (var sheet = reader.OpenWorksheet("Data"))
formulaText = ((ExcelFormula)sheet.ReadRows().Last()[0]!).FormulaText;
// Evaluate it
object? result;
using (var sheet = reader.OpenWorksheet("Data"))
result = evaluator.EvaluateCell(sheet, row: 4, col: 1);
Console.WriteLine($"Formula: {formulaText}"); // SUM(A1:A3)
Console.WriteLine($"Result: {result}"); // 60
Example 2 — Cell arithmetic
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("multiply.xlsx");
using var evaluator = new ExcelFormulaEvaluator();
// Read the formula text (row 1, column 3)
string formulaText;
using (var sheet = reader.OpenWorksheet("Data"))
formulaText = ((ExcelFormula)sheet.ReadRows().First()[2]!).FormulaText;
// Evaluate it
object? result;
using (var sheet = reader.OpenWorksheet("Data"))
result = evaluator.EvaluateCell(sheet, row: 1, col: 3);
Console.WriteLine($"Formula: {formulaText}"); // A1*B1
Console.WriteLine($"Result: {result}"); // 42
Example 3 — Conditional logic (medium)
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("conditional.xlsx");
using var evaluator = new ExcelFormulaEvaluator();
// Read the formula text (row 2, column 2)
string formulaText;
using (var sheet = reader.OpenWorksheet("Scores"))
formulaText = ((ExcelFormula)sheet.ReadRows().Last()[1]!).FormulaText;
// Evaluate it
object? result;
using (var sheet = reader.OpenWorksheet("Scores"))
result = evaluator.EvaluateCell(sheet, row: 2, col: 2);
Console.WriteLine($"Formula: {formulaText}"); // IF(A2>100, "High", "Low")
Console.WriteLine($"Result: {result}"); // High
Example 4 — VLOOKUP over a table (difficult)
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("lookup.xlsx");
using var evaluator = new ExcelFormulaEvaluator();
// Read the formula text (row 4, column 1)
string formulaText;
using (var sheet = reader.OpenWorksheet("Regions"))
formulaText = ((ExcelFormula)sheet.ReadRows().Last()[0]!).FormulaText;
// Evaluate it
object? result;
using (var sheet = reader.OpenWorksheet("Regions"))
result = evaluator.EvaluateCell(sheet, row: 4, col: 1);
Console.WriteLine($"Formula: {formulaText}"); // VLOOKUP("APAC", A1:B3, 2, FALSE)
Console.WriteLine($"Result: {result}"); // 2180000
Example 5 — Multiple formulas in one sheet (advanced)
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("invoice.xlsx");
using var evaluator = new ExcelFormulaEvaluator();
// Read the formula text from every row (formula cells are in column 4)
List<string> formulaTexts;
using (var sheet = reader.OpenWorksheet("Invoice"))
formulaTexts = sheet.ReadRows()
.Where(row => row.Length > 3 && row[3] is ExcelFormula)
.Select(row => ((ExcelFormula)row[3]!).FormulaText)
.ToList();
// Evaluate the formula cell in each row (rows 2 through 8, column 4)
List<object?> results;
using (var sheet = reader.OpenWorksheet("Invoice"))
results = Enumerable.Range(2, 7)
.Select(rowNum => evaluator.EvaluateCell(sheet, row: rowNum, col: 4))
.ToList();
for (int i = 0; i < formulaTexts.Count; i++)
Console.WriteLine($"Formula: {formulaTexts[i],-40} Result: {results[i]}");
// Formula: B2*C2 Result: 100
// Formula: B3*C3 Result: 160
// Formula: B4*C4 Result: 35
// Formula: SUM(D2:D4) Result: 295
// Formula: D5*0.08 Result: 23.6
// Formula: D5+D6 Result: 318.6
// Formula: IF(D7>200,"Large order","Standard") Result: Large order
You can also evaluate an entire sheet at once with evaluator.EvaluateSheet(sheet), which returns each row with formula cells replaced by their computed values.
The formula engine
The engine has been verified against hundreds of formulas drawn from production-style workbooks — covering the lookup, financial, statistical, aggregate, date/time, text, logical, and information families. Where Excel's cached values exist in the source files, the evaluator matches them bit-for-bit. Floating-point arithmetic follows IEEE 754 exactly, including the canonical edge cases Excel itself produces.
Function families
- Lookup —
LOOKUP,VLOOKUP,HLOOKUP,XLOOKUP,INDEX,MATCH— including wildcards, case-sensitive matching, reverse search, multi-criteria, and structured table references - Dynamic arrays —
FILTER,SEQUENCE,TRANSPOSE,SORT,UNIQUE, spill semantics, array-to-array concatenation, boolean-to-numeric coercion - Financial —
PMT,IPMT,PPMT,IRR,XIRR,MIRR,NPV,XNPV,PV,FV,RATE,NPER, and more — verified to last-ULP precision across every compounding frequency - Date and time —
DATE,EDATE,EOMONTH,YEAR,MONTH,DAY,TODAY,NOW,WORKDAY,NETWORKDAYS,YEARFRAC— with correct leap-year handling and end-of-month clamping - Aggregate —
SUM,AVERAGE,COUNT,COUNTA,COUNTIF,COUNTIFS,SUMIF,SUMIFS,AVERAGEIF,AVERAGEIFS,SUMPRODUCT,AGGREGATE,SUBTOTAL - Logical and information —
IF,IFS,AND,OR,NOT,XOR,IFERROR,IFNA,SWITCH,ISBLANK,ISERR,ISNA,ISNUMBER,ISEVEN,ISODD,TYPE,ERROR.TYPE,CELL - Text —
CONCAT,CONCATENATE,TEXTJOIN,TEXT,LEFT,MID,RIGHT,LEN,SEARCH,FIND,SUBSTITUTE,REPLACE,EXACT,VALUE - Reference — named ranges (workbook- and sheet-scoped), cross-sheet references, structured table references (
Table[Col],Table[#Headers],Table[]),INDIRECTwith scalar or array arguments,OFFSET - Database —
DSUM,DCOUNT,DAVERAGE,DMAX,DMIN,DGET, and the rest of the D-function family
FormulaEngineer also handles the patterns that break most non-Microsoft formula engines — INDIRECT fed an array of sheet names, header-driven nested XLOOKUP that returns an entire column dynamically, FILTER + SEQUENCE for Nth-occurrence lookups, the CHOOSE-virtual-table case-sensitive VLOOKUP trick, and matrix lookups with composite headers — all evaluated correctly against real workbooks.
Reading and writing plain workbooks
FormulaEngineer is also a fast streaming reader and writer for ordinary (non-formula) spreadsheets.
Writing a workbook
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using (var writer = new ExcelWriter("report.xlsx"))
{
using (var sheet = writer.CreateWorksheet("Q4"))
{
sheet.WriteRow("Region", "Revenue", "Growth");
sheet.WriteRow("EMEA", 1_240_000, 0.18);
sheet.WriteRow("APAC", 2_180_000, 0.32);
sheet.WriteRow("AMER", 3_950_000, 0.14);
}
writer.Close();
}
Forward-only, one active worksheet at a time. WriteRows, SkipRows, SkipColumns, MergeCells, and named ranges are all supported.
Reading a workbook
using FormulaEngineer.Api;
using FormulaEngineer.Licensing;
LicenseManager.ActivateFromFile("license.lic");
using var reader = new ExcelReader("report.xlsx");
foreach (var sheetName in reader.WorksheetNames)
{
using var sheet = reader.OpenWorksheet(sheetName);
foreach (object?[] row in sheet.ReadRows())
{
for (int i = 0; i < row.Length; i++)
Console.WriteLine(row[i]);
}
}
Worksheets are single-enumeration — read top to bottom, once. The reader streams; memory stays flat regardless of file size.
Licensing
FormulaEngineer includes a built-in 7-day trial. No license required to evaluate.
| Tier | Use case |
|---|---|
| Trial | 7 days, full API, throttled request counts per capability |
| Pro | Production use |
| Enterprise | Production use with extended terms |
Above the trial caps, each subsequent request incurs a short delay. Paid licenses bypass throttling entirely.
To purchase a Pro or Enterprise license, visit nasvelocityexcel.com/pricing.
Getting a license
Each license is bound to a machine fingerprint. To obtain yours, visit nasvelocityexcel.com and use the machine hash calculator, then include the hash with your purchase. Your .lic file is issued for that machine.
Activation
using FormulaEngineer.Licensing;
// Activate from a .lic file
LicenseManager.ActivateFromFile("license.lic");
// Check licensing state
if (!LicenseManager.IsLicensed())
{
int trialDays = LicenseManager.GetRemainingTrialDays();
Console.WriteLine($"Not licensed. Trial days remaining: {trialDays}");
}
Requirements
- .NET 6 or later
- Network access for trial registration and license validation
License
FormulaEngineer is proprietary software. Refer to the LICENSE file for full terms.
Links
- Website: nasvelocityexcel.com/about
- Pricing: nasvelocityexcel.com/pricing
- Sales and support: nasvelocityexcel.com/contact
© 2026 Mohd Nasrullah Kazmi. All rights reserved.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. 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. |
-
net6.0
- System.Security.Cryptography.ProtectedData (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.