Skip to content

Sheet should preserve absolute range origin for non-A1 sheets #6

@wolfiesch

Description

@wolfiesch

Context

Sheet (in crates/wolfxl-core/src/sheet.rs) currently stores cells in a Vec<Vec<Cell>> indexed from (0, 0), regardless of where worksheet_range() reports the populated region starts. For a sheet whose first populated cell is C5, calamine returns a Range with start = (4, 2) (0-indexed), and we copy its contents into rows[0..h][0..w] using Range::get((r, c)) (which is the correct relative-coord API).

That works fine for the v0.4.0 peek output (it renders the populated block as a tabular preview, matching xleak's behavior on non-A1 sheets), but it loses the absolute origin.

Why this matters for sprint 2

Several planned features need the absolute origin:

  • wolfxl peek --cell B7:D12 - addressable cell queries
  • wolfxl peek --emit-citations - provenance with absolute Excel cell addresses (e.g. "value at C5", not "value at row 0 col 0")
  • wolfxl map - when reporting a sheet's dimensions, distinguish a tiny C5:D6 island from an A1:B2 block
  • wolfxl peek --find "revenue" - return absolute-address matches

Proposal

Add (start_row, start_col): (u32, u32) to Sheet, populated from value_range.start() at load time. Add public methods:

impl Sheet {
    pub fn origin(&self) -> (u32, u32) { ... }
    pub fn cell_address(&self, internal_row: usize, internal_col: usize) -> String { ... }
    pub fn get_at_address(&self, address: &str) -> Option<&Cell> { ... }
}

The current rows() / headers() / dimensions() API stays unchanged (relative to the populated block) so render.rs keeps working.

Out of scope for this issue

  • Whether dimensions() should return relative or absolute is a separate API decision deferred until a --cell consumer actually exists.
  • Padding the rendered output with leading empty rows/cols for non-A1 sheets is a render-layer choice, not a Sheet concern.

Origin

Surfaced in PR #4 round-9 review (#4 (comment)). The reviewer's framing was "Range::get expects absolute coordinates" which is incorrect (calamine's get takes relative coords; get_value takes absolute), but the underlying ergonomic concern about losing absolute position is real and deferred to this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions