iOfficeAI / iOfficeAI/OfficeCLI

xlsx: get /<Sheet> reports freeze from topLeftCell, ignoring xSplit/ySplit

Open Beginner friendly
#400 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.