uCalc API Version: 2.1.3-preview.2 Released: 6/17/2026

Warning

uCalc API Preview Release Notice:The documentation describes the intended behavior of the API. The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.

Project: Creating a Spreadsheet Formula Evaluator

Product: 

Class: 

A step-by-step project to build a reactive spreadsheet engine where changing one cell automatically updates all dependent cells.

Remarks

📊 Project: Creating a Spreadsheet Formula Evaluator

This project demonstrates one of uCalc's most powerful features: building a reactive calculation engine, similar to a spreadsheet. You'll learn how to define cells with formulas that depend on other cells and see how uCalc automatically handles the complex task of recalculating dependencies when a value changes.

The Goal: A Reactive Spreadsheet

Our goal is to simulate a simple spreadsheet where:

  • Cell A1 contains the value 10.
  • Cell B1 contains the formula A1 * 2.
  • Cell C1 contains the formula A1 + B1.

The critical requirement is that if we change the value of A1, the values of B1 and C1 must update automatically, without any manual intervention.

The Challenge: Dependency Tracking

In a traditional programming environment, solving this problem is surprisingly complex. You would need to:

  1. Parse Formulas: Manually parse each formula (A1 + B1) to identify its dependencies (A1, B1).
  2. Build a Dependency Graph: Create a data structure (like a directed graph) that maps which cells depend on which others.
  3. Implement a Recalculation Engine: When a cell is changed, you must traverse this graph (using an algorithm like topological sort) to find all "dirty" cells and re-evaluate them in the correct order.

This is a non-trivial computer science problem.

The uCalc Solution: The Overwrite Flag

uCalc abstracts away this entire complexity with a single, powerful feature: the overwrite flag in its definition methods. When you define a function with overwrite: true, uCalc automatically handles the dependency tracking and re-parsing for you.


Step 1: Representing Cells as Functions

We can represent each cell in our spreadsheet as a uCalc function with no parameters (e.g., A1(), B2()). The body of the function will be the cell's content—either a literal value or a formula.

// Cell A1 is a function named "A1" that returns 10.uc.DefineFunction("A1() = 10", overwrite: true);

Step 2: Defining the Initial Spreadsheet

Let's define our three cells. The key is to use the overwrite: true flag (or the Overwrite ~~ command with the generic Define method). This tells uCalc that these definitions can be replaced later and that it should track dependencies.

// Define our three cells with the overwrite flaguc.DefineFunction("A1() = 10", overwrite: true);uc.DefineFunction("B1() = A1() * 2", overwrite: true);uc.DefineFunction("C1() = A1() + B1()", overwrite: true);// Let's check the initial valuesConsole.WriteLine($"Initial B1: {uc.Eval("B1()")}"); // Expected: 20Console.WriteLine($"Initial C1: {uc.Eval("C1()")}"); // Expected: 30

Step 3: The Magic - Overwriting a Cell

Now, let's change the value of A1. We simply redefine it using the same overwrite flag.

// Overwrite the definition of A1uc.DefineFunction("A1() = 50", overwrite: true);

Behind the scenes, uCalc detects that A1 has changed. It then automatically finds all other functions (B1 and C1) that depended on A1 and re-parses their definitions. Their internal execution plans are updated to reflect the new logic.

Now, when we evaluate B1 and C1 again, they return the new, correct values without any further work from us.

// Re-evaluate the dependent cellsConsole.WriteLine($"Updated B1: {uc.Eval("B1()")}"); // Expected: 100Console.WriteLine($"Updated C1: {uc.Eval("C1()")}"); // Expected: 150

💡 Why uCalc? (Comparative Analysis)

uCalc's overwrite feature is a specialized tool that provides a massive advantage for building reactive systems.

  • vs. Manual Dependency Graph: As described above, building a dependency graph manually is complex and error-prone. uCalc's engine has this logic built-in, saving hundreds of lines of code and significant development time.
  • vs. Reactive Frameworks (e.g., Rx.NET): While powerful, reactive frameworks are a very different paradigm. They are designed for handling streams of events over time. uCalc's overwrite feature is specifically tailored for the static dependency graph problem found in spreadsheets and configuration systems, offering a much simpler and more direct solution for this specific use case.

By abstracting away the complexity of dependency management, uCalc allows you to focus on defining your logic, not on the mechanics of how it's updated.

Examples

A succinct example demonstrating automatic recalculation when a source cell is changed.
				
					using uCalcSoftware;

