Error Handling of public Set functions (#88)

What are we trying to achieve ?

++ Currently all the major public set functions is panic prone and does not handle and return error. This PR tries to address to all those functions.

What major errors that could happen in these functions ?

++ All the functions which are being made as error safe is being tested against invalid sheet, row and column values, which could given by user

What are the list of functions whose return type has been altered ?

**base/src/model.rs**
1. update_cell_with_text
2. update_cell_with_bool
3. update_cell_with_number
4. set_user_input
5. get_cell_style_index
6. get_style_for_cell
7. set_cell_with_string

++> New functions being added

1. set_cell_with_boolean
2. set_cell_with_number

**base/src/styles.rs**

1. get_style_with_quote_prefix
3. get_style_with_format
4. get_style_without_quote_prefix
5. get_style

**base/src/worksheet.rs**

1. update_cell
2. set_cell_style
3. set_cell_with_formula
4. set_cell_with_number
6. set_cell_with_string
8. set_cell_with_boolean
9. set_cell_with_error
10. cell_clear_contents
11. cell_clear_contents_with_style

++> Above is the comprehensive list of all functions being ( most are public, some are private ) altered for better error handling. As a side effect of changing function signature, there are many changes being done to other functions ( mostly adding "?" to enable to error propagation further )
This commit is contained in:
Varun Hegde
2024-09-14 21:07:31 +05:30
committed by GitHub
parent 83a4431417
commit 2b03b3e3b9
26 changed files with 1087 additions and 362 deletions

View File

@@ -3,15 +3,15 @@ use ironcalc_base::{types::CellType, Model};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut model = Model::new_empty("formulas-and-errors", "en", "UTC")?; let mut model = Model::new_empty("formulas-and-errors", "en", "UTC")?;
// A1 // A1
model.set_user_input(0, 1, 1, "1".to_string()); model.set_user_input(0, 1, 1, "1".to_string())?;
// A2 // A2
model.set_user_input(0, 2, 1, "2".to_string()); model.set_user_input(0, 2, 1, "2".to_string())?;
// A3 // A3
model.set_user_input(0, 3, 1, "3".to_string()); model.set_user_input(0, 3, 1, "3".to_string())?;
// B1 // B1
model.set_user_input(0, 1, 2, "=SUM(A1:A3)".to_string()); model.set_user_input(0, 1, 2, "=SUM(A1:A3)".to_string())?;
// B2 // B2
model.set_user_input(0, 2, 2, "=B1/0".to_string()); model.set_user_input(0, 2, 2, "=B1/0".to_string())?;
// Evaluate // Evaluate
model.evaluate(); model.evaluate();

View File

@@ -3,11 +3,11 @@ use ironcalc_base::{cell::CellValue, Model};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut model = Model::new_empty("hello-world", "en", "UTC")?; let mut model = Model::new_empty("hello-world", "en", "UTC")?;
// A1 // A1
model.set_user_input(0, 1, 1, "Hello".to_string()); model.set_user_input(0, 1, 1, "Hello".to_string())?;
// B1 // B1
model.set_user_input(0, 1, 2, "world!".to_string()); model.set_user_input(0, 1, 2, "world!".to_string())?;
// C1 // C1
model.set_user_input(0, 1, 3, "=CONCAT(A1, \" \", B1".to_string()); model.set_user_input(0, 1, 3, "=CONCAT(A1, \" \", B1".to_string())?;
// evaluates // evaluates
model.evaluate(); model.evaluate();

View File

@@ -79,12 +79,11 @@ impl Model {
let formula_or_value = self let formula_or_value = self
.get_cell_formula(sheet, source_row, source_column)? .get_cell_formula(sheet, source_row, source_column)?
.unwrap_or_else(|| source_cell.get_text(&self.workbook.shared_strings, &self.language)); .unwrap_or_else(|| source_cell.get_text(&self.workbook.shared_strings, &self.language));
self.set_user_input(sheet, target_row, target_column, formula_or_value); self.set_user_input(sheet, target_row, target_column, formula_or_value)?;
self.workbook self.workbook
.worksheet_mut(sheet)? .worksheet_mut(sheet)?
.set_cell_style(target_row, target_column, style); .set_cell_style(target_row, target_column, style)?;
self.cell_clear_all(sheet, source_row, source_column)?; self.cell_clear_all(sheet, source_row, source_column)
Ok(())
} }
/// Inserts one or more new columns into the model at the specified index. /// Inserts one or more new columns into the model at the specified index.

View File

