pub struct Sheet {
pub id: u64,
pub name: String,
pub tables: Vec<ExcelTable>,
pub dependencies: HashMap<Dependency, HashSet<CellRef>>,
pub dependencies_rev: HashMap<CellRef, HashSet<Dependency>>,
pub uncommitted_actions: Vec<SheetAction>,
/* private fields */
}Expand description
One worksheet: a grid of cells, the formulas over them, and the dependency graph that keeps them up to date.
§Coordinates
Everything here is 0-based (row, col). A1 notation exists only at the
parser and CLI boundaries – see parse_a1_coordinates and
col_idx_to_letters to convert.
§Naming trap
A Sheet is informally called a “table” in places (a new one is named
table_1, and Context::add_table registers one). That is not an
ExcelTable, which is a ListObject – a named rectangular range on a
sheet – and lives in Sheet::tables.
§Storage
Storage is column-oriented: each DataColumn keeps the raw user text,
the computed values and the compiled formulas in three parallel vectors
that must stay the same length. The row and column insert/delete paths
maintain that invariant by hand, so a new one has to do the same.
§Recalculation
Sheet::commit recomputes the dirty cells and propagates through
Dependency::Local and Dependency::LocalColumn edges only.
Cross-sheet edges are WorkbookManager::evaluate’s job, and evaluating a
formula with a remote reference requires a Context – without one it
errors.
Fields§
§id: u64Workbook-unique identifier. Formulas compile references against this rather than the name, which is what makes a rename non-destructive.
name: StringDisplay name, as it appears in a cross-sheet reference.
tables: Vec<ExcelTable>Excel Tables (ListObjects) defined on this sheet.
dependencies: HashMap<Dependency, HashSet<CellRef>>Forward edges: which cells must be recomputed when a dependency changes. Rebuilt from the formulas, so not serialized.
dependencies_rev: HashMap<CellRef, HashSet<Dependency>>Reverse edges: what each cell currently reads, so its old edges can be dropped when its formula changes. Rebuilt, so not serialized.
uncommitted_actions: Vec<SheetAction>Edits made since the last commit, for callers that want to observe or replay them.
Implementations§
Source§impl Sheet
impl Sheet
Sourcepub fn get_result_data(&self, cell: &CellRef) -> ResultData
pub fn get_result_data(&self, cell: &CellRef) -> ResultData
The computed value of a cell, or ResultData::None if it is empty
or outside the sheet’s allocated grid.
Reflects the last Sheet::commit; a cell edited since then still
reads as its old value.
A date reads back as the plain numeric serial it is. Rendering it in
the notation the cell carries is Sheet::get_display_string’s job, and
only its – do not format a ResultData directly if a user will see it.
Sourcepub fn get_display_string(&self, cell: &CellRef) -> String
pub fn get_display_string(&self, cell: &CellRef) -> String
The cell’s value as it should be shown, honoring the cell’s number format.
A date cell holds a plain numeric serial, exactly as in Excel, so
rendering it as a date is a display-time concern: this is the only
place that turns 46195 back into 6/22/26. Everything that shows a
value to a user should go through here rather than formatting
ResultData directly, which knows nothing about formats.
Sourcepub fn set_cell_src(&mut self, row: usize, col: usize, src: String)
pub fn set_cell_src(&mut self, row: usize, col: usize, src: String)
Updates the src text of a particular cell but does
not automatically evaluate. Call Sheet::commit to evaluate
updated cells.
Directly sets the src of a cell and marks it dirty.
Sourcepub fn insert(&mut self, pos: TextCellRef, input: &str)
pub fn insert(&mut self, pos: TextCellRef, input: &str)
Inserts text into a cell’s source at a character offset, as typing into it would, then recompiles and marks it dirty.
This is a text edit within one cell, not a range insert; see
Sheet::insert_row and Sheet::insert_col for the structural
operations. Out-of-range positions are ignored.
Sourcepub fn delete_one_before(&mut self, pos: TextCellRef)
pub fn delete_one_before(&mut self, pos: TextCellRef)
Delete one before (like backspace)
Sourcepub fn delete(&mut self, start: TextCellRef, end: TextCellRef)
pub fn delete(&mut self, start: TextCellRef, end: TextCellRef)
Deletes the text between two positions, recompiling and dirtying every cell it touches.
Within a single cell this removes a character range; spanning cells it
truncates the first, clears those in between and trims the last.
Ignored if end precedes start.
Sourcepub fn extend(&mut self, direction: Direction)
pub fn extend(&mut self, direction: Direction)
Grows the sheet by one empty row or column on the given side.
Direction::None does nothing. Rows are unbounded, but sideways
growth stops once the sheet has 26 columns.
Sourcepub fn ensure_capacity(&mut self, target_row: usize, target_col: usize)
pub fn ensure_capacity(&mut self, target_row: usize, target_col: usize)
Ensure sheet has at least target_row+1 rows and target_col+1 columns
Sourcepub fn get_cell_style(&self, row: usize, col: usize) -> Option<&CellStyle>
pub fn get_cell_style(&self, row: usize, col: usize) -> Option<&CellStyle>
The style set on a cell, or None if it has none.
This is where a date cell’s num_format lives – the notation half of
a date, the value half being the serial in the cell.
Sourcepub fn set_cell_style(&mut self, row: usize, col: usize, style: CellStyle)
pub fn set_cell_style(&mut self, row: usize, col: usize, style: CellStyle)
Replaces a cell’s style, growing the sheet if the cell is past its current bounds. An empty style is stored as no style at all.
Sourcepub fn update_cell_style<F>(&mut self, row: usize, col: usize, f: F)
pub fn update_cell_style<F>(&mut self, row: usize, col: usize, f: F)
Mutates a cell’s style in place, starting from the default if it has none, so one attribute can be changed without disturbing the others.
Grows the sheet if needed; a style left empty is dropped.
Sourcepub fn clear_cell_style(&mut self, row: usize, col: usize)
pub fn clear_cell_style(&mut self, row: usize, col: usize)
Removes a cell’s style. Unlike the setters, this never grows the sheet.
Sourcepub fn insert_row(&mut self, index: usize)
pub fn insert_row(&mut self, index: usize)
Insert a new empty row at the specified index If index is >= row_count, appends at the end
Sourcepub fn delete_row(&mut self, index: usize)
pub fn delete_row(&mut self, index: usize)
Deletes a row, shifting the rows below it up.
Removes the entry from all three parallel per-row vectors together, which is what keeps them the same length, and rebases the dirty queue. Out-of-range indices are ignored. Everything is marked dirty, since formulas above the deleted row may refer to it.
Sourcepub fn insert_cells_shift_down(
&mut self,
row: usize,
first_col: usize,
last_col: usize,
count: usize,
)
pub fn insert_cells_shift_down( &mut self, row: usize, first_col: usize, last_col: usize, count: usize, )
Excel’s Insert cells, shift down over an inclusive column band.
Unlike Sheet::insert_row this moves only first_col..=last_col,
leaving every other column where it is – which is what
ListRows.Add actually does. Measured: adding a row to a table at
A1:C4 moves A8 down to A9 but leaves E2 alone.
Every column keeps the same length: the sheet first grows by count
rows, so the rows pushed off the bottom of the band are the blank ones
just added rather than data. Everything moves through DataColumn’s
paired operations, so src / data / compiled_src / styles stay
aligned.
Out-of-range bands and a zero count are no-ops. Formula references
are not rewritten here – that is
WorkbookManager::insert_cells_shift_down’s job, since it spans
sheets.
Sourcepub fn delete_cells_shift_up(
&mut self,
row: usize,
first_col: usize,
last_col: usize,
count: usize,
)
pub fn delete_cells_shift_up( &mut self, row: usize, first_col: usize, last_col: usize, count: usize, )
Excel’s Delete cells, shift up over an inclusive column band; the
inverse of Sheet::insert_cells_shift_down.
The band’s rows below row move up and blank rows appear at its
bottom, so the sheet keeps its shape and other columns are untouched.
Sourcepub fn delete_col(&mut self, index: usize)
pub fn delete_col(&mut self, index: usize)
Deletes a column, shifting the columns to its right left.
Out-of-range indices are ignored; everything is marked dirty.
Sourcepub fn insert_col(&mut self, index: usize)
pub fn insert_col(&mut self, index: usize)
Insert a new empty column at the specified index If index is >= columns.len(), appends at the end
Sourcepub fn columns(&self) -> &[DataColumn]
pub fn columns(&self) -> &[DataColumn]
The sheet’s columns.
Read-only: every column must keep the same number of rows, so growing
or replacing one from outside would desync the sheet. Use
Sheet::insert_col, Sheet::delete_col and Sheet::extend to
change the shape.
Source§impl Sheet
impl Sheet
Sourcepub fn new(args: SheetInit) -> Sheet
pub fn new(args: SheetInit) -> Sheet
Creates a sheet of args.rows x args.cols empty cells, every one of
them queued as a pending edit so the first Sheet::commit sees them.
Sourcepub fn setup_after_deserialization(&mut self)
pub fn setup_after_deserialization(&mut self)
Rebuilds what serialization drops.
Only the raw source text is persisted, so this resizes the value and
compiled-formula vectors back to match it – restoring the
same-length invariant – and marks everything dirty. Call it after
deserializing, before Sheet::commit.
Sourcepub fn mark_all_dirty(&mut self)
pub fn mark_all_dirty(&mut self)
Queues every cell for recomputation on the next Sheet::commit.
This is how cross-sheet staleness is handled: WorkbookManager cannot
tell which cells a remote edit reached, so it marks whole sheets.
Sourcepub fn commit(
&mut self,
context: Option<&Context<'_>>,
) -> Result<HashSet<CellRef>, EngineError>
pub fn commit( &mut self, context: Option<&Context<'_>>, ) -> Result<HashSet<CellRef>, EngineError>
Commit all changed src items with a context for sheet lookups
Sourcepub fn eval_with_row(
&self,
input: &str,
context: Option<&Context<'_>>,
row: Option<usize>,
col: Option<usize>,
) -> Result<(ResultData, Vec<Dependency>), EngineError>
pub fn eval_with_row( &self, input: &str, context: Option<&Context<'_>>, row: Option<usize>, col: Option<usize>, ) -> Result<(ResultData, Vec<Dependency>), EngineError>
Evaluates cell source text without storing it, as
Sheet::eval does, but from the point of view of (row, col).
The position is what makes relative constructs work – a structured
reference like [@Amount] means “this row”, so it needs to know which
row is asking. Pass None for both when there is no anchor.
§Errors
Returns an EngineError if the formula cannot be parsed. An Excel
error is not a Rust error: =1/0 succeeds, returning
ResultData::Error("#DIV/0!").
Sourcepub fn eval(
&self,
input: &str,
context: Option<&Context<'_>>,
) -> Result<(ResultData, Vec<Dependency>), EngineError>
pub fn eval( &self, input: &str, context: Option<&Context<'_>>, ) -> Result<(ResultData, Vec<Dependency>), EngineError>
Evaluates cell source text against this sheet without storing it, returning the value and the references it read.
Text with a leading = is a formula; anything else is parsed as a
literal. context supplies the other sheets, and is required for a
cross-sheet reference to resolve.
§Errors
Returns an EngineError if the formula cannot be parsed. An Excel
error is not a Rust error: =1/0 succeeds, returning
ResultData::Error("#DIV/0!").
Sourcepub fn get_src(&self, cell: &CellRef) -> Option<&String>
pub fn get_src(&self, cell: &CellRef) -> Option<&String>
The raw text typed into a cell – "10", "=SUM(A1:A2)" – or None
if the cell is outside the sheet’s allocated grid.
This is the input, not the result; see Sheet::get_result_data for
the computed value and Sheet::get_display_string for what a user
should see.
Sourcepub fn get_src_str(&self, cell: &CellRef) -> String
pub fn get_src_str(&self, cell: &CellRef) -> String
Sheet::get_src with an out-of-range cell flattened to an owned
empty string.
Sourcepub fn get_src_str_ref(&self, cell: &CellRef) -> Option<&str>
pub fn get_src_str_ref(&self, cell: &CellRef) -> Option<&str>
Sheet::get_src as a borrowed &str, for callers that only read.
Sourcepub fn get_word_boundaries(
&self,
cell: &CellRef,
char_offset: usize,
) -> (usize, usize)
pub fn get_word_boundaries( &self, cell: &CellRef, char_offset: usize, ) -> (usize, usize)
The word surrounding char_offset in a cell’s source text, as a
half-open range of character (not byte) indices – what an editor needs
for word-wise selection. See get_word_boundaries_from_str.
Source§impl Sheet
impl Sheet
Sourcepub fn find_table(&self, name: &str) -> Option<&ExcelTable>
pub fn find_table(&self, name: &str) -> Option<&ExcelTable>
Finds a table on this sheet by name, matched case-insensitively as Excel does.
Sourcepub fn find_table_mut(&mut self, name: &str) -> Option<&mut ExcelTable>
pub fn find_table_mut(&mut self, name: &str) -> Option<&mut ExcelTable>
Sheet::find_table, mutably.
Sourcepub fn add_table(
&mut self,
name: String,
start_row: usize,
start_col: usize,
end_row: usize,
end_col: usize,
has_header_row: bool,
has_totals_row: bool,
) -> Result<u64, String>
pub fn add_table( &mut self, name: String, start_row: usize, start_col: usize, end_row: usize, end_col: usize, has_header_row: bool, has_totals_row: bool, ) -> Result<u64, String>
Defines a new Excel Table over the rectangular range
start_row..=end_row x start_col..=end_col (0-based, inclusive)
on this sheet. Column names are read from the header row’s existing
cell text when has_header_row is true, falling back to “ColumnN”
for blank cells; otherwise every column gets a default “ColumnN”
name.
Sourcepub fn delete_table_by_name(&mut self, name: &str) -> Result<(), String>
pub fn delete_table_by_name(&mut self, name: &str) -> Result<(), String>
Removes a table definition from this sheet, leaving the cells it covered untouched.
§Errors
Returns a message if no table on this sheet has that name.
Sourcepub fn rename_table(
&mut self,
old_name: &str,
new_name: &str,
) -> Result<(), String>
pub fn rename_table( &mut self, old_name: &str, new_name: &str, ) -> Result<(), String>
Renames a table on this sheet.
Renaming here does not rewrite the formulas that reference the table
– that cascade is WorkbookManager::rename_table’s job, and it is
what keeps Sales[Amount] pointing at the renamed table. Prefer that
entry point unless you are rewriting the references yourself.
§Errors
Returns a message if the new name is not a valid table name, if
another table on this sheet already has it, or if no table on this
sheet has old_name.
Sourcepub fn resize_table(
&mut self,
name: &str,
new_end_row: usize,
new_end_col: usize,
) -> Result<(), String>
pub fn resize_table( &mut self, name: &str, new_end_row: usize, new_end_col: usize, ) -> Result<(), String>
Extends or shrinks a table’s range by moving its bottom-right corner
to new_end_row/new_end_col (the top-left corner never moves).
Column names for any newly-included columns are read from the
header row (or default to “ColumnN”); names for columns that
already existed are preserved by position.