This closes #2303, add File.Recalc for whole-workbook recalc#2312
Open
krystophny wants to merge 3 commits into
Open
This closes #2303, add File.Recalc for whole-workbook recalc#2312krystophny wants to merge 3 commits into
krystophny wants to merge 3 commits into
Conversation
CalcCellValue returns a formatted string but does not touch the stored workbook. Every SetCell* writer strips the <f> element, so callers that need to refresh the cached value of a formula cell without losing the formula currently have no path. Readers that honour <v> without recomputing (LibreOffice headless, Numbers, etc.) therefore see stale numbers after any excelize round trip. Add (*File).RecalcCell(sheet, cell string) error. It evaluates the formula via the existing recursive calc engine, then writes the typed result into <v>/<t> through a private setCellCachedValue helper that leaves <f>, the shared-formula master, ref span, and si index intact. A new sentinel ErrCellNoFormula is returned when the target cell has no formula. Dependency resolution reuses calcCellValue, so chained formulas across cells converge in one pass; circular references are bounded by the workbook's existing MaxCalcIterations option. Signed-off-by: Christopher Albert <albert@tugraz.at>
Users who open a workbook, mutate inputs, and save it back have
had no way to refresh the cached values their downstream readers
depend on. LibreOffice headless, Numbers, and readers that trust
<v> without recomputing therefore see stale results after any
excelize round trip.
Build (*File).Recalc on top of the single-cell RecalcCell added
in the previous commit. It walks every formula cell in the
workbook and calls RecalcCell on each, preserving <f> and shared
formula grouping while refreshing <v>/<t> through the private
setCellCachedValue helper. Dependency resolution reuses the
existing recursive calc engine, so chained formulas across
sheets converge in a single pass; the calc cache is cleared
before and after the sweep to avoid cross-call contamination.
Failures never abort the pass. Each failing cell contributes an
fmt.Errorf("<sheet>!<cell>: %w", cause) entry to an
errors.Join(...) result; cells that did compute are still
persisted. Callers can descend with errors.Is / errors.As
through the Unwrap() []error provided by the joined error.
Signed-off-by: Christopher Albert <albert@tugraz.at>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add
(*File).Recalc() error, built on top ofRecalcCellfrom the companion PR #2311.Recalcwalks every formula cell in the workbook, callsRecalcCellon each, and returns anerrors.Join-aggregated error listing any per-cell failures wrapped as"<sheet>!<cell>: <cause>". Cells that did compute are still persisted when later cells fail.Public surface introduced by this PR:
(*File).Recalc() errorNo existing API is changed or removed.
Related Issue
Closes umbrella #2303. Depends on #2311 (introduces
RecalcCell); this PR's branch is stacked on that PR's branch so CI runs against the combined state. It will rebase cleanly on master once #2311 merges.Documentation
Reference-site entries for this PR ship in a companion docs PR: xuri/excelize-doc#31. That PR covers the English version; other language versions follow the project's usual rollout cadence.
Motivation and Context
Users who open a workbook, mutate inputs, and save it back currently have no way to refresh the cached values downstream consumers rely on.
CalcCellValuereturns a formatted string but does not persist it, and everySetCell*writer removes the formula while writing a new value, which makes them useless for this purpose. The result is that LibreOffice-headless, Numbers, and other readers that trust<v>without recomputing see stale results after a round trip through excelize.Recalccloses that gap with a single entry point and zero cost to callers who do not use it.Design notes reviewers are likely to ask about:
calcCellValuealready recurses into referenced cells during evaluation, so a single pass converges chained dependencies across sheets. The calc cache is cleared before and after the sweep to avoid cross-call contamination.fmt.Errorf("<sheet>!<cell>: %w", cause); the collection is returned viaerrors.Join(...). Callers descend witherrors.Is/errors.Asthrough the standardUnwrap() []errormethod the joined error provides. This replaces the typedRecalcError/RecalcCellErrorsurface that an earlier draft proposed — no new exported error types are added here.Scoping via a
RecalcOptions{Sheet, Ref}value is intentionally deferred to #2308 so this PR keeps the API surface minimal; the zero-option form covers the umbrella's stated requirement.How Has This Been Tested
Full suite:
go test -skip TestZip64 -timeout 10m .passes cleanly.gofmt -s -l .andgo vet ./...are clean. ARM cross-builds (GOARM=5|6|7,arm64,android/arm64) all build.Types of changes
Checklist
Documentation for the new exported surface lives in the doc comment on
Recalc.