#2303·excelize

Add (*File).Recalc to evaluate formulas and persist cached values

Author: krystophnyCreated Apr 20, 2026Updated May 25, 2026
Labelsenhancement

Problem

excelize has no "open → recalc → save" workflow. A consumer that wants it hits three walls:

  1. No cached-value writer. SetCellFloat / SetCellStr / etc. call removeFormula, which deletes <f> and wipes shared-formula children.
  2. Round-tripping. CalcCellValue returns a string; writing it back via SetCellValue records t="s". Aggregates over that shared-string blob return 0.
  3. 3D references:
    • SUM(Sheet1:Sheet3!A1) unquoted → #NAME? invalid reference.
    • SUM('Sheet1':'Sheet3'!A1) quoted → parses, but rangeResolver overwrites sheet per iteration and evaluates only the last sheet.

Proposal

Add two exported methods:

go
func (f *File) RecalcCell(sheet, cell string) error
func (f *File) Recalc(opts ...RecalcOptions) error

RecalcCell evaluates one formula cell and writes the typed result into <v>/<t>, preserving <f> and shared-formula grouping. Recalc walks formula cells and calls RecalcCell on each. Dependency resolution reuses the existing recursive calcCellValue evaluator; circular references are bounded by MaxCalcIterations.

Scope

Four narrow PRs split under this umbrella, each with its own tracking issue where appropriate:

  1. 3D references, unquoted form. parseReference recognises <sheetA>:<sheetB>!<ref> and expands in workbook order; aggregates consume the expanded matrix. Covers SUM(Jänner:Dezember!M40) etc. Closes this issue (partial).
  2. RecalcCell + private setCellCachedValue helper + ErrCellNoFormula sentinel. Tracked in #2307.
  3. File.Recalc whole-workbook sweep built on RecalcCell, aggregating failures via errors.Join. Closes this issue.
  4. RecalcOptions{Sheet, Ref} scoping for File.Recalc. Tracked in #2308.

Out of scope (tracked elsewhere)

  • Quoted 3D references (SUM('A':'B'!ref)) — mis-tokenised by github.com/xuri/efp upstream of parseReference. Tracked in #2309.

Not needed (verified)

  • _xlfn. prefix stripping already works (calc.go:210).
  • ISOWEEKNUM and SHEET are registered and correct.