feat(spreadsheet): read the formula of every cell of a shared group - #885
Merged
Conversation
This was referenced Sep 11, 2026
andiwand
force-pushed
the
feat/formula-parser
branch
from
September 12, 2026 06:50
7ac5c1d to
682162e
Compare
andiwand
force-pushed
the
feat/shared-formulas
branch
2 times, most recently
from
September 12, 2026 07:27
0a3fbfc to
412bd36
Compare
andiwand
force-pushed
the
feat/formula-parser
branch
from
September 12, 2026 07:27
682162e to
295425a
Compare
andiwand
force-pushed
the
feat/shared-formulas
branch
from
September 12, 2026 07:31
412bd36 to
60a0943
Compare
andiwand
force-pushed
the
feat/formula-parser
branch
from
September 12, 2026 07:31
295425a to
fa5bc31
Compare
andiwand
force-pushed
the
feat/shared-formulas
branch
from
September 12, 2026 07:51
60a0943 to
5eebf32
Compare
andiwand
force-pushed
the
feat/formula-parser
branch
from
September 12, 2026 07:51
fa5bc31 to
2d04667
Compare
[ECMA-376] 18.3.1.40 spells a shared formula on the group's master alone, and a member states its `si` and nothing else. A member reported an empty formula, so a formula bar had nothing to show and a dependency has nothing to read. The parser collects the masters per sheet, and `sheet_cell_value` reads a member through the one its `si` names: parse the master's expression, move every relative reference by the offset between the two cells, and write it again. An absolute axis does not move, and a reference moved off the grid becomes `#REF!`, as a sheet makes it. That takes two pieces beside the parser, both in `internal/formula`: `shift` over the tree, and a writer that spells a tree back in either syntax. The writer drops a parenthesis the precedence already states, so what it writes is the tree rather than the producer's own text. A number that overflows to infinity no longer parses, because no formula spells one. A master the parser cannot read is handed out as it stands, and a member whose `si` names no master stays set and empty: it computes, and nothing here can spell what. Step 3.1 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
force-pushed
the
feat/shared-formulas
branch
from
September 12, 2026 08:03
5eebf32 to
f2855af
Compare
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.
🤖 Generated with Claude Code
Step 3.1 of
docs/design/spreadsheet-editing.md, finishing what the parser was for.The problem
[ECMA-376] 18.3.1.40 spells a shared formula on the group's master alone:
Excel writes this whenever you fill a column down, so most formula cells in a real workbook are members. A member reported an empty formula, which leaves a formula bar with nothing to show and the dependency graph (next PR) with nothing to read.
What it does
The parser collects the masters per sheet, and
sheet_cell_valuereads a member through the one itssinames: parse the master's expression, move every relative reference by the offset between the two cells, write it again. So C2 above answersA2+$B$1and C3A3+$B$1— the$B$1does not move, because a$axis never does.That needs two pieces beside the parser, both in
internal/formula:shiftover the tree. A reference moved off the grid becomes#REF!, as a sheet makes it.to_string(node, syntax), which spells a tree back in either syntax. It drops a parenthesis the precedence already states, so1+(2*3)comes back as1+2*3while1-(2-3)keeps its own.One fix fell out of having a writer: the parser accepted
1e999as infinity, which the writer would then spellinf. It refuses the number instead, so the master's own text is what a member gets.Two cells that keep what they had
sinames no master stays set and empty — it computes, and nothing here can spell what.An array formula (
t="array") writes no<f>at all on its members, so those still report none. Noted in the module'sAGENTS.md.Test
test/src/internal/formula/formula_writer_test.cppround-trips both syntaxes and pins the shift; the shared-formula cases are inooxml_spreadsheet_value_test.cpp, from inline fixtures.test/data/input/odr-public/xlsx/sample.xlsxis a real file of the shape — 32 members of oneRAND()group.