pub struct CalculationSnapshot { /* private fields */ }Expand description
Immutable formula results, separate from source literals and saved XLSX values.
Implementations§
Source§impl CalculationSnapshot
impl CalculationSnapshot
Sourcepub fn cell(&self, cell: CalculationCellId) -> Option<&CalculationCellResult>
pub fn cell(&self, cell: CalculationCellId) -> Option<&CalculationCellResult>
Returns one calculated formula result.
Examples found in repository?
examples/select_calculation_modes.rs (line 74)
73fn render(calculation: &CalculationSnapshot, cell: CalculationCellId) -> String {
74 match calculation.cell(cell) {
75 Some(CalculationCellResult::Value(CellValue::Number(number))) => {
76 render_number(number.get())
77 }
78 Some(CalculationCellResult::Value(CellValue::Logical(logical))) => logical.to_string(),
79 Some(CalculationCellResult::Value(CellValue::Error(error))) => error.as_str().to_owned(),
80 Some(CalculationCellResult::Unavailable(issue)) => {
81 format!("unavailable: {}", issue.code().as_str())
82 }
83 // `CellValue` and `CalculationCellResult` are `#[non_exhaustive]`, so a wildcard arm is
84 // required even when every variant this example can produce is handled above.
85 Some(_) => "<other value>".to_owned(),
86 None => "<not calculated>".to_owned(),
87 }
88}More examples
examples/compare_saved_vs_calculated.rs (line 27)
11fn main() -> Result<(), Box<dyn Error>> {
12 let bytes = support::minimal_workbook_bytes();
13 let workbook = read_xlsx_bytes(&bytes, ReadOptions::default())?;
14 let sheet = workbook.sheet_by_name("Sheet1").expect("Sheet1 exists");
15
16 let address = CellAddress::from_a1("B1")?;
17 let CellContent::Formula(formula) = sheet.cell(address).expect("B1 exists").content() else {
18 return Err("B1 must contain a formula".into());
19 };
20 println!(
21 "saved result, straight from the file, untouched by calculation: {:?}",
22 formula.saved_result()
23 );
24
25 let calculation = calculate_workbook(&workbook, CalculationOptions::default());
26 let cell_id = CalculationCellId::new(sheet.id(), address);
27 let result = calculation.cell(cell_id).expect("B1 was calculated");
28 println!("calculated result, a separate owned snapshot: {result:?}");
29
30 let SavedResult::Present(saved_value) = formula.saved_result() else {
31 return Err("this example's fixture always saves a value".into());
32 };
33 let CalculationCellResult::Value(calculated_value) = result else {
34 return Err("this example's fixture always calculates successfully".into());
35 };
36 assert_eq!(
37 saved_value, calculated_value,
38 "the producer's saved SUM should agree with CellRune's calculation"
39 );
40 println!("saved and calculated results agree; reading never rewrote the saved result");
41
42 Ok(())
43}Sourcepub fn cells(
&self,
) -> impl ExactSizeIterator<Item = (CalculationCellId, &CalculationCellResult)>
pub fn cells( &self, ) -> impl ExactSizeIterator<Item = (CalculationCellId, &CalculationCellResult)>
Iterates formula results in sheet-ID and row-major address order.
Examples found in repository?
examples/read_and_calculate.rs (line 115)
18fn main() -> Result<(), Box<dyn Error>> {
19 let Some(path) = std::env::args_os().nth(1) else {
20 eprintln!("{USAGE}");
21 return Ok(());
22 };
23
24 let workbook = read_xlsx_path(path, ReadOptions::default())?;
25 println!(
26 "read {} sheets and {} compatibility diagnostics",
27 workbook.sheets().len(),
28 workbook.diagnostics().len()
29 );
30 for diagnostic in workbook.diagnostics() {
31 eprintln!(
32 "[{:?}] {}: {}",
33 diagnostic.severity(),
34 diagnostic.code().as_str(),
35 diagnostic.message()
36 );
37 }
38
39 let second_argument = std::env::args_os().nth(2);
40 if second_argument.as_deref() == Some(std::ffi::OsStr::new(READ_ONLY)) {
41 return Ok(());
42 }
43
44 let limits = match std::env::var(MAX_DEPENDENCY_EDGES_ENV) {
45 Ok(value) => {
46 CalculationLimits::default().with_max_dependency_edges(value.parse::<u64>()?)?
47 }
48 Err(std::env::VarError::NotPresent) => CalculationLimits::default(),
49 Err(error) => return Err(error.into()),
50 };
51 let options = CalculationOptions::default().with_limits(limits);
52 if second_argument.as_deref() == Some(std::ffi::OsStr::new(SCAN_ONLY)) {
53 let capabilities = scan_formula_capabilities_with_options(&workbook, options);
54 println!(
55 "formula capability inventory: {} supported, {} unsupported",
56 capabilities.supported_count(),
57 capabilities.unsupported_count()
58 );
59 let mut issue_counts =
60 BTreeMap::<(cellrune::CalculationIssueCode, Option<String>), usize>::new();
61 let mut issue_samples =
62 BTreeMap::<(cellrune::CalculationIssueCode, Option<String>), Vec<String>>::new();
63 for entry in capabilities.entries() {
64 let FormulaCapability::Unsupported(issues) = entry.capability() else {
65 continue;
66 };
67 let sheet_name = workbook
68 .sheet_by_id(entry.cell().sheet_id())
69 .map_or("<unknown>", |sheet| sheet.name().as_str());
70 for issue in issues {
71 let key = (issue.code(), issue.detail().map(str::to_owned));
72 *issue_counts.entry(key.clone()).or_default() += 1;
73 let samples = issue_samples.entry(key).or_default();
74 if samples.len() < MAX_SAMPLES_PER_ISSUE {
75 let formula = workbook
76 .sheet_by_id(entry.cell().sheet_id())
77 .and_then(|sheet| sheet.cell(entry.cell().address()))
78 .and_then(|cell| match cell.content() {
79 CellContent::Formula(formula) => formula.text(),
80 CellContent::Literal(_) => None,
81 })
82 .map_or("<missing formula text>".to_owned(), |formula| {
83 truncate_formula(formula.as_str())
84 });
85 samples.push(format!(
86 "{sheet_name}!{}: ={formula}",
87 entry.cell().address()
88 ));
89 }
90 }
91 }
92 for (key @ (code, detail), count) in &issue_counts {
93 let rendered_detail = detail
94 .as_deref()
95 .map_or(String::new(), |detail| format!(" ({detail})"));
96 eprintln!("{count:>8} {}{rendered_detail}", code.as_str());
97 if let Some(samples) = issue_samples.get(key) {
98 for sample in samples {
99 eprintln!(" {sample}");
100 }
101 }
102 }
103 return Ok(());
104 }
105
106 let options = match second_argument {
107 Some(serial) => {
108 let serial = serial.to_string_lossy().parse::<f64>()?;
109 options.with_today_serial(FiniteNumber::new(serial)?)
110 }
111 None => options,
112 };
113 let calculation = calculate_workbook(&workbook, options);
114 let mut issue_counts = BTreeMap::<cellrune::CalculationIssueCode, usize>::new();
115 for (_, result) in calculation.cells() {
116 if let CalculationCellResult::Unavailable(issue) = result {
117 *issue_counts.entry(issue.code()).or_default() += 1;
118 }
119 }
120 let unavailable = issue_counts.values().sum::<usize>();
121 println!(
122 "calculated {} formula cells; {} unavailable",
123 calculation.len(),
124 unavailable
125 );
126 for (code, count) in issue_counts {
127 eprintln!("{count:>8} {}", code.as_str());
128 }
129
130 Ok(())
131}Sourcepub fn materialized_cell(
&self,
cell: CalculationCellId,
) -> Option<&MaterializedCalculationCell>
pub fn materialized_cell( &self, cell: CalculationCellId, ) -> Option<&MaterializedCalculationCell>
Returns one result from the complete formula and array materialization view.
Sourcepub fn materialized_cells(
&self,
) -> impl ExactSizeIterator<Item = (CalculationCellId, &MaterializedCalculationCell)>
pub fn materialized_cells( &self, ) -> impl ExactSizeIterator<Item = (CalculationCellId, &MaterializedCalculationCell)>
Iterates the complete materialization view in sheet-ID and row-major address order.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of formula results.
Examples found in repository?
examples/read_and_calculate.rs (line 123)
18fn main() -> Result<(), Box<dyn Error>> {
19 let Some(path) = std::env::args_os().nth(1) else {
20 eprintln!("{USAGE}");
21 return Ok(());
22 };
23
24 let workbook = read_xlsx_path(path, ReadOptions::default())?;
25 println!(
26 "read {} sheets and {} compatibility diagnostics",
27 workbook.sheets().len(),
28 workbook.diagnostics().len()
29 );
30 for diagnostic in workbook.diagnostics() {
31 eprintln!(
32 "[{:?}] {}: {}",
33 diagnostic.severity(),
34 diagnostic.code().as_str(),
35 diagnostic.message()
36 );
37 }
38
39 let second_argument = std::env::args_os().nth(2);
40 if second_argument.as_deref() == Some(std::ffi::OsStr::new(READ_ONLY)) {
41 return Ok(());
42 }
43
44 let limits = match std::env::var(MAX_DEPENDENCY_EDGES_ENV) {
45 Ok(value) => {
46 CalculationLimits::default().with_max_dependency_edges(value.parse::<u64>()?)?
47 }
48 Err(std::env::VarError::NotPresent) => CalculationLimits::default(),
49 Err(error) => return Err(error.into()),
50 };
51 let options = CalculationOptions::default().with_limits(limits);
52 if second_argument.as_deref() == Some(std::ffi::OsStr::new(SCAN_ONLY)) {
53 let capabilities = scan_formula_capabilities_with_options(&workbook, options);
54 println!(
55 "formula capability inventory: {} supported, {} unsupported",
56 capabilities.supported_count(),
57 capabilities.unsupported_count()
58 );
59 let mut issue_counts =
60 BTreeMap::<(cellrune::CalculationIssueCode, Option<String>), usize>::new();
61 let mut issue_samples =
62 BTreeMap::<(cellrune::CalculationIssueCode, Option<String>), Vec<String>>::new();
63 for entry in capabilities.entries() {
64 let FormulaCapability::Unsupported(issues) = entry.capability() else {
65 continue;
66 };
67 let sheet_name = workbook
68 .sheet_by_id(entry.cell().sheet_id())
69 .map_or("<unknown>", |sheet| sheet.name().as_str());
70 for issue in issues {
71 let key = (issue.code(), issue.detail().map(str::to_owned));
72 *issue_counts.entry(key.clone()).or_default() += 1;
73 let samples = issue_samples.entry(key).or_default();
74 if samples.len() < MAX_SAMPLES_PER_ISSUE {
75 let formula = workbook
76 .sheet_by_id(entry.cell().sheet_id())
77 .and_then(|sheet| sheet.cell(entry.cell().address()))
78 .and_then(|cell| match cell.content() {
79 CellContent::Formula(formula) => formula.text(),
80 CellContent::Literal(_) => None,
81 })
82 .map_or("<missing formula text>".to_owned(), |formula| {
83 truncate_formula(formula.as_str())
84 });
85 samples.push(format!(
86 "{sheet_name}!{}: ={formula}",
87 entry.cell().address()
88 ));
89 }
90 }
91 }
92 for (key @ (code, detail), count) in &issue_counts {
93 let rendered_detail = detail
94 .as_deref()
95 .map_or(String::new(), |detail| format!(" ({detail})"));
96 eprintln!("{count:>8} {}{rendered_detail}", code.as_str());
97 if let Some(samples) = issue_samples.get(key) {
98 for sample in samples {
99 eprintln!(" {sample}");
100 }
101 }
102 }
103 return Ok(());
104 }
105
106 let options = match second_argument {
107 Some(serial) => {
108 let serial = serial.to_string_lossy().parse::<f64>()?;
109 options.with_today_serial(FiniteNumber::new(serial)?)
110 }
111 None => options,
112 };
113 let calculation = calculate_workbook(&workbook, options);
114 let mut issue_counts = BTreeMap::<cellrune::CalculationIssueCode, usize>::new();
115 for (_, result) in calculation.cells() {
116 if let CalculationCellResult::Unavailable(issue) = result {
117 *issue_counts.entry(issue.code()).or_default() += 1;
118 }
119 }
120 let unavailable = issue_counts.values().sum::<usize>();
121 println!(
122 "calculated {} formula cells; {} unavailable",
123 calculation.len(),
124 unavailable
125 );
126 for (code, count) in issue_counts {
127 eprintln!("{count:>8} {}", code.as_str());
128 }
129
130 Ok(())
131}Sourcepub const fn options(&self) -> CalculationOptions
pub const fn options(&self) -> CalculationOptions
Returns the deterministic policy inputs used for this calculation.
Sourcepub const fn provenance(&self) -> &Provenance
pub const fn provenance(&self) -> &Provenance
Returns deterministic calculation provenance.
Sourcepub const fn source_revision(&self) -> u64
pub const fn source_revision(&self) -> u64
Returns the workbook semantic revision used to produce this result.
Sourcepub const fn source_fingerprint(&self) -> WorkbookFingerprint
pub const fn source_fingerprint(&self) -> WorkbookFingerprint
Returns the versioned semantic fingerprint of the source workbook.
Trait Implementations§
Source§impl Clone for CalculationSnapshot
impl Clone for CalculationSnapshot
Source§fn clone(&self) -> CalculationSnapshot
fn clone(&self) -> CalculationSnapshot
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for CalculationSnapshot
impl RefUnwindSafe for CalculationSnapshot
impl Send for CalculationSnapshot
impl Sync for CalculationSnapshot
impl Unpin for CalculationSnapshot
impl UnsafeUnpin for CalculationSnapshot
impl UnwindSafe for CalculationSnapshot
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more