var uc = new uCalc();
// Define cells A1 and B1, where B1 depends on A1
uc.Define("Overwrite ~~ Function: A1() = 10");
uc.Define("Overwrite ~~ Function: B1() = A1() * 5");

Console.WriteLine($"Initial B1 value: {uc.Eval("B1()")}"); // Expected: 50

// Now, change the value of A1. B1 will update automatically.
uc.Define("Overwrite ~~ Function: A1() = 20");

Console.WriteLine($"Updated B1 value: {uc.Eval("B1()")}"); // Expected: 100
				
			
Initial B1 value: 50
Updated B1 value: 100
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Define cells A1 and B1, where B1 depends on A1
   uc.Define("Overwrite ~~ Function: A1() = 10");
   uc.Define("Overwrite ~~ Function: B1() = A1() * 5");

   cout << "Initial B1 value: " << uc.Eval("B1()") << endl; // Expected: 50

   // Now, change the value of A1. B1 will update automatically.
   uc.Define("Overwrite ~~ Function: A1() = 20");

   cout << "Updated B1 value: " << uc.Eval("B1()") << endl; // Expected: 100
}
				
			
Initial B1 value: 50
Updated B1 value: 100
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Define cells A1 and B1, where B1 depends on A1
      uc.Define("Overwrite ~~ Function: A1() = 10")
      uc.Define("Overwrite ~~ Function: B1() = A1() * 5")
      
      Console.WriteLine($"Initial B1 value: {uc.Eval("B1()")}") '// Expected: 50
      
      '// Now, change the value of A1. B1 will update automatically.
      uc.Define("Overwrite ~~ Function: A1() = 20")
      
      Console.WriteLine($"Updated B1 value: {uc.Eval("B1()")}") '// Expected: 100
   End Sub
End Module
				
			
Initial B1 value: 50
Updated B1 value: 100
A practical example simulating a small spreadsheet with interdependent cells.
				
					using uCalcSoftware;

var uc = new uCalc();
// Define interdependent 'cells' using the Overwrite command.
uc.Define("Overwrite ~~ Function: A1() = 10");
uc.Define("Overwrite ~~ Function: B1() = A1() * 2");
uc.Define("Overwrite ~~ Function: C1() = A1() + B1()");

Console.WriteLine($"Initial C1: {uc.Eval("C1()")}"); // Should be 10 + (10 * 2) = 30

// Now, overwrite the source cell A1. All dependent cells should automatically update.
uc.Define("Overwrite ~~ Function: A1() = 50");

Console.WriteLine($"Updated B1: {uc.Eval("B1()")}"); // Should now be 50 * 2 = 100
Console.WriteLine($"Updated C1: {uc.Eval("C1()")}"); // Should now be 50 + 100 = 150
				
			
Initial C1: 30
Updated B1: 100
Updated C1: 150
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   // Define interdependent 'cells' using the Overwrite command.
   uc.Define("Overwrite ~~ Function: A1() = 10");
   uc.Define("Overwrite ~~ Function: B1() = A1() * 2");
   uc.Define("Overwrite ~~ Function: C1() = A1() + B1()");

   cout << "Initial C1: " << uc.Eval("C1()") << endl; // Should be 10 + (10 * 2) = 30

   // Now, overwrite the source cell A1. All dependent cells should automatically update.
   uc.Define("Overwrite ~~ Function: A1() = 50");

   cout << "Updated B1: " << uc.Eval("B1()") << endl; // Should now be 50 * 2 = 100
   cout << "Updated C1: " << uc.Eval("C1()") << endl; // Should now be 50 + 100 = 150
}
				
			
Initial C1: 30
Updated B1: 100
Updated C1: 150
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      '// Define interdependent 'cells' using the Overwrite command.
      uc.Define("Overwrite ~~ Function: A1() = 10")
      uc.Define("Overwrite ~~ Function: B1() = A1() * 2")
      uc.Define("Overwrite ~~ Function: C1() = A1() + B1()")
      
      Console.WriteLine($"Initial C1: {uc.Eval("C1()")}") '// Should be 10 + (10 * 2) = 30
      
      '// Now, overwrite the source cell A1. All dependent cells should automatically update.
      uc.Define("Overwrite ~~ Function: A1() = 50")
      
      Console.WriteLine($"Updated B1: {uc.Eval("B1()")}") '// Should now be 50 * 2 = 100
      Console.WriteLine($"Updated C1: {uc.Eval("C1()")}") '// Should now be 50 + 100 = 150
   End Sub
End Module
				
			
Initial C1: 30
Updated B1: 100
Updated C1: 150