iOfficeAI / iOfficeAI/OfficeCLI
xlsx: get /<Sheet> reports freeze from topLeftCell, ignoring xSplit/ySplit
- Dominant language
- C#
- Stars
- 30.7k
- Forks
- 2.1k
- Avg merge
- 9d 8h
- Merged PRs (30d)
- 5
Description
## Summary
`officecli get /` reports the `freeze` property by echoing the `` element's `topLeftCell` attribute instead of deriving it from `xSplit` / `ySplit`. Whenever a workbook was saved while scrolled away from the frozen boundary — the normal state of any real spreadsheet — the reported freeze position is wrong.
Writing is correct; only the readback is affected.
## Environment
- officecli 1.0.149 (win-x64), Windows 11
- Reproduced on a file authored by Excel 16.0 and on a file created by officecli itself
## Reproduction
Self-contained, no external file needed:
```bash
officecli create repro.xlsx
officecli set repro.xlsx /Sheet1/A1 --prop value="header"
officecli set repro.xlsx /Sheet1 --prop freeze=A2
officecli close repro.xlsx
officecli get repro.xlsx /Sheet1
# /Sheet1 (sheet) freeze=A2 <- correct
officecli raw repro.xlsx /Sheet1 | grep -o ']*>'
#
# Simulate what Excel writes when the sheet is saved while scrolled down.
# Only topLeftCell changes; ySplit="1" is untouched, so the freeze is still row 1.
officecli raw-set repro.xlsx /Sheet1 --xpath "//x:pane" --action setattr --xml 'topLeftCell="A50"'
officecli close repro.xlsx
officecli get repro.xlsx /Sheet1
# /Sheet1 (sheet) freeze=A50 <- WRONG, should still be A2
officecli raw repro.xlsx /Sheet1 | grep -o ']*>'
#
```
## Expected vs actual
| `` | Excel's actual freeze | `get /Sheet1` reports |
|---|---|---|
| `ySplit="1" topLeftCell="A2"` | A2 | `freeze=A2` ✅ |
| `ySplit="1" topLeftCell="A50"` | A2 | `freeze=A50` ❌ |
| `ySplit="1" topLeftCell="A329"` | A2 | `freeze=A329` ❌ |
The third row is from a real 369-row workbook saved by Excel with the cursor near the bottom. It reports `freeze=A329` while the sheet is, and always was, frozen at A2.
## Root cause
`topLeftCell` is the scroll position of the scrolled pane — it drifts every time the user saves while scrolled. The freeze boundary is defined solely by `xSplit` / `ySplit`. They coincide only in a freshly created file, which is why round-tripping through officecli alone looks correct and hides the bug.
Correct derivation:
```
freezeCell = columnLetter(xSplit + 1) + (ySplit + 1)
```
with absent attributes treated as 0. Also worth guarding `state`: `state="split"` is a split pane, not a freeze, and `state="frozenSplit"` differs again.
## The write path is already correct
```
set freeze=A5 ->
set freeze=B2 ->
set freeze=C10 ->
```
So the fix is confined to the getter.
## Impact
The readback is silently and plausibly wrong — it returns a valid-looking cell reference, so there is no error to notice. An agent inspecting a workbook will report a wrong freeze configuration with full confidence, and a round-trip that reads `freeze` and writes it back would move a correct freeze pane to wherever the file happened to be scrolled.
Contributor guide
Research direction
Start with the getter behind `officecli get /` and reproduce the readback using the self-contained commands, including the `raw-set` scroll simulation. Done means `get` reports the freeze boundary from the pane split values, handles the pane states described in the issue, and leaves the write path unchanged; cover the A2, A50, B2, and C10 examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100