pub struct WorkbookManager {
pub sheets: Vec<Sheet>,
pub charts: Vec<Chart>,
pub pivot_tables: Vec<PivotTable>,
pub vba_project: Option<VbaProject>,
}Expand description
A whole workbook: its sheets, charts, pivot tables and VBA project, and the operations that span more than one of them.
The entry point to this crate, and the layer an embedder should drive. Two behaviors are only correct at this level:
- Cross-sheet formulas.
Sheet::commitpropagates local dependencies only;WorkbookManager::evaluateis what carries values between sheets. - Pivot tables. Nothing recomputes one implicitly.
WorkbookManager::refresh_pivot_tableis the only thing that writes a computed grid into cells.
Editing the Sheets directly is allowed – the fields are public – but
skips both, so cross-sheet formulas and pivot output go stale silently.
Fields§
§sheets: Vec<Sheet>The worksheets, in workbook order. Cell coordinates within them are 0-based.
charts: Vec<Chart>The charts. Workbook-level rather than sheet-scoped; which sheet a
chart is drawn on comes from its data_range.
pivot_tables: Vec<PivotTable>The pivot table definitions. Workbook-level, since a pivot’s source and destination may be on different sheets.
vba_project: Option<VbaProject>The VBA project, if the workbook has macros.
Implementations§
Source§impl WorkbookManager
impl WorkbookManager
Sourcepub fn run_macro(
&mut self,
module: Option<&str>,
procedure: &str,
args: &[&str],
) -> Result<RunOutcome, Error>
pub fn run_macro( &mut self, module: Option<&str>, procedure: &str, args: &[&str], ) -> Result<RunOutcome, Error>
Runs one of this workbook’s own VBA procedures against this workbook.
Phase 2 of docs/vba-macro-support.md, and the entry point that
separates it from Phase 1: the interpreter borrows the workbook for
the duration, so a macro can read and write cells, walk the sheets,
and call worksheet functions. run_macro stays as the text-only
form – it is what visi_core.run_macro and fuzz/fuzz_vba.py drive,
and a macro that touches no workbook has no reason to need one.
module picks which module to take the procedure from; None
searches every module for one that declares it, which is the common
single-module case. Resolving it here rather than in each caller is
Runs a VBA procedure in the workbook’s project.
The workbook is left recalculated, so a caller that saves afterwards writes the values the macro itself would have read.
Sourcepub fn run_open_events(&mut self) -> Result<RunOutcome, Error>
pub fn run_open_events(&mut self) -> Result<RunOutcome, Error>
Runs startup macro events (Workbook_Open in ThisWorkbook then Auto_Open in standard modules).
Source§impl WorkbookManager
impl WorkbookManager
Sourcepub fn load_bytes(buffer: &[u8]) -> Result<Self>
pub fn load_bytes(buffer: &[u8]) -> Result<Self>
Load Excel workbook from bytes buffer
Sourcepub fn save_bytes(&self) -> Result<Vec<u8>>
pub fn save_bytes(&self) -> Result<Vec<u8>>
Serialize the workbook to .xlsx bytes.
The byte-level counterpart to Self::load_bytes. Callers that want
to read or write an actual file supply their own IO – the visi CLI
does so through its WorkbookFile trait.
Sourcepub fn new_empty() -> Result<Self>
pub fn new_empty() -> Result<Self>
A new workbook containing a single empty sheet named Sheet1.
Sourcepub fn evaluate(&mut self) -> Result<()>
pub fn evaluate(&mut self) -> Result<()>
Recalculate all formulas in all sheets using visi-core engine
Sourcepub fn find_sheet_index(&self, name_opt: Option<&str>) -> Result<usize>
pub fn find_sheet_index(&self, name_opt: Option<&str>) -> Result<usize>
Find index of sheet by name, or return default index 0 if name is None.
Sourcepub fn get_summary(&self, file_name: &str) -> WorkbookSummary
pub fn get_summary(&self, file_name: &str) -> WorkbookSummary
Get structural summary of workbook
Sourcepub fn ensure_capacity(
&mut self,
sheet_idx: usize,
target_row: usize,
target_col: usize,
)
pub fn ensure_capacity( &mut self, sheet_idx: usize, target_row: usize, target_col: usize, )
Ensure sheet bounds can accommodate specified target_row and target_col
Sourcepub fn set_cell_style(
&mut self,
sheet_name: Option<&str>,
row: usize,
col: usize,
style: CellStyle,
) -> Result<()>
pub fn set_cell_style( &mut self, sheet_name: Option<&str>, row: usize, col: usize, style: CellStyle, ) -> Result<()>
Merges style into one cell’s existing style.
Row and column are 0-based, like every other coordinate on this type.
A1 notation is a CLI/parser-boundary concern: callers holding a
string like "Sheet2!B3" parse it themselves and resolve the sheet
prefix against sheet_name before calling in.
Sourcepub fn set_range_style(
&mut self,
sheet_name: Option<&str>,
start_row: usize,
start_col: usize,
end_row: usize,
end_col: usize,
style: CellStyle,
) -> Result<()>
pub fn set_range_style( &mut self, sheet_name: Option<&str>, start_row: usize, start_col: usize, end_row: usize, end_col: usize, style: CellStyle, ) -> Result<()>
Merges style into every cell of an inclusive 0-based range.
Sourcepub fn get_cell_style(
&self,
sheet_name: Option<&str>,
row: usize,
col: usize,
) -> Result<Option<CellStyle>>
pub fn get_cell_style( &self, sheet_name: Option<&str>, row: usize, col: usize, ) -> Result<Option<CellStyle>>
The style applied to one 0-based cell, if it has one.
Sourcepub fn set_table_style(
&mut self,
table_name: &str,
style_name: &str,
) -> Result<()>
pub fn set_table_style( &mut self, table_name: &str, style_name: &str, ) -> Result<()>
Sets an Excel Table’s visual style, looking the table up by name across every sheet.
§Errors
Error::NotFound if no table in the workbook has that name.
Sourcepub fn get_table_style(&self, table_name: &str) -> Result<Option<String>>
pub fn get_table_style(&self, table_name: &str) -> Result<Option<String>>
An Excel Table’s visual style, or None if it has none set.
§Errors
Error::NotFound if no table in the workbook has that name.
Sourcepub fn set_cell(
&mut self,
sheet_idx: usize,
row: usize,
col: usize,
value: String,
)
pub fn set_cell( &mut self, sheet_idx: usize, row: usize, col: usize, value: String, )
Update cell source / value at (row, col)
Sourcepub fn insert_row(&mut self, sheet_idx: usize, row_idx: usize) -> Result<()>
pub fn insert_row(&mut self, sheet_idx: usize, row_idx: usize) -> Result<()>
Insert row at 0-based index.
Formulas throughout the workbook are rewritten to follow the cells
that moved, as in Excel, and Excel Table and pivot ranges move with
the cells they cover. See core::grid_edit for the rules.
Sourcepub fn delete_row(&mut self, sheet_idx: usize, row_idx: usize) -> Result<()>
pub fn delete_row(&mut self, sheet_idx: usize, row_idx: usize) -> Result<()>
Delete row at 0-based index.
References to the deleted row become #REF! and references below it
move up, as in Excel.
Sourcepub fn insert_col(&mut self, sheet_idx: usize, col_idx: usize) -> Result<()>
pub fn insert_col(&mut self, sheet_idx: usize, col_idx: usize) -> Result<()>
Insert column at 0-based index.
Sourcepub fn delete_col(&mut self, sheet_idx: usize, col_idx: usize) -> Result<()>
pub fn delete_col(&mut self, sheet_idx: usize, col_idx: usize) -> Result<()>
Delete column at 0-based index.
Sourcepub fn insert_cells_shift_down(
&mut self,
sheet_idx: usize,
row: usize,
first_col: usize,
last_col: usize,
count: usize,
) -> Result<()>
pub fn insert_cells_shift_down( &mut self, sheet_idx: usize, row: usize, first_col: usize, last_col: usize, count: usize, ) -> Result<()>
Excel’s Insert cells, shift down over an inclusive column band, with the workbook-wide formula rewrite that goes with it.
This is what ListRows.Add is: only first_col..=last_col move, so a
formula beside the band stays put while one inside it shifts. See
core::grid_edit’s band field for the reference rules, which are
measured rather than assumed.
Sourcepub fn delete_cells_shift_up(
&mut self,
sheet_idx: usize,
row: usize,
first_col: usize,
last_col: usize,
count: usize,
) -> Result<()>
pub fn delete_cells_shift_up( &mut self, sheet_idx: usize, row: usize, first_col: usize, last_col: usize, count: usize, ) -> Result<()>
Excel’s Delete cells, shift up over an inclusive column band; the
inverse of WorkbookManager::insert_cells_shift_down.
Sourcepub fn delete_sheet(&mut self, name: &str) -> Result<()>
pub fn delete_sheet(&mut self, name: &str) -> Result<()>
Delete sheet by name
Sourcepub fn add_chart(
&mut self,
sheet_name: &str,
chart_type: ChartType,
range: String,
title: Option<String>,
anchor: Option<(usize, usize)>,
) -> Result<u64>
pub fn add_chart( &mut self, sheet_name: &str, chart_type: ChartType, range: String, title: Option<String>, anchor: Option<(usize, usize)>, ) -> Result<u64>
Add chart to workbook
Sourcepub fn edit_chart(
&mut self,
id: u64,
name: Option<String>,
chart_type: Option<ChartType>,
data_range: Option<String>,
title: Option<Option<String>>,
xlabel: Option<Option<String>>,
ylabel: Option<Option<String>>,
show_legend: Option<bool>,
anchor: Option<(usize, usize)>,
) -> Result<()>
pub fn edit_chart( &mut self, id: u64, name: Option<String>, chart_type: Option<ChartType>, data_range: Option<String>, title: Option<Option<String>>, xlabel: Option<Option<String>>, ylabel: Option<Option<String>>, show_legend: Option<bool>, anchor: Option<(usize, usize)>, ) -> Result<()>
Edit an existing chart’s properties. Every parameter is optional;
None leaves that field unchanged. title/xlabel/ylabel are
tri-state (Option<Option<String>>): outer None leaves the field
unchanged, Some(None) clears it, Some(Some(text)) sets it.
Sourcepub fn has_vba_project(&self) -> bool
pub fn has_vba_project(&self) -> bool
Whether the workbook carries a VBA project.
Sourcepub fn list_vba_modules(&self) -> Vec<&VbaModule>
pub fn list_vba_modules(&self) -> Vec<&VbaModule>
Lists every module in the workbook’s VBA project, if it has one.
Sourcepub fn ensure_vba_project(&mut self) -> Result<()>
pub fn ensure_vba_project(&mut self) -> Result<()>
Creates an empty, entirely synthetic VBA project (see
VbaProject::new_empty) if this workbook doesn’t already have one.
Idempotent.
Sourcepub fn add_vba_module(
&mut self,
name: String,
kind: VbaModuleKind,
source: String,
bound_sheet_id: Option<u64>,
) -> Result<()>
pub fn add_vba_module( &mut self, name: String, kind: VbaModuleKind, source: String, bound_sheet_id: Option<u64>, ) -> Result<()>
Adds a new module to the workbook’s VBA project (creating the
project from the bundled template first, if needed). bound_sheet_id
is required for VbaModuleKind::Document (except when name is
"ThisWorkbook", which – like real Excel’s own always-present
ThisWorkbook module – isn’t tied to a specific sheet; any
bound_sheet_id passed alongside it is ignored rather than stored)
– note this does NOT rename the sheet, or vice versa; Excel allows a
document module’s own name and its sheet’s display name to diverge,
and this codebase deliberately doesn’t cascade one into the other.
Sourcepub fn remove_vba_module(&mut self, name: &str) -> Result<()>
pub fn remove_vba_module(&mut self, name: &str) -> Result<()>
Removes a VBA module by name, matched case-insensitively.
§Errors
Error::Vba if the workbook has no VBA project, or
Error::NotFound if it has no module by that name.
Sourcepub fn rename_vba_module(
&mut self,
old_name: &str,
new_name: &str,
) -> Result<()>
pub fn rename_vba_module( &mut self, old_name: &str, new_name: &str, ) -> Result<()>
Renames a VBA module.
Renames only the module; VBA source that calls into it is not rewritten, so a module referenced by name elsewhere will no longer resolve.
§Errors
Error::InvalidName if new_name is not a valid VBA identifier,
Error::AlreadyExists if another module already has it,
Error::Vba if the workbook has no VBA project, or
Error::NotFound if it has no module called old_name.
Sourcepub fn set_vba_module_source(
&mut self,
name: &str,
source: String,
) -> Result<()>
pub fn set_vba_module_source( &mut self, name: &str, source: String, ) -> Result<()>
Replaces a VBA module’s source text.
The caller supplies the whole module body, including its
Attribute VB_Name = "..." line, matching how real Excel-authored
module streams are shaped.
§Errors
Error::Vba if the workbook has no VBA project, or
Error::NotFound if it has no module by that name.
Sourcepub fn delete_chart(&mut self, id: u64) -> Result<()>
pub fn delete_chart(&mut self, id: u64) -> Result<()>
Delete chart by u64 ID
Sourcepub fn find_table(&self, name: &str) -> Option<(&Sheet, &ExcelTable)>
pub fn find_table(&self, name: &str) -> Option<(&Sheet, &ExcelTable)>
Find the sheet that owns the table with the given name, and the table itself. Table names are unique across the whole workbook.
Sourcepub fn list_tables(&self) -> Vec<(&str, &ExcelTable)>
pub fn list_tables(&self) -> Vec<(&str, &ExcelTable)>
List every table in the workbook, alongside the name of the sheet it lives on.
Sourcepub fn add_table(
&mut self,
sheet_name: Option<&str>,
name: &str,
start_row: usize,
start_col: usize,
end_row: usize,
end_col: usize,
has_header_row: bool,
has_totals_row: bool,
) -> Result<u64>
pub fn add_table( &mut self, sheet_name: Option<&str>, name: &str, start_row: usize, start_col: usize, end_row: usize, end_col: usize, has_header_row: bool, has_totals_row: bool, ) -> Result<u64>
Define a new Excel Table over an existing cell range on a sheet. Table names are unique across the entire workbook (not just the sheet), matching how Excel itself scopes structured-reference names.
Sourcepub fn delete_table(&mut self, name: &str) -> Result<()>
pub fn delete_table(&mut self, name: &str) -> Result<()>
Delete a table by name (leaves the underlying cell contents alone).
Sourcepub fn resize_table(
&mut self,
name: &str,
new_end_row: usize,
new_end_col: usize,
) -> Result<()>
pub fn resize_table( &mut self, name: &str, new_end_row: usize, new_end_col: usize, ) -> Result<()>
Resize a table by moving its bottom-right corner.
Sourcepub fn rename_table_column(
&mut self,
table_name: &str,
col_index: usize,
new_name: &str,
) -> Result<()>
pub fn rename_table_column( &mut self, table_name: &str, col_index: usize, new_name: &str, ) -> Result<()>
Rename one column (0-based, relative to the table) of a table.
Sourcepub fn find_pivot_table(&self, name: &str) -> Option<&PivotTable>
pub fn find_pivot_table(&self, name: &str) -> Option<&PivotTable>
Find a pivot table by name (case-insensitive).
Sourcepub fn list_pivot_tables(&self) -> &[PivotTable]
pub fn list_pivot_tables(&self) -> &[PivotTable]
List every pivot table in the workbook.
Sourcepub fn add_pivot_table_from_table(
&mut self,
name: &str,
source_table_name: &str,
dest_sheet_name: Option<&str>,
dest_row: usize,
dest_col: usize,
grand_totals_row: bool,
grand_totals_col: bool,
) -> Result<u64>
pub fn add_pivot_table_from_table( &mut self, name: &str, source_table_name: &str, dest_sheet_name: Option<&str>, dest_row: usize, dest_col: usize, grand_totals_row: bool, grand_totals_col: bool, ) -> Result<u64>
Defines a new pivot table sourced from an existing Excel Table, with no fields assigned yet – mirroring Excel inserting an empty PivotTable shell that fills in as fields are added to it.
Sourcepub fn add_pivot_table_from_range(
&mut self,
name: &str,
source_sheet_name: Option<&str>,
start_row: usize,
start_col: usize,
end_row: usize,
end_col: usize,
dest_sheet_name: Option<&str>,
dest_row: usize,
dest_col: usize,
grand_totals_row: bool,
grand_totals_col: bool,
) -> Result<u64>
pub fn add_pivot_table_from_range( &mut self, name: &str, source_sheet_name: Option<&str>, start_row: usize, start_col: usize, end_row: usize, end_col: usize, dest_sheet_name: Option<&str>, dest_row: usize, dest_col: usize, grand_totals_row: bool, grand_totals_col: bool, ) -> Result<u64>
Defines a new pivot table sourced from a plain cell range (its first row is treated as column headers), with no fields assigned yet.
Sourcepub fn delete_pivot_table(&mut self, name: &str) -> Result<()>
pub fn delete_pivot_table(&mut self, name: &str) -> Result<()>
Deletes a pivot table definition and clears its last rendered output range (leaves the source data untouched).
Sourcepub fn rename_pivot_table(
&mut self,
old_name: &str,
new_name: &str,
) -> Result<()>
pub fn rename_pivot_table( &mut self, old_name: &str, new_name: &str, ) -> Result<()>
Renames a pivot table (names are unique workbook-wide, like tables).
Sourcepub fn add_pivot_field(
&mut self,
pivot_name: &str,
area: PivotArea,
column: &str,
aggregation: Option<PivotAggregation>,
) -> Result<()>
pub fn add_pivot_field( &mut self, pivot_name: &str, area: PivotArea, column: &str, aggregation: Option<PivotAggregation>, ) -> Result<()>
Adds a field to one of a pivot table’s four areas (Row/Column/ Value/Filter) and immediately refreshes its output, mirroring Excel’s live-updating field list.
A field can only occupy one area at a time, exactly like dragging a
field to a new area in Excel’s field list moves it rather than
duplicating it (confirmed via the win32com driver: setting
PivotField.Orientation a second time relocates the field). Value
fields are the one exception – Excel allows the same source column
to appear as multiple value fields simultaneously (e.g. both “Sum of
Amount” and “Min of Amount”), so adding to PivotArea::Value does
not evict the column from Row/Column/Filter, and vice versa a
Row/Column/Filter add does not evict existing value fields.
Sourcepub fn remove_pivot_field(
&mut self,
pivot_name: &str,
area: PivotArea,
column: &str,
) -> Result<()>
pub fn remove_pivot_field( &mut self, pivot_name: &str, area: PivotArea, column: &str, ) -> Result<()>
Removes a field from one of a pivot table’s four areas and refreshes its output.
Sourcepub fn set_pivot_filter(
&mut self,
pivot_name: &str,
column: &str,
values: Option<Vec<String>>,
) -> Result<()>
pub fn set_pivot_filter( &mut self, pivot_name: &str, column: &str, values: Option<Vec<String>>, ) -> Result<()>
Restricts (or clears, with values: None) a filter field’s allowed
values and refreshes the pivot table’s output.
Sourcepub fn refresh_pivot_table(&mut self, pivot_name: &str) -> Result<()>
pub fn refresh_pivot_table(&mut self, pivot_name: &str) -> Result<()>
Recomputes a pivot table’s aggregation and re-materializes it as plain values onto its destination sheet. Like Excel, a pivot table only updates on an explicit refresh, never automatically as its source data changes.