Skip to content

ValueSnapshot

A snapshot of every cell’s value (and every spill range) in a Model at the moment ValueSnapshot.capture was called. See capture and applyTo for ownership and reuse semantics.

Captures and restores cell values (boxed, so number formats are preserved), spill-anchor matrices, and defined-name values. Cell and defined-name formulas are captured as a fingerprint only - apply uses them to detect a formula change since capture but does NOT restore them. Styles, the dependency graph, row/column metadata, and sheet structure are untouched. Structural edits (row/column inserts/deletes, sheet adds/removes/renames, moveCells) are out of scope; for those, use serializeModel + deserializeModel.

Handling of edits between capture and apply

Section titled “Handling of edits between capture and apply”
  • Same formula at apply time (cell or name): captured value is restored directly, without re-evaluating. For a spill anchor the captured matrix is swapped in if the live spill’s extent and mask still match, otherwise a fresh spill node is built and reattached.
  • Formula state differs (added, edited, or removed; cell or name): the captured value is NOT restored. The cell/name is pushed onto changedSinceRecalc so the trailing recalc re-evaluates it against the live state, and after all sheets and names are processed, one WARNING-level ModelError with type: 'snapshot_formula_mismatch' is emitted per workbook, listing every affected cell/name.
  • Value cells added after capture: cleared. If cell.style == null the Cell is deleted outright; if it carries style (user-assigned format, style index, or propagated formula format) the Cell is kept with v = null so the style survives.
  • Defined names removed after capture are not recreated; apply iterates the workbook’s current defined names.

After processing every entry, apply also pushes the direct dependents of every mismatched vertex so that any matched-formula cell reading from a mismatched cell gets re-evaluated against the live state. The recalc engine’s normal value-change cascade then handles transitive dependents.

Best-effort mismatch detection, not full invariant enforcement

Section titled “Best-effort mismatch detection, not full invariant enforcement”

The formula-state check is per-cell: captured f vs live f at the same position. A moveCells or other structural edit that rearranges cells across positions can leave applyTo with a partial revert - the value-cell halves of the move silently restore / delete with no WARNING, only the formula-cell halves warn. Matched-formula cells that depended on a moved-away formula cell can also lose their captured value silently when the dependents-of-mismatches push triggers a re-evaluation against the now-empty source. Treat the WARNINGs as a signal that something is wrong, not as a complete inventory; for guaranteed-correct reverts across structural edits, serialise the model.

new ValueSnapshot(): ValueSnapshot;

ValueSnapshot

applyTo(model, options?): void;

Restore model’s cell values (and spill ranges) to the snapshot’s state, then trigger a recalculation. See the class docstring for how cases like a formula change at a spill anchor are handled.

Throws if model is not the same instance the snapshot was captured from; workbook keys are model-scoped, so applying to a different model would silently no-op on every mismatch.

Apply also discards cached-formula defined names (auto-created via Workbook.getCachedFormulaCell) and tears down any dynamic-dependency edges built since capture, so revert semantics are consistent across the model.

The snapshot is unchanged after the call and can be applied again.

Model

boolean

passed through to the trailing model.recalculate(). Defaults to true so the post-apply model is fully consistent.

boolean

skip the trailing model.recalculate(). The caller is then expected to flush changedSinceRecalc itself.

void


static capture(model): ValueSnapshot;

Capture a snapshot of model’s current cell values (boxed, so number formats are preserved), spill matrices, and defined-name values. Cell and defined-name formulas are captured as a fingerprint only (used by applyTo to detect formula changes since capture). The returned snapshot owns a copy of the data; the model does not retain a reference, and subsequent edits do not flow into the snapshot.

Capture cost is roughly proportional to the number of cells that have their own Cell instance, plus the populated region of each spill matrix. Cells in the defaulted region of a whole-column / whole-row spill (e.g. Sheet1!A:XFD+1) are intentionally not enumerated.

Model

ValueSnapshot

const snap = ValueSnapshot.capture(model);
workbook.editCell('A1', { v: 99 });
model.recalculate();
// ... inspect, then revert:
snap.applyTo(model);