Skip to content

feat(odf): a write takes the cached result of what reads it away - #888

Merged
andiwand merged 1 commit into
mainfrom
feat/ods-stale-cache
Sep 12, 2026
Merged

andiwand merged 1 commit into
mainfrom
feat/ods-stale-cache

Conversation

@andiwand

@andiwand andiwand commented Sep 11, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Rebased on main, now that the rest of the step-3 stack has landed. One commit.

Step 3.4 of docs/design/spreadsheet-editing.md.

The problem

An edited input leaves every formula reading it computing an old number, and the saved .ods went on showing the result its producer cached. An .xlsx has a switch for exactly this — calcPr/@fullCalcOnLoad, which every save already sets. ODF has none.

What it does

So the result goes instead. drop_stale_results asks SheetDependencies which cells read the written position — directly or through another formula — and takes the attributes stating a value off each. The text:p showing it goes as an element rather than as a node, so the registry keeps no dangling one.

<!-- before --><table:table-cell table:formula="of:=SUM([.A1:.A2])" office:value-type="float" office:value="3"><text:p>3</text:p></table:table-cell>
<!-- after  --><table:table-cell table:formula="of:=SUM([.A1:.A2])"/>

The formula, the cell's style and a drawing anchored in the cell all stay. A cell stating a formula and no result is one a reader has to compute, and none can show a wrong number for.

A formula the graph could read no position out of keeps its result. Nothing links it to the write. Document::unresolved_formulas() is what names them.

The cost until step 4: a cleared cell renders empty here too. That is the trade the design accepted — an empty cell says "not computed", a stale one says nothing.

The spike, as far as a CLI can answer it

LibreOffice's --convert-to recomputes whatever a file cached — a file whose cached result I hand-edited to 999 converted back to 3 — so it cannot show what a reader that does not recompute would display, and setting ODFRecalcMode to "never" in a scratch profile changed nothing. ODF states no recalculation switch at all, so the rule the file itself can carry is what is left.

End-to-end check: a real LibreOffice-written .ods, edited through Sheet::set_cell and saved by us, opens as a valid package and LibreOffice computes the cell we cleared (10 / 2 / 12, where the file states no result for the third).

Test

test/src/internal/odf/odf_sheet_stale_test.cpp, 8 cases from inline fixtures: the direct reader, the chain, a formula reading something else, a reader on another sheet, what the cell keeps, a drawing anchored in a cleared cell, the saved file, and a write nothing reads.

Reference output: this PR emits no different html — it changes the write path only. compare-html stays red until the output repos take the commit #887 still owes them.

https://claude.ai/code/session_01VVmjmddv2Ui17Nptc1ggue

@andiwand
andiwand force-pushed the feat/ods-stale-cache branch from 7102637 to ae5ed82 Compare September 11, 2026 22:16
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch 2 times, most recently from f105f4d to e26716b Compare September 12, 2026 06:50
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch 2 times, most recently from c043c0f to 469c9ec Compare September 12, 2026 07:31
@andiwand
andiwand force-pushed the feat/stale-formulas branch 2 times, most recently from eadb004 to ea2abd7 Compare September 12, 2026 07:39
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch from 469c9ec to caadfdf Compare September 12, 2026 07:39
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch from caadfdf to ba6e5d3 Compare September 12, 2026 07:51
@andiwand
andiwand force-pushed the feat/stale-formulas branch 2 times, most recently from 388788b to 34064b9 Compare September 12, 2026 15:36
Base automatically changed from feat/stale-formulas to main September 12, 2026 15:42
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch from ba6e5d3 to 3b11075 Compare September 12, 2026 15:53
An edited input leaves every formula reading it computing an old number, and
the saved file went on showing the result its producer cached. ODF states no
switch asking a reader to recompute - ooxml's `fullCalcOnLoad`, which every
xlsx save sets - so the result goes instead: a cell stating a formula and no
result is one a reader has to compute, and none can show a wrong number for.

`drop_stale_results` asks `SheetDependencies` which cells read the written
position, directly or through another formula, and takes the attributes
stating a value off each. The `text:p` showing it goes as an element rather
than as a node, so the registry keeps no dangling one. The formula, the
cell's style and a drawing anchored in the cell stay, and a formula the graph
could read no position out of keeps its result.

Until the evaluator lands, a cleared cell renders empty here too. The spike
cannot say more: LibreOffice's `--convert-to` recomputes whatever a file
cached, so it cannot show what a reader that does not recompute would display.

Step 3.4 of `docs/design/spreadsheet-editing.md`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VVmjmddv2Ui17Nptc1ggue
@andiwand
andiwand force-pushed the feat/ods-stale-cache branch from 3b11075 to 602c39c Compare September 12, 2026 16:00
@andiwand
andiwand merged commit e375723 into main Sep 12, 2026
36 checks passed
@andiwand
andiwand deleted the feat/ods-stale-cache branch September 12, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant