Skip to content

Row, column and freeze commands act on the sheet they are given (sheet, or a Sheet! prefix) - #885

Open
CouchRiv wants to merge 3 commits into
storytold:mainfrom
CouchRiv:fix/sheet-param-honoured
Open

CouchRiv wants to merge 3 commits into
storytold:mainfrom
CouchRiv:fix/sheet-param-honoured

Conversation

@CouchRiv

@CouchRiv CouchRiv commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

view.freezePanes, home.rowHeight, home.columnWidth and the other row and column commands always changed the active sheet. A sheet parameter was accepted and silently ignored, so a programmatic caller (MCP, control channel, CLI) laying out a sheet that isn't active got a success while the frozen panes, widths or heights landed on the active sheet, over what it had set there before. Found while building a four-sheet review workbook through MCP: the panes and column widths meant for two other sheets ended up on the first one.

Repro on main (fc45b7f), gridcraft-cli mcp, after home.insertSheet {name: "Data"} and sheet.activate {sheet: "Sheet1"}:

call main this branch
view.freezePanes {sheet: "Data", cell: "A2"} {"freeze":[1,0]}, applied to Sheet1 applied to Data
home.columnWidth {sheet: "Data", cols: "A:A", chars: 30} Sheet1!A:A resized Data!A:A resized
home.rowHeight {sheet: "Data", rows: "1:1", height: 40} Sheet1 row 1 Data row 1
home.columnWidth {cols: "Data!B:B", chars: 30} invalid parameters for cols: not a range: Data!B:B Data!B:B resized
view.freezePanes {cell: "Data!A2"} Data!A2 for cell names a sheet other than the one this command works on Data frozen at A2

Saved file on main: sheet1.xml has the <col> and <row ht>, sheet2.xml (Data) has no pane, no <cols>, no row height. On the branch it's the other way round.

What changed

  • format.rs: line_targets now returns the sheet with the lines. The sheet is sheet (name or index, through target_sheet like home.insertRows or data.validation), else a Sheet! prefix on rows/cols ("Data!B:B,D:F", same convention as range in target_ranges), else the active sheet. A prefix that contradicts sheet is an error; a null sheet counts as absent, as in target_sheet (second commit). home.rowHeight, home.columnWidth, home.autofitRowHeight, home.autofitColumnWidth, home.hideRows/hideColumns/unhideRows/unhideColumns use it; home.defaultWidth uses target_sheet.
  • view.rs: view.freezePanes resolves its sheet the same way, so sheet works and a cell prefixed with another sheet freezes that sheet instead of being refused. view.freezeTopRow, view.freezeFirstColumn and view.unfreezePanes take sheet.
  • The selection belongs to the active sheet, so on another sheet these commands need explicit rows/cols (or cell for Freeze Panes) and say so (missing cols: the selection is on the active sheet) rather than reusing the active sheet's selection.
  • Without sheet or a prefix nothing changes, so the UI (header drags, dialogs, context menus) behaves as before.
  • The params texts list sheet? and the prefixed form. The Freeze Panes one also says that without cell it unfreezes a frozen sheet, since a misspelt cell key otherwise removes the panes without a word.

Verification (Linux x86_64)

  • cargo test -p gridcraft-engine --lib tests::line_sizes_and_freeze_panes_take_a_sheet: with Sheet1 active, freezes, sizes, hides and sets the default width on Data through sheet (by name and by index) and through prefixes, checks Data and that Sheet1 is unchanged, then a null sheet with a prefix and the error cases. On main it fails at home.columnWidth {cols: "Data!B:B,D:D"} (not a range); with that line removed it fails at the first check, data.freeze left: None, right: Some((1, 0)). Passes here.
  • gridcraft-mcp: tests::other_sheet_prefix_is_error no longer expects Freeze Panes to refuse Other!B2, and keeps the "never silently fall back to the active sheet" check with formulas.tracePrecedents; tests::cross_sheet_cell_refs_resolve now checks that Other!C4 freezes that sheet and leaves the active one alone (read back with inspect_workbook).
  • The MCP repro above replayed on a release build of the branch.
  • cargo fmt --all -- --check, cargo clippy -p gridcraft-engine -p gridcraft-mcp --all-targets -- -D warnings, cargo test -p gridcraft-engine -p gridcraft-mcp

Limits

CouchRiv and others added 2 commits October 12, 2026 22:50
view.freezePanes, home.rowHeight, home.columnWidth, the AutoFit, Hide and
Unhide row/column commands and home.defaultWidth always changed the active
sheet: a `sheet` parameter was silently ignored, so a programmatic caller
laying out a sheet that isn't active changed the wrong one, and `Sheet!`
prefixes on `rows`/`cols` were refused as "not a range".

They now take `sheet` (name or index) like the commands that already use
target_sheet, accept a `Sheet!` prefix on `rows`/`cols` (and on Freeze
Panes' `cell`, which was refused), and refuse a prefix that contradicts
`sheet`. The selection belongs to the active sheet, so another sheet needs
explicit lines or a cell. Freeze Top Row, Freeze First Column and Unfreeze
Panes take `sheet` too. Without `sheet`, nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`{"sheet": null, "cols": "Data!B:B"}` was refused as naming a sheet other than `sheet`,
while `target_sheet` and the cell parameters read a null `sheet` as absent. The prefix now
decides, as it does when `sheet` is left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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