FIX: Make clippy happy
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
46ea92966f
commit
0be7d9b85a
@@ -159,7 +159,7 @@ impl Model {
|
|||||||
// FIXME: I think when casting a number we should convert it to_precision(x, 15)
|
// FIXME: I think when casting a number we should convert it to_precision(x, 15)
|
||||||
// See function Exact
|
// See function Exact
|
||||||
match result {
|
match result {
|
||||||
CalcResult::Number(f) => Ok(format!("{}", f)),
|
CalcResult::Number(f) => Ok(format!("{f}")),
|
||||||
CalcResult::String(s) => Ok(s),
|
CalcResult::String(s) => Ok(s),
|
||||||
CalcResult::Boolean(f) => {
|
CalcResult::Boolean(f) => {
|
||||||
if f {
|
if f {
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ impl Lexer {
|
|||||||
pub fn expect(&mut self, tk: TokenType) -> Result<()> {
|
pub fn expect(&mut self, tk: TokenType) -> Result<()> {
|
||||||
let nt = self.next_token();
|
let nt = self.next_token();
|
||||||
if mem::discriminant(&nt) != mem::discriminant(&tk) {
|
if mem::discriminant(&nt) != mem::discriminant(&tk) {
|
||||||
return Err(self.set_error(&format!("Error, expected {:?}", tk), self.position));
|
return Err(self.set_error(&format!("Error, expected {tk:?}"), self.position));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -511,7 +511,7 @@ impl Lexer {
|
|||||||
self.position = position;
|
self.position = position;
|
||||||
chars.parse::<i32>().map_err(|_| LexerError {
|
chars.parse::<i32>().map_err(|_| LexerError {
|
||||||
position,
|
position,
|
||||||
message: format!("Failed to parse to int: {}", chars),
|
message: format!("Failed to parse to int: {chars}"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ impl Lexer {
|
|||||||
self.position = position;
|
self.position = position;
|
||||||
match chars.parse::<f64>() {
|
match chars.parse::<f64>() {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
Err(self.set_error(&format!("Failed to parse to double: {}", chars), position))
|
Err(self.set_error(&format!("Failed to parse to double: {chars}"), position))
|
||||||
}
|
}
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,14 +149,14 @@ impl Lexer {
|
|||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(self
|
return Err(self
|
||||||
.set_error(&format!("Failed parsing row {}", row_left), position))
|
.set_error(&format!("Failed parsing row {row_left}"), position))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let row_right = match row_right.parse::<i32>() {
|
let row_right = match row_right.parse::<i32>() {
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(self
|
return Err(self
|
||||||
.set_error(&format!("Failed parsing row {}", row_right), position))
|
.set_error(&format!("Failed parsing row {row_right}"), position))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if row_left > LAST_ROW {
|
if row_left > LAST_ROW {
|
||||||
|
|||||||
@@ -828,7 +828,7 @@ impl Parser {
|
|||||||
| TokenType::Percent => Node::ParseErrorKind {
|
| TokenType::Percent => Node::ParseErrorKind {
|
||||||
formula: self.lexer.get_formula(),
|
formula: self.lexer.get_formula(),
|
||||||
position: 0,
|
position: 0,
|
||||||
message: format!("Unexpected token: '{:?}'", next_token),
|
message: format!("Unexpected token: '{next_token:?}'"),
|
||||||
},
|
},
|
||||||
TokenType::LeftBracket => Node::ParseErrorKind {
|
TokenType::LeftBracket => Node::ParseErrorKind {
|
||||||
formula: self.lexer.get_formula(),
|
formula: self.lexer.get_formula(),
|
||||||
|
|||||||
@@ -53,24 +53,24 @@ fn move_function(name: &str, args: &Vec<Node>, move_context: &MoveContext) -> St
|
|||||||
arguments = to_string_moved(el, move_context);
|
arguments = to_string_moved(el, move_context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
format!("{}({})", name, arguments)
|
format!("{name}({arguments})")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_string_array_node(node: &ArrayNode) -> String {
|
pub(crate) fn to_string_array_node(node: &ArrayNode) -> String {
|
||||||
match node {
|
match node {
|
||||||
ArrayNode::Boolean(value) => format!("{}", value).to_ascii_uppercase(),
|
ArrayNode::Boolean(value) => format!("{value}").to_ascii_uppercase(),
|
||||||
ArrayNode::Number(number) => to_excel_precision_str(*number),
|
ArrayNode::Number(number) => to_excel_precision_str(*number),
|
||||||
ArrayNode::String(value) => format!("\"{}\"", value),
|
ArrayNode::String(value) => format!("\"{value}\""),
|
||||||
ArrayNode::Error(kind) => format!("{}", kind),
|
ArrayNode::Error(kind) => format!("{kind}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
||||||
use self::Node::*;
|
use self::Node::*;
|
||||||
match node {
|
match node {
|
||||||
BooleanKind(value) => format!("{}", value).to_ascii_uppercase(),
|
BooleanKind(value) => format!("{value}").to_ascii_uppercase(),
|
||||||
NumberKind(number) => to_excel_precision_str(*number),
|
NumberKind(number) => to_excel_precision_str(*number),
|
||||||
StringKind(value) => format!("\"{}\"", value),
|
StringKind(value) => format!("\"{value}\""),
|
||||||
ReferenceKind {
|
ReferenceKind {
|
||||||
sheet_name,
|
sheet_name,
|
||||||
sheet_index,
|
sheet_index,
|
||||||
@@ -241,7 +241,7 @@ fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
|||||||
full_row,
|
full_row,
|
||||||
full_column,
|
full_column,
|
||||||
);
|
);
|
||||||
format!("{}:{}", s1, s2)
|
format!("{s1}:{s2}")
|
||||||
}
|
}
|
||||||
WrongReferenceKind {
|
WrongReferenceKind {
|
||||||
sheet_name,
|
sheet_name,
|
||||||
@@ -325,7 +325,7 @@ fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
|||||||
full_row,
|
full_row,
|
||||||
full_column,
|
full_column,
|
||||||
);
|
);
|
||||||
format!("{}:{}", s1, s2)
|
format!("{s1}:{s2}")
|
||||||
}
|
}
|
||||||
OpRangeKind { left, right } => format!(
|
OpRangeKind { left, right } => format!(
|
||||||
"{}:{}",
|
"{}:{}",
|
||||||
@@ -358,7 +358,7 @@ fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
|||||||
}
|
}
|
||||||
_ => to_string_moved(right, move_context),
|
_ => to_string_moved(right, move_context),
|
||||||
};
|
};
|
||||||
format!("{}{}{}", x, kind, y)
|
format!("{x}{kind}{y}")
|
||||||
}
|
}
|
||||||
OpPowerKind { left, right } => format!(
|
OpPowerKind { left, right } => format!(
|
||||||
"{}^{}",
|
"{}^{}",
|
||||||
@@ -403,7 +403,7 @@ fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enclose the whole matrix in braces
|
// Enclose the whole matrix in braces
|
||||||
format!("{{{}}}", matrix_string)
|
format!("{{{matrix_string}}}")
|
||||||
}
|
}
|
||||||
DefinedNameKind((name, ..)) => name.to_string(),
|
DefinedNameKind((name, ..)) => name.to_string(),
|
||||||
TableNameKind(name) => name.to_string(),
|
TableNameKind(name) => name.to_string(),
|
||||||
@@ -418,7 +418,7 @@ fn to_string_moved(node: &Node, move_context: &MoveContext) -> String {
|
|||||||
OpUnary::Minus => format!("-{}", to_string_moved(right, move_context)),
|
OpUnary::Minus => format!("-{}", to_string_moved(right, move_context)),
|
||||||
OpUnary::Percentage => format!("{}%", to_string_moved(right, move_context)),
|
OpUnary::Percentage => format!("{}%", to_string_moved(right, move_context)),
|
||||||
},
|
},
|
||||||
ErrorKind(kind) => format!("{}", kind),
|
ErrorKind(kind) => format!("{kind}"),
|
||||||
ParseErrorKind {
|
ParseErrorKind {
|
||||||
formula,
|
formula,
|
||||||
message: _,
|
message: _,
|
||||||
|
|||||||
@@ -184,16 +184,16 @@ pub(crate) fn stringify_reference(
|
|||||||
return "#REF!".to_string();
|
return "#REF!".to_string();
|
||||||
}
|
}
|
||||||
let mut row_abs = if absolute_row {
|
let mut row_abs = if absolute_row {
|
||||||
format!("${}", row)
|
format!("${row}")
|
||||||
} else {
|
} else {
|
||||||
format!("{}", row)
|
format!("{row}")
|
||||||
};
|
};
|
||||||
let column = match crate::expressions::utils::number_to_column(column) {
|
let column = match crate::expressions::utils::number_to_column(column) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return "#REF!".to_string(),
|
None => return "#REF!".to_string(),
|
||||||
};
|
};
|
||||||
let mut col_abs = if absolute_column {
|
let mut col_abs = if absolute_column {
|
||||||
format!("${}", column)
|
format!("${column}")
|
||||||
} else {
|
} else {
|
||||||
column
|
column
|
||||||
};
|
};
|
||||||
@@ -208,27 +208,27 @@ pub(crate) fn stringify_reference(
|
|||||||
format!("{}!{}{}", quote_name(name), col_abs, row_abs)
|
format!("{}!{}{}", quote_name(name), col_abs, row_abs)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
format!("{}{}", col_abs, row_abs)
|
format!("{col_abs}{row_abs}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let row_abs = if absolute_row {
|
let row_abs = if absolute_row {
|
||||||
format!("R{}", row)
|
format!("R{row}")
|
||||||
} else {
|
} else {
|
||||||
format!("R[{}]", row)
|
format!("R[{row}]")
|
||||||
};
|
};
|
||||||
let col_abs = if absolute_column {
|
let col_abs = if absolute_column {
|
||||||
format!("C{}", column)
|
format!("C{column}")
|
||||||
} else {
|
} else {
|
||||||
format!("C[{}]", column)
|
format!("C[{column}]")
|
||||||
};
|
};
|
||||||
match &sheet_name {
|
match &sheet_name {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
format!("{}!{}{}", quote_name(name), row_abs, col_abs)
|
format!("{}!{}{}", quote_name(name), row_abs, col_abs)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
format!("{}{}", row_abs, col_abs)
|
format!("{row_abs}{col_abs}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,7 +256,7 @@ fn format_function(
|
|||||||
arguments = stringify(el, context, displace_data, export_to_excel);
|
arguments = stringify(el, context, displace_data, export_to_excel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
format!("{}({})", name, arguments)
|
format!("{name}({arguments})")
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is just one representation in the AST (Abstract Syntax Tree) of a formula.
|
// There is just one representation in the AST (Abstract Syntax Tree) of a formula.
|
||||||
@@ -292,9 +292,9 @@ fn stringify(
|
|||||||
) -> String {
|
) -> String {
|
||||||
use self::Node::*;
|
use self::Node::*;
|
||||||
match node {
|
match node {
|
||||||
BooleanKind(value) => format!("{}", value).to_ascii_uppercase(),
|
BooleanKind(value) => format!("{value}").to_ascii_uppercase(),
|
||||||
NumberKind(number) => to_excel_precision_str(*number),
|
NumberKind(number) => to_excel_precision_str(*number),
|
||||||
StringKind(value) => format!("\"{}\"", value),
|
StringKind(value) => format!("\"{value}\""),
|
||||||
WrongReferenceKind {
|
WrongReferenceKind {
|
||||||
sheet_name,
|
sheet_name,
|
||||||
column,
|
column,
|
||||||
@@ -384,7 +384,7 @@ fn stringify(
|
|||||||
full_row,
|
full_row,
|
||||||
full_column,
|
full_column,
|
||||||
);
|
);
|
||||||
format!("{}:{}", s1, s2)
|
format!("{s1}:{s2}")
|
||||||
}
|
}
|
||||||
WrongRangeKind {
|
WrongRangeKind {
|
||||||
sheet_name,
|
sheet_name,
|
||||||
@@ -433,7 +433,7 @@ fn stringify(
|
|||||||
full_row,
|
full_row,
|
||||||
full_column,
|
full_column,
|
||||||
);
|
);
|
||||||
format!("{}:{}", s1, s2)
|
format!("{s1}:{s2}")
|
||||||
}
|
}
|
||||||
OpRangeKind { left, right } => format!(
|
OpRangeKind { left, right } => format!(
|
||||||
"{}:{}",
|
"{}:{}",
|
||||||
@@ -484,7 +484,7 @@ fn stringify(
|
|||||||
),
|
),
|
||||||
_ => stringify(right, context, displace_data, export_to_excel),
|
_ => stringify(right, context, displace_data, export_to_excel),
|
||||||
};
|
};
|
||||||
format!("{}{}{}", x, kind, y)
|
format!("{x}{kind}{y}")
|
||||||
}
|
}
|
||||||
OpPowerKind { left, right } => {
|
OpPowerKind { left, right } => {
|
||||||
let x = match **left {
|
let x = match **left {
|
||||||
@@ -547,7 +547,7 @@ fn stringify(
|
|||||||
stringify(right, context, displace_data, export_to_excel)
|
stringify(right, context, displace_data, export_to_excel)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
format!("{}^{}", x, y)
|
format!("{x}^{y}")
|
||||||
}
|
}
|
||||||
InvalidFunctionKind { name, args } => {
|
InvalidFunctionKind { name, args } => {
|
||||||
format_function(name, args, context, displace_data, export_to_excel)
|
format_function(name, args, context, displace_data, export_to_excel)
|
||||||
@@ -582,7 +582,7 @@ fn stringify(
|
|||||||
}
|
}
|
||||||
matrix_string.push_str(&row_string);
|
matrix_string.push_str(&row_string);
|
||||||
}
|
}
|
||||||
format!("{{{}}}", matrix_string)
|
format!("{{{matrix_string}}}")
|
||||||
}
|
}
|
||||||
TableNameKind(value) => value.to_string(),
|
TableNameKind(value) => value.to_string(),
|
||||||
DefinedNameKind((name, ..)) => name.to_string(),
|
DefinedNameKind((name, ..)) => name.to_string(),
|
||||||
@@ -601,7 +601,7 @@ fn stringify(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ErrorKind(kind) => format!("{}", kind),
|
ErrorKind(kind) => format!("{kind}"),
|
||||||
ParseErrorKind {
|
ParseErrorKind {
|
||||||
formula,
|
formula,
|
||||||
position: _,
|
position: _,
|
||||||
|
|||||||
@@ -21,14 +21,12 @@ fn is_date_within_range(date: NaiveDate) -> bool {
|
|||||||
pub fn from_excel_date(days: i64) -> Result<NaiveDate, String> {
|
pub fn from_excel_date(days: i64) -> Result<NaiveDate, String> {
|
||||||
if days < MINIMUM_DATE_SERIAL_NUMBER as i64 {
|
if days < MINIMUM_DATE_SERIAL_NUMBER as i64 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Excel date must be greater than {}",
|
"Excel date must be greater than {MINIMUM_DATE_SERIAL_NUMBER}"
|
||||||
MINIMUM_DATE_SERIAL_NUMBER
|
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
if days > MAXIMUM_DATE_SERIAL_NUMBER as i64 {
|
if days > MAXIMUM_DATE_SERIAL_NUMBER as i64 {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Excel date must be less than {}",
|
"Excel date must be less than {MAXIMUM_DATE_SERIAL_NUMBER}"
|
||||||
MAXIMUM_DATE_SERIAL_NUMBER
|
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
// We should have different codepaths for general formatting and errors
|
// We should have different codepaths for general formatting and errors
|
||||||
let value_abs = value.abs();
|
let value_abs = value.abs();
|
||||||
if (1.0e-8..1.0e+11).contains(&value_abs) {
|
if (1.0e-8..1.0e+11).contains(&value_abs) {
|
||||||
let mut text = format!("{:.9}", value);
|
let mut text = format!("{value:.9}");
|
||||||
text = text.trim_end_matches('0').trim_end_matches('.').to_string();
|
text = text.trim_end_matches('0').trim_end_matches('.').to_string();
|
||||||
Formatted {
|
Formatted {
|
||||||
text,
|
text,
|
||||||
@@ -138,7 +138,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
let exponent = value_abs.log10().floor();
|
let exponent = value_abs.log10().floor();
|
||||||
value /= 10.0_f64.powf(exponent);
|
value /= 10.0_f64.powf(exponent);
|
||||||
let sign = if exponent < 0.0 { '-' } else { '+' };
|
let sign = if exponent < 0.0 { '-' } else { '+' };
|
||||||
let s = format!("{:.5}", value);
|
let s = format!("{value:.5}");
|
||||||
Formatted {
|
Formatted {
|
||||||
text: format!(
|
text: format!(
|
||||||
"{}E{}{:02}",
|
"{}E{}{:02}",
|
||||||
@@ -167,33 +167,33 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
for token in tokens {
|
for token in tokens {
|
||||||
match token {
|
match token {
|
||||||
TextToken::Literal(c) => {
|
TextToken::Literal(c) => {
|
||||||
text = format!("{}{}", text, c);
|
text = format!("{text}{c}");
|
||||||
}
|
}
|
||||||
TextToken::Text(t) => {
|
TextToken::Text(t) => {
|
||||||
text = format!("{}{}", text, t);
|
text = format!("{text}{t}");
|
||||||
}
|
}
|
||||||
TextToken::Ghost(_) => {
|
TextToken::Ghost(_) => {
|
||||||
// we just leave a whitespace
|
// we just leave a whitespace
|
||||||
// This is what the TEXT function does
|
// This is what the TEXT function does
|
||||||
text = format!("{} ", text);
|
text = format!("{text} ");
|
||||||
}
|
}
|
||||||
TextToken::Spacer(_) => {
|
TextToken::Spacer(_) => {
|
||||||
// we just leave a whitespace
|
// we just leave a whitespace
|
||||||
// This is what the TEXT function does
|
// This is what the TEXT function does
|
||||||
text = format!("{} ", text);
|
text = format!("{text} ");
|
||||||
}
|
}
|
||||||
TextToken::Raw => {
|
TextToken::Raw => {
|
||||||
text = format!("{}{}", text, value);
|
text = format!("{text}{value}");
|
||||||
}
|
}
|
||||||
TextToken::Digit(_) => {}
|
TextToken::Digit(_) => {}
|
||||||
TextToken::Period => {}
|
TextToken::Period => {}
|
||||||
TextToken::Day => {
|
TextToken::Day => {
|
||||||
let day = date.day() as usize;
|
let day = date.day() as usize;
|
||||||
text = format!("{}{}", text, day);
|
text = format!("{text}{day}");
|
||||||
}
|
}
|
||||||
TextToken::DayPadded => {
|
TextToken::DayPadded => {
|
||||||
let day = date.day() as usize;
|
let day = date.day() as usize;
|
||||||
text = format!("{}{:02}", text, day);
|
text = format!("{text}{day:02}");
|
||||||
}
|
}
|
||||||
TextToken::DayNameShort => {
|
TextToken::DayNameShort => {
|
||||||
let mut day = date.weekday().number_from_monday() as usize;
|
let mut day = date.weekday().number_from_monday() as usize;
|
||||||
@@ -211,11 +211,11 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
}
|
}
|
||||||
TextToken::Month => {
|
TextToken::Month => {
|
||||||
let month = date.month() as usize;
|
let month = date.month() as usize;
|
||||||
text = format!("{}{}", text, month);
|
text = format!("{text}{month}");
|
||||||
}
|
}
|
||||||
TextToken::MonthPadded => {
|
TextToken::MonthPadded => {
|
||||||
let month = date.month() as usize;
|
let month = date.month() as usize;
|
||||||
text = format!("{}{:02}", text, month);
|
text = format!("{text}{month:02}");
|
||||||
}
|
}
|
||||||
TextToken::MonthNameShort => {
|
TextToken::MonthNameShort => {
|
||||||
let month = date.month() as usize;
|
let month = date.month() as usize;
|
||||||
@@ -228,7 +228,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
TextToken::MonthLetter => {
|
TextToken::MonthLetter => {
|
||||||
let month = date.month() as usize;
|
let month = date.month() as usize;
|
||||||
let months_letter = &locale.dates.months_letter[month - 1];
|
let months_letter = &locale.dates.months_letter[month - 1];
|
||||||
text = format!("{}{}", text, months_letter);
|
text = format!("{text}{months_letter}");
|
||||||
}
|
}
|
||||||
TextToken::YearShort => {
|
TextToken::YearShort => {
|
||||||
text = format!("{}{}", text, date.format("%y"));
|
text = format!("{}{}", text, date.format("%y"));
|
||||||
@@ -247,7 +247,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
ParsePart::Number(p) => {
|
ParsePart::Number(p) => {
|
||||||
let mut text = "".to_string();
|
let mut text = "".to_string();
|
||||||
if let Some(c) = p.currency {
|
if let Some(c) = p.currency {
|
||||||
text = format!("{}", c);
|
text = format!("{c}");
|
||||||
}
|
}
|
||||||
let tokens = &p.tokens;
|
let tokens = &p.tokens;
|
||||||
value = value * 100.0_f64.powi(p.percent) / (1000.0_f64.powi(p.comma));
|
value = value * 100.0_f64.powi(p.percent) / (1000.0_f64.powi(p.comma));
|
||||||
@@ -295,26 +295,26 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
for token in tokens {
|
for token in tokens {
|
||||||
match token {
|
match token {
|
||||||
TextToken::Literal(c) => {
|
TextToken::Literal(c) => {
|
||||||
text = format!("{}{}", text, c);
|
text = format!("{text}{c}");
|
||||||
}
|
}
|
||||||
TextToken::Text(t) => {
|
TextToken::Text(t) => {
|
||||||
text = format!("{}{}", text, t);
|
text = format!("{text}{t}");
|
||||||
}
|
}
|
||||||
TextToken::Ghost(_) => {
|
TextToken::Ghost(_) => {
|
||||||
// we just leave a whitespace
|
// we just leave a whitespace
|
||||||
// This is what the TEXT function does
|
// This is what the TEXT function does
|
||||||
text = format!("{} ", text);
|
text = format!("{text} ");
|
||||||
}
|
}
|
||||||
TextToken::Spacer(_) => {
|
TextToken::Spacer(_) => {
|
||||||
// we just leave a whitespace
|
// we just leave a whitespace
|
||||||
// This is what the TEXT function does
|
// This is what the TEXT function does
|
||||||
text = format!("{} ", text);
|
text = format!("{text} ");
|
||||||
}
|
}
|
||||||
TextToken::Raw => {
|
TextToken::Raw => {
|
||||||
text = format!("{}{}", text, value);
|
text = format!("{text}{value}");
|
||||||
}
|
}
|
||||||
TextToken::Period => {
|
TextToken::Period => {
|
||||||
text = format!("{}{}", text, decimal_separator);
|
text = format!("{text}{decimal_separator}");
|
||||||
}
|
}
|
||||||
TextToken::Digit(digit) => {
|
TextToken::Digit(digit) => {
|
||||||
if digit.number == 'i' {
|
if digit.number == 'i' {
|
||||||
@@ -322,7 +322,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
let index = digit.index;
|
let index = digit.index;
|
||||||
let number_index = ln - digit_count + index;
|
let number_index = ln - digit_count + index;
|
||||||
if index == 0 && is_negative {
|
if index == 0 && is_negative {
|
||||||
text = format!("-{}", text);
|
text = format!("-{text}");
|
||||||
}
|
}
|
||||||
if ln <= digit_count {
|
if ln <= digit_count {
|
||||||
// The number of digits is less or equal than the number of digit tokens
|
// The number of digits is less or equal than the number of digit tokens
|
||||||
@@ -347,7 +347,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
text = format!("{}{}{}", text, c, sep);
|
text = format!("{text}{c}{sep}");
|
||||||
}
|
}
|
||||||
digit_index += 1;
|
digit_index += 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -373,18 +373,18 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
if index < fract_part.len() {
|
if index < fract_part.len() {
|
||||||
text = format!("{}{}", text, fract_part[index]);
|
text = format!("{}{}", text, fract_part[index]);
|
||||||
} else if digit.kind == '0' {
|
} else if digit.kind == '0' {
|
||||||
text = format!("{}0", text);
|
text = format!("{text}0");
|
||||||
} else if digit.kind == '?' {
|
} else if digit.kind == '?' {
|
||||||
text = format!("{} ", text);
|
text = format!("{text} ");
|
||||||
}
|
}
|
||||||
} else if digit.number == 'e' {
|
} else if digit.number == 'e' {
|
||||||
// 3. Exponent part
|
// 3. Exponent part
|
||||||
let index = digit.index;
|
let index = digit.index;
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
if exponent_is_negative {
|
if exponent_is_negative {
|
||||||
text = format!("{}E-", text);
|
text = format!("{text}E-");
|
||||||
} else {
|
} else {
|
||||||
text = format!("{}E+", text);
|
text = format!("{text}E+");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let number_index = l_exp - (p.exponent_digit_count - index);
|
let number_index = l_exp - (p.exponent_digit_count - index);
|
||||||
@@ -400,7 +400,7 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form
|
|||||||
exponent_part[number_index as usize]
|
exponent_part[number_index as usize]
|
||||||
};
|
};
|
||||||
|
|
||||||
text = format!("{}{}", text, c);
|
text = format!("{text}{c}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for i in 0..number_index + 1 {
|
for i in 0..number_index + 1 {
|
||||||
@@ -614,7 +614,7 @@ pub(crate) fn parse_formatted_number(
|
|||||||
|
|
||||||
// check if it is a currency in currencies
|
// check if it is a currency in currencies
|
||||||
for currency in currencies {
|
for currency in currencies {
|
||||||
if let Some(p) = value.strip_prefix(&format!("-{}", currency)) {
|
if let Some(p) = value.strip_prefix(&format!("-{currency}")) {
|
||||||
let (f, options) = parse_number(p.trim())?;
|
let (f, options) = parse_number(p.trim())?;
|
||||||
if options.is_scientific {
|
if options.is_scientific {
|
||||||
return Ok((f, Some(scientific_format.to_string())));
|
return Ok((f, Some(scientific_format.to_string())));
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ impl Lexer {
|
|||||||
} else if s == '-' {
|
} else if s == '-' {
|
||||||
Token::ScientificMinus
|
Token::ScientificMinus
|
||||||
} else {
|
} else {
|
||||||
self.set_error(&format!("Unexpected char: {}. Expected + or -", s));
|
self.set_error(&format!("Unexpected char: {s}. Expected + or -"));
|
||||||
Token::ILLEGAL
|
Token::ILLEGAL
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -385,14 +385,14 @@ impl Lexer {
|
|||||||
for c in "eneral".chars() {
|
for c in "eneral".chars() {
|
||||||
let cc = self.read_next_char();
|
let cc = self.read_next_char();
|
||||||
if Some(c) != cc {
|
if Some(c) != cc {
|
||||||
self.set_error(&format!("Unexpected character: {}", x));
|
self.set_error(&format!("Unexpected character: {x}"));
|
||||||
return Token::ILLEGAL;
|
return Token::ILLEGAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::General
|
Token::General
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.set_error(&format!("Unexpected character: {}", x));
|
self.set_error(&format!("Unexpected character: {x}"));
|
||||||
Token::ILLEGAL
|
Token::ILLEGAL
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,18 +46,18 @@ impl fmt::Display for Complex {
|
|||||||
// it is a bit weird what Excel does but it seems it uses general notation for
|
// it is a bit weird what Excel does but it seems it uses general notation for
|
||||||
// numbers > 1e-20 and scientific notation for the rest
|
// numbers > 1e-20 and scientific notation for the rest
|
||||||
let y_str = if y.abs() <= 9e-20 {
|
let y_str = if y.abs() <= 9e-20 {
|
||||||
format!("{:E}", y)
|
format!("{y:E}")
|
||||||
} else if y == 1.0 {
|
} else if y == 1.0 {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else if y == -1.0 {
|
} else if y == -1.0 {
|
||||||
"-".to_string()
|
"-".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{}", y)
|
format!("{y}")
|
||||||
};
|
};
|
||||||
let x_str = if x.abs() <= 9e-20 {
|
let x_str = if x.abs() <= 9e-20 {
|
||||||
format!("{:E}", x)
|
format!("{x:E}")
|
||||||
} else {
|
} else {
|
||||||
format!("{}", x)
|
format!("{x}")
|
||||||
};
|
};
|
||||||
if y == 0.0 && x == 0.0 {
|
if y == 0.0 && x == 0.0 {
|
||||||
write!(f, "0")
|
write!(f, "0")
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
CalcResult::String(format!("{:0width$X}", HEX_MAX + value, width = 9))
|
CalcResult::String(format!("{:0width$X}", HEX_MAX + value, width = 9))
|
||||||
} else {
|
} else {
|
||||||
let result = format!("{:X}", value);
|
let result = format!("{value:X}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if places < result.len() as i32 {
|
if places < result.len() as i32 {
|
||||||
return CalcResult::new_error(
|
return CalcResult::new_error(
|
||||||
@@ -120,7 +120,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
CalcResult::String(format!("{:0width$o}", OCT_MAX + value, width = 9))
|
CalcResult::String(format!("{:0width$o}", OCT_MAX + value, width = 9))
|
||||||
} else {
|
} else {
|
||||||
let result = format!("{:o}", value);
|
let result = format!("{value:o}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if places < result.len() as i32 {
|
if places < result.len() as i32 {
|
||||||
return CalcResult::new_error(
|
return CalcResult::new_error(
|
||||||
@@ -163,7 +163,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += 1024;
|
value += 1024;
|
||||||
}
|
}
|
||||||
let result = format!("{:b}", value);
|
let result = format!("{value:b}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if value_raw > 0.0 && places < result.len() as i32 {
|
if value_raw > 0.0 && places < result.len() as i32 {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -202,7 +202,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += HEX_MAX;
|
value += HEX_MAX;
|
||||||
}
|
}
|
||||||
let result = format!("{:X}", value);
|
let result = format!("{value:X}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if value_raw > 0.0 && places < result.len() as i32 {
|
if value_raw > 0.0 && places < result.len() as i32 {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -242,7 +242,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += OCT_MAX;
|
value += OCT_MAX;
|
||||||
}
|
}
|
||||||
let result = format!("{:o}", value);
|
let result = format!("{value:o}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if value_raw > 0.0 && places < result.len() as i32 {
|
if value_raw > 0.0 && places < result.len() as i32 {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -301,7 +301,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += 1024;
|
value += 1024;
|
||||||
}
|
}
|
||||||
let result = format!("{:b}", value);
|
let result = format!("{value:b}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if places <= 0 || (value > 0 && places < result.len() as i32) {
|
if places <= 0 || (value > 0 && places < result.len() as i32) {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -391,7 +391,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += OCT_MAX;
|
value += OCT_MAX;
|
||||||
}
|
}
|
||||||
let result = format!("{:o}", value);
|
let result = format!("{value:o}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if places <= 0 || (value > 0 && places < result.len() as i32) {
|
if places <= 0 || (value > 0 && places < result.len() as i32) {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -446,7 +446,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += 1024;
|
value += 1024;
|
||||||
}
|
}
|
||||||
let result = format!("{:b}", value);
|
let result = format!("{value:b}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if value < 512 && places < result.len() as i32 {
|
if value < 512 && places < result.len() as i32 {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
@@ -532,7 +532,7 @@ impl Model {
|
|||||||
if value < 0 {
|
if value < 0 {
|
||||||
value += HEX_MAX;
|
value += HEX_MAX;
|
||||||
}
|
}
|
||||||
let result = format!("{:X}", value);
|
let result = format!("{value:X}");
|
||||||
if let Some(places) = places {
|
if let Some(places) = places {
|
||||||
if value < HEX_MAX_HALF && places < result.len() as i32 {
|
if value < HEX_MAX_HALF && places < result.len() as i32 {
|
||||||
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
return CalcResult::new_error(Error::NUM, cell, "Out of bounds".to_string());
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ impl Model {
|
|||||||
CalcResult::new_error(
|
CalcResult::new_error(
|
||||||
Error::ERROR,
|
Error::ERROR,
|
||||||
*cell,
|
*cell,
|
||||||
format!("Invalid worksheet index: '{}'", sheet),
|
format!("Invalid worksheet index: '{sheet}'"),
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
@@ -245,7 +245,7 @@ impl Model {
|
|||||||
CalcResult::new_error(
|
CalcResult::new_error(
|
||||||
Error::ERROR,
|
Error::ERROR,
|
||||||
*cell,
|
*cell,
|
||||||
format!("Invalid worksheet index: '{}'", sheet),
|
format!("Invalid worksheet index: '{sheet}'"),
|
||||||
)
|
)
|
||||||
})?
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
|
|||||||
@@ -1214,7 +1214,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// We make a list with their functions names, but we escape ".": ERROR.TYPE => ERRORTYPE
|
// We make a list with their functions names, but we escape ".": ERROR.TYPE => ERRORTYPE
|
||||||
let iter_list = Function::into_iter()
|
let iter_list = Function::into_iter()
|
||||||
.map(|f| format!("{}", f).replace('.', ""))
|
.map(|f| format!("{f}").replace('.', ""))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let len = iter_list.len();
|
let len = iter_list.len();
|
||||||
|
|||||||
@@ -55,14 +55,14 @@ impl Model {
|
|||||||
let mut result = "".to_string();
|
let mut result = "".to_string();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match self.evaluate_node_in_context(arg, cell) {
|
match self.evaluate_node_in_context(arg, cell) {
|
||||||
CalcResult::String(value) => result = format!("{}{}", result, value),
|
CalcResult::String(value) => result = format!("{result}{value}"),
|
||||||
CalcResult::Number(value) => result = format!("{}{}", result, value),
|
CalcResult::Number(value) => result = format!("{result}{value}"),
|
||||||
CalcResult::EmptyCell | CalcResult::EmptyArg => {}
|
CalcResult::EmptyCell | CalcResult::EmptyArg => {}
|
||||||
CalcResult::Boolean(value) => {
|
CalcResult::Boolean(value) => {
|
||||||
if value {
|
if value {
|
||||||
result = format!("{}TRUE", result);
|
result = format!("{result}TRUE");
|
||||||
} else {
|
} else {
|
||||||
result = format!("{}FALSE", result);
|
result = format!("{result}FALSE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error @ CalcResult::Error { .. } => return error,
|
error @ CalcResult::Error { .. } => return error,
|
||||||
@@ -82,16 +82,16 @@ impl Model {
|
|||||||
column,
|
column,
|
||||||
}) {
|
}) {
|
||||||
CalcResult::String(value) => {
|
CalcResult::String(value) => {
|
||||||
result = format!("{}{}", result, value);
|
result = format!("{result}{value}");
|
||||||
}
|
}
|
||||||
CalcResult::Number(value) => {
|
CalcResult::Number(value) => {
|
||||||
result = format!("{}{}", result, value)
|
result = format!("{result}{value}")
|
||||||
}
|
}
|
||||||
CalcResult::Boolean(value) => {
|
CalcResult::Boolean(value) => {
|
||||||
if value {
|
if value {
|
||||||
result = format!("{}TRUE", result);
|
result = format!("{result}TRUE");
|
||||||
} else {
|
} else {
|
||||||
result = format!("{}FALSE", result);
|
result = format!("{result}FALSE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error @ CalcResult::Error { .. } => return error,
|
error @ CalcResult::Error { .. } => return error,
|
||||||
@@ -282,7 +282,7 @@ impl Model {
|
|||||||
pub(crate) fn fn_len(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
pub(crate) fn fn_len(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -317,7 +317,7 @@ impl Model {
|
|||||||
pub(crate) fn fn_trim(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
pub(crate) fn fn_trim(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -352,7 +352,7 @@ impl Model {
|
|||||||
pub(crate) fn fn_lower(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
pub(crate) fn fn_lower(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -387,7 +387,7 @@ impl Model {
|
|||||||
pub(crate) fn fn_unicode(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
pub(crate) fn fn_unicode(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -441,7 +441,7 @@ impl Model {
|
|||||||
pub(crate) fn fn_upper(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
pub(crate) fn fn_upper(&mut self, args: &[Node], cell: CellReferenceIndex) -> CalcResult {
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -478,7 +478,7 @@ impl Model {
|
|||||||
return CalcResult::new_args_number_error(cell);
|
return CalcResult::new_args_number_error(cell);
|
||||||
}
|
}
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -560,7 +560,7 @@ impl Model {
|
|||||||
return CalcResult::new_args_number_error(cell);
|
return CalcResult::new_args_number_error(cell);
|
||||||
}
|
}
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
@@ -642,7 +642,7 @@ impl Model {
|
|||||||
return CalcResult::new_args_number_error(cell);
|
return CalcResult::new_args_number_error(cell);
|
||||||
}
|
}
|
||||||
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
let s = match self.evaluate_node_in_context(&args[0], cell) {
|
||||||
CalcResult::Number(v) => format!("{}", v),
|
CalcResult::Number(v) => format!("{v}"),
|
||||||
CalcResult::String(v) => v,
|
CalcResult::String(v) => v,
|
||||||
CalcResult::Boolean(b) => {
|
CalcResult::Boolean(b) => {
|
||||||
if b {
|
if b {
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ pub(crate) fn from_wildcard_to_regex(
|
|||||||
|
|
||||||
// And we have a valid Perl regex! (As Kim Kardashian said before me: "I know, right?")
|
// And we have a valid Perl regex! (As Kim Kardashian said before me: "I know, right?")
|
||||||
if exact {
|
if exact {
|
||||||
return regex::Regex::new(&format!("^{}$", reg));
|
return regex::Regex::new(&format!("^{reg}$"));
|
||||||
}
|
}
|
||||||
regex::Regex::new(reg)
|
regex::Regex::new(reg)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,6 @@ static LANGUAGES: Lazy<HashMap<String, Language>> = Lazy::new(|| {
|
|||||||
pub fn get_language(id: &str) -> Result<&Language, String> {
|
pub fn get_language(id: &str) -> Result<&Language, String> {
|
||||||
let language = LANGUAGES
|
let language = LANGUAGES
|
||||||
.get(id)
|
.get(id)
|
||||||
.ok_or(format!("Language is not supported: '{}'", id))?;
|
.ok_or(format!("Language is not supported: '{id}'"))?;
|
||||||
Ok(language)
|
Ok(language)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ impl Model {
|
|||||||
_ => CalcResult::new_error(
|
_ => CalcResult::new_error(
|
||||||
Error::ERROR,
|
Error::ERROR,
|
||||||
cell,
|
cell,
|
||||||
format!("Error with Implicit Intersection in cell {:?}", cell),
|
format!("Error with Implicit Intersection in cell {cell:?}"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
_ => self.evaluate_node_in_context(node, cell),
|
_ => self.evaluate_node_in_context(node, cell),
|
||||||
@@ -355,7 +355,7 @@ impl Model {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let result = format!("{}{}", l, r);
|
let result = format!("{l}{r}");
|
||||||
CalcResult::String(result)
|
CalcResult::String(result)
|
||||||
}
|
}
|
||||||
OpProductKind { kind, left, right } => match kind {
|
OpProductKind { kind, left, right } => match kind {
|
||||||
@@ -375,7 +375,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
FunctionKind { kind, args } => self.evaluate_function(kind, args, cell),
|
FunctionKind { kind, args } => self.evaluate_function(kind, args, cell),
|
||||||
InvalidFunctionKind { name, args: _ } => {
|
InvalidFunctionKind { name, args: _ } => {
|
||||||
CalcResult::new_error(Error::ERROR, cell, format!("Invalid function: {}", name))
|
CalcResult::new_error(Error::ERROR, cell, format!("Invalid function: {name}"))
|
||||||
}
|
}
|
||||||
ArrayKind(s) => CalcResult::Array(s.to_owned()),
|
ArrayKind(s) => CalcResult::Array(s.to_owned()),
|
||||||
DefinedNameKind((name, scope, _)) => {
|
DefinedNameKind((name, scope, _)) => {
|
||||||
@@ -391,26 +391,26 @@ impl Model {
|
|||||||
ParsedDefinedName::InvalidDefinedNameFormula => CalcResult::new_error(
|
ParsedDefinedName::InvalidDefinedNameFormula => CalcResult::new_error(
|
||||||
Error::NAME,
|
Error::NAME,
|
||||||
cell,
|
cell,
|
||||||
format!("Defined name \"{}\" is not a reference.", name),
|
format!("Defined name \"{name}\" is not a reference."),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CalcResult::new_error(
|
CalcResult::new_error(
|
||||||
Error::NAME,
|
Error::NAME,
|
||||||
cell,
|
cell,
|
||||||
format!("Defined name \"{}\" not found.", name),
|
format!("Defined name \"{name}\" not found."),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TableNameKind(s) => CalcResult::new_error(
|
TableNameKind(s) => CalcResult::new_error(
|
||||||
Error::NAME,
|
Error::NAME,
|
||||||
cell,
|
cell,
|
||||||
format!("table name \"{}\" not supported.", s),
|
format!("table name \"{s}\" not supported."),
|
||||||
),
|
),
|
||||||
WrongVariableKind(s) => CalcResult::new_error(
|
WrongVariableKind(s) => CalcResult::new_error(
|
||||||
Error::NAME,
|
Error::NAME,
|
||||||
cell,
|
cell,
|
||||||
format!("Variable name \"{}\" not found.", s),
|
format!("Variable name \"{s}\" not found."),
|
||||||
),
|
),
|
||||||
CompareKind { kind, left, right } => {
|
CompareKind { kind, left, right } => {
|
||||||
let l = self.evaluate_node_in_context(left, cell);
|
let l = self.evaluate_node_in_context(left, cell);
|
||||||
@@ -487,7 +487,7 @@ impl Model {
|
|||||||
} => CalcResult::new_error(
|
} => CalcResult::new_error(
|
||||||
Error::ERROR,
|
Error::ERROR,
|
||||||
cell,
|
cell,
|
||||||
format!("Error parsing {}: {}", formula, message),
|
format!("Error parsing {formula}: {message}"),
|
||||||
),
|
),
|
||||||
EmptyArgKind => CalcResult::EmptyArg,
|
EmptyArgKind => CalcResult::EmptyArg,
|
||||||
ImplicitIntersection {
|
ImplicitIntersection {
|
||||||
@@ -500,7 +500,7 @@ impl Model {
|
|||||||
None => CalcResult::new_error(
|
None => CalcResult::new_error(
|
||||||
Error::VALUE,
|
Error::VALUE,
|
||||||
cell,
|
cell,
|
||||||
format!("Error with Implicit Intersection in cell {:?}", cell),
|
format!("Error with Implicit Intersection in cell {cell:?}"),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,7 +697,7 @@ impl Model {
|
|||||||
worksheet.color = Some(color.to_string());
|
worksheet.color = Some(color.to_string());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Err(format!("Invalid color: {}", color))
|
Err(format!("Invalid color: {color}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the visibility of a sheet
|
/// Changes the visibility of a sheet
|
||||||
@@ -1027,7 +1027,7 @@ impl Model {
|
|||||||
let source_sheet_name = self
|
let source_sheet_name = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(source.sheet)
|
.worksheet(source.sheet)
|
||||||
.map_err(|e| format!("Could not find source worksheet: {}", e))?
|
.map_err(|e| format!("Could not find source worksheet: {e}"))?
|
||||||
.get_name();
|
.get_name();
|
||||||
if source.sheet != area.sheet {
|
if source.sheet != area.sheet {
|
||||||
return Err("Source and area are in different sheets".to_string());
|
return Err("Source and area are in different sheets".to_string());
|
||||||
@@ -1041,7 +1041,7 @@ impl Model {
|
|||||||
let target_sheet_name = self
|
let target_sheet_name = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(target.sheet)
|
.worksheet(target.sheet)
|
||||||
.map_err(|e| format!("Could not find target worksheet: {}", e))?
|
.map_err(|e| format!("Could not find target worksheet: {e}"))?
|
||||||
.get_name();
|
.get_name();
|
||||||
if let Some(formula) = value.strip_prefix('=') {
|
if let Some(formula) = value.strip_prefix('=') {
|
||||||
let cell_reference = CellReferenceRC {
|
let cell_reference = CellReferenceRC {
|
||||||
@@ -1061,7 +1061,7 @@ impl Model {
|
|||||||
column_delta: target.column - source.column,
|
column_delta: target.column - source.column,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Ok(format!("={}", formula_str))
|
Ok(format!("={formula_str}"))
|
||||||
} else {
|
} else {
|
||||||
Ok(value.to_string())
|
Ok(value.to_string())
|
||||||
}
|
}
|
||||||
@@ -1538,7 +1538,7 @@ impl Model {
|
|||||||
// If the formula fails to parse try adding a parenthesis
|
// If the formula fails to parse try adding a parenthesis
|
||||||
// SUM(A1:A3 => SUM(A1:A3)
|
// SUM(A1:A3 => SUM(A1:A3)
|
||||||
if let Node::ParseErrorKind { .. } = parsed_formula {
|
if let Node::ParseErrorKind { .. } = parsed_formula {
|
||||||
let new_parsed_formula = self.parser.parse(&format!("{})", formula), &cell_reference);
|
let new_parsed_formula = self.parser.parse(&format!("{formula})"), &cell_reference);
|
||||||
match new_parsed_formula {
|
match new_parsed_formula {
|
||||||
Node::ParseErrorKind { .. } => {}
|
Node::ParseErrorKind { .. } => {}
|
||||||
_ => parsed_formula = new_parsed_formula,
|
_ => parsed_formula = new_parsed_formula,
|
||||||
|
|||||||
@@ -168,11 +168,11 @@ impl Model {
|
|||||||
.get_worksheet_names()
|
.get_worksheet_names()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_uppercase())
|
.map(|s| s.to_uppercase())
|
||||||
.any(|x| x == format!("{}{}", base_name_uppercase, index))
|
.any(|x| x == format!("{base_name_uppercase}{index}"))
|
||||||
{
|
{
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
let sheet_name = format!("{}{}", base_name, index);
|
let sheet_name = format!("{base_name}{index}");
|
||||||
// Now we need a sheet_id
|
// Now we need a sheet_id
|
||||||
let sheet_id = self.get_new_sheet_id();
|
let sheet_id = self.get_new_sheet_id();
|
||||||
let view_ids: Vec<&u32> = self.workbook.views.keys().collect();
|
let view_ids: Vec<&u32> = self.workbook.views.keys().collect();
|
||||||
@@ -192,7 +192,7 @@ impl Model {
|
|||||||
sheet_id: Option<u32>,
|
sheet_id: Option<u32>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
if !is_valid_sheet_name(sheet_name) {
|
if !is_valid_sheet_name(sheet_name) {
|
||||||
return Err(format!("Invalid name for a sheet: '{}'", sheet_name));
|
return Err(format!("Invalid name for a sheet: '{sheet_name}'"));
|
||||||
}
|
}
|
||||||
if self
|
if self
|
||||||
.workbook
|
.workbook
|
||||||
@@ -234,7 +234,7 @@ impl Model {
|
|||||||
if let Some(sheet_index) = self.get_sheet_index_by_name(old_name) {
|
if let Some(sheet_index) = self.get_sheet_index_by_name(old_name) {
|
||||||
return self.rename_sheet_by_index(sheet_index, new_name);
|
return self.rename_sheet_by_index(sheet_index, new_name);
|
||||||
}
|
}
|
||||||
Err(format!("Could not find sheet {}", old_name))
|
Err(format!("Could not find sheet {old_name}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renames a sheet and updates all existing references to that sheet.
|
/// Renames a sheet and updates all existing references to that sheet.
|
||||||
@@ -248,10 +248,10 @@ impl Model {
|
|||||||
new_name: &str,
|
new_name: &str,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
if !is_valid_sheet_name(new_name) {
|
if !is_valid_sheet_name(new_name) {
|
||||||
return Err(format!("Invalid name for a sheet: '{}'.", new_name));
|
return Err(format!("Invalid name for a sheet: '{new_name}'."));
|
||||||
}
|
}
|
||||||
if self.get_sheet_index_by_name(new_name).is_some() {
|
if self.get_sheet_index_by_name(new_name).is_some() {
|
||||||
return Err(format!("Sheet already exists: '{}'.", new_name));
|
return Err(format!("Sheet already exists: '{new_name}'."));
|
||||||
}
|
}
|
||||||
// Gets the new name and checks that a sheet with that index exists
|
// Gets the new name and checks that a sheet with that index exists
|
||||||
let old_name = self.workbook.worksheet(sheet_index)?.get_name();
|
let old_name = self.workbook.worksheet(sheet_index)?.get_name();
|
||||||
@@ -362,14 +362,14 @@ impl Model {
|
|||||||
};
|
};
|
||||||
let locale = match get_locale(locale_id) {
|
let locale = match get_locale(locale_id) {
|
||||||
Ok(l) => l.clone(),
|
Ok(l) => l.clone(),
|
||||||
Err(_) => return Err(format!("Invalid locale: {}", locale_id)),
|
Err(_) => return Err(format!("Invalid locale: {locale_id}")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let milliseconds = get_milliseconds_since_epoch();
|
let milliseconds = get_milliseconds_since_epoch();
|
||||||
let seconds = milliseconds / 1000;
|
let seconds = milliseconds / 1000;
|
||||||
let dt = match DateTime::from_timestamp(seconds, 0) {
|
let dt = match DateTime::from_timestamp(seconds, 0) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return Err(format!("Invalid timestamp: {}", milliseconds)),
|
None => return Err(format!("Invalid timestamp: {milliseconds}")),
|
||||||
};
|
};
|
||||||
// "2020-08-06T21:20:53Z
|
// "2020-08-06T21:20:53Z
|
||||||
let now = dt.format("%Y-%m-%dT%H:%M:%SZ").to_string();
|
let now = dt.format("%Y-%m-%dT%H:%M:%SZ").to_string();
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ pub fn to_precision_str(value: f64, precision: usize) -> String {
|
|||||||
let exponent = value.abs().log10().floor();
|
let exponent = value.abs().log10().floor();
|
||||||
let base = value / 10.0_f64.powf(exponent);
|
let base = value / 10.0_f64.powf(exponent);
|
||||||
let base = format!("{0:.1$}", base, precision - 1);
|
let base = format!("{0:.1$}", base, precision - 1);
|
||||||
let value = format!("{}e{}", base, exponent).parse::<f64>().unwrap_or({
|
let value = format!("{base}e{exponent}").parse::<f64>().unwrap_or({
|
||||||
// TODO: do this in a way that does not require a possible error
|
// TODO: do this in a way that does not require a possible error
|
||||||
0.0
|
0.0
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ impl Styles {
|
|||||||
return Ok(cell_style.xf_id);
|
return Ok(cell_style.xf_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(format!("Style '{}' not found", style_name))
|
Err(format!("Style '{style_name}' not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ fn fn_or_xor_no_arguments() {
|
|||||||
println!("Testing function: {func}");
|
println!("Testing function: {func}");
|
||||||
|
|
||||||
let mut model = new_empty_model();
|
let mut model = new_empty_model();
|
||||||
model._set("A1", &format!("={}()", func));
|
model._set("A1", &format!("={func}()"));
|
||||||
model.evaluate();
|
model.evaluate();
|
||||||
assert_eq!(model._get_text("A1"), *"#ERROR!");
|
assert_eq!(model._get_text("A1"), *"#ERROR!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,10 +50,7 @@ fn check_borders(model: &UserModel) {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(top_border),
|
Some(top_border),
|
||||||
top_cell_style.border.bottom,
|
top_cell_style.border.bottom,
|
||||||
"(Top). Sheet: {}, row: {}, column: {}",
|
"(Top). Sheet: {sheet}, row: {row}, column: {column}"
|
||||||
sheet,
|
|
||||||
row,
|
|
||||||
column
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,10 +62,7 @@ fn check_borders(model: &UserModel) {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(right_border),
|
Some(right_border),
|
||||||
right_cell_style.border.left,
|
right_cell_style.border.left,
|
||||||
"(Right). Sheet: {}, row: {}, column: {}",
|
"(Right). Sheet: {sheet}, row: {row}, column: {column}"
|
||||||
sheet,
|
|
||||||
row,
|
|
||||||
column
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,10 +74,7 @@ fn check_borders(model: &UserModel) {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(bottom_border),
|
Some(bottom_border),
|
||||||
bottom_cell_style.border.top,
|
bottom_cell_style.border.top,
|
||||||
"(Bottom). Sheet: {}, row: {}, column: {}",
|
"(Bottom). Sheet: {sheet}, row: {row}, column: {column}"
|
||||||
sheet,
|
|
||||||
row,
|
|
||||||
column
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,10 +85,7 @@ fn check_borders(model: &UserModel) {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Some(left_border),
|
Some(left_border),
|
||||||
left_cell_style.border.right,
|
left_cell_style.border.right,
|
||||||
"(Left). Sheet: {}, row: {}, column: {}",
|
"(Left). Sheet: {sheet}, row: {row}, column: {column}"
|
||||||
sheet,
|
|
||||||
row,
|
|
||||||
column
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fn set_user_input_errors() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn user_model_debug_message() {
|
fn user_model_debug_message() {
|
||||||
let model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
let model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||||
let s = &format!("{:?}", model);
|
let s = &format!("{model:?}");
|
||||||
assert_eq!(s, "UserModel");
|
assert_eq!(s, "UserModel");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ impl UserModel {
|
|||||||
r##"{{
|
r##"{{
|
||||||
"item": {{
|
"item": {{
|
||||||
"style": "thin",
|
"style": "thin",
|
||||||
"color": "{}"
|
"color": "{color}"
|
||||||
}},
|
}},
|
||||||
"type": "All"
|
"type": "All"
|
||||||
}}"##,
|
}}"##
|
||||||
color
|
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let range = &Area {
|
let range = &Area {
|
||||||
@@ -40,11 +39,10 @@ impl UserModel {
|
|||||||
r##"{{
|
r##"{{
|
||||||
"item": {{
|
"item": {{
|
||||||
"style": "thin",
|
"style": "thin",
|
||||||
"color": "{}"
|
"color": "{color}"
|
||||||
}},
|
}},
|
||||||
"type": "{}"
|
"type": "{kind}"
|
||||||
}}"##,
|
}}"##
|
||||||
color, kind
|
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let range = &Area {
|
let range = &Area {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ impl Model {
|
|||||||
if cell.contains('!') {
|
if cell.contains('!') {
|
||||||
self.parse_reference(cell).unwrap()
|
self.parse_reference(cell).unwrap()
|
||||||
} else {
|
} else {
|
||||||
self.parse_reference(&format!("Sheet1!{}", cell)).unwrap()
|
self.parse_reference(&format!("Sheet1!{cell}")).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn _set(&mut self, cell: &str, value: &str) {
|
pub fn _set(&mut self, cell: &str, value: &str) {
|
||||||
|
|||||||
@@ -1487,10 +1487,10 @@ impl UserModel {
|
|||||||
return Err(format!("Invalid row: '{first_row}'"));
|
return Err(format!("Invalid row: '{first_row}'"));
|
||||||
}
|
}
|
||||||
if !is_valid_column_number(last_column) {
|
if !is_valid_column_number(last_column) {
|
||||||
return Err(format!("Invalid column: '{}'", last_column));
|
return Err(format!("Invalid column: '{last_column}'"));
|
||||||
}
|
}
|
||||||
if !is_valid_row(last_row) {
|
if !is_valid_row(last_row) {
|
||||||
return Err(format!("Invalid row: '{}'", last_row));
|
return Err(format!("Invalid row: '{last_row}'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_valid_row(to_column) {
|
if !is_valid_row(to_column) {
|
||||||
@@ -1623,15 +1623,15 @@ impl UserModel {
|
|||||||
text_row.push(text);
|
text_row.push(text);
|
||||||
}
|
}
|
||||||
wtr.write_record(text_row)
|
wtr.write_record(text_row)
|
||||||
.map_err(|e| format!("Error while processing csv: {}", e))?;
|
.map_err(|e| format!("Error while processing csv: {e}"))?;
|
||||||
data.insert(row, data_row);
|
data.insert(row, data_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
let csv = String::from_utf8(
|
let csv = String::from_utf8(
|
||||||
wtr.into_inner()
|
wtr.into_inner()
|
||||||
.map_err(|e| format!("Processing error: '{}'", e))?,
|
.map_err(|e| format!("Processing error: '{e}'"))?,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Error converting from utf8: '{}'", e))?;
|
.map_err(|e| format!("Error converting from utf8: '{e}'"))?;
|
||||||
|
|
||||||
Ok(Clipboard {
|
Ok(Clipboard {
|
||||||
csv,
|
csv,
|
||||||
@@ -2391,7 +2391,7 @@ mod tests {
|
|||||||
VerticalAlignment::Top,
|
VerticalAlignment::Top,
|
||||||
];
|
];
|
||||||
for a in all {
|
for a in all {
|
||||||
assert_eq!(vertical(&format!("{}", a)), Ok(a));
|
assert_eq!(vertical(&format!("{a}")), Ok(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2408,7 +2408,7 @@ mod tests {
|
|||||||
HorizontalAlignment::Right,
|
HorizontalAlignment::Right,
|
||||||
];
|
];
|
||||||
for a in all {
|
for a in all {
|
||||||
assert_eq!(horizontal(&format!("{}", a)), Ok(a));
|
assert_eq!(horizontal(&format!("{a}")), Ok(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl UserModel {
|
|||||||
/// Sets the the selected sheet
|
/// Sets the the selected sheet
|
||||||
pub fn set_selected_sheet(&mut self, sheet: u32) -> Result<(), String> {
|
pub fn set_selected_sheet(&mut self, sheet: u32) -> Result<(), String> {
|
||||||
if self.model.workbook.worksheet(sheet).is_err() {
|
if self.model.workbook.worksheet(sheet).is_err() {
|
||||||
return Err(format!("Invalid worksheet index {}", sheet));
|
return Err(format!("Invalid worksheet index {sheet}"));
|
||||||
}
|
}
|
||||||
if let Some(view) = self.model.workbook.views.get_mut(&0) {
|
if let Some(view) = self.model.workbook.views.get_mut(&0) {
|
||||||
view.sheet = sheet;
|
view.sheet = sheet;
|
||||||
@@ -98,7 +98,7 @@ impl UserModel {
|
|||||||
return Err(format!("Invalid row: '{row}'"));
|
return Err(format!("Invalid row: '{row}'"));
|
||||||
}
|
}
|
||||||
if self.model.workbook.worksheet(sheet).is_err() {
|
if self.model.workbook.worksheet(sheet).is_err() {
|
||||||
return Err(format!("Invalid worksheet index {}", sheet));
|
return Err(format!("Invalid worksheet index {sheet}"));
|
||||||
}
|
}
|
||||||
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
||||||
if let Some(view) = worksheet.views.get_mut(&0) {
|
if let Some(view) = worksheet.views.get_mut(&0) {
|
||||||
@@ -138,7 +138,7 @@ impl UserModel {
|
|||||||
return Err(format!("Invalid row: '{end_row}'"));
|
return Err(format!("Invalid row: '{end_row}'"));
|
||||||
}
|
}
|
||||||
if self.model.workbook.worksheet(sheet).is_err() {
|
if self.model.workbook.worksheet(sheet).is_err() {
|
||||||
return Err(format!("Invalid worksheet index {}", sheet));
|
return Err(format!("Invalid worksheet index {sheet}"));
|
||||||
}
|
}
|
||||||
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
||||||
if let Some(view) = worksheet.views.get_mut(&0) {
|
if let Some(view) = worksheet.views.get_mut(&0) {
|
||||||
@@ -147,14 +147,12 @@ impl UserModel {
|
|||||||
// The selected cells must be on one of the corners of the selected range:
|
// The selected cells must be on one of the corners of the selected range:
|
||||||
if selected_row != start_row && selected_row != end_row {
|
if selected_row != start_row && selected_row != end_row {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"The selected cells is not in one of the corners. Row: '{}' and row range '({}, {})'",
|
"The selected cells is not in one of the corners. Row: '{selected_row}' and row range '({start_row}, {end_row})'"
|
||||||
selected_row, start_row, end_row
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if selected_column != start_column && selected_column != end_column {
|
if selected_column != start_column && selected_column != end_column {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"The selected cells is not in one of the corners. Column '{}' and column range '({}, {})'",
|
"The selected cells is not in one of the corners. Column '{selected_column}' and column range '({start_column}, {end_column})'"
|
||||||
selected_column, start_column, end_column
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
view.range = [start_row, start_column, end_row, end_column];
|
view.range = [start_row, start_column, end_row, end_column];
|
||||||
@@ -307,7 +305,7 @@ impl UserModel {
|
|||||||
return Err(format!("Invalid row: '{top_row}'"));
|
return Err(format!("Invalid row: '{top_row}'"));
|
||||||
}
|
}
|
||||||
if self.model.workbook.worksheet(sheet).is_err() {
|
if self.model.workbook.worksheet(sheet).is_err() {
|
||||||
return Err(format!("Invalid worksheet index {}", sheet));
|
return Err(format!("Invalid worksheet index {sheet}"));
|
||||||
}
|
}
|
||||||
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
if let Ok(worksheet) = self.model.workbook.worksheet_mut(sheet) {
|
||||||
if let Some(view) = worksheet.views.get_mut(&0) {
|
if let Some(view) = worksheet.views.get_mut(&0) {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ 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}"))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Adds a new sheet
|
// Adds a new sheet
|
||||||
model.add_sheet("Calculation")?;
|
model.add_sheet("Calculation")?;
|
||||||
// column 100 is CV
|
// column 100 is CV
|
||||||
let last_column = number_to_column(100).ok_or("Invalid column number")?;
|
let last_column = number_to_column(100).ok_or("Invalid column number")?;
|
||||||
let formula = format!("=SUM(Sheet1!A1:{}100)", last_column);
|
let formula = format!("=SUM(Sheet1!A1:{last_column}100)");
|
||||||
model.set_user_input(1, 1, 1, formula)?;
|
model.set_user_input(1, 1, 1, formula)?;
|
||||||
|
|
||||||
// evaluates
|
// evaluates
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn main() {
|
|||||||
let file_name = &args[1];
|
let file_name = &args[1];
|
||||||
println!("Testing file: {file_name}");
|
println!("Testing file: {file_name}");
|
||||||
if let Err(message) = test_file(file_name) {
|
if let Err(message) = test_file(file_name) {
|
||||||
println!("{}", message);
|
println!("{message}");
|
||||||
panic!("Model was evaluated inconsistently with XLSX data.")
|
panic!("Model was evaluated inconsistently with XLSX data.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ pub(crate) fn compare_models(m1: &Model, m2: &Model) -> Result<(), String> {
|
|||||||
diff.reason
|
diff.reason
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(format!("Models are different: {}", message))
|
Err(format!("Models are different: {message}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(r) => Err(format!("Models are different: {}", r.message)),
|
Err(r) => Err(format!("Models are different: {}", r.message)),
|
||||||
|
|||||||
@@ -19,10 +19,9 @@ pub(crate) fn get_app_xml(_: &Workbook) -> String {
|
|||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>
|
||||||
<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" \
|
<Properties xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties\" \
|
||||||
xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">\
|
xmlns:vt=\"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes\">\
|
||||||
<Application>{}</Application>\
|
<Application>{APPLICATION}</Application>\
|
||||||
<AppVersion>{}</AppVersion>\
|
<AppVersion>{APP_VERSION}</AppVersion>\
|
||||||
</Properties>",
|
</Properties>"
|
||||||
APPLICATION, APP_VERSION
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +39,7 @@ pub(crate) fn get_core_xml(workbook: &Workbook, milliseconds: i64) -> Result<Str
|
|||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => {
|
None => {
|
||||||
return Err(XlsxError::Xml(format!(
|
return Err(XlsxError::Xml(format!(
|
||||||
"Invalid timestamp: {}",
|
"Invalid timestamp: {milliseconds}"
|
||||||
milliseconds
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -54,16 +52,15 @@ pub(crate) fn get_core_xml(workbook: &Workbook, milliseconds: i64) -> Result<Str
|
|||||||
xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" \
|
xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" \
|
||||||
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \
|
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \
|
||||||
<dc:title></dc:title><dc:subject></dc:subject>\
|
<dc:title></dc:title><dc:subject></dc:subject>\
|
||||||
<dc:creator>{}</dc:creator>\
|
<dc:creator>{creator}</dc:creator>\
|
||||||
<cp:keywords></cp:keywords>\
|
<cp:keywords></cp:keywords>\
|
||||||
<dc:description></dc:description>\
|
<dc:description></dc:description>\
|
||||||
<cp:lastModifiedBy>{}</cp:lastModifiedBy>\
|
<cp:lastModifiedBy>{last_modified_by}</cp:lastModifiedBy>\
|
||||||
<cp:revision></cp:revision>\
|
<cp:revision></cp:revision>\
|
||||||
<dcterms:created xsi:type=\"dcterms:W3CDTF\">{}</dcterms:created>\
|
<dcterms:created xsi:type=\"dcterms:W3CDTF\">{created}</dcterms:created>\
|
||||||
<dcterms:modified xsi:type=\"dcterms:W3CDTF\">{}</dcterms:modified>\
|
<dcterms:modified xsi:type=\"dcterms:W3CDTF\">{last_modified}</dcterms:modified>\
|
||||||
<cp:category></cp:category>\
|
<cp:category></cp:category>\
|
||||||
<cp:contentStatus></cp:contentStatus>\
|
<cp:contentStatus></cp:contentStatus>\
|
||||||
</cp:coreProperties>",
|
</cp:coreProperties>"
|
||||||
creator, last_modified_by, created, last_modified
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ fn get_content_types_xml(workbook: &Workbook) -> String {
|
|||||||
pub fn save_to_xlsx(model: &Model, file_name: &str) -> Result<(), XlsxError> {
|
pub fn save_to_xlsx(model: &Model, file_name: &str) -> Result<(), XlsxError> {
|
||||||
let file_path = std::path::Path::new(&file_name);
|
let file_path = std::path::Path::new(&file_name);
|
||||||
if file_path.exists() {
|
if file_path.exists() {
|
||||||
return Err(XlsxError::IO(format!("file {} already exists", file_name)));
|
return Err(XlsxError::IO(format!("file {file_name} already exists")));
|
||||||
}
|
}
|
||||||
let file = fs::File::create(file_path).unwrap();
|
let file = fs::File::create(file_path).unwrap();
|
||||||
let writer = BufWriter::new(file);
|
let writer = BufWriter::new(file);
|
||||||
@@ -140,7 +140,7 @@ pub fn save_xlsx_to_writer<W: Write + Seek>(model: &Model, writer: W) -> Result<
|
|||||||
pub fn save_to_icalc(model: &Model, file_name: &str) -> Result<(), XlsxError> {
|
pub fn save_to_icalc(model: &Model, file_name: &str) -> Result<(), XlsxError> {
|
||||||
let file_path = std::path::Path::new(&file_name);
|
let file_path = std::path::Path::new(&file_name);
|
||||||
if file_path.exists() {
|
if file_path.exists() {
|
||||||
return Err(XlsxError::IO(format!("file {} already exists", file_name)));
|
return Err(XlsxError::IO(format!("file {file_name} already exists")));
|
||||||
}
|
}
|
||||||
let s = bitcode::encode(&model.workbook);
|
let s = bitcode::encode(&model.workbook);
|
||||||
let mut file = fs::File::create(file_path)?;
|
let mut file = fs::File::create(file_path)?;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fn get_cell_style_attribute(s: i32) -> String {
|
|||||||
if s == 0 {
|
if s == 0 {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!(" s=\"{}\"", s)
|
format!(" s=\"{s}\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,8 +148,8 @@ pub fn load_from_xlsx(file_name: &str, locale: &str, tz: &str) -> Result<Model,
|
|||||||
/// Loads a [Model] from an `ic` file (a file in the IronCalc internal representation)
|
/// Loads a [Model] from an `ic` file (a file in the IronCalc internal representation)
|
||||||
pub fn load_from_icalc(file_name: &str) -> Result<Model, XlsxError> {
|
pub fn load_from_icalc(file_name: &str) -> Result<Model, XlsxError> {
|
||||||
let contents = fs::read(file_name)
|
let contents = fs::read(file_name)
|
||||||
.map_err(|e| XlsxError::IO(format!("Could not extract workbook name: {}", e)))?;
|
.map_err(|e| XlsxError::IO(format!("Could not extract workbook name: {e}")))?;
|
||||||
let workbook: Workbook = bitcode::decode(&contents)
|
let workbook: Workbook = bitcode::decode(&contents)
|
||||||
.map_err(|e| XlsxError::IO(format!("Failed to decode file: {}", e)))?;
|
.map_err(|e| XlsxError::IO(format!("Failed to decode file: {e}")))?;
|
||||||
Model::from_workbook(workbook).map_err(XlsxError::Workbook)
|
Model::from_workbook(workbook).map_err(XlsxError::Workbook)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ pub(super) fn load_styles<R: Read + std::io::Seek>(
|
|||||||
}
|
}
|
||||||
"charset" => {}
|
"charset" => {}
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unexpected feature {:?}", feature);
|
println!("Unexpected feature {feature:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ where
|
|||||||
{
|
{
|
||||||
let attr_name = attr_name.into();
|
let attr_name = attr_name.into();
|
||||||
node.attribute(attr_name)
|
node.attribute(attr_name)
|
||||||
.ok_or_else(|| XlsxError::Xml(format!("Missing \"{:?}\" XML attribute", attr_name)))
|
.ok_or_else(|| XlsxError::Xml(format!("Missing \"{attr_name:?}\" XML attribute")))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_value_or_default(node: &Node, tag_name: &str, default: &str) -> String {
|
pub(super) fn get_value_or_default(node: &Node, tag_name: &str, default: &str) -> String {
|
||||||
@@ -64,7 +64,7 @@ pub(super) fn get_color(node: Node) -> Result<Option<String>, XlsxError> {
|
|||||||
// A boolean value indicating the color is automatic and system color dependent.
|
// A boolean value indicating the color is automatic and system color dependent.
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
println!("Unexpected color node {:?}", node);
|
println!("Unexpected color node {node:?}");
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ pub(super) fn load_workbook<R: Read + std::io::Seek>(
|
|||||||
Some("visible") | None => SheetState::Visible,
|
Some("visible") | None => SheetState::Visible,
|
||||||
Some("hidden") => SheetState::Hidden,
|
Some("hidden") => SheetState::Hidden,
|
||||||
Some("veryHidden") => SheetState::VeryHidden,
|
Some("veryHidden") => SheetState::VeryHidden,
|
||||||
Some(state) => return Err(XlsxError::Xml(format!("Unknown sheet state: {}", state))),
|
Some(state) => return Err(XlsxError::Xml(format!("Unknown sheet state: {state}"))),
|
||||||
};
|
};
|
||||||
sheets.push(Sheet {
|
sheets.push(Sheet {
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ fn parse_cell_reference(cell: &str) -> Result<(i32, i32), String> {
|
|||||||
if let Some(r) = parse_reference_a1(cell) {
|
if let Some(r) = parse_reference_a1(cell) {
|
||||||
Ok((r.row, r.column))
|
Ok((r.row, r.column))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Invalid cell reference: '{}'", cell))
|
Err(format!("Invalid cell reference: '{cell}'"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,17 +91,17 @@ fn parse_range(range: &str) -> Result<(i32, i32, i32, i32), String> {
|
|||||||
if let Some(r) = parse_reference_a1(parts[0]) {
|
if let Some(r) = parse_reference_a1(parts[0]) {
|
||||||
Ok((r.row, r.column, r.row, r.column))
|
Ok((r.row, r.column, r.row, r.column))
|
||||||
} else {
|
} else {
|
||||||
Err(format!("Invalid range: '{}'", range))
|
Err(format!("Invalid range: '{range}'"))
|
||||||
}
|
}
|
||||||
} else if parts.len() == 2 {
|
} else if parts.len() == 2 {
|
||||||
match (parse_reference_a1(parts[0]), parse_reference_a1(parts[1])) {
|
match (parse_reference_a1(parts[0]), parse_reference_a1(parts[1])) {
|
||||||
(Some(left), Some(right)) => {
|
(Some(left), Some(right)) => {
|
||||||
return Ok((left.row, left.column, right.row, right.column));
|
return Ok((left.row, left.column, right.row, right.column));
|
||||||
}
|
}
|
||||||
_ => return Err(format!("Invalid range: '{}'", range)),
|
_ => return Err(format!("Invalid range: '{range}'")),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("Invalid range: '{}'", range));
|
return Err(format!("Invalid range: '{range}'"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ fn get_cell_from_excel(
|
|||||||
}
|
}
|
||||||
"d" => {
|
"d" => {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
println!("Invalid type (d) in {}!{}", sheet_name, cell_ref);
|
println!("Invalid type (d) in {sheet_name}!{cell_ref}");
|
||||||
Cell::ErrorCell {
|
Cell::ErrorCell {
|
||||||
ei: Error::NIMPL,
|
ei: Error::NIMPL,
|
||||||
s: cell_style,
|
s: cell_style,
|
||||||
@@ -398,7 +398,7 @@ fn get_cell_from_excel(
|
|||||||
}
|
}
|
||||||
"inlineStr" => {
|
"inlineStr" => {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
println!("Invalid type (inlineStr) in {}!{}", sheet_name, cell_ref);
|
println!("Invalid type (inlineStr) in {sheet_name}!{cell_ref}");
|
||||||
Cell::ErrorCell {
|
Cell::ErrorCell {
|
||||||
ei: Error::NIMPL,
|
ei: Error::NIMPL,
|
||||||
s: cell_style,
|
s: cell_style,
|
||||||
@@ -408,8 +408,7 @@ fn get_cell_from_excel(
|
|||||||
_ => {
|
_ => {
|
||||||
// error
|
// error
|
||||||
println!(
|
println!(
|
||||||
"Unexpected type ({}) in {}!{}",
|
"Unexpected type ({cell_type}) in {sheet_name}!{cell_ref}"
|
||||||
cell_type, sheet_name, cell_ref
|
|
||||||
);
|
);
|
||||||
Cell::ErrorCell {
|
Cell::ErrorCell {
|
||||||
ei: Error::ERROR,
|
ei: Error::ERROR,
|
||||||
@@ -444,15 +443,15 @@ fn get_cell_from_excel(
|
|||||||
f: formula_index,
|
f: formula_index,
|
||||||
ei: get_error_by_english_name(error_name).unwrap_or(Error::ERROR),
|
ei: get_error_by_english_name(error_name).unwrap_or(Error::ERROR),
|
||||||
s: cell_style,
|
s: cell_style,
|
||||||
o: format!("{}!{}", sheet_name, cell_ref),
|
o: format!("{sheet_name}!{cell_ref}"),
|
||||||
m: cell_value.unwrap_or("#ERROR!").to_string(),
|
m: cell_value.unwrap_or("#ERROR!").to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"s" => {
|
"s" => {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
let o = format!("{}!{}", sheet_name, cell_ref);
|
let o = format!("{sheet_name}!{cell_ref}");
|
||||||
let m = Error::NIMPL.to_string();
|
let m = Error::NIMPL.to_string();
|
||||||
println!("Invalid type (s) in {}!{}", sheet_name, cell_ref);
|
println!("Invalid type (s) in {sheet_name}!{cell_ref}");
|
||||||
Cell::CellFormulaError {
|
Cell::CellFormulaError {
|
||||||
f: formula_index,
|
f: formula_index,
|
||||||
ei: Error::NIMPL,
|
ei: Error::NIMPL,
|
||||||
@@ -471,8 +470,8 @@ fn get_cell_from_excel(
|
|||||||
}
|
}
|
||||||
"d" => {
|
"d" => {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
println!("Invalid type (d) in {}!{}", sheet_name, cell_ref);
|
println!("Invalid type (d) in {sheet_name}!{cell_ref}");
|
||||||
let o = format!("{}!{}", sheet_name, cell_ref);
|
let o = format!("{sheet_name}!{cell_ref}");
|
||||||
let m = Error::NIMPL.to_string();
|
let m = Error::NIMPL.to_string();
|
||||||
Cell::CellFormulaError {
|
Cell::CellFormulaError {
|
||||||
f: formula_index,
|
f: formula_index,
|
||||||
@@ -484,9 +483,9 @@ fn get_cell_from_excel(
|
|||||||
}
|
}
|
||||||
"inlineStr" => {
|
"inlineStr" => {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
let o = format!("{}!{}", sheet_name, cell_ref);
|
let o = format!("{sheet_name}!{cell_ref}");
|
||||||
let m = Error::NIMPL.to_string();
|
let m = Error::NIMPL.to_string();
|
||||||
println!("Invalid type (inlineStr) in {}!{}", sheet_name, cell_ref);
|
println!("Invalid type (inlineStr) in {sheet_name}!{cell_ref}");
|
||||||
Cell::CellFormulaError {
|
Cell::CellFormulaError {
|
||||||
f: formula_index,
|
f: formula_index,
|
||||||
ei: Error::NIMPL,
|
ei: Error::NIMPL,
|
||||||
@@ -498,10 +497,9 @@ fn get_cell_from_excel(
|
|||||||
_ => {
|
_ => {
|
||||||
// error
|
// error
|
||||||
println!(
|
println!(
|
||||||
"Unexpected type ({}) in {}!{}",
|
"Unexpected type ({cell_type}) in {sheet_name}!{cell_ref}"
|
||||||
cell_type, sheet_name, cell_ref
|
|
||||||
);
|
);
|
||||||
let o = format!("{}!{}", sheet_name, cell_ref);
|
let o = format!("{sheet_name}!{cell_ref}");
|
||||||
let m = Error::ERROR.to_string();
|
let m = Error::ERROR.to_string();
|
||||||
Cell::CellFormulaError {
|
Cell::CellFormulaError {
|
||||||
f: formula_index,
|
f: formula_index,
|
||||||
@@ -886,7 +884,7 @@ pub(super) fn load_sheet<R: Read + std::io::Seek>(
|
|||||||
Some(_) => {
|
Some(_) => {
|
||||||
// It's the mother cell. We do not use the ref attribute in IronCalc
|
// It's the mother cell. We do not use the ref attribute in IronCalc
|
||||||
let formula = fs[0].text().unwrap_or("").to_string();
|
let formula = fs[0].text().unwrap_or("").to_string();
|
||||||
let context = format!("{}!{}", sheet_name, cell_ref);
|
let context = format!("{sheet_name}!{cell_ref}");
|
||||||
let formula = from_a1_to_rc(
|
let formula = from_a1_to_rc(
|
||||||
formula,
|
formula,
|
||||||
worksheets,
|
worksheets,
|
||||||
@@ -949,7 +947,7 @@ pub(super) fn load_sheet<R: Read + std::io::Seek>(
|
|||||||
}
|
}
|
||||||
// Its a cell with a simple formula
|
// Its a cell with a simple formula
|
||||||
let formula = fs[0].text().unwrap_or("").to_string();
|
let formula = fs[0].text().unwrap_or("").to_string();
|
||||||
let context = format!("{}!{}", sheet_name, cell_ref);
|
let context = format!("{sheet_name}!{cell_ref}");
|
||||||
let formula = from_a1_to_rc(
|
let formula = from_a1_to_rc(
|
||||||
formula,
|
formula,
|
||||||
worksheets,
|
worksheets,
|
||||||
@@ -968,8 +966,7 @@ pub(super) fn load_sheet<R: Read + std::io::Seek>(
|
|||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(XlsxError::Xml(format!(
|
return Err(XlsxError::Xml(format!(
|
||||||
"Invalid formula type {:?}.",
|
"Invalid formula type {formula_type:?}.",
|
||||||
formula_type,
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -350,11 +350,11 @@ fn test_xlsx() {
|
|||||||
for file_path in entries {
|
for file_path in entries {
|
||||||
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
||||||
let file_path_str = file_path.to_str().unwrap();
|
let file_path_str = file_path.to_str().unwrap();
|
||||||
println!("Testing file: {}", file_path_str);
|
println!("Testing file: {file_path_str}");
|
||||||
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
||||||
if let Err(message) = test_file(file_path_str) {
|
if let Err(message) = test_file(file_path_str) {
|
||||||
println!("Error with file: '{file_path_str}'");
|
println!("Error with file: '{file_path_str}'");
|
||||||
println!("{}", message);
|
println!("{message}");
|
||||||
is_error = true;
|
is_error = true;
|
||||||
}
|
}
|
||||||
let t = test_load_and_saving(file_path_str, &dir);
|
let t = test_load_and_saving(file_path_str, &dir);
|
||||||
@@ -389,11 +389,11 @@ fn no_export() {
|
|||||||
for file_path in entries {
|
for file_path in entries {
|
||||||
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
||||||
let file_path_str = file_path.to_str().unwrap();
|
let file_path_str = file_path.to_str().unwrap();
|
||||||
println!("Testing file: {}", file_path_str);
|
println!("Testing file: {file_path_str}");
|
||||||
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
||||||
if let Err(message) = test_file(file_path_str) {
|
if let Err(message) = test_file(file_path_str) {
|
||||||
println!("Error with file: '{file_path_str}'");
|
println!("Error with file: '{file_path_str}'");
|
||||||
println!("{}", message);
|
println!("{message}");
|
||||||
is_error = true;
|
is_error = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -485,7 +485,7 @@ fn test_documentation_xlsx() {
|
|||||||
// Numerically unstable
|
// Numerically unstable
|
||||||
skip.push("TAN.xlsx");
|
skip.push("TAN.xlsx");
|
||||||
let skip: Vec<String> = skip.iter().map(|s| format!("tests/docs/{s}")).collect();
|
let skip: Vec<String> = skip.iter().map(|s| format!("tests/docs/{s}")).collect();
|
||||||
println!("{:?}", skip);
|
println!("{skip:?}");
|
||||||
// dumb counter to make sure we are actually testing the files
|
// dumb counter to make sure we are actually testing the files
|
||||||
assert!(entries.len() > 7);
|
assert!(entries.len() > 7);
|
||||||
let temp_folder = env::temp_dir();
|
let temp_folder = env::temp_dir();
|
||||||
@@ -497,13 +497,13 @@ fn test_documentation_xlsx() {
|
|||||||
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
let file_name_str = file_path.file_name().unwrap().to_str().unwrap();
|
||||||
let file_path_str = file_path.to_str().unwrap();
|
let file_path_str = file_path.to_str().unwrap();
|
||||||
if skip.contains(&file_path_str.to_string()) {
|
if skip.contains(&file_path_str.to_string()) {
|
||||||
println!("Skipping file: {}", file_path_str);
|
println!("Skipping file: {file_path_str}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
println!("Testing file: {}", file_path_str);
|
println!("Testing file: {file_path_str}");
|
||||||
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
if file_name_str.ends_with(".xlsx") && !file_name_str.starts_with('~') {
|
||||||
if let Err(message) = test_file(file_path_str) {
|
if let Err(message) = test_file(file_path_str) {
|
||||||
println!("{}", message);
|
println!("{message}");
|
||||||
is_error = true;
|
is_error = true;
|
||||||
}
|
}
|
||||||
assert!(test_load_and_saving(file_path_str, &dir).is_ok());
|
assert!(test_load_and_saving(file_path_str, &dir).is_ok());
|
||||||
|
|||||||
Reference in New Issue
Block a user