Skip to main content

visi_core/core/
formula.rs

1use crate::core::RefType;
2use serde::{Deserialize, Serialize};
3
4/// Which part of an Excel Table a structured reference selects, as in
5/// `Sales[#Headers]`.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7pub enum SheetSection {
8    /// The body rows, excluding header and totals (default)
9    Data,
10    /// The header row.
11    Headers,
12    /// The totals row.
13    Totals,
14    /// Header, data and totals together.
15    All,
16}
17
18/// One piece of a compiled formula
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20pub enum FormulaPart {
21    /// A literal stretch of the formula -- operators, function names,
22    /// constants -- copied through unchanged.
23    Text(String),
24    /// A single cell, as in `Sheet2!$A1`.
25    SheetReference {
26        /// Sheet the cell is on.
27        sheet_id: u64,
28        /// Row, 0-based.
29        row: usize,
30        /// Column, 0-based.
31        col: usize,
32        /// Whether the row was written with a `$`.
33        row_ref_type: RefType,
34        /// Whether the column was written with a `$`.
35        col_ref_type: RefType,
36    },
37    /// A whole column, held by column id so a column rename survives.
38    ColumnReference {
39        /// Sheet the column is on.
40        sheet_id: u64,
41        /// The column's identifier, not its position.
42        col_id: u64,
43    },
44    /// An Excel Table structured reference, as in `Sales[Amount]` or
45    /// `[@Amount]`.
46    StructuredReference {
47        /// Sheet the reference resolves against.
48        sheet_id: u64,
49        /// The referenced column, or `None` for a whole-table reference.
50        col_id: Option<u64>,
51        /// `true` for the `[@Amount]` form, which means the current row.
52        is_this_row: bool,
53        /// Which part of the table is selected.
54        section: SheetSection,
55    },
56    /// A rectangular range, as in `Sheet2!A1:$B$10`.
57    RangeReference {
58        /// Sheet the range is on.
59        sheet_id: u64,
60        /// First row, 0-based.
61        start_row: usize,
62        /// First column, 0-based.
63        start_col: usize,
64        /// Last row, 0-based and inclusive.
65        end_row: usize,
66        /// Last column, 0-based and inclusive.
67        end_col: usize,
68        /// Whether the start row was written with a `$`.
69        start_row_ref_type: RefType,
70        /// Whether the start column was written with a `$`.
71        start_col_ref_type: RefType,
72        /// Whether the end row was written with a `$`.
73        end_row_ref_type: RefType,
74        /// Whether the end column was written with a `$`.
75        end_col_ref_type: RefType,
76    },
77}
78
79/// A formula split into literal text and id-held references
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81pub struct CompiledFormula {
82    /// The pieces, in the order they appear in the formula text.
83    pub parts: Vec<FormulaPart>,
84}
85
86impl CompiledFormula {
87    /// Creates a plain formula from a raw string, without any parsed references.
88    pub fn plain(text: String) -> Self {
89        Self {
90            parts: vec![FormulaPart::Text(text)],
91        }
92    }
93}
94
95impl Default for CompiledFormula {
96    fn default() -> Self {
97        Self::plain(String::new())
98    }
99}