@@ -7,19 +7,15 @@ use crate::{
calc_result::{CalcResult, Range}, calc_result::{CalcResult, Range},
cell::CellValue, cell::CellValue,
constants::{self, LAST_COLUMN, LAST_ROW}, constants::{self, LAST_COLUMN, LAST_ROW},
expressions::token::{Error, OpCompare, OpProduct, OpSum, OpUnary},
expressions::{
parser::move_formula::{move_formula, MoveContext},
token::get_error_by_name,
types::*,
utils::{self, is_valid_row},
},
expressions::{ expressions::{
parser::{ parser::{
move_formula::{move_formula, MoveContext},
stringify::{to_rc_format, to_string}, stringify::{to_rc_format, to_string},
Node, Parser, Node, Parser,
}, },
utils::is_valid_column_number, token::{get_error_by_name, Error, OpCompare, OpProduct, OpSum, OpUnary},
types::*,
utils::{self, is_valid_column_number, is_valid_row},
}, },
formatter::{ formatter::{
format::{format_number, parse_formatted_number}, format::{format_number, parse_formatted_number},
@@ -1204,10 +1200,10 @@ impl Model {
/// # fn main() -> Result<(), Box<dyn std::error::Error>> { /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut model = Model::new_empty("model", "en", "UTC")?; /// let mut model = Model::new_empty("model", "en", "UTC")?;
/// let (sheet, row, column) = (0, 1, 1); /// let (sheet, row, column) = (0, 1, 1);
/// model.set_user_input(sheet, row, column, "Hello!".to_string()); /// model.set_user_input(sheet, row, column, "Hello!".to_string())?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "Hello!".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "Hello!".to_string());
/// ///
/// model.update_cell_with_text(sheet, row, column, "Goodbye!"); /// model.update_cell_with_text(sheet, row, column, "Goodbye!")?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "Goodbye!".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "Goodbye!".to_string());
/// # Ok(()) /// # Ok(())
/// # } /// # }
@@ -1218,23 +1214,30 @@ impl Model {
/// * [Model::update_cell_with_number()] /// * [Model::update_cell_with_number()]
/// * [Model::update_cell_with_bool()] /// * [Model::update_cell_with_bool()]
/// * [Model::update_cell_with_formula()] /// * [Model::update_cell_with_formula()]
pub fn update_cell_with_text(&mut self, sheet: u32, row: i32, column: i32, value: &str) { pub fn update_cell_with_text(
let style_index = self.get_cell_style_index(sheet, row, column); &mut self,
sheet: u32,
row: i32,
column: i32,
value: &str,
) -> Result<(), String> {
let style_index = self.get_cell_style_index(sheet, row, column)?;
let new_style_index; let new_style_index;
if common::value_needs_quoting(value, &self.language) { if common::value_needs_quoting(value, &self.language) {
new_style_index = self new_style_index = self
.workbook .workbook
.styles .styles
.get_style_with_quote_prefix(style_index); .get_style_with_quote_prefix(style_index)?;
} else if self.workbook.styles.style_is_quote_prefix(style_index) { } else if self.workbook.styles.style_is_quote_prefix(style_index) {
new_style_index = self new_style_index = self
.workbook .workbook
.styles .styles
.get_style_without_quote_prefix(style_index); .get_style_without_quote_prefix(style_index)?;
} else { } else {
new_style_index = style_index; new_style_index = style_index;
} }
self.set_cell_with_string(sheet, row, column, value, new_style_index);
self.set_cell_with_string(sheet, row, column, value, new_style_index)
} }
/// Updates the value of a cell with a boolean value /// Updates the value of a cell with a boolean value
@@ -1247,10 +1250,10 @@ impl Model {
/// # fn main() -> Result<(), Box<dyn std::error::Error>> { /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut model = Model::new_empty("model", "en", "UTC")?; /// let mut model = Model::new_empty("model", "en", "UTC")?;
/// let (sheet, row, column) = (0, 1, 1); /// let (sheet, row, column) = (0, 1, 1);
/// model.set_user_input(sheet, row, column, "TRUE".to_string()); /// model.set_user_input(sheet, row, column, "TRUE".to_string())?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "TRUE".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "TRUE".to_string());
/// ///
/// model.update_cell_with_bool(sheet, row, column, false); /// model.update_cell_with_bool(sheet, row, column, false)?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "FALSE".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "FALSE".to_string());
/// # Ok(()) /// # Ok(())
/// # } /// # }
@@ -1261,17 +1264,22 @@ impl Model {
/// * [Model::update_cell_with_number()] /// * [Model::update_cell_with_number()]
/// * [Model::update_cell_with_text()] /// * [Model::update_cell_with_text()]
/// * [Model::update_cell_with_formula()] /// * [Model::update_cell_with_formula()]
pub fn update_cell_with_bool(&mut self, sheet: u32, row: i32, column: i32, value: bool) { pub fn update_cell_with_bool(
let style_index = self.get_cell_style_index(sheet, row, column); &mut self,
sheet: u32,
row: i32,
column: i32,
value: bool,
) -> Result<(), String> {
let style_index = self.get_cell_style_index(sheet, row, column)?;
let new_style_index = if self.workbook.styles.style_is_quote_prefix(style_index) { let new_style_index = if self.workbook.styles.style_is_quote_prefix(style_index) {
self.workbook self.workbook
.styles .styles
.get_style_without_quote_prefix(style_index) .get_style_without_quote_prefix(style_index)?
} else { } else {
style_index style_index
}; };
let worksheet = &mut self.workbook.worksheets[sheet as usize]; self.set_cell_with_boolean(sheet, row, column, value, new_style_index)
worksheet.set_cell_with_boolean(row, column, value, new_style_index);
} }
/// Updates the value of a cell with a number /// Updates the value of a cell with a number
@@ -1284,10 +1292,10 @@ impl Model {
/// # fn main() -> Result<(), Box<dyn std::error::Error>> { /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut model = Model::new_empty("model", "en", "UTC")?; /// let mut model = Model::new_empty("model", "en", "UTC")?;
/// let (sheet, row, column) = (0, 1, 1); /// let (sheet, row, column) = (0, 1, 1);
/// model.set_user_input(sheet, row, column, "42".to_string()); /// model.set_user_input(sheet, row, column, "42".to_string())?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "42".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "42".to_string());
/// ///
/// model.update_cell_with_number(sheet, row, column, 23.0); /// model.update_cell_with_number(sheet, row, column, 23.0)?;
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "23".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "23".to_string());
/// # Ok(()) /// # Ok(())
/// # } /// # }
@@ -1298,17 +1306,22 @@ impl Model {
/// * [Model::update_cell_with_text()] /// * [Model::update_cell_with_text()]
/// * [Model::update_cell_with_bool()] /// * [Model::update_cell_with_bool()]
/// * [Model::update_cell_with_formula()] /// * [Model::update_cell_with_formula()]
pub fn update_cell_with_number(&mut self, sheet: u32, row: i32, column: i32, value: f64) { pub fn update_cell_with_number(
let style_index = self.get_cell_style_index(sheet, row, column); &mut self,
sheet: u32,
row: i32,
column: i32,
value: f64,
) -> Result<(), String> {
let style_index = self.get_cell_style_index(sheet, row, column)?;
let new_style_index = if self.workbook.styles.style_is_quote_prefix(style_index) { let new_style_index = if self.workbook.styles.style_is_quote_prefix(style_index) {
self.workbook self.workbook
.styles .styles
.get_style_without_quote_prefix(style_index) .get_style_without_quote_prefix(style_index)?
} else { } else {
style_index style_index
}; };
let worksheet = &mut self.workbook.worksheets[sheet as usize]; self.set_cell_with_number(sheet, row, column, value, new_style_index)
worksheet.set_cell_with_number(row, column, value, new_style_index);
} }
/// Updates the formula of given cell /// Updates the formula of given cell
@@ -1322,11 +1335,11 @@ impl Model {
/// # fn main() -> Result<(), Box<dyn std::error::Error>> { /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut model = Model::new_empty("model", "en", "UTC")?; /// let mut model = Model::new_empty("model", "en", "UTC")?;
/// let (sheet, row, column) = (0, 1, 1); /// let (sheet, row, column) = (0, 1, 1);
/// model.set_user_input(sheet, row, column, "=A2*2".to_string()); /// model.set_user_input(sheet, row, column, "=A2*2".to_string())?;
/// model.evaluate(); /// model.evaluate();
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "=A2*2".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "=A2*2".to_string());
/// ///
/// model.update_cell_with_formula(sheet, row, column, "=A3*2".to_string()); /// model.update_cell_with_formula(sheet, row, column, "=A3*2".to_string())?;
/// model.evaluate(); /// model.evaluate();
/// assert_eq!(model.get_cell_content(sheet, row, column)?, "=A3*2".to_string()); /// assert_eq!(model.get_cell_content(sheet, row, column)?, "=A3*2".to_string());
/// # Ok(()) /// # Ok(())
@@ -1345,12 +1358,12 @@ impl Model {
column: i32, column: i32,
formula: String, formula: String,
) -> Result<(), String> { ) -> Result<(), String> {
let mut style_index = self.get_cell_style_index(sheet, row, column); let mut style_index = self.get_cell_style_index(sheet, row, column)?;
if self.workbook.styles.style_is_quote_prefix(style_index) { if self.workbook.styles.style_is_quote_prefix(style_index) {
style_index = self style_index = self
.workbook .workbook
.styles .styles
.get_style_without_quote_prefix(style_index); .get_style_without_quote_prefix(style_index)?;
} }
let formula = formula let formula = formula
.strip_prefix('=') .strip_prefix('=')
@@ -1390,31 +1403,36 @@ impl Model {
/// * [Model::update_cell_with_number()] /// * [Model::update_cell_with_number()]
/// * [Model::update_cell_with_bool()] /// * [Model::update_cell_with_bool()]
/// * [Model::update_cell_with_text()] /// * [Model::update_cell_with_text()]
pub fn set_user_input(&mut self, sheet: u32, row: i32, column: i32, value: String) { pub fn set_user_input(
&mut self,
sheet: u32,
row: i32,
column: i32,
value: String,
) -> Result<(), String> {
// If value starts with "'" then we force the style to be quote_prefix // If value starts with "'" then we force the style to be quote_prefix
let style_index = self.get_cell_style_index(sheet, row, column); let style_index = self.get_cell_style_index(sheet, row, column)?;
if let Some(new_value) = value.strip_prefix('\'') { if let Some(new_value) = value.strip_prefix('\'') {
// First check if it needs quoting // First check if it needs quoting
let new_style = if common::value_needs_quoting(new_value, &self.language) { let new_style = if common::value_needs_quoting(new_value, &self.language) {
self.workbook self.workbook
.styles .styles
.get_style_with_quote_prefix(style_index) .get_style_with_quote_prefix(style_index)?
} else { } else {
style_index style_index
}; };
self.set_cell_with_string(sheet, row, column, new_value, new_style); self.set_cell_with_string(sheet, row, column, new_value, new_style)?;
} else { } else {
let mut new_style_index = style_index; let mut new_style_index = style_index;
if self.workbook.styles.style_is_quote_prefix(style_index) { if self.workbook.styles.style_is_quote_prefix(style_index) {
new_style_index = self new_style_index = self
.workbook .workbook
.styles .styles
.get_style_without_quote_prefix(style_index); .get_style_without_quote_prefix(style_index)?;
} }
if let Some(formula) = value.strip_prefix('=') { if let Some(formula) = value.strip_prefix('=') {
let formula_index = self let formula_index =
.set_cell_with_formula(sheet, row, column, formula, new_style_index) self.set_cell_with_formula(sheet, row, column, formula, new_style_index)?;
.expect("could not set the cell formula");
// Update the style if needed // Update the style if needed
let cell = CellReferenceIndex { sheet, row, column }; let cell = CellReferenceIndex { sheet, row, column };
let parsed_formula = &self.parsed_formulas[sheet as usize][formula_index as usize]; let parsed_formula = &self.parsed_formulas[sheet as usize][formula_index as usize];
@@ -1422,15 +1440,11 @@ impl Model {
let new_style_index = self let new_style_index = self
.workbook .workbook
.styles .styles
.get_style_with_format(new_style_index, &units.get_num_fmt()); .get_style_with_format(new_style_index, &units.get_num_fmt())?;
let style = self.workbook.styles.get_style(new_style_index); let style = self.workbook.styles.get_style(new_style_index)?;
self.set_cell_style(sheet, row, column, &style) self.set_cell_style(sheet, row, column, &style)?
.expect("Failed setting the style");
} }
} else { } else {
let worksheets = &mut self.workbook.worksheets;
let worksheet = &mut worksheets[sheet as usize];
// The list of currencies is '$', '€' and the local currency // The list of currencies is '$', '€' and the local currency
let mut currencies = vec!["$", ""]; let mut currencies = vec!["$", ""];
let currency = &self.locale.currency.symbol; let currency = &self.locale.currency.symbol;
@@ -1443,35 +1457,39 @@ impl Model {
// Should not apply the format in the following cases: // Should not apply the format in the following cases:
// - we assign a date to already date-formatted cell // - we assign a date to already date-formatted cell
let should_apply_format = !(is_likely_date_number_format( let should_apply_format = !(is_likely_date_number_format(
&self.workbook.styles.get_style(new_style_index).num_fmt, &self.workbook.styles.get_style(new_style_index)?.num_fmt,
) && is_likely_date_number_format(&num_fmt)); ) && is_likely_date_number_format(&num_fmt));
if should_apply_format { if should_apply_format {
new_style_index = self new_style_index = self
.workbook .workbook
.styles .styles
.get_style_with_format(new_style_index, &num_fmt); .get_style_with_format(new_style_index, &num_fmt)?;
} }
} }
worksheet.set_cell_with_number(row, column, v, new_style_index); let worksheet = self.workbook.worksheet_mut(sheet)?;
return; worksheet.set_cell_with_number(row, column, v, new_style_index)?;
return Ok(());
} }
// We try to parse as boolean // We try to parse as boolean
if let Ok(v) = value.to_lowercase().parse::<bool>() { if let Ok(v) = value.to_lowercase().parse::<bool>() {
worksheet.set_cell_with_boolean(row, column, v, new_style_index); let worksheet = self.workbook.worksheet_mut(sheet)?;
return; worksheet.set_cell_with_boolean(row, column, v, new_style_index)?;
return Ok(());
} }
// Check is it is error value // Check is it is error value
let upper = value.to_uppercase(); let upper = value.to_uppercase();
let worksheet = self.workbook.worksheet_mut(sheet)?;
match get_error_by_name(&upper, &self.language) { match get_error_by_name(&upper, &self.language) {
Some(error) => { Some(error) => {
worksheet.set_cell_with_error(row, column, error, new_style_index); worksheet.set_cell_with_error(row, column, error, new_style_index)?;
} }
None => { None => {
self.set_cell_with_string(sheet, row, column, &value, new_style_index); self.set_cell_with_string(sheet, row, column, &value, new_style_index)?;
} }
} }
} }
} }
Ok(())
} }
fn set_cell_with_formula( fn set_cell_with_formula(
@@ -1512,24 +1530,66 @@ impl Model {
self.parsed_formulas[sheet as usize].push(parsed_formula); self.parsed_formulas[sheet as usize].push(parsed_formula);
formula_index = (shared_formulas.len() as i32) - 1; formula_index = (shared_formulas.len() as i32) - 1;
} }
worksheet.set_cell_with_formula(row, column, formula_index, style); worksheet.set_cell_with_formula(row, column, formula_index, style)?;
Ok(formula_index) Ok(formula_index)
} }
fn set_cell_with_string(&mut self, sheet: u32, row: i32, column: i32, value: &str, style: i32) { fn set_cell_with_string(
let worksheets = &mut self.workbook.worksheets; &mut self,
let worksheet = &mut worksheets[sheet as usize]; sheet: u32,
row: i32,
column: i32,
value: &str,
style: i32,
) -> Result<(), String> {
match self.shared_strings.get(value) { match self.shared_strings.get(value) {
Some(string_index) => { Some(string_index) => {
worksheet.set_cell_with_string(row, column, *string_index as i32, style); self.workbook.worksheet_mut(sheet)?.set_cell_with_string(
row,
column,
*string_index as i32,
style,
)?;
} }
None => { None => {
let string_index = self.workbook.shared_strings.len(); let string_index = self.workbook.shared_strings.len();
self.workbook.shared_strings.push(value.to_string()); self.workbook.shared_strings.push(value.to_string());
self.shared_strings.insert(value.to_string(), string_index); self.shared_strings.insert(value.to_string(), string_index);
worksheet.set_cell_with_string(row, column, string_index as i32, style); self.workbook.worksheet_mut(sheet)?.set_cell_with_string(
row,
column,
string_index as i32,
style,
)?;
} }
} }
Ok(())
}
fn set_cell_with_boolean(
&mut self,
sheet: u32,
row: i32,
column: i32,
value: bool,
style: i32,
) -> Result<(), String> {
self.workbook
.worksheet_mut(sheet)?
.set_cell_with_boolean(row, column, value, style)
}
fn set_cell_with_number(
&mut self,
sheet: u32,
row: i32,
column: i32,
value: f64,
style: i32,
) -> Result<(), String> {
self.workbook
.worksheet_mut(sheet)?
.set_cell_with_number(row, column, value, style)
} }
/// Gets the Excel Value (Bool, Number, String) of a cell /// Gets the Excel Value (Bool, Number, String) of a cell
@@ -1596,7 +1656,7 @@ impl Model {
) -> Result<String, String> { ) -> Result<String, String> {
match self.workbook.worksheet(sheet_index)?.cell(row, column) { match self.workbook.worksheet(sheet_index)?.cell(row, column) {
Some(cell) => { Some(cell) => {
let format = self.get_style_for_cell(sheet_index, row, column).num_fmt; let format = self.get_style_for_cell(sheet_index, row, column)?.num_fmt;
let formatted_value = let formatted_value =
cell.formatted_value(&self.workbook.shared_strings, &self.language, |value| { cell.formatted_value(&self.workbook.shared_strings, &self.language, |value| {
format_number(value, &format, &self.locale).text format_number(value, &format, &self.locale).text
@@ -1699,7 +1759,7 @@ impl Model {
pub fn cell_clear_contents(&mut self, sheet: u32, row: i32, column: i32) -> Result<(), String> { pub fn cell_clear_contents(&mut self, sheet: u32, row: i32, column: i32) -> Result<(), String> {
self.workbook self.workbook
.worksheet_mut(sheet)? .worksheet_mut(sheet)?
.cell_clear_contents(row, column); .cell_clear_contents(row, column)?;
Ok(()) Ok(())
} }
@@ -1734,43 +1794,40 @@ impl Model {
} }
/// Returns the style index for cell (`sheet`, `row`, `column`) /// Returns the style index for cell (`sheet`, `row`, `column`)
pub fn get_cell_style_index(&self, sheet: u32, row: i32, column: i32) -> i32 { pub fn get_cell_style_index(&self, sheet: u32, row: i32, column: i32) -> Result<i32, String> {
// First check the cell, then row, the column // First check the cell, then row, the column
let cell = self let cell = self.workbook.worksheet(sheet)?.cell(row, column);
.workbook
.worksheet(sheet)
.expect("Invalid sheet")
.cell(row, column);
match cell { match cell {
Some(cell) => cell.get_style(), Some(cell) => Ok(cell.get_style()),
None => { None => {
let rows = &self.workbook.worksheets[sheet as usize].rows; let rows = &self.workbook.worksheet(sheet)?.rows;
for r in rows { for r in rows {
if r.r == row { if r.r == row {
if r.custom_format { if r.custom_format {
return r.s; return Ok(r.s);
} }
break; break;
} }
} }
let cols = &self.workbook.worksheets[sheet as usize].cols; let cols = &self.workbook.worksheet(sheet)?.cols;
for c in cols.iter() { for c in cols.iter() {
let min = c.min; let min = c.min;
let max = c.max; let max = c.max;
if column >= min && column <= max { if column >= min && column <= max {
return c.style.unwrap_or(0); return Ok(c.style.unwrap_or(0));
} }
} }
0 Ok(0)
} }
} }
} }
/// Returns the style for cell (`sheet`, `row`, `column`) /// Returns the style for cell (`sheet`, `row`, `column`)
pub fn get_style_for_cell(&self, sheet: u32, row: i32, column: i32) -> Style { pub fn get_style_for_cell(&self, sheet: u32, row: i32, column: i32) -> Result<Style, String> {
self.workbook let style_index = self.get_cell_style_index(sheet, row, column)?;
.styles let style = self.workbook.styles.get_style(style_index)?;
.get_style(self.get_cell_style_index(sheet, row, column)) Ok(style)
} }
/// Returns an internal binary representation of the workbook /// Returns an internal binary representation of the workbook
@@ -1810,7 +1867,7 @@ impl Model {
Some(formula) => formula, Some(formula) => formula,
None => self.get_formatted_cell_value(sheet, row, column)?, None => self.get_formatted_cell_value(sheet, row, column)?,
}; };
let style = self.get_style_for_cell(sheet, row, column); let style = self.get_style_for_cell(sheet, row, column)?;
if style.font.b { if style.font.b {
cell_markup = format!("**{cell_markup}**") cell_markup = format!("**{cell_markup}**")
} }

View File

@@ -161,26 +161,29 @@ impl Styles {
pub fn create_named_style(&mut self, style_name: &str, style: &Style) -> Result<(), String> { pub fn create_named_style(&mut self, style_name: &str, style: &Style) -> Result<(), String> {
let style_index = self.create_new_style(style); let style_index = self.create_new_style(style);
self.add_named_cell_style(style_name, style_index)?; self.add_named_cell_style(style_name, style_index)
Ok(())
} }
pub(crate) fn get_style_with_quote_prefix(&mut self, index: i32) -> i32 { pub(crate) fn get_style_with_quote_prefix(&mut self, index: i32) -> Result<i32, String> {
let mut style = self.get_style(index); let mut style = self.get_style(index)?;
style.quote_prefix = true; style.quote_prefix = true;
self.get_style_index_or_create(&style) Ok(self.get_style_index_or_create(&style))
} }
pub(crate) fn get_style_with_format(&mut self, index: i32, num_fmt: &str) -> i32 { pub(crate) fn get_style_with_format(
let mut style = self.get_style(index); &mut self,
index: i32,
num_fmt: &str,
) -> Result<i32, String> {
let mut style = self.get_style(index)?;
style.num_fmt = num_fmt.to_string(); style.num_fmt = num_fmt.to_string();
self.get_style_index_or_create(&style) Ok(self.get_style_index_or_create(&style))
} }
pub(crate) fn get_style_without_quote_prefix(&mut self, index: i32) -> i32 { pub(crate) fn get_style_without_quote_prefix(&mut self, index: i32) -> Result<i32, String> {
let mut style = self.get_style(index); let mut style = self.get_style(index)?;
style.quote_prefix = false; style.quote_prefix = false;
self.get_style_index_or_create(&style) Ok(self.get_style_index_or_create(&style))
} }
pub(crate) fn style_is_quote_prefix(&self, index: i32) -> bool { pub(crate) fn style_is_quote_prefix(&self, index: i32) -> bool {
@@ -188,9 +191,11 @@ impl Styles {
cell_xf.quote_prefix cell_xf.quote_prefix
} }
pub(crate) fn get_style(&self, index: i32) -> Style { pub(crate) fn get_style(&self, index: i32) -> Result<Style, String> {
let cell_xf = &self.cell_xfs[index as usize]; let cell_xf = &self
.cell_xfs
.get(index as usize)
.ok_or("Invalid index provided".to_string())?;
let border_id = cell_xf.border_id as usize; let border_id = cell_xf.border_id as usize;
let fill_id = cell_xf.fill_id as usize; let fill_id = cell_xf.fill_id as usize;
let font_id = cell_xf.font_id as usize; let font_id = cell_xf.font_id as usize;
@@ -198,14 +203,14 @@ impl Styles {
let quote_prefix = cell_xf.quote_prefix; let quote_prefix = cell_xf.quote_prefix;
let alignment = cell_xf.alignment.clone(); let alignment = cell_xf.alignment.clone();
Style { Ok(Style {
alignment, alignment,
num_fmt: get_num_fmt(num_fmt_id, &self.num_fmts), num_fmt: get_num_fmt(num_fmt_id, &self.num_fmts),
fill: self.fills[fill_id].clone(), fill: self.fills[fill_id].clone(),
font: self.fonts[font_id].clone(), font: self.fonts[font_id].clone(),
border: self.borders[border_id].clone(), border: self.borders[border_id].clone(),
quote_prefix, quote_prefix,
} })
} }
} }
@@ -221,8 +226,7 @@ impl Model {
let style_index = self.workbook.styles.get_style_index_or_create(style); let style_index = self.workbook.styles.get_style_index_or_create(style);
self.workbook self.workbook
.worksheet_mut(sheet)? .worksheet_mut(sheet)?
.set_cell_style(row, column, style_index); .set_cell_style(row, column, style_index)
Ok(())
} }
pub fn copy_cell_style( pub fn copy_cell_style(
@@ -237,9 +241,7 @@ impl Model {
self.workbook self.workbook
.worksheet_mut(destination_cell.0)? .worksheet_mut(destination_cell.0)?
.set_cell_style(destination_cell.1, destination_cell.2, source_style_index); .set_cell_style(destination_cell.1, destination_cell.2, source_style_index)
Ok(())
} }
/// Sets the style "style_name" in cell /// Sets the style "style_name" in cell
@@ -253,8 +255,7 @@ impl Model {
let style_index = self.workbook.styles.get_style_index_by_name(style_name)?; let style_index = self.workbook.styles.get_style_index_by_name(style_name)?;
self.workbook self.workbook
.worksheet_mut(sheet)? .worksheet_mut(sheet)?
.set_cell_style(row, column, style_index); .set_cell_style(row, column, style_index)
Ok(())
} }
pub fn set_sheet_style(&mut self, sheet: u32, style_name: &str) -> Result<(), String> { pub fn set_sheet_style(&mut self, sheet: u32, style_name: &str) -> Result<(), String> {

View File

@@ -52,6 +52,7 @@ mod test_fn_type;
mod test_frozen_rows_and_columns; mod test_frozen_rows_and_columns;
mod test_get_cell_content; mod test_get_cell_content;
mod test_percentage; mod test_percentage;
mod test_set_functions_error_handling;
mod test_today; mod test_today;
mod test_types; mod test_types;
mod user_model; mod user_model;

View File

@@ -26,7 +26,7 @@ fn test_column_width() {
assert!((worksheet.get_column_width(1).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON); assert!((worksheet.get_column_width(1).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
assert!((worksheet.get_column_width(2).unwrap() - 30.0).abs() < f64::EPSILON); assert!((worksheet.get_column_width(2).unwrap() - 30.0).abs() < f64::EPSILON);
assert!((worksheet.get_column_width(3).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON); assert!((worksheet.get_column_width(3).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
assert_eq!(model.get_cell_style_index(0, 23, 2), 6); assert_eq!(model.get_cell_style_index(0, 23, 2), Ok(6));
} }
#[test] #[test]
@@ -53,7 +53,7 @@ fn test_column_width_lower_edge() {
assert!( assert!(
(worksheet.get_column_width(6).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON (worksheet.get_column_width(6).unwrap() - 10.0 * COLUMN_WIDTH_FACTOR).abs() < f64::EPSILON
); );
assert_eq!(model.get_cell_style_index(0, 23, 5), 1); assert_eq!(model.get_cell_style_index(0, 23, 5), Ok(1));
} }
#[test] #[test]
@@ -80,5 +80,5 @@ fn test_column_width_higher_edge() {
); );
assert!((worksheet.get_column_width(16).unwrap() - 30.0).abs() < f64::EPSILON); assert!((worksheet.get_column_width(16).unwrap() - 30.0).abs() < f64::EPSILON);
assert!((worksheet.get_column_width(17).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON); assert!((worksheet.get_column_width(17).unwrap() - DEFAULT_COLUMN_WIDTH).abs() < f64::EPSILON);
assert_eq!(model.get_cell_style_index(0, 23, 16), 1); assert_eq!(model.get_cell_style_index(0, 23, 16), Ok(1));
} }

View File

@@ -17,7 +17,9 @@ fn test_empty_model() {
#[test] #[test]
fn test_model_simple_evaluation() { fn test_model_simple_evaluation() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "= 1 + 3".to_string()); model
.set_user_input(0, 1, 1, "= 1 + 3".to_string())
.unwrap();
model.evaluate(); model.evaluate();
let result = model._get_text_at(0, 1, 1); let result = model._get_text_at(0, 1, 1);
assert_eq!(result, *"4"); assert_eq!(result, *"4");
@@ -43,7 +45,7 @@ fn test_model_simple_evaluation_order() {
#[test] #[test]
fn test_model_invalid_formula() { fn test_model_invalid_formula() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "= 1 +".to_string()); model.set_user_input(0, 1, 1, "= 1 +".to_string()).unwrap();
model.evaluate(); model.evaluate();
let result = model._get_text_at(0, 1, 1); let result = model._get_text_at(0, 1, 1);
assert_eq!(result, *"#ERROR!"); assert_eq!(result, *"#ERROR!");
@@ -54,8 +56,10 @@ fn test_model_invalid_formula() {
#[test] #[test]
fn test_model_dependencies() { fn test_model_dependencies() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "23".to_string()); // A1 model.set_user_input(0, 1, 1, "23".to_string()).unwrap(); // A1
model.set_user_input(0, 1, 2, "= A1* 2-4".to_string()); // B1 model
.set_user_input(0, 1, 2, "= A1* 2-4".to_string())
.unwrap(); // B1
model.evaluate(); model.evaluate();
let result = model._get_text_at(0, 1, 1); let result = model._get_text_at(0, 1, 1);
assert_eq!(result, *"23"); assert_eq!(result, *"23");
@@ -65,7 +69,9 @@ fn test_model_dependencies() {
let result = model._get_formula("B1"); let result = model._get_formula("B1");
assert_eq!(result, *"=A1*2-4"); assert_eq!(result, *"=A1*2-4");
model.set_user_input(0, 2, 1, "=SUM(A1, B1)".to_string()); // A2 model
.set_user_input(0, 2, 1, "=SUM(A1, B1)".to_string())
.unwrap(); // A2
model.evaluate(); model.evaluate();
let result = model._get_text_at(0, 2, 1); let result = model._get_text_at(0, 2, 1);
assert_eq!(result, *"65"); assert_eq!(result, *"65");
@@ -74,8 +80,10 @@ fn test_model_dependencies() {
#[test] #[test]
fn test_model_strings() { fn test_model_strings() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "Hello World".to_string()); model
model.set_user_input(0, 1, 2, "=A1".to_string()); .set_user_input(0, 1, 1, "Hello World".to_string())
.unwrap();
model.set_user_input(0, 1, 2, "=A1".to_string()).unwrap();
model.evaluate(); model.evaluate();
let result = model._get_text_at(0, 1, 1); let result = model._get_text_at(0, 1, 1);
assert_eq!(result, *"Hello World"); assert_eq!(result, *"Hello World");
@@ -152,21 +160,35 @@ fn test_to_excel_precision_str() {
#[test] #[test]
fn test_booleans() { fn test_booleans() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "true".to_string()); model.set_user_input(0, 1, 1, "true".to_string()).unwrap();
model.set_user_input(0, 2, 1, "TRUE".to_string()); model.set_user_input(0, 2, 1, "TRUE".to_string()).unwrap();
model.set_user_input(0, 3, 1, "True".to_string()); model.set_user_input(0, 3, 1, "True".to_string()).unwrap();
model.set_user_input(0, 4, 1, "false".to_string()); model.set_user_input(0, 4, 1, "false".to_string()).unwrap();
model.set_user_input(0, 5, 1, "FALSE".to_string()); model.set_user_input(0, 5, 1, "FALSE".to_string()).unwrap();
model.set_user_input(0, 6, 1, "False".to_string()); model.set_user_input(0, 6, 1, "False".to_string()).unwrap();
model.set_user_input(0, 1, 2, "=ISLOGICAL(A1)".to_string()); model
model.set_user_input(0, 2, 2, "=ISLOGICAL(A2)".to_string()); .set_user_input(0, 1, 2, "=ISLOGICAL(A1)".to_string())
model.set_user_input(0, 3, 2, "=ISLOGICAL(A3)".to_string()); .unwrap();
model.set_user_input(0, 4, 2, "=ISLOGICAL(A4)".to_string()); model
model.set_user_input(0, 5, 2, "=ISLOGICAL(A5)".to_string()); .set_user_input(0, 2, 2, "=ISLOGICAL(A2)".to_string())
model.set_user_input(0, 6, 2, "=ISLOGICAL(A6)".to_string()); .unwrap();
model
.set_user_input(0, 3, 2, "=ISLOGICAL(A3)".to_string())
.unwrap();
model
.set_user_input(0, 4, 2, "=ISLOGICAL(A4)".to_string())
.unwrap();
model
.set_user_input(0, 5, 2, "=ISLOGICAL(A5)".to_string())
.unwrap();
model
.set_user_input(0, 6, 2, "=ISLOGICAL(A6)".to_string())
.unwrap();
model.set_user_input(0, 1, 5, "=IF(false, True, FALSe)".to_string()); model
.set_user_input(0, 1, 5, "=IF(false, True, FALSe)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -191,19 +213,19 @@ fn test_booleans() {
#[test] #[test]
fn test_set_cell_style() { fn test_set_cell_style() {
let mut model = new_empty_model(); let mut model = new_empty_model();
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(!style.font.b); assert!(!style.font.b);
style.font.b = true; style.font.b = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(style.font.b); assert!(style.font.b);
style.font.b = false; style.font.b = false;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let style = model.get_style_for_cell(0, 1, 1); let style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(!style.font.b); assert!(!style.font.b);
} }
@@ -211,21 +233,21 @@ fn test_set_cell_style() {
fn test_copy_cell_style() { fn test_copy_cell_style() {
let mut model = new_empty_model(); let mut model = new_empty_model();
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.font.b = true; style.font.b = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let mut style = model.get_style_for_cell(0, 1, 2); let mut style = model.get_style_for_cell(0, 1, 2).unwrap();
style.font.i = true; style.font.i = true;
assert!(model.set_cell_style(0, 1, 2, &style).is_ok()); assert!(model.set_cell_style(0, 1, 2, &style).is_ok());
assert!(model.copy_cell_style((0, 1, 1), (0, 1, 2)).is_ok()); assert!(model.copy_cell_style((0, 1, 1), (0, 1, 2)).is_ok());
let style = model.get_style_for_cell(0, 1, 1); let style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(style.font.b); assert!(style.font.b);
assert!(!style.font.i); assert!(!style.font.i);
let style = model.get_style_for_cell(0, 1, 2); let style = model.get_style_for_cell(0, 1, 2).unwrap();
assert!(style.font.b); assert!(style.font.b);
assert!(!style.font.i); assert!(!style.font.i);
} }
@@ -234,15 +256,15 @@ fn test_copy_cell_style() {
fn test_get_cell_style_index() { fn test_get_cell_style_index() {
let mut model = new_empty_model(); let mut model = new_empty_model();
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
let style_index = model.get_cell_style_index(0, 1, 1); let style_index = model.get_cell_style_index(0, 1, 1).unwrap();
assert_eq!(style_index, 0); assert_eq!(style_index, 0);
assert!(!style.font.b); assert!(!style.font.b);
style.font.b = true; style.font.b = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let style_index = model.get_cell_style_index(0, 1, 1); let style_index = model.get_cell_style_index(0, 1, 1).unwrap();
assert_eq!(style_index, 1); assert_eq!(style_index, 1);
} }
@@ -250,29 +272,29 @@ fn test_get_cell_style_index() {
fn test_model_set_cells_with_values_styles() { fn test_model_set_cells_with_values_styles() {
let mut model = new_empty_model(); let mut model = new_empty_model();
// Inputs // Inputs
model.set_user_input(0, 1, 1, "21".to_string()); // A1 model.set_user_input(0, 1, 1, "21".to_string()).unwrap(); // A1
model.set_user_input(0, 2, 1, "2".to_string()); // A2 model.set_user_input(0, 2, 1, "2".to_string()).unwrap(); // A2
let style_index = model.get_cell_style_index(0, 1, 1); let style_index = model.get_cell_style_index(0, 1, 1).unwrap();
assert_eq!(style_index, 0); assert_eq!(style_index, 0);
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.font.b = true; style.font.b = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
assert!(model.set_cell_style(0, 2, 1, &style).is_ok()); assert!(model.set_cell_style(0, 2, 1, &style).is_ok());
let style_index = model.get_cell_style_index(0, 1, 1); let style_index = model.get_cell_style_index(0, 1, 1).unwrap();
assert_eq!(style_index, 1); assert_eq!(style_index, 1);
let style_index = model.get_cell_style_index(0, 2, 1); let style_index = model.get_cell_style_index(0, 2, 1).unwrap();
assert_eq!(style_index, 1); assert_eq!(style_index, 1);
model.update_cell_with_number(0, 1, 2, 1.0); model.update_cell_with_number(0, 1, 2, 1.0).unwrap();
model.update_cell_with_number(0, 2, 1, 2.0); model.update_cell_with_number(0, 2, 1, 2.0).unwrap();
model.evaluate(); model.evaluate();
// Styles are not modified // Styles are not modified
let style_index = model.get_cell_style_index(0, 1, 1); let style_index = model.get_cell_style_index(0, 1, 1).unwrap();
assert_eq!(style_index, 1); assert_eq!(style_index, 1);
let style_index = model.get_cell_style_index(0, 2, 1); let style_index = model.get_cell_style_index(0, 2, 1).unwrap();
assert_eq!(style_index, 1); assert_eq!(style_index, 1);
} }
@@ -280,20 +302,20 @@ fn test_model_set_cells_with_values_styles() {
fn test_style_fmt_id() { fn test_style_fmt_id() {
let mut model = new_empty_model(); let mut model = new_empty_model();
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.num_fmt = "#.##".to_string(); style.num_fmt = "#.##".to_string();
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let style = model.get_style_for_cell(0, 1, 1); let style = model.get_style_for_cell(0, 1, 1).unwrap();
assert_eq!(style.num_fmt, "#.##"); assert_eq!(style.num_fmt, "#.##");
let mut style = model.get_style_for_cell(0, 10, 1); let mut style = model.get_style_for_cell(0, 10, 1).unwrap();
style.num_fmt = "$$#,##0.0000".to_string(); style.num_fmt = "$$#,##0.0000".to_string();
assert!(model.set_cell_style(0, 10, 1, &style).is_ok()); assert!(model.set_cell_style(0, 10, 1, &style).is_ok());
let style = model.get_style_for_cell(0, 10, 1); let style = model.get_style_for_cell(0, 10, 1).unwrap();
assert_eq!(style.num_fmt, "$$#,##0.0000"); assert_eq!(style.num_fmt, "$$#,##0.0000");
// Make sure old style is not touched // Make sure old style is not touched
let style = model.get_style_for_cell(0, 1, 1); let style = model.get_style_for_cell(0, 1, 1).unwrap();
assert_eq!(style.num_fmt, "#.##"); assert_eq!(style.num_fmt, "#.##");
} }
@@ -357,9 +379,13 @@ fn set_input_autocomplete() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model._set("A1", "1"); model._set("A1", "1");
model._set("A2", "2"); model._set("A2", "2");
model.set_user_input(0, 3, 1, "=SUM(A1:A2".to_string()); model
.set_user_input(0, 3, 1, "=SUM(A1:A2".to_string())
.unwrap();
// This will fail anyway // This will fail anyway
model.set_user_input(0, 4, 1, "=SUM(A1*".to_string()); model
.set_user_input(0, 4, 1, "=SUM(A1*".to_string())
.unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_formula("A3"), "=SUM(A1:A2)"); assert_eq!(model._get_formula("A3"), "=SUM(A1:A2)");
@@ -405,7 +431,7 @@ fn test_get_formatted_cell_value() {
model._set("A5", "123.456"); model._set("A5", "123.456");
// change A5 format // change A5 format
let mut style = model.get_style_for_cell(0, 5, 1); let mut style = model.get_style_for_cell(0, 5, 1).unwrap();
style.num_fmt = "$#,##0.00".to_string(); style.num_fmt = "$#,##0.00".to_string();
model.set_cell_style(0, 5, 1, &style).unwrap(); model.set_cell_style(0, 5, 1, &style).unwrap();

View File

@@ -5,8 +5,12 @@ use crate::test::util::new_empty_model;
#[test] #[test]
fn test_formulas() { fn test_formulas() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "$100.348".to_string()); model
model.set_user_input(0, 1, 2, "=ISNUMBER(A1)".to_string()); .set_user_input(0, 1, 1, "$100.348".to_string())
.unwrap();
model
.set_user_input(0, 1, 2, "=ISNUMBER(A1)".to_string())
.unwrap();
model.evaluate(); model.evaluate();

View File

@@ -3,7 +3,7 @@ use crate::test::util::new_empty_model;
#[test] #[test]
fn test_metadata_new_model() { fn test_metadata_new_model() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "5.5".to_string()); model.set_user_input(0, 1, 1, "5.5".to_string()).unwrap();
model.evaluate(); model.evaluate();
let metadata = &model.workbook.metadata; let metadata = &model.workbook.metadata;
assert_eq!(metadata.application, "IronCalc Sheets"); assert_eq!(metadata.application, "IronCalc Sheets");

View File

@@ -14,7 +14,9 @@ fn test_is_empty_cell_non_existing_sheet() {
fn test_is_empty_cell() { fn test_is_empty_cell() {
let mut model = new_empty_model(); let mut model = new_empty_model();
assert!(model.is_empty_cell(0, 3, 1).unwrap()); assert!(model.is_empty_cell(0, 3, 1).unwrap());
model.set_user_input(0, 3, 1, "Hello World".to_string()); model
.set_user_input(0, 3, 1, "Hello World".to_string())
.unwrap();
assert!(!model.is_empty_cell(0, 3, 1).unwrap()); assert!(!model.is_empty_cell(0, 3, 1).unwrap());
model.cell_clear_contents(0, 3, 1).unwrap(); model.cell_clear_contents(0, 3, 1).unwrap();
assert!(model.is_empty_cell(0, 3, 1).unwrap()); assert!(model.is_empty_cell(0, 3, 1).unwrap());

View File

@@ -57,12 +57,12 @@ fn test_quote_prefix_enter() {
model._set("A2", "=ISTEXT(A1)"); model._set("A2", "=ISTEXT(A1)");
model.evaluate(); model.evaluate();
// We introduce a value with a "quote prefix" index // We introduce a value with a "quote prefix" index
model.set_user_input(0, 1, 3, "'=A1".to_string()); model.set_user_input(0, 1, 3, "'=A1".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("C1"), *"=A1"); assert_eq!(model._get_text("C1"), *"=A1");
// But if we enter with a quote_prefix but without the "'" it won't be quote_prefix // But if we enter with a quote_prefix but without the "'" it won't be quote_prefix
model.set_user_input(0, 1, 4, "=A1".to_string()); model.set_user_input(0, 1, 4, "=A1".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("D1"), *"123"); assert_eq!(model._get_text("D1"), *"123");
} }
@@ -75,7 +75,7 @@ fn test_quote_prefix_reenter() {
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
// We introduce a value with a "quote prefix" index // We introduce a value with a "quote prefix" index
model.set_user_input(0, 1, 1, "123".to_string()); model.set_user_input(0, 1, 1, "123".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"FALSE"); assert_eq!(model._get_text("A2"), *"FALSE");
} }
@@ -83,7 +83,7 @@ fn test_quote_prefix_reenter() {
#[test] #[test]
fn test_update_cell_quote() { fn test_update_cell_quote() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.update_cell_with_text(0, 1, 1, "= 1 + 3"); model.update_cell_with_text(0, 1, 1, "= 1 + 3").unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), *"= 1 + 3"); assert_eq!(model._get_text("A1"), *"= 1 + 3");
assert!(!model._has_formula("A1")); assert!(!model._has_formula("A1"));
@@ -92,12 +92,12 @@ fn test_update_cell_quote() {
#[test] #[test]
fn test_update_quote_prefix_reenter() { fn test_update_quote_prefix_reenter() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.update_cell_with_text(0, 1, 1, "123"); model.update_cell_with_text(0, 1, 1, "123").unwrap();
model._set("A2", "=ISTEXT(A1)"); model._set("A2", "=ISTEXT(A1)");
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
// We reenter as a number // We reenter as a number
model.update_cell_with_number(0, 1, 1, 123.0); model.update_cell_with_number(0, 1, 1, 123.0).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"FALSE"); assert_eq!(model._get_text("A2"), *"FALSE");
} }
@@ -105,12 +105,12 @@ fn test_update_quote_prefix_reenter() {
#[test] #[test]
fn test_update_quote_prefix_reenter_bool() { fn test_update_quote_prefix_reenter_bool() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.update_cell_with_text(0, 1, 1, "TRUE"); model.update_cell_with_text(0, 1, 1, "TRUE").unwrap();
model._set("A2", "=ISTEXT(A1)"); model._set("A2", "=ISTEXT(A1)");
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
// We enter a bool // We enter a bool
model.update_cell_with_bool(0, 1, 1, true); model.update_cell_with_bool(0, 1, 1, true).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"FALSE"); assert_eq!(model._get_text("A2"), *"FALSE");
} }
@@ -118,29 +118,29 @@ fn test_update_quote_prefix_reenter_bool() {
#[test] #[test]
fn test_update_quote_prefix_reenter_text() { fn test_update_quote_prefix_reenter_text() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.update_cell_with_text(0, 1, 1, "123"); model.update_cell_with_text(0, 1, 1, "123").unwrap();
model._set("A2", "=ISTEXT(A1)"); model._set("A2", "=ISTEXT(A1)");
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
assert!(model.get_style_for_cell(0, 1, 1).quote_prefix); assert!(model.get_style_for_cell(0, 1, 1).unwrap().quote_prefix);
// We enter a string // We enter a string
model.update_cell_with_text(0, 1, 1, "Hello"); model.update_cell_with_text(0, 1, 1, "Hello").unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
assert!(!model.get_style_for_cell(0, 1, 1).quote_prefix); assert!(!model.get_style_for_cell(0, 1, 1).unwrap().quote_prefix);
} }
#[test] #[test]
fn test_update_quote_prefix_reenter_text_2() { fn test_update_quote_prefix_reenter_text_2() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.update_cell_with_text(0, 1, 1, "123"); model.update_cell_with_text(0, 1, 1, "123").unwrap();
model._set("A2", "=ISTEXT(A1)"); model._set("A2", "=ISTEXT(A1)");
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
assert!(model.get_style_for_cell(0, 1, 1).quote_prefix); assert!(model.get_style_for_cell(0, 1, 1).unwrap().quote_prefix);
// We enter another number // We enter another number
model.update_cell_with_text(0, 1, 1, "42"); model.update_cell_with_text(0, 1, 1, "42").unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE");
assert!(model.get_style_for_cell(0, 1, 1).quote_prefix); assert!(model.get_style_for_cell(0, 1, 1).unwrap().quote_prefix);
} }

View File

@@ -0,0 +1,449 @@
use crate::{expressions::token, test::util::new_empty_model, types::Cell};
#[test]
fn test_update_cell_with_text() {
let mut model = new_empty_model();
// Below are safe inputs
model.set_user_input(0, 1, 1, "Hello".to_string()).unwrap();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.update_cell_with_text(1, 1, 1, "new value");
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// Case2 : Invalid Row
let update_result = model.update_cell_with_text(0, 0, 1, "new value");
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Invalid Column
let update_result = model.update_cell_with_text(0, 1, 1048579, "new value");
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_update_cell_with_number() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_number(0, 1, 1, 10.0).unwrap();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.update_cell_with_number(1, 1, 1, 20.0);
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// Case2 : Invalid Row
let update_result = model.update_cell_with_number(0, 0, 1, 20.0);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Invalid Column
let update_result = model.update_cell_with_number(0, 1, 1048579, 20.0);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_update_cell_with_bool() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_bool(0, 1, 1, true).unwrap();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.update_cell_with_bool(1, 1, 1, false);
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// Case2 : Invalid Row
let update_result = model.update_cell_with_bool(0, 0, 1, false);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Invalid Column
let update_result = model.update_cell_with_bool(0, 1, 1048579, false);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_update_cell_with_formula() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_number(0, 1, 1, 10.0).unwrap();
model
.update_cell_with_formula(0, 1, 2, "=A1*2".to_string())
.unwrap();
model.evaluate();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.update_cell_with_formula(1, 1, 2, "=A1*2".to_string());
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// Case2 : Invalid Row
let update_result = model.update_cell_with_formula(0, 0, 2, "=A1*2".to_string());
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Invalid Column
let update_result = model.update_cell_with_formula(0, 1, 1048579, "=A1*2".to_string());
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_set_user_input() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_number(0, 1, 1, 10.0).unwrap();
model.evaluate();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.set_user_input(1, 1, 2, "20.0".to_string());
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// Case2 : Invalid Row
let update_result = model.set_user_input(0, 0, 2, "20.0".to_string());
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Invalid Column
let update_result = model.set_user_input(0, 1, 1048579, "20.0".to_string());
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_get_style_for_cell() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_number(0, 1, 1, 10.0).unwrap();
model.evaluate();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.get_style_for_cell(1, 1, 2);
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// ATTENTION : get_cell_style_index tries to get cell using row and col
// if we invalid row or column is given, it will return index 0.
// Case2 : Invalid Row
let update_result = model.get_style_for_cell(0, 0, 2);
assert_eq!(update_result.is_ok(), true);
// Case3 : Invalid Column
let update_result = model.get_style_for_cell(0, 1, 1048579);
assert_eq!(update_result.is_ok(), true);
}
#[test]
fn test_get_cell_style_index() {
let mut model = new_empty_model();
// Below are safe inputs
model.update_cell_with_number(0, 1, 1, 10.0).unwrap();
model.evaluate();
// Now testing all the possible error scenarios
// Case1 : Invalid sheet
let update_result = model.get_cell_style_index(1, 1, 2);
assert_eq!(update_result, Err("Invalid sheet index".to_string()));
// ATTENTION : get_cell_style_index tries to get cell using row and col
// if we invalid row or column is given, it will return index 0.
// Case2 : Invalid Row
let update_result = model.get_cell_style_index(0, 0, 2);
assert_eq!(update_result, Ok(0));
// Case3 : Invalid Column
let update_result = model.get_cell_style_index(0, 1, 1048579);
assert_eq!(update_result, Ok(0));
}
#[test]
fn test_worksheet_update_cell() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result =
model
.workbook
.worksheet_mut(0)
.unwrap()
.update_cell(0, 1, Cell::new_number(10.0, 1));
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result =
model
.workbook
.worksheet_mut(0)
.unwrap()
.update_cell(1, 1048579, Cell::new_number(10.0, 1));
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_style() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_style(0, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_style(1, 1048579, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_with_formula() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_formula(0, 1, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_formula(1, 1048579, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_with_number() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_number(0, 1, 1.0, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_number(1, 1048579, 1.0, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_with_string() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_string(0, 1, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_string(1, 1048579, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_with_boolean() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_boolean(0, 1, true, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_boolean(1, 1048579, true, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_set_cell_with_error() {
let mut model = new_empty_model();
// Now testing all the possible error scenarios
// Case1: Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_error(0, 1, token::Error::ERROR, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.set_cell_with_error(1, 1048579, token::Error::ERROR, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
}
#[test]
fn test_worksheet_cell_clear_contents() {
let mut model = new_empty_model();
model
.workbook
.worksheet_mut(0)
.unwrap()
.update_cell(1, 1, Cell::new_number(10.0, 1))
.unwrap();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents(0, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents(1, 1048579);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Valid case
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents(1, 1);
assert_eq!(update_result, Ok(()))
}
#[test]
fn test_worksheet_cell_clear_contents_with_style() {
let mut model = new_empty_model();
model
.workbook
.worksheet_mut(0)
.unwrap()
.update_cell(1, 1, Cell::new_number(10.0, 1))
.unwrap();
// Now testing all the possible error scenarios
// Case1 : Invalid Row
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents_with_style(0, 1, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case2 : Invalid Column
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents_with_style(1, 1048579, 1);
assert_eq!(update_result, Err("Incorrect row or column".to_string()));
// Case3 : Valid case
let update_result = model
.workbook
.worksheet_mut(0)
.unwrap()
.cell_clear_contents_with_style(1, 1, 1);
assert_eq!(update_result, Ok(()))
}
#[test]
fn workbook_styles_get_style_error_handling() {
let model = new_empty_model();
// case 1 : Invalid index
assert_eq!(
model.workbook.styles.get_style(15),
Err("Invalid index provided".to_string())
);
}
#[test]
fn workbook_styles_get_style_without_quote_prefix_error_handling() {
let mut model = new_empty_model();
// case 1 : Invalid index
assert_eq!(
model.workbook.styles.get_style_without_quote_prefix(15),
Err("Invalid index provided".to_string())
);
}
#[test]
fn workbook_styles_get_style_with_format_error_handling() {
let mut model = new_empty_model();
// case 1 : Invalid index
assert_eq!(
model
.workbook
.styles
.get_style_with_format(15, "dummy_num_format"),
Err("Invalid index provided".to_string())
);
}
#[test]
fn workbook_styles_get_style_with_quote_prefix_handling() {
let mut model = new_empty_model();
// case 1 : Invalid index
assert_eq!(
model.workbook.styles.get_style_with_quote_prefix(15),
Err("Invalid index provided".to_string())
);
}

View File

@@ -5,16 +5,28 @@ use crate::{cell::CellValue, test::util::new_empty_model};
#[test] #[test]
fn test_currencies() { fn test_currencies() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "$100.348".to_string()); model
model.set_user_input(0, 1, 2, "=ISNUMBER(A1)".to_string()); .set_user_input(0, 1, 1, "$100.348".to_string())
.unwrap();
model
.set_user_input(0, 1, 2, "=ISNUMBER(A1)".to_string())
.unwrap();
model.set_user_input(0, 2, 1, "$ 100.348".to_string()); model
model.set_user_input(0, 2, 2, "=ISNUMBER(A2)".to_string()); .set_user_input(0, 2, 1, "$ 100.348".to_string())
.unwrap();
model
.set_user_input(0, 2, 2, "=ISNUMBER(A2)".to_string())
.unwrap();
model.set_user_input(0, 3, 1, "100$".to_string()); model.set_user_input(0, 3, 1, "100$".to_string()).unwrap();
model.set_user_input(0, 3, 2, "=ISNUMBER(A3)".to_string()); model
.set_user_input(0, 3, 2, "=ISNUMBER(A3)".to_string())
.unwrap();
model.set_user_input(0, 4, 1, "3.1415926$".to_string()); model
.set_user_input(0, 4, 1, "3.1415926$".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -43,9 +55,9 @@ fn test_currencies() {
#[test] #[test]
fn scientific() { fn scientific() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "3e-4".to_string()); model.set_user_input(0, 1, 1, "3e-4".to_string()).unwrap();
model.set_user_input(0, 2, 1, "5e-4$".to_string()); model.set_user_input(0, 2, 1, "5e-4$".to_string()).unwrap();
model.set_user_input(0, 3, 1, "6e-4%".to_string()); model.set_user_input(0, 3, 1, "6e-4%".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -61,9 +73,13 @@ fn scientific() {
#[test] #[test]
fn test_percentage() { fn test_percentage() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 10, 1, "50%".to_string()); model.set_user_input(0, 10, 1, "50%".to_string()).unwrap();
model.set_user_input(0, 10, 2, "=ISNUMBER(A10)".to_string()); model
model.set_user_input(0, 11, 1, "55.759%".to_string()); .set_user_input(0, 10, 2, "=ISNUMBER(A10)".to_string())
.unwrap();
model
.set_user_input(0, 11, 1, "55.759%".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -81,8 +97,8 @@ fn test_percentage_ops() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model._set("A1", "5%"); model._set("A1", "5%");
model._set("A2", "20%"); model._set("A2", "20%");
model.set_user_input(0, 3, 1, "=A1+A2".to_string()); model.set_user_input(0, 3, 1, "=A1+A2".to_string()).unwrap();
model.set_user_input(0, 4, 1, "=A1*A2".to_string()); model.set_user_input(0, 4, 1, "=A1*A2".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -93,11 +109,19 @@ fn test_percentage_ops() {
#[test] #[test]
fn test_numbers() { fn test_numbers() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "1,000,000".to_string()); model
.set_user_input(0, 1, 1, "1,000,000".to_string())
.unwrap();
model.set_user_input(0, 20, 1, "50,123.549".to_string()); model
model.set_user_input(0, 21, 1, "50,12.549".to_string()); .set_user_input(0, 20, 1, "50,123.549".to_string())
model.set_user_input(0, 22, 1, "1,234567".to_string()); .unwrap();
model
.set_user_input(0, 21, 1, "50,12.549".to_string())
.unwrap();
model
.set_user_input(0, 22, 1, "1,234567".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -131,7 +155,7 @@ fn test_numbers() {
#[test] #[test]
fn test_negative_numbers() { fn test_negative_numbers() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "-100".to_string()); model.set_user_input(0, 1, 1, "-100".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -144,15 +168,19 @@ fn test_negative_numbers() {
#[test] #[test]
fn test_negative_currencies() { fn test_negative_currencies() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "-$100".to_string()); model.set_user_input(0, 1, 1, "-$100".to_string()).unwrap();
model.set_user_input(0, 2, 1, "-$99.123".to_string()); model
.set_user_input(0, 2, 1, "-$99.123".to_string())
.unwrap();
// This is valid! // This is valid!
model.set_user_input(0, 3, 1, "$-345".to_string()); model.set_user_input(0, 3, 1, "$-345".to_string()).unwrap();
model.set_user_input(0, 1, 2, "-200$".to_string()); model.set_user_input(0, 1, 2, "-200$".to_string()).unwrap();
model.set_user_input(0, 2, 2, "-92.689$".to_string()); model
.set_user_input(0, 2, 2, "-92.689$".to_string())
.unwrap();
// This is valid! // This is valid!
model.set_user_input(0, 3, 2, "-22$".to_string()); model.set_user_input(0, 3, 2, "-22$".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -174,8 +202,10 @@ fn test_formulas() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model._set("A1", "$100"); model._set("A1", "$100");
model._set("A2", "$200"); model._set("A2", "$200");
model.set_user_input(0, 3, 1, "=A1+A2".to_string()); model.set_user_input(0, 3, 1, "=A1+A2".to_string()).unwrap();
model.set_user_input(0, 4, 1, "=SUM(A1:A3)".to_string()); model
.set_user_input(0, 4, 1, "=SUM(A1:A3)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -198,9 +228,9 @@ fn test_product() {
model._set("A2", "$5"); model._set("A2", "$5");
model._set("A3", "4"); model._set("A3", "4");
model.set_user_input(0, 1, 2, "=A1*A2".to_string()); model.set_user_input(0, 1, 2, "=A1*A2".to_string()).unwrap();
model.set_user_input(0, 2, 2, "=A1*A3".to_string()); model.set_user_input(0, 2, 2, "=A1*A3".to_string()).unwrap();
model.set_user_input(0, 3, 2, "=A1*3".to_string()); model.set_user_input(0, 3, 2, "=A1*3".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -216,10 +246,12 @@ fn test_division() {
model._set("A2", "$5"); model._set("A2", "$5");
model._set("A3", "4"); model._set("A3", "4");
model.set_user_input(0, 1, 2, "=A1/A2".to_string()); model.set_user_input(0, 1, 2, "=A1/A2".to_string()).unwrap();
model.set_user_input(0, 2, 2, "=A1/A3".to_string()); model.set_user_input(0, 2, 2, "=A1/A3".to_string()).unwrap();
model.set_user_input(0, 3, 2, "=A1/2".to_string()); model.set_user_input(0, 3, 2, "=A1/2".to_string()).unwrap();
model.set_user_input(0, 4, 2, "=100/A2".to_string()); model
.set_user_input(0, 4, 2, "=100/A2".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -235,54 +267,54 @@ fn test_some_complex_examples() {
// $3.00 / 2 = $1.50 // $3.00 / 2 = $1.50
model._set("A1", "$3.00"); model._set("A1", "$3.00");
model._set("A2", "2"); model._set("A2", "2");
model.set_user_input(0, 3, 1, "=A1/A2".to_string()); model.set_user_input(0, 3, 1, "=A1/A2".to_string()).unwrap();
// $3 / 2 = $1 // $3 / 2 = $1
model._set("B1", "$3"); model._set("B1", "$3");
model._set("B2", "2"); model._set("B2", "2");
model.set_user_input(0, 3, 2, "=B1/B2".to_string()); model.set_user_input(0, 3, 2, "=B1/B2".to_string()).unwrap();
// $5.00 * 25% = 25% * $5.00 = $1.25 // $5.00 * 25% = 25% * $5.00 = $1.25
model._set("C1", "$5.00"); model._set("C1", "$5.00");
model._set("C2", "25%"); model._set("C2", "25%");
model.set_user_input(0, 3, 3, "=C1*C2".to_string()); model.set_user_input(0, 3, 3, "=C1*C2".to_string()).unwrap();
model.set_user_input(0, 4, 3, "=C2*C1".to_string()); model.set_user_input(0, 4, 3, "=C2*C1".to_string()).unwrap();
// $5 * 75% = 75% * $5 = $1 // $5 * 75% = 75% * $5 = $1
model._set("D1", "$5"); model._set("D1", "$5");
model._set("D2", "75%"); model._set("D2", "75%");
model.set_user_input(0, 3, 4, "=D1*D2".to_string()); model.set_user_input(0, 3, 4, "=D1*D2".to_string()).unwrap();
model.set_user_input(0, 4, 4, "=D2*D1".to_string()); model.set_user_input(0, 4, 4, "=D2*D1".to_string()).unwrap();
// $10 + $9.99 = $9.99 + $10 = $19.99 // $10 + $9.99 = $9.99 + $10 = $19.99
model._set("E1", "$10"); model._set("E1", "$10");
model._set("E2", "$9.99"); model._set("E2", "$9.99");
model.set_user_input(0, 3, 5, "=E1+E2".to_string()); model.set_user_input(0, 3, 5, "=E1+E2".to_string()).unwrap();
model.set_user_input(0, 4, 5, "=E2+E1".to_string()); model.set_user_input(0, 4, 5, "=E2+E1".to_string()).unwrap();
// $2 * 2 = 2 * $2 = $4 // $2 * 2 = 2 * $2 = $4
model._set("F1", "$2"); model._set("F1", "$2");
model._set("F2", "2"); model._set("F2", "2");
model.set_user_input(0, 3, 6, "=F1*F2".to_string()); model.set_user_input(0, 3, 6, "=F1*F2".to_string()).unwrap();
model.set_user_input(0, 4, 6, "=F2*F1".to_string()); model.set_user_input(0, 4, 6, "=F2*F1".to_string()).unwrap();
// $2.50 * 2 = 2 * $2.50 = $5.00 // $2.50 * 2 = 2 * $2.50 = $5.00
model._set("G1", "$2.50"); model._set("G1", "$2.50");
model._set("G2", "2"); model._set("G2", "2");
model.set_user_input(0, 3, 7, "=G1*G2".to_string()); model.set_user_input(0, 3, 7, "=G1*G2".to_string()).unwrap();
model.set_user_input(0, 4, 7, "=G2*G1".to_string()); model.set_user_input(0, 4, 7, "=G2*G1".to_string()).unwrap();
// $2 * 2.5 = 2.5 * $2 = $5 // $2 * 2.5 = 2.5 * $2 = $5
model._set("H1", "$2"); model._set("H1", "$2");
model._set("H2", "2.5"); model._set("H2", "2.5");
model.set_user_input(0, 3, 8, "=H1*H2".to_string()); model.set_user_input(0, 3, 8, "=H1*H2".to_string()).unwrap();
model.set_user_input(0, 4, 8, "=H2*H1".to_string()); model.set_user_input(0, 4, 8, "=H2*H1".to_string()).unwrap();
// 10% * 1,000 = 1,000 * 10% = 100 // 10% * 1,000 = 1,000 * 10% = 100
model._set("I1", "10%"); model._set("I1", "10%");
model._set("I2", "1,000"); model._set("I2", "1,000");
model.set_user_input(0, 3, 9, "=I1*I2".to_string()); model.set_user_input(0, 3, 9, "=I1*I2".to_string()).unwrap();
model.set_user_input(0, 4, 9, "=I2*I1".to_string()); model.set_user_input(0, 4, 9, "=I2*I1".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -320,9 +352,15 @@ fn test_financial_functions() {
model._set("A3", "10"); model._set("A3", "10");
model._set("A4", "$10,000"); model._set("A4", "$10,000");
model.set_user_input(0, 5, 1, "=PMT(A2/12,A3,A4)".to_string()); model
model.set_user_input(0, 6, 1, "=PMT(A2/12,A3,A4,,1)".to_string()); .set_user_input(0, 5, 1, "=PMT(A2/12,A3,A4)".to_string())
model.set_user_input(0, 7, 1, "=PMT(0.2, 3, -200)".to_string()); .unwrap();
model
.set_user_input(0, 6, 1, "=PMT(A2/12,A3,A4,,1)".to_string())
.unwrap();
model
.set_user_input(0, 7, 1, "=PMT(0.2, 3, -200)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -339,9 +377,15 @@ fn test_sum_function() {
model._set("A1", "$100"); model._set("A1", "$100");
model._set("A2", "$300"); model._set("A2", "$300");
model.set_user_input(0, 1, 2, "=SUM(A:A)".to_string()); model
model.set_user_input(0, 2, 2, "=SUM(A1:A2)".to_string()); .set_user_input(0, 1, 2, "=SUM(A:A)".to_string())
model.set_user_input(0, 3, 2, "=SUM(A1, A2, A3)".to_string()); .unwrap();
model
.set_user_input(0, 2, 2, "=SUM(A1:A2)".to_string())
.unwrap();
model
.set_user_input(0, 3, 2, "=SUM(A1, A2, A3)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -353,7 +397,7 @@ fn test_sum_function() {
#[test] #[test]
fn test_number() { fn test_number() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "3".to_string()); model.set_user_input(0, 1, 1, "3".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -367,7 +411,9 @@ fn test_number() {
#[test] #[test]
fn test_currencies_eur_prefix() { fn test_currencies_eur_prefix() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "€100.348".to_string()); model
.set_user_input(0, 1, 1, "€100.348".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -381,19 +427,27 @@ fn test_currencies_eur_prefix() {
#[test] #[test]
fn test_currencies_eur_suffix() { fn test_currencies_eur_suffix() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "100.348€".to_string()); model
model.set_user_input(0, 2, 1, "25".to_string()); .set_user_input(0, 1, 1, "100.348".to_string())
.unwrap();
model.set_user_input(0, 2, 1, "25€".to_string()).unwrap();
// negatives // negatives
model.set_user_input(0, 1, 2, "-123.348€".to_string()); model
model.set_user_input(0, 2, 2, "-42".to_string()); .set_user_input(0, 1, 2, "-123.348".to_string())
.unwrap();
model.set_user_input(0, 2, 2, "-42€".to_string()).unwrap();
// with a space // with a space
model.set_user_input(0, 1, 3, "101.348 €".to_string()); model
model.set_user_input(0, 2, 3, "26".to_string()); .set_user_input(0, 1, 3, "101.348".to_string())
.unwrap();
model.set_user_input(0, 2, 3, "26 €".to_string()).unwrap();
model.set_user_input(0, 1, 4, "-12.348 €".to_string()); model
model.set_user_input(0, 2, 4, "-45".to_string()); .set_user_input(0, 1, 4, "-12.348".to_string())
.unwrap();
model.set_user_input(0, 2, 4, "-45 €".to_string()).unwrap();
model.evaluate(); model.evaluate();
@@ -449,9 +503,15 @@ fn test_sum_function_eur() {
model._set("A1", "€100"); model._set("A1", "€100");
model._set("A2", "€300"); model._set("A2", "€300");
model.set_user_input(0, 1, 2, "=SUM(A:A)".to_string()); model
model.set_user_input(0, 2, 2, "=SUM(A1:A2)".to_string()); .set_user_input(0, 1, 2, "=SUM(A:A)".to_string())
model.set_user_input(0, 3, 2, "=SUM(A1, A2, A3)".to_string()); .unwrap();
model
.set_user_input(0, 2, 2, "=SUM(A1:A2)".to_string())
.unwrap();
model
.set_user_input(0, 3, 2, "=SUM(A1, A2, A3)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -463,7 +523,9 @@ fn test_sum_function_eur() {
#[test] #[test]
fn input_dates() { fn input_dates() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "3/4/2025".to_string()); model
.set_user_input(0, 1, 1, "3/4/2025".to_string())
.unwrap();
model.evaluate(); model.evaluate();
@@ -474,7 +536,9 @@ fn input_dates() {
); );
// further date assignments do not change the format // further date assignments do not change the format
model.set_user_input(0, 1, 1, "08-08-2028".to_string()); model
.set_user_input(0, 1, 1, "08-08-2028".to_string())
.unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), "8/8/2028"); assert_eq!(model._get_text("A1"), "8/8/2028");
} }

View File

@@ -14,7 +14,7 @@ fn test_sheet_markup() {
model._set("A4", "Total"); model._set("A4", "Total");
model._set("B4", "=SUM(B2:B3)"); model._set("B4", "=SUM(B2:B3)");
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.font.b = true; style.font.b = true;
model.set_cell_style(0, 1, 1, &style).unwrap(); model.set_cell_style(0, 1, 1, &style).unwrap();
model.set_cell_style(0, 1, 2, &style).unwrap(); model.set_cell_style(0, 1, 2, &style).unwrap();

View File

@@ -138,14 +138,14 @@ fn test_insert_sheet() {
// Insert the sheet at the end and check the formula // Insert the sheet at the end and check the formula
assert!(model.insert_sheet("Bacchus", 1, None).is_ok()); assert!(model.insert_sheet("Bacchus", 1, None).is_ok());
model.set_user_input(1, 3, 1, "42".to_string()); model.set_user_input(1, 3, 1, "42".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), "42"); assert_eq!(model._get_text("A1"), "42");
assert_eq!(model._get_text("A2"), "#REF!"); assert_eq!(model._get_text("A2"), "#REF!");
// Insert a sheet in between the other two // Insert a sheet in between the other two
assert!(model.insert_sheet("Dionysus", 1, None).is_ok()); assert!(model.insert_sheet("Dionysus", 1, None).is_ok());
model.set_user_input(1, 3, 1, "111".to_string()); model.set_user_input(1, 3, 1, "111".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), "42"); assert_eq!(model._get_text("A1"), "42");
assert_eq!(model._get_text("A2"), "111"); assert_eq!(model._get_text("A2"), "111");
@@ -176,7 +176,7 @@ fn test_rename_sheet() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.new_sheet(); model.new_sheet();
model._set("A1", "=NewSheet!A3"); model._set("A1", "=NewSheet!A3");
model.set_user_input(1, 3, 1, "25".to_string()); model.set_user_input(1, 3, 1, "25".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), "#REF!"); assert_eq!(model._get_text("A1"), "#REF!");
assert!(model.rename_sheet("Sheet2", "NewSheet").is_ok()); assert!(model.rename_sheet("Sheet2", "NewSheet").is_ok());
@@ -189,7 +189,7 @@ fn test_rename_sheet_by_index() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.new_sheet(); model.new_sheet();
model._set("A1", "=NewSheet!A1"); model._set("A1", "=NewSheet!A1");
model.set_user_input(1, 1, 1, "25".to_string()); model.set_user_input(1, 1, 1, "25".to_string()).unwrap();
model.evaluate(); model.evaluate();
assert_eq!(model._get_text("A1"), "#REF!"); assert_eq!(model._get_text("A1"), "#REF!");
assert!(model.rename_sheet_by_index(1, "NewSheet").is_ok()); assert!(model.rename_sheet_by_index(1, "NewSheet").is_ok());

View File

@@ -7,10 +7,10 @@ use crate::types::Style;
fn test_model_set_cells_with_values_styles() { fn test_model_set_cells_with_values_styles() {
let mut model = new_empty_model(); let mut model = new_empty_model();
// Inputs // Inputs
model.set_user_input(0, 1, 1, "21".to_string()); // A1 model.set_user_input(0, 1, 1, "21".to_string()).unwrap(); // A1
model.set_user_input(0, 2, 1, "42".to_string()); // A2 model.set_user_input(0, 2, 1, "42".to_string()).unwrap(); // A2
let style_base = model.get_style_for_cell(0, 1, 1); let style_base = model.get_style_for_cell(0, 1, 1).unwrap();
let mut style = style_base.clone(); let mut style = style_base.clone();
style.font.b = true; style.font.b = true;
style.num_fmt = "#,##0.00".to_string(); style.num_fmt = "#,##0.00".to_string();
@@ -19,7 +19,7 @@ fn test_model_set_cells_with_values_styles() {
let mut style = style_base; let mut style = style_base;
style.num_fmt = "#,##0.00".to_string(); style.num_fmt = "#,##0.00".to_string();
assert!(model.set_cell_style(0, 2, 1, &style).is_ok()); assert!(model.set_cell_style(0, 2, 1, &style).is_ok());
let style: Style = model.get_style_for_cell(0, 2, 1); let style: Style = model.get_style_for_cell(0, 2, 1).unwrap();
assert_eq!(style.num_fmt, "#,##0.00".to_string()); assert_eq!(style.num_fmt, "#,##0.00".to_string());
} }
@@ -27,21 +27,21 @@ fn test_model_set_cells_with_values_styles() {
fn test_named_styles() { fn test_named_styles() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model._set("A1", "42"); model._set("A1", "42");
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.font.b = true; style.font.b = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let bold_style_index = model.get_cell_style_index(0, 1, 1); let bold_style_index = model.get_cell_style_index(0, 1, 1).unwrap();
let e = model let e = model
.workbook .workbook
.styles .styles
.add_named_cell_style("bold", bold_style_index); .add_named_cell_style("bold", bold_style_index);
assert!(e.is_ok()); assert!(e.is_ok());
model._set("A2", "420"); model._set("A2", "420");
let a2_style_index = model.get_cell_style_index(0, 2, 1); let a2_style_index = model.get_cell_style_index(0, 2, 1).unwrap();
assert!(a2_style_index != bold_style_index); assert!(a2_style_index != bold_style_index);
let e = model.set_cell_style_by_name(0, 2, 1, "bold"); let e = model.set_cell_style_by_name(0, 2, 1, "bold");
assert!(e.is_ok()); assert!(e.is_ok());
assert_eq!(model.get_cell_style_index(0, 2, 1), bold_style_index); assert_eq!(model.get_cell_style_index(0, 2, 1), Ok(bold_style_index));
} }
#[test] #[test]
@@ -49,7 +49,7 @@ fn test_create_named_style() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model._set("A1", "42"); model._set("A1", "42");
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(!style.font.b); assert!(!style.font.b);
style.font.b = true; style.font.b = true;
@@ -59,6 +59,6 @@ fn test_create_named_style() {
let e = model.set_cell_style_by_name(0, 1, 1, "bold"); let e = model.set_cell_style_by_name(0, 1, 1, "bold");
assert!(e.is_ok()); assert!(e.is_ok());
let style = model.get_style_for_cell(0, 1, 1); let style = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(style.font.b); assert!(style.font.b);
} }

View File

@@ -100,7 +100,9 @@ fn test_worksheet_dimension_progressive() {
} }
); );
model.set_user_input(0, 30, 50, "Hello World".to_string()); model
.set_user_input(0, 30, 50, "Hello World".to_string())
.unwrap();
assert_eq!( assert_eq!(
model.workbook.worksheet(0).unwrap().dimension(), model.workbook.worksheet(0).unwrap().dimension(),
WorksheetDimension { WorksheetDimension {
@@ -111,7 +113,9 @@ fn test_worksheet_dimension_progressive() {
} }
); );
model.set_user_input(0, 10, 15, "Hello World".to_string()); model
.set_user_input(0, 10, 15, "Hello World".to_string())
.unwrap();
assert_eq!( assert_eq!(
model.workbook.worksheet(0).unwrap().dimension(), model.workbook.worksheet(0).unwrap().dimension(),
WorksheetDimension { WorksheetDimension {
@@ -122,7 +126,9 @@ fn test_worksheet_dimension_progressive() {
} }
); );
model.set_user_input(0, 5, 25, "Hello World".to_string()); model
.set_user_input(0, 5, 25, "Hello World".to_string())
.unwrap();
assert_eq!( assert_eq!(
model.workbook.worksheet(0).unwrap().dimension(), model.workbook.worksheet(0).unwrap().dimension(),
WorksheetDimension { WorksheetDimension {
@@ -133,7 +139,9 @@ fn test_worksheet_dimension_progressive() {
} }
); );
model.set_user_input(0, 10, 250, "Hello World".to_string()); model
.set_user_input(0, 10, 250, "Hello World".to_string())
.unwrap();
assert_eq!( assert_eq!(
model.workbook.worksheet(0).unwrap().dimension(), model.workbook.worksheet(0).unwrap().dimension(),
WorksheetDimension { WorksheetDimension {
@@ -162,12 +170,14 @@ fn test_worksheet_navigate_to_edge_in_direction() {
for (row_index, row) in inline_spreadsheet.into_iter().enumerate() { for (row_index, row) in inline_spreadsheet.into_iter().enumerate() {
for (column_index, value) in row.into_iter().enumerate() { for (column_index, value) in row.into_iter().enumerate() {
if value != 0 { if value != 0 {
model.update_cell_with_number( model
0, .update_cell_with_number(
(row_index as i32) + 1, 0,
(column_index as i32) + 1, (row_index as i32) + 1,
value.into(), (column_index as i32) + 1,
); value.into(),
)
.unwrap();
} }
} }
} }

View File

@@ -20,7 +20,8 @@ impl Model {
let cell_reference = self._parse_reference(cell); let cell_reference = self._parse_reference(cell);
let column = cell_reference.column; let column = cell_reference.column;
let row = cell_reference.row; let row = cell_reference.row;
self.set_user_input(cell_reference.sheet, row, column, value.to_string()); self.set_user_input(cell_reference.sheet, row, column, value.to_string())
.unwrap();
} }
pub fn _has_formula(&self, cell: &str) -> bool { pub fn _has_formula(&self, cell: &str) -> bool {
self._get_formula_opt(cell).is_some() self._get_formula_opt(cell).is_some()

View File

@@ -86,12 +86,15 @@ fn get_units_from_format_string(num_fmt: &str) -> Option<Units> {
impl Model { impl Model {
fn compute_cell_units(&self, cell_reference: &CellReferenceIndex) -> Option<Units> { fn compute_cell_units(&self, cell_reference: &CellReferenceIndex) -> Option<Units> {
let style = &self.get_style_for_cell( let cell_style_res = &self.get_style_for_cell(
cell_reference.sheet, cell_reference.sheet,
cell_reference.row, cell_reference.row,
cell_reference.column, cell_reference.column,
); );
get_units_from_format_string(&style.num_fmt) match cell_style_res {
Ok(style) => get_units_from_format_string(&style.num_fmt),
Err(_) => None,
}
} }
pub(crate) fn compute_node_units( pub(crate) fn compute_node_units(

View File

@@ -331,7 +331,7 @@ impl UserModel {
.cell(row, column) .cell(row, column)
.cloned(); .cloned();
self.model self.model
.set_user_input(sheet, row, column, value.to_string()); .set_user_input(sheet, row, column, value.to_string())?;
self.evaluate_if_not_paused(); self.evaluate_if_not_paused();
@@ -457,7 +457,7 @@ impl UserModel {
.worksheet(sheet)? .worksheet(sheet)?
.cell(row, column) .cell(row, column)
.cloned(); .cloned();
let old_style = self.model.get_style_for_cell(sheet, row, column); let old_style = self.model.get_style_for_cell(sheet, row, column)?;
self.model.cell_clear_all(sheet, row, column)?; self.model.cell_clear_all(sheet, row, column)?;
diff_list.push(Diff::CellClearAll { diff_list.push(Diff::CellClearAll {
sheet, sheet,
@@ -720,7 +720,7 @@ impl UserModel {
let row_index = ((row - row_start) % styles_heigh) as usize; let row_index = ((row - row_start) % styles_heigh) as usize;
let column_index = ((column - column_start) % styles_width) as usize; let column_index = ((column - column_start) % styles_width) as usize;
let style = &styles[row_index][column_index]; let style = &styles[row_index][column_index];
let old_value = self.model.get_style_for_cell(sheet, row, column); let old_value = self.model.get_style_for_cell(sheet, row, column)?;
self.model.set_cell_style(sheet, row, column, style)?; self.model.set_cell_style(sheet, row, column, style)?;
diff_list.push(Diff::SetCellStyle { diff_list.push(Diff::SetCellStyle {
sheet, sheet,
@@ -755,7 +755,7 @@ impl UserModel {
let last_column = range.column + range.width - 1; let last_column = range.column + range.width - 1;
for row in range.row..=last_row { for row in range.row..=last_row {
for column in range.column..=last_column { for column in range.column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column); let old_value = self.model.get_style_for_cell(sheet, row, column)?;
let mut style = old_value.clone(); let mut style = old_value.clone();
// First remove all existing borders // First remove all existing borders
@@ -852,7 +852,7 @@ impl UserModel {
let mut diff_list = Vec::new(); let mut diff_list = Vec::new();
for row in range.row..range.row + range.height { for row in range.row..range.row + range.height {
for column in range.column..range.column + range.width { for column in range.column..range.column + range.width {
let old_value = self.model.get_style_for_cell(sheet, row, column); let old_value = self.model.get_style_for_cell(sheet, row, column)?;
let mut style = old_value.clone(); let mut style = old_value.clone();
match style_path { match style_path {
"font.b" => { "font.b" => {
@@ -951,7 +951,7 @@ impl UserModel {
/// * [Model::get_style_for_cell] /// * [Model::get_style_for_cell]
#[inline] #[inline]
pub fn get_cell_style(&mut self, sheet: u32, row: i32, column: i32) -> Result<Style, String> { pub fn get_cell_style(&mut self, sheet: u32, row: i32, column: i32) -> Result<Style, String> {
Ok(self.model.get_style_for_cell(sheet, row, column)) self.model.get_style_for_cell(sheet, row, column)
} }
/// Fills the cells from `source_area` until `to_row`. /// Fills the cells from `source_area` until `to_row`.
@@ -1017,7 +1017,7 @@ impl UserModel {
.worksheet(sheet)? .worksheet(sheet)?
.cell(row, column) .cell(row, column)
.cloned(); .cloned();
let old_style = self.model.get_style_for_cell(sheet, row, column); let old_style = self.model.get_style_for_cell(sheet, row, column)?;
// compute the new value and set it // compute the new value and set it
let source_row = anchor_row + index; let source_row = anchor_row + index;
@@ -1025,10 +1025,10 @@ impl UserModel {
.model .model
.extend_to(sheet, source_row, column, row, column)?; .extend_to(sheet, source_row, column, row, column)?;
self.model self.model
.set_user_input(sheet, row, column, target_value.to_string()); .set_user_input(sheet, row, column, target_value.to_string())?;
// Compute the new style and set it // Compute the new style and set it
let new_style = self.model.get_style_for_cell(sheet, source_row, column); let new_style = self.model.get_style_for_cell(sheet, source_row, column)?;
self.model.set_cell_style(sheet, row, column, &new_style)?; self.model.set_cell_style(sheet, row, column, &new_style)?;
// Add the diffs // Add the diffs
@@ -1118,7 +1118,7 @@ impl UserModel {
.worksheet(sheet)? .worksheet(sheet)?
.cell(row, column) .cell(row, column)
.cloned(); .cloned();
let old_style = self.model.get_style_for_cell(sheet, row, column); let old_style = self.model.get_style_for_cell(sheet, row, column)?;
// compute the new value and set it // compute the new value and set it
let source_column = anchor_column + index; let source_column = anchor_column + index;
@@ -1126,10 +1126,10 @@ impl UserModel {
.model .model
.extend_to(sheet, row, source_column, row, column)?; .extend_to(sheet, row, source_column, row, column)?;
self.model self.model
.set_user_input(sheet, row, column, target_value.to_string()); .set_user_input(sheet, row, column, target_value.to_string())?;
// Compute the new style and set it // Compute the new style and set it
let new_style = self.model.get_style_for_cell(sheet, row, source_column); let new_style = self.model.get_style_for_cell(sheet, row, source_column)?;
self.model.set_cell_style(sheet, row, column, &new_style)?; self.model.set_cell_style(sheet, row, column, &new_style)?;
// Add the diffs // Add the diffs
@@ -1216,7 +1216,7 @@ impl UserModel {
self.model self.model
.workbook .workbook
.worksheet_mut(*sheet)? .worksheet_mut(*sheet)?
.update_cell(*row, *column, value); .update_cell(*row, *column, value)?;
} }
None => { None => {
self.model.cell_clear_all(*sheet, *row, *column)?; self.model.cell_clear_all(*sheet, *row, *column)?;
@@ -1246,7 +1246,7 @@ impl UserModel {
self.model self.model
.workbook .workbook
.worksheet_mut(*sheet)? .worksheet_mut(*sheet)?
.update_cell(*row, *column, value); .update_cell(*row, *column, value)?;
} }
} }
Diff::CellClearAll { Diff::CellClearAll {
@@ -1261,7 +1261,7 @@ impl UserModel {
self.model self.model
.workbook .workbook
.worksheet_mut(*sheet)? .worksheet_mut(*sheet)?
.update_cell(*row, *column, value); .update_cell(*row, *column, value)?;
self.model self.model
.set_cell_style(*sheet, *row, *column, old_style)?; .set_cell_style(*sheet, *row, *column, old_style)?;
} }
@@ -1307,7 +1307,7 @@ impl UserModel {
// puts all the data back // puts all the data back
let worksheet = self.model.workbook.worksheet_mut(*sheet)?; let worksheet = self.model.workbook.worksheet_mut(*sheet)?;
for (row, cell) in &old_data.data { for (row, cell) in &old_data.data {
worksheet.update_cell(*row, *column, cell.clone()); worksheet.update_cell(*row, *column, cell.clone())?;
} }
// makes sure that the width and style is correct // makes sure that the width and style is correct
if let Some(col) = &old_data.column { if let Some(col) = &old_data.column {
@@ -1375,7 +1375,7 @@ impl UserModel {
} => { } => {
needs_evaluation = true; needs_evaluation = true;
self.model self.model
.set_user_input(*sheet, *row, *column, new_value.to_string()); .set_user_input(*sheet, *row, *column, new_value.to_string())?;
} }
Diff::SetColumnWidth { Diff::SetColumnWidth {
sheet, sheet,

View File

@@ -42,7 +42,17 @@ impl Worksheet {
self.sheet_data.get_mut(&row)?.get_mut(&column) self.sheet_data.get_mut(&row)?.get_mut(&column)
} }
pub(crate) fn update_cell(&mut self, row: i32, column: i32, new_cell: Cell) { pub(crate) fn update_cell(
&mut self,
row: i32,
column: i32,
new_cell: Cell,
) -> Result<(), String> {
// validate row and column arg before updating cell of worksheet
if !is_valid_row(row) || !is_valid_column_number(column) {
return Err("Incorrect row or column".to_string());
}
match self.sheet_data.get_mut(&row) { match self.sheet_data.get_mut(&row) {
Some(column_data) => match column_data.get(&column) { Some(column_data) => match column_data.get(&column) {
Some(_cell) => { Some(_cell) => {
@@ -58,6 +68,7 @@ impl Worksheet {
self.sheet_data.insert(row, column_data); self.sheet_data.insert(row, column_data);
} }
} }
Ok(())
} }
// TODO [MVP]: Pass the cell style from the model // TODO [MVP]: Pass the cell style from the model
@@ -128,53 +139,94 @@ impl Worksheet {
Ok(()) Ok(())
} }
pub fn set_cell_style(&mut self, row: i32, column: i32, style_index: i32) { pub fn set_cell_style(
&mut self,
row: i32,
column: i32,
style_index: i32,
) -> Result<(), String> {
match self.cell_mut(row, column) { match self.cell_mut(row, column) {
Some(cell) => { Some(cell) => {
cell.set_style(style_index); cell.set_style(style_index);
} }
None => { None => {
self.cell_clear_contents_with_style(row, column, style_index); self.cell_clear_contents_with_style(row, column, style_index)?;
} }
} }
Ok(())
// TODO: cleanup check if the old cell style is still in use // TODO: cleanup check if the old cell style is still in use
} }
pub fn set_cell_with_formula(&mut self, row: i32, column: i32, index: i32, style: i32) { pub fn set_cell_with_formula(
&mut self,
row: i32,
column: i32,
index: i32,
style: i32,
) -> Result<(), String> {
let cell = Cell::new_formula(index, style); let cell = Cell::new_formula(index, style);
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn set_cell_with_number(&mut self, row: i32, column: i32, value: f64, style: i32) { pub fn set_cell_with_number(
&mut self,
row: i32,
column: i32,
value: f64,
style: i32,
) -> Result<(), String> {
let cell = Cell::new_number(value, style); let cell = Cell::new_number(value, style);
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn set_cell_with_string(&mut self, row: i32, column: i32, index: i32, style: i32) { pub fn set_cell_with_string(
&mut self,
row: i32,
column: i32,
index: i32,
style: i32,
) -> Result<(), String> {
let cell = Cell::new_string(index, style); let cell = Cell::new_string(index, style);
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn set_cell_with_boolean(&mut self, row: i32, column: i32, value: bool, style: i32) { pub fn set_cell_with_boolean(
&mut self,
row: i32,
column: i32,
value: bool,
style: i32,
) -> Result<(), String> {
let cell = Cell::new_boolean(value, style); let cell = Cell::new_boolean(value, style);
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn set_cell_with_error(&mut self, row: i32, column: i32, error: Error, style: i32) { pub fn set_cell_with_error(
&mut self,
row: i32,
column: i32,
error: Error,
style: i32,
) -> Result<(), String> {
let cell = Cell::new_error(error, style); let cell = Cell::new_error(error, style);
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn cell_clear_contents(&mut self, row: i32, column: i32) { pub fn cell_clear_contents(&mut self, row: i32, column: i32) -> Result<(), String> {
let s = self.get_style(row, column); let s = self.get_style(row, column);
let cell = Cell::EmptyCell { s }; let cell = Cell::EmptyCell { s };
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn cell_clear_contents_with_style(&mut self, row: i32, column: i32, style: i32) { pub fn cell_clear_contents_with_style(
&mut self,
row: i32,
column: i32,
style: i32,
) -> Result<(), String> {
let cell = Cell::EmptyCell { s: style }; let cell = Cell::EmptyCell { s: style };
self.update_cell(row, column, cell); self.update_cell(row, column, cell)
} }
pub fn set_frozen_rows(&mut self, frozen_rows: i32) -> Result<(), String> { pub fn set_frozen_rows(&mut self, frozen_rows: i32) -> Result<(), String> {

View File

@@ -9,7 +9,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
for row in 1..100 { for row in 1..100 {
for column in 1..100 { for column in 1..100 {
let value = row * column; let value = row * column;
model.set_user_input(0, row, column, format!("{}", value)); model
.set_user_input(0, row, column, format!("{}", value))
.unwrap();
} }
} }
// Adds a new sheet // Adds a new sheet
@@ -17,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// column 100 is CV // column 100 is CV
let last_column = number_to_column(100).unwrap(); let last_column = number_to_column(100).unwrap();
let formula = format!("=SUM(Sheet1!A1:{}100)", last_column); let formula = format!("=SUM(Sheet1!A1:{}100)", last_column);
model.set_user_input(1, 1, 1, formula); model.set_user_input(1, 1, 1, formula).unwrap();
// evaluates // evaluates
model.evaluate(); model.evaluate();

View File

@@ -5,7 +5,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// We are going to change styles in cell A1 // We are going to change styles in cell A1
let (sheet, row, column) = (0, 1, 1); let (sheet, row, column) = (0, 1, 1);
let mut style = model.get_style_for_cell(sheet, row, column); let mut style = model.get_style_for_cell(sheet, row, column)?;
style.fill.fg_color = Some("#FF9011".to_string()); style.fill.fg_color = Some("#FF9011".to_string());
style.font.b = true; style.font.b = true;
style.font.color = Some("#E91E63".to_string()); style.font.color = Some("#E91E63".to_string());

View File

@@ -15,16 +15,26 @@ pub fn new_empty_model() -> Model {
fn test_values() { fn test_values() {
let mut model = new_empty_model(); let mut model = new_empty_model();
// numbers // numbers
model.set_user_input(0, 1, 1, "123.456".to_string()); model
.set_user_input(0, 1, 1, "123.456".to_string())
.unwrap();
// strings // strings
model.set_user_input(0, 2, 1, "Hello world!".to_string()); model
model.set_user_input(0, 3, 1, "Hello world!".to_string()); .set_user_input(0, 2, 1, "Hello world!".to_string())
model.set_user_input(0, 4, 1, "你好世界!".to_string()); .unwrap();
model
.set_user_input(0, 3, 1, "Hello world!".to_string())
.unwrap();
model
.set_user_input(0, 4, 1, "你好世界!".to_string())
.unwrap();
// booleans // booleans
model.set_user_input(0, 5, 1, "TRUE".to_string()); model.set_user_input(0, 5, 1, "TRUE".to_string()).unwrap();
model.set_user_input(0, 6, 1, "FALSE".to_string()); model.set_user_input(0, 6, 1, "FALSE".to_string()).unwrap();
// errors // errors
model.set_user_input(0, 7, 1, "#VALUE!".to_string()); model
.set_user_input(0, 7, 1, "#VALUE!".to_string())
.unwrap();
// noop // noop
model.evaluate(); model.evaluate();
@@ -81,14 +91,16 @@ fn test_values() {
#[test] #[test]
fn test_formulas() { fn test_formulas() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "5.5".to_string()); model.set_user_input(0, 1, 1, "5.5".to_string()).unwrap();
model.set_user_input(0, 2, 1, "6.5".to_string()); model.set_user_input(0, 2, 1, "6.5".to_string()).unwrap();
model.set_user_input(0, 3, 1, "7.5".to_string()); model.set_user_input(0, 3, 1, "7.5".to_string()).unwrap();
model.set_user_input(0, 1, 2, "=A1*2".to_string()); model.set_user_input(0, 1, 2, "=A1*2".to_string()).unwrap();
model.set_user_input(0, 2, 2, "=A2*2".to_string()); model.set_user_input(0, 2, 2, "=A2*2".to_string()).unwrap();
model.set_user_input(0, 3, 2, "=A3*2".to_string()); model.set_user_input(0, 3, 2, "=A3*2".to_string()).unwrap();
model.set_user_input(0, 4, 2, "=SUM(A1:B3)".to_string()); model
.set_user_input(0, 4, 2, "=SUM(A1:B3)".to_string())
.unwrap();
model.evaluate(); model.evaluate();
let temp_file_name = "temp_file_test_formulas.xlsx"; let temp_file_name = "temp_file_test_formulas.xlsx";
@@ -127,12 +139,12 @@ fn test_sheets() {
#[test] #[test]
fn test_named_styles() { fn test_named_styles() {
let mut model = new_empty_model(); let mut model = new_empty_model();
model.set_user_input(0, 1, 1, "5.5".to_string()); model.set_user_input(0, 1, 1, "5.5".to_string()).unwrap();
let mut style = model.get_style_for_cell(0, 1, 1); let mut style = model.get_style_for_cell(0, 1, 1).unwrap();
style.font.b = true; style.font.b = true;
style.font.i = true; style.font.i = true;
assert!(model.set_cell_style(0, 1, 1, &style).is_ok()); assert!(model.set_cell_style(0, 1, 1, &style).is_ok());
let bold_style_index = model.get_cell_style_index(0, 1, 1); let bold_style_index = model.get_cell_style_index(0, 1, 1).unwrap();
let e = model let e = model
.workbook .workbook
.styles .styles

View File

@@ -158,42 +158,42 @@ fn test_split() {
fn test_model_has_correct_styles(model: &Model) { fn test_model_has_correct_styles(model: &Model) {
// A1 is bold // A1 is bold
let style_a1 = model.get_style_for_cell(0, 1, 1); let style_a1 = model.get_style_for_cell(0, 1, 1).unwrap();
assert!(style_a1.font.b); assert!(style_a1.font.b);
assert!(!style_a1.font.i); assert!(!style_a1.font.i);
assert!(!style_a1.font.u); assert!(!style_a1.font.u);
// B1 is Italics // B1 is Italics
let style_b1 = model.get_style_for_cell(0, 1, 2); let style_b1 = model.get_style_for_cell(0, 1, 2).unwrap();
assert!(style_b1.font.i); assert!(style_b1.font.i);
assert!(!style_b1.font.b); assert!(!style_b1.font.b);
assert!(!style_b1.font.u); assert!(!style_b1.font.u);
// C1 Underlined // C1 Underlined
let style_c1 = model.get_style_for_cell(0, 1, 3); let style_c1 = model.get_style_for_cell(0, 1, 3).unwrap();
assert!(style_c1.font.u); assert!(style_c1.font.u);
assert!(!style_c1.font.b); assert!(!style_c1.font.b);
assert!(!style_c1.font.i); assert!(!style_c1.font.i);
// D1 Bold and Italics // D1 Bold and Italics
let style_d1 = model.get_style_for_cell(0, 1, 4); let style_d1 = model.get_style_for_cell(0, 1, 4).unwrap();
assert!(style_d1.font.b); assert!(style_d1.font.b);
assert!(style_d1.font.i); assert!(style_d1.font.i);
assert!(!style_d1.font.u); assert!(!style_d1.font.u);
// E1 Bold, italics and underlined // E1 Bold, italics and underlined
let style_e1 = model.get_style_for_cell(0, 1, 5); let style_e1 = model.get_style_for_cell(0, 1, 5).unwrap();
assert!(style_e1.font.b); assert!(style_e1.font.b);
assert!(style_e1.font.i); assert!(style_e1.font.i);
assert!(style_e1.font.u); assert!(style_e1.font.u);
assert!(!style_e1.font.strike); assert!(!style_e1.font.strike);
// F1 strikethrough // F1 strikethrough
let style_f1 = model.get_style_for_cell(0, 1, 6); let style_f1 = model.get_style_for_cell(0, 1, 6).unwrap();
assert!(style_f1.font.strike); assert!(style_f1.font.strike);
// G1 Double underlined just get simple underlined // G1 Double underlined just get simple underlined
let style_g1 = model.get_style_for_cell(0, 1, 7); let style_g1 = model.get_style_for_cell(0, 1, 7).unwrap();
assert!(style_g1.font.u); assert!(style_g1.font.u);
let height_row_3 = model.workbook.worksheet(0).unwrap().row_height(3).unwrap(); let height_row_3 = model.workbook.worksheet(0).unwrap().row_height(3).unwrap();
@@ -204,44 +204,84 @@ fn test_model_has_correct_styles(model: &Model) {
// Second sheet has alignment // Second sheet has alignment
// Horizontal // Horizontal
let alignment = model.get_style_for_cell(1, 2, 1).alignment; let alignment = model.get_style_for_cell(1, 2, 1).unwrap().alignment;
assert_eq!(alignment, None); assert_eq!(alignment, None);
let alignment = model.get_style_for_cell(1, 3, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 3, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Left); assert_eq!(alignment.horizontal, HorizontalAlignment::Left);
let alignment = model.get_style_for_cell(1, 4, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 4, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Distributed); assert_eq!(alignment.horizontal, HorizontalAlignment::Distributed);
let alignment = model.get_style_for_cell(1, 5, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 5, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Right); assert_eq!(alignment.horizontal, HorizontalAlignment::Right);
let alignment = model.get_style_for_cell(1, 6, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 6, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Center); assert_eq!(alignment.horizontal, HorizontalAlignment::Center);
let alignment = model.get_style_for_cell(1, 7, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 7, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Fill); assert_eq!(alignment.horizontal, HorizontalAlignment::Fill);
let alignment = model.get_style_for_cell(1, 8, 1).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 8, 1)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.horizontal, HorizontalAlignment::Justify); assert_eq!(alignment.horizontal, HorizontalAlignment::Justify);
// Vertical // Vertical
let alignment = model.get_style_for_cell(1, 2, 2).alignment; let alignment = model.get_style_for_cell(1, 2, 2).unwrap().alignment;
assert_eq!(alignment, None); assert_eq!(alignment, None);
let alignment = model.get_style_for_cell(1, 3, 2).alignment; let alignment = model.get_style_for_cell(1, 3, 2).unwrap().alignment;
assert_eq!(alignment, None); assert_eq!(alignment, None);
let alignment = model.get_style_for_cell(1, 4, 2).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 4, 2)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.vertical, VerticalAlignment::Top); assert_eq!(alignment.vertical, VerticalAlignment::Top);
let alignment = model.get_style_for_cell(1, 5, 2).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 5, 2)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.vertical, VerticalAlignment::Center); assert_eq!(alignment.vertical, VerticalAlignment::Center);
let alignment = model.get_style_for_cell(1, 6, 2).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 6, 2)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.vertical, VerticalAlignment::Justify); assert_eq!(alignment.vertical, VerticalAlignment::Justify);
let alignment = model.get_style_for_cell(1, 7, 2).alignment.unwrap(); let alignment = model
.get_style_for_cell(1, 7, 2)
.unwrap()
.alignment
.unwrap();
assert_eq!(alignment.vertical, VerticalAlignment::Distributed); assert_eq!(alignment.vertical, VerticalAlignment::Distributed);
} }
@@ -280,7 +320,9 @@ fn test_defined_names_casing() {
("=NaMeD3", "33"), ("=NaMeD3", "33"),
]; ];
for (formula, expected_value) in test_cases { for (formula, expected_value) in test_cases {
model.set_user_input(0, row, column, formula.to_string()); model
.set_user_input(0, row, column, formula.to_string())
.unwrap();
model.evaluate(); model.evaluate();
assert_eq!( assert_eq!(
model.get_formatted_cell_value(0, row, column).unwrap(), model.get_formatted_cell_value(0, row, column).unwrap(),