Recursive AI

Use Excel Goal Seek in C#

OneDocument is a free, open-source Word, Excel and PowerPoint document library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Goal Seek solves for one input cell.

Terminal
dotnet add package RecursiveAI.OneDocument.Spreadsheets

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

C#
using RecursiveAI.OneDocument.Spreadsheets;
using var book = Workbook.Create();
var sheet = book.Sheets[0];
sheet["A1"].SetNumber(1);
sheet["B1"].Formula = "A1*3+2";
var result = book.GoalSeek(
    sheet["B1"], 14, sheet["A1"]);
Console.WriteLine(result.Status);

Prints Found; A1 becomes approximately 4. The full program saves solved.xlsx only when a solution is found.

Unzip the example, then dotnet run.

The full program

No input file is needed. A1 starts at 1; B1 is the formula cell, 14 is the target, and A1 is the changing cell. The program checks Found before saving.

C#
using RecursiveAI.OneDocument.Spreadsheets;
using RecursiveAI.OneDocument.Spreadsheets.Calc;
 
using Workbook book = Workbook.Create();
var sheet = book.Sheets[0];
sheet["A1"].SetNumber(1);
sheet["B1"].Formula = "A1*3+2";
var result = book.GoalSeek(sheet["B1"], 14, sheet["A1"],
    new GoalSeekOptions { MaxChange = 0.001, MaxIterations = 100 });
Console.WriteLine($"Status: {result.Status}");
if (result.Found)
{
    book.SaveAs("solved.xlsx");
    Console.WriteLine($"A1: {sheet["A1"].Number:0.###}");
    Console.WriteLine($"B1: {sheet["B1"].Number:0.###}");
}
else
{
    Console.WriteLine("No solution applied; no file saved.");
}

dotnet run prints:

Text
Status: Found
A1: 4
B1: 14

A failed search applies no trial value; check the returned status instead of assuming the last trial is a solution.

Variations

Set search limits and preview without applying. MaxChange sets the allowed difference from the target, and MaxIterations caps formula evaluations for this call. Apply = false leaves the input unchanged even when the search succeeds.

C#
using RecursiveAI.OneDocument.Spreadsheets;
using RecursiveAI.OneDocument.Spreadsheets.Calc;
using var book = Workbook.Create();
var sheet = book.Sheets[0];
sheet["A1"].SetNumber(1);
sheet["B1"].Formula = "A1*3+2";
var result = book.GoalSeek(sheet["B1"], 14,
    sheet["A1"], new GoalSeekOptions
    {
        MaxChange = 0.001,
        MaxIterations = 100,
        Apply = false
    });
Console.WriteLine(result.Status);
Console.WriteLine(sheet["A1"].Number);
Text
Found
1

The short answer

Use Workbook.GoalSeek(setCell, toValue, changingCell) from OneDocument’s Spreadsheets package. The set cell must contain a formula that evaluates to a number. The changing cell must not itself be a formula. Inspect the result before saving: Found means the target was reached within the configured tolerance, not necessarily with an exact mathematical equality.

The example needs no spreadsheet template. It creates a workbook, puts a starting guess in A1 and a formula in B1, and asks for B1 to equal 14. The solution is A1 approximately 4. Replace that small model with the cells in your own workbook, but keep the success check.

How do I use the Goal Seek function in Excel?

In C#, identify three things: the formula cell, the desired formula result, and the single input cell you allow to change. The snippet at the top passes them in that order. GoalSeek calculates the workbook first, searches using temporary trial values, and only writes the found input at the end. When it applies a result, it recalculates the workbook too.

The input’s existing value is the starting guess. For a model with multiple possible roots, the starting point can matter; the API is a numerical search rather than an algebraic simplifier. Use the preview variation if you want to inspect a candidate without applying it. GoalSeekResult.ChangingValue holds the last or best value tried; do not confuse that with a successful result when the status is not Found.

Why does GoalSeek return NotFound?

NotFound means the search did not reach the target within the allowed evaluations, or a formula stopped returning a number during the search. Check GoalSeekResult.Status to distinguish this from invalid-cell statuses. SetCellNotFormula means the target cell does not contain a formula. ChangingCellIsFormula means you selected a formula as the input. SetCellNotNumeric means the formula did not return a numeric value. A valid model need not have a reachable target.

The calculation docs state that formulas reached through INDIRECT or OFFSET are not followed by this search. Unsupported functions elsewhere in the model can also stop it being a useful numeric problem. Test the formula result before asking Goal Seek to solve it.

You can override the stopping settings per call with GoalSeekOptions.MaxChange and MaxIterations, as in the variation. Without overrides, the default stopping settings come from the workbook’s maximum change and iteration count: 0.001 and 100 when unspecified. The implementation uses a secant iteration. Excel does not document its search method, so iteration counts are this library’s, not a claim of identical Excel behavior. A failed search applies no trial input; the initial workbook calculation still happens.

What is the difference between goal seeker and solver?

This API answers one question: which value in one changing cell makes one formula reach a given target? It is not a general optimization solver. It has no interface here for a group of changing cells, inequalities, integer constraints, or maximizing a business objective subject to bounds.

Use Goal Seek when your requirement can genuinely be stated as one formula, one target and one unknown input. If you need several independent inputs or constraints, this method does not express that problem. Do not repeatedly overwrite unrelated cells and treat a Found status for one formula as evidence that all your constraints are satisfied.

All onedocument recipes