FIX: Forbid unwrap, expect and panic in the base code
This commit is contained in:
committed by
Nicolás Hatcher Andrés
parent
bdd2c8fe04
commit
49ae2d8915
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
|||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
cargo fmt -- --check
|
cargo fmt -- --check
|
||||||
cargo clippy --all-targets --all-features
|
cargo clippy --all-targets --all-features -- -W clippy::unwrap_used -W clippy::expect_used -W clippy::panic -D warnings
|
||||||
cd webapp && npm install && npm run check
|
cd webapp && npm install && npm run check
|
||||||
|
|
||||||
.PHONY: format
|
.PHONY: format
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ pub struct SetCellValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
pub(crate) fn shift_cell_formula(
|
pub(crate) fn shift_cell_formula(
|
||||||
&mut self,
|
&mut self,
|
||||||
sheet: u32,
|
sheet: u32,
|
||||||
@@ -57,6 +58,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
pub fn forward_references(
|
pub fn forward_references(
|
||||||
&mut self,
|
&mut self,
|
||||||
source_area: &Area,
|
source_area: &Area,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::expect_used)]
|
||||||
|
|
||||||
use crate::expressions::{
|
use crate::expressions::{
|
||||||
lexer::util::get_tokens,
|
lexer::util::get_tokens,
|
||||||
token::{OpCompare, OpSum, TokenType},
|
token::{OpCompare, OpSum, TokenType},
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ pub fn get_tokens(formula: &str) -> Vec<MarkedToken> {
|
|||||||
let mut lexer = Lexer::new(
|
let mut lexer = Lexer::new(
|
||||||
formula,
|
formula,
|
||||||
LexerMode::A1,
|
LexerMode::A1,
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_locale("en").expect(""),
|
get_locale("en").expect(""),
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_language("en").expect(""),
|
get_language("en").expect(""),
|
||||||
);
|
);
|
||||||
let mut start = lexer.get_position();
|
let mut start = lexer.get_position();
|
||||||
|
|||||||
@@ -63,7 +63,9 @@ pub(crate) fn parse_range(formula: &str) -> Result<(i32, i32, i32, i32), String>
|
|||||||
let mut lexer = lexer::Lexer::new(
|
let mut lexer = lexer::Lexer::new(
|
||||||
formula,
|
formula,
|
||||||
lexer::LexerMode::A1,
|
lexer::LexerMode::A1,
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_locale("en").expect(""),
|
get_locale("en").expect(""),
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_language("en").expect(""),
|
get_language("en").expect(""),
|
||||||
);
|
);
|
||||||
if let TokenType::Range {
|
if let TokenType::Range {
|
||||||
@@ -202,7 +204,9 @@ impl Parser {
|
|||||||
let lexer = lexer::Lexer::new(
|
let lexer = lexer::Lexer::new(
|
||||||
"",
|
"",
|
||||||
lexer::LexerMode::A1,
|
lexer::LexerMode::A1,
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_locale("en").expect(""),
|
get_locale("en").expect(""),
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
get_language("en").expect(""),
|
get_language("en").expect(""),
|
||||||
);
|
);
|
||||||
Parser {
|
Parser {
|
||||||
@@ -675,14 +679,23 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// table-name => table
|
// table-name => table
|
||||||
let table = self.tables.get(&table_name).unwrap_or_else(|| {
|
let table = match self.tables.get(&table_name) {
|
||||||
panic!(
|
Some(t) => t,
|
||||||
|
None => {
|
||||||
|
let message = format!(
|
||||||
"Table not found: '{table_name}' at '{}!{}{}'",
|
"Table not found: '{table_name}' at '{}!{}{}'",
|
||||||
context.sheet,
|
context.sheet,
|
||||||
number_to_column(context.column).expect(""),
|
number_to_column(context.column)
|
||||||
|
.unwrap_or(format!("{}", context.column)),
|
||||||
context.row
|
context.row
|
||||||
)
|
);
|
||||||
});
|
return Node::ParseErrorKind {
|
||||||
|
formula: self.lexer.get_formula(),
|
||||||
|
position: 0,
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
let table_sheet_index = match self.get_sheet_index_by_name(&table.sheet_name) {
|
let table_sheet_index = match self.get_sheet_index_by_name(&table.sheet_name) {
|
||||||
Some(i) => i,
|
Some(i) => i,
|
||||||
None => {
|
None => {
|
||||||
@@ -701,6 +714,7 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// context must be with tables.reference
|
// context must be with tables.reference
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
let (column_start, mut row_start, column_end, mut row_end) =
|
let (column_start, mut row_start, column_end, mut row_end) =
|
||||||
parse_range(&table.reference).expect("Failed parsing range");
|
parse_range(&table.reference).expect("Failed parsing range");
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::expressions::lexer::LexerMode;
|
use crate::expressions::lexer::LexerMode;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use chrono::NaiveDate;
|
|||||||
use crate::constants::EXCEL_DATE_BASE;
|
use crate::constants::EXCEL_DATE_BASE;
|
||||||
|
|
||||||
pub fn from_excel_date(days: i64) -> NaiveDate {
|
pub fn from_excel_date(days: i64) -> NaiveDate {
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
let dt = NaiveDate::from_ymd_opt(1900, 1, 1).expect("problem with chrono::NaiveDate");
|
let dt = NaiveDate::from_ymd_opt(1900, 1, 1).expect("problem with chrono::NaiveDate");
|
||||||
dt + Duration::days(days - 2)
|
dt + Duration::days(days - 2)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -220,7 +220,13 @@ impl Model {
|
|||||||
row2 = self
|
row2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_row;
|
.max_row;
|
||||||
}
|
}
|
||||||
@@ -228,7 +234,13 @@ impl Model {
|
|||||||
column2 = self
|
column2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_column;
|
.max_column;
|
||||||
}
|
}
|
||||||
@@ -283,7 +295,13 @@ impl Model {
|
|||||||
row2 = self
|
row2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_row;
|
.max_row;
|
||||||
}
|
}
|
||||||
@@ -291,7 +309,13 @@ impl Model {
|
|||||||
column2 = self
|
column2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_column;
|
.max_column;
|
||||||
}
|
}
|
||||||
@@ -359,7 +383,13 @@ impl Model {
|
|||||||
row2 = self
|
row2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_row;
|
.max_row;
|
||||||
}
|
}
|
||||||
@@ -367,7 +397,13 @@ impl Model {
|
|||||||
column2 = self
|
column2 = self
|
||||||
.workbook
|
.workbook
|
||||||
.worksheet(left.sheet)
|
.worksheet(left.sheet)
|
||||||
.expect("Sheet expected during evaluation.")
|
.map_err(|_| {
|
||||||
|
CalcResult::new_error(
|
||||||
|
Error::ERROR,
|
||||||
|
*cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
)
|
||||||
|
})?
|
||||||
.dimension()
|
.dimension()
|
||||||
.max_column;
|
.max_column;
|
||||||
}
|
}
|
||||||
@@ -862,20 +898,28 @@ impl Model {
|
|||||||
let column1 = left.column;
|
let column1 = left.column;
|
||||||
let mut column2 = right.column;
|
let mut column2 = right.column;
|
||||||
if row1 == 1 && row2 == LAST_ROW {
|
if row1 == 1 && row2 == LAST_ROW {
|
||||||
row2 = self
|
row2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if column1 == 1 && column2 == LAST_COLUMN {
|
if column1 == 1 && column2 == LAST_COLUMN {
|
||||||
column2 = self
|
column2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
for row in row1..row2 + 1 {
|
for row in row1..row2 + 1 {
|
||||||
for column in column1..(column2 + 1) {
|
for column in column1..(column2 + 1) {
|
||||||
|
|||||||
@@ -128,20 +128,28 @@ impl Model {
|
|||||||
let column1 = left.column;
|
let column1 = left.column;
|
||||||
let mut column2 = right.column;
|
let mut column2 = right.column;
|
||||||
if row1 == 1 && row2 == LAST_ROW {
|
if row1 == 1 && row2 == LAST_ROW {
|
||||||
row2 = self
|
row2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if column1 == 1 && column2 == LAST_COLUMN {
|
if column1 == 1 && column2 == LAST_COLUMN {
|
||||||
column2 = self
|
column2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
for row in row1..row2 + 1 {
|
for row in row1..row2 + 1 {
|
||||||
for column in column1..(column2 + 1) {
|
for column in column1..(column2 + 1) {
|
||||||
@@ -195,20 +203,28 @@ impl Model {
|
|||||||
let column1 = left.column;
|
let column1 = left.column;
|
||||||
let mut column2 = right.column;
|
let mut column2 = right.column;
|
||||||
if row1 == 1 && row2 == LAST_ROW {
|
if row1 == 1 && row2 == LAST_ROW {
|
||||||
row2 = self
|
row2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if column1 == 1 && column2 == LAST_COLUMN {
|
if column1 == 1 && column2 == LAST_COLUMN {
|
||||||
column2 = self
|
column2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
for row in row1..row2 + 1 {
|
for row in row1..row2 + 1 {
|
||||||
for column in column1..(column2 + 1) {
|
for column in column1..(column2 + 1) {
|
||||||
|
|||||||
@@ -1148,6 +1148,7 @@ impl Model {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader},
|
||||||
|
|||||||
@@ -381,11 +381,16 @@ impl Model {
|
|||||||
let right_row = first_range.right.row;
|
let right_row = first_range.right.row;
|
||||||
let right_column = first_range.right.column;
|
let right_column = first_range.right.column;
|
||||||
|
|
||||||
let dimension = self
|
let dimension = match self.workbook.worksheet(first_range.left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension(),
|
||||||
.worksheet(first_range.left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension();
|
Error::ERROR,
|
||||||
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", first_range.left.sheet),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
let max_row = dimension.max_row;
|
let max_row = dimension.max_row;
|
||||||
let max_column = dimension.max_column;
|
let max_column = dimension.max_column;
|
||||||
|
|
||||||
@@ -526,20 +531,28 @@ impl Model {
|
|||||||
let mut right_column = sum_range.right.column;
|
let mut right_column = sum_range.right.column;
|
||||||
|
|
||||||
if left_row == 1 && right_row == LAST_ROW {
|
if left_row == 1 && right_row == LAST_ROW {
|
||||||
right_row = self
|
right_row = match self.workbook.worksheet(sum_range.left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(sum_range.left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return Err(CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", sum_range.left.sheet),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if left_column == 1 && right_column == LAST_COLUMN {
|
if left_column == 1 && right_column == LAST_COLUMN {
|
||||||
right_column = self
|
right_column = match self.workbook.worksheet(sum_range.left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(sum_range.left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return Err(CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", sum_range.left.sheet),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for row in left_row..right_row + 1 {
|
for row in left_row..right_row + 1 {
|
||||||
|
|||||||
@@ -53,8 +53,13 @@ impl Model {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cell_hidden_status(&self, sheet_index: u32, row: i32, column: i32) -> CellTableStatus {
|
fn cell_hidden_status(
|
||||||
let worksheet = self.workbook.worksheet(sheet_index).expect("");
|
&self,
|
||||||
|
sheet_index: u32,
|
||||||
|
row: i32,
|
||||||
|
column: i32,
|
||||||
|
) -> Result<CellTableStatus, String> {
|
||||||
|
let worksheet = self.workbook.worksheet(sheet_index)?;
|
||||||
let mut hidden = false;
|
let mut hidden = false;
|
||||||
for row_style in &worksheet.rows {
|
for row_style in &worksheet.rows {
|
||||||
if row_style.r == row {
|
if row_style.r == row {
|
||||||
@@ -63,13 +68,13 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !hidden {
|
if !hidden {
|
||||||
return CellTableStatus::Normal;
|
return Ok(CellTableStatus::Normal);
|
||||||
}
|
}
|
||||||
// The row is hidden we need to know if the table has filters
|
// The row is hidden we need to know if the table has filters
|
||||||
if self.get_table_for_cell(sheet_index, row, column) {
|
if self.get_table_for_cell(sheet_index, row, column) {
|
||||||
CellTableStatus::Filtered
|
Ok(CellTableStatus::Filtered)
|
||||||
} else {
|
} else {
|
||||||
CellTableStatus::Hidden
|
Ok(CellTableStatus::Hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +148,11 @@ impl Model {
|
|||||||
let column2 = right.column;
|
let column2 = right.column;
|
||||||
|
|
||||||
for row in row1..=row2 {
|
for row in row1..=row2 {
|
||||||
let cell_status = self.cell_hidden_status(left.sheet, row, column1);
|
let cell_status = self
|
||||||
|
.cell_hidden_status(left.sheet, row, column1)
|
||||||
|
.map_err(|message| {
|
||||||
|
CalcResult::new_error(Error::ERROR, cell, message)
|
||||||
|
})?;
|
||||||
if cell_status == CellTableStatus::Filtered {
|
if cell_status == CellTableStatus::Filtered {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -380,7 +389,14 @@ impl Model {
|
|||||||
let column2 = right.column;
|
let column2 = right.column;
|
||||||
|
|
||||||
for row in row1..=row2 {
|
for row in row1..=row2 {
|
||||||
let cell_status = self.cell_hidden_status(left.sheet, row, column1);
|
let cell_status = match self
|
||||||
|
.cell_hidden_status(left.sheet, row, column1)
|
||||||
|
{
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(message) => {
|
||||||
|
return CalcResult::new_error(Error::ERROR, cell, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
if cell_status == CellTableStatus::Filtered {
|
if cell_status == CellTableStatus::Filtered {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -449,7 +465,14 @@ impl Model {
|
|||||||
let column2 = right.column;
|
let column2 = right.column;
|
||||||
|
|
||||||
for row in row1..=row2 {
|
for row in row1..=row2 {
|
||||||
let cell_status = self.cell_hidden_status(left.sheet, row, column1);
|
let cell_status = match self
|
||||||
|
.cell_hidden_status(left.sheet, row, column1)
|
||||||
|
{
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(message) => {
|
||||||
|
return CalcResult::new_error(Error::ERROR, cell, message);
|
||||||
|
}
|
||||||
|
};
|
||||||
if cell_status == CellTableStatus::Filtered {
|
if cell_status == CellTableStatus::Filtered {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -888,20 +888,28 @@ impl Model {
|
|||||||
let column1 = left.column;
|
let column1 = left.column;
|
||||||
let mut column2 = right.column;
|
let mut column2 = right.column;
|
||||||
if row1 == 1 && row2 == LAST_ROW {
|
if row1 == 1 && row2 == LAST_ROW {
|
||||||
row2 = self
|
row2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if column1 == 1 && column2 == LAST_COLUMN {
|
if column1 == 1 && column2 == LAST_COLUMN {
|
||||||
column2 = self
|
column2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
for row in row1..row2 + 1 {
|
for row in row1..row2 + 1 {
|
||||||
for column in column1..(column2 + 1) {
|
for column in column1..(column2 + 1) {
|
||||||
|
|||||||
@@ -251,20 +251,28 @@ impl Model {
|
|||||||
let column1 = left.column;
|
let column1 = left.column;
|
||||||
|
|
||||||
if row1 == 1 && row2 == LAST_ROW {
|
if row1 == 1 && row2 == LAST_ROW {
|
||||||
row2 = self
|
row2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_row,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_row;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if column1 == 1 && column2 == LAST_COLUMN {
|
if column1 == 1 && column2 == LAST_COLUMN {
|
||||||
column2 = self
|
column2 = match self.workbook.worksheet(left.sheet) {
|
||||||
.workbook
|
Ok(s) => s.dimension().max_column,
|
||||||
.worksheet(left.sheet)
|
Err(_) => {
|
||||||
.expect("Sheet expected during evaluation.")
|
return CalcResult::new_error(
|
||||||
.dimension()
|
Error::ERROR,
|
||||||
.max_column;
|
cell,
|
||||||
|
format!("Invalid worksheet index: '{}'", left.sheet),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
let left = CellReferenceIndex {
|
let left = CellReferenceIndex {
|
||||||
sheet: left.sheet,
|
sheet: left.sheet,
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ pub struct Language {
|
|||||||
pub errors: Errors,
|
pub errors: Errors,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
static LANGUAGES: Lazy<HashMap<String, Language>> = Lazy::new(|| {
|
static LANGUAGES: Lazy<HashMap<String, Language>> = Lazy::new(|| {
|
||||||
bitcode::decode(include_bytes!("language.bin")).expect("Failed parsing language file")
|
bitcode::decode(include_bytes!("language.bin")).expect("Failed parsing language file")
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ pub struct DecimalFormats {
|
|||||||
pub standard: String,
|
pub standard: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
static LOCALES: Lazy<HashMap<String, Locale>> =
|
static LOCALES: Lazy<HashMap<String, Locale>> =
|
||||||
Lazy::new(|| bitcode::decode(include_bytes!("locales.bin")).expect("Failed parsing locale"));
|
Lazy::new(|| bitcode::decode(include_bytes!("locales.bin")).expect("Failed parsing locale"));
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ pub use crate::mock_time::get_milliseconds_since_epoch;
|
|||||||
/// * Or mocked for tests
|
/// * Or mocked for tests
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
pub fn get_milliseconds_since_epoch() -> i64 {
|
pub fn get_milliseconds_since_epoch() -> i64 {
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
@@ -529,6 +530,7 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
fn cell_reference_to_string(
|
fn cell_reference_to_string(
|
||||||
&self,
|
&self,
|
||||||
cell_reference: &CellReferenceIndex,
|
cell_reference: &CellReferenceIndex,
|
||||||
@@ -544,6 +546,7 @@ impl Model {
|
|||||||
/// Sets `result` in the cell given by `sheet` sheet index, row and column
|
/// Sets `result` in the cell given by `sheet` sheet index, row and column
|
||||||
/// Note that will panic if the cell does not exist
|
/// Note that will panic if the cell does not exist
|
||||||
/// It will do nothing if the cell does not have a formula
|
/// It will do nothing if the cell does not have a formula
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
fn set_cell_value(&mut self, cell_reference: CellReferenceIndex, result: &CalcResult) {
|
fn set_cell_value(&mut self, cell_reference: CellReferenceIndex, result: &CalcResult) {
|
||||||
let CellReferenceIndex { sheet, column, row } = cell_reference;
|
let CellReferenceIndex { sheet, column, row } = cell_reference;
|
||||||
let cell = &self.workbook.worksheets[sheet as usize].sheet_data[&row][&column];
|
let cell = &self.workbook.worksheets[sheet as usize].sheet_data[&row][&column];
|
||||||
@@ -875,6 +878,7 @@ impl Model {
|
|||||||
.map_err(|_| format!("Invalid timezone: {}", workbook.settings.tz))?;
|
.map_err(|_| format!("Invalid timezone: {}", workbook.settings.tz))?;
|
||||||
|
|
||||||
// FIXME: Add support for display languages
|
// FIXME: Add support for display languages
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
let language = get_language("en").expect("").clone();
|
let language = get_language("en").expect("").clone();
|
||||||
let mut shared_strings = HashMap::new();
|
let mut shared_strings = HashMap::new();
|
||||||
for (index, s) in workbook.shared_strings.iter().enumerate() {
|
for (index, s) in workbook.shared_strings.iter().enumerate() {
|
||||||
@@ -1986,6 +1990,7 @@ impl Model {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#![allow(clippy::expect_used)]
|
||||||
use super::CellReferenceIndex as CellReference;
|
use super::CellReferenceIndex as CellReference;
|
||||||
use crate::{test::util::new_empty_model, types::Cell};
|
use crate::{test::util::new_empty_model, types::Cell};
|
||||||
|
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ impl Model {
|
|||||||
let cells = HashMap::new();
|
let cells = HashMap::new();
|
||||||
|
|
||||||
// FIXME: Add support for display languages
|
// FIXME: Add support for display languages
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
let language = get_language("en").expect("").clone();
|
let language = get_language("en").expect("").clone();
|
||||||
|
|
||||||
let mut model = Model {
|
let mut model = Model {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
use crate::test::util::new_empty_model;
|
use crate::test::util::new_empty_model;
|
||||||
use crate::types::Cell;
|
use crate::types::Cell;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use crate::test::util::new_empty_model;
|
use crate::test::util::new_empty_model;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use crate::{expressions::token, test::util::new_empty_model, types::Cell};
|
use crate::{expressions::token, test::util::new_empty_model, types::Cell};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::{DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_HEIGHT},
|
constants::{DEFAULT_COLUMN_WIDTH, DEFAULT_ROW_HEIGHT},
|
||||||
test::util::new_empty_model,
|
test::util::new_empty_model,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use crate::{expressions::types::Area, UserModel};
|
use crate::{expressions::types::Area, UserModel};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -571,7 +571,10 @@ impl UserModel {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let data = worksheet.sheet_data.get(&row).unwrap().clone();
|
let data = match worksheet.sheet_data.get(&row) {
|
||||||
|
Some(s) => s.clone(),
|
||||||
|
None => return Err(format!("Row number '{row}' is not valid.")),
|
||||||
|
};
|
||||||
let old_data = Box::new(RowData {
|
let old_data = Box::new(RowData {
|
||||||
row: row_data,
|
row: row_data,
|
||||||
data,
|
data,
|
||||||
@@ -1369,11 +1372,16 @@ impl UserModel {
|
|||||||
);
|
);
|
||||||
text_row.push(text);
|
text_row.push(text);
|
||||||
}
|
}
|
||||||
wtr.write_record(text_row).unwrap();
|
wtr.write_record(text_row)
|
||||||
|
.map_err(|e| format!("Error while processing csv: {}", e))?;
|
||||||
data.insert(row, data_row);
|
data.insert(row, data_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
let csv = String::from_utf8(wtr.into_inner().unwrap()).unwrap();
|
let csv = String::from_utf8(
|
||||||
|
wtr.into_inner()
|
||||||
|
.map_err(|e| format!("Processing error: '{}'", e))?,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("Error converting from utf8: '{}'", e))?;
|
||||||
|
|
||||||
Ok(Clipboard {
|
Ok(Clipboard {
|
||||||
csv,
|
csv,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ impl ParsedReference {
|
|||||||
locale: &Locale,
|
locale: &Locale,
|
||||||
get_sheet_index_by_name: F,
|
get_sheet_index_by_name: F,
|
||||||
) -> Result<ParsedReference, String> {
|
) -> Result<ParsedReference, String> {
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
let language = get_language("en").expect("");
|
let language = get_language("en").expect("");
|
||||||
let mut lexer = Lexer::new(reference, LexerMode::A1, locale, language);
|
let mut lexer = Lexer::new(reference, LexerMode::A1, locale, language);
|
||||||
|
|
||||||
@@ -151,6 +152,8 @@ pub(crate) fn is_valid_hex_color(color: &str) -> bool {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#![allow(clippy::expect_used)]
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::language::get_language;
|
use crate::language::get_language;
|
||||||
use crate::locale::{get_locale, Locale};
|
use crate::locale::{get_locale, Locale};
|
||||||
|
|||||||
@@ -19,6 +19,3 @@ pyo3 = { version = "0.22.3", features = ["extension-module"] }
|
|||||||
[features]
|
[features]
|
||||||
extension-module = ["pyo3/extension-module"]
|
extension-module = ["pyo3/extension-module"]
|
||||||
default = ["extension-module"]
|
default = ["extension-module"]
|
||||||
|
|
||||||
[tool.maturin]
|
|
||||||
features = ["pyo3/extension-module"]
|
|
||||||
@@ -208,6 +208,7 @@ impl PyModel {
|
|||||||
.map_err(|e| WorkbookError::new_err(e.to_string()))
|
.map_err(|e| WorkbookError::new_err(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::panic)]
|
||||||
pub fn test_panic(&self) -> PyResult<()> {
|
pub fn test_panic(&self) -> PyResult<()> {
|
||||||
panic!("This function panics for testing panic handling");
|
panic!("This function panics for testing panic handling");
|
||||||
}
|
}
|
||||||
@@ -240,6 +241,7 @@ pub fn create(name: &str, locale: &str, tz: &str) -> PyResult<PyModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
|
#[allow(clippy::panic)]
|
||||||
pub fn test_panic() {
|
pub fn test_panic() {
|
||||||
panic!("This function panics for testing panic handling");
|
panic!("This function panics for testing panic handling");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,15 +274,18 @@ impl Model {
|
|||||||
row: i32,
|
row: i32,
|
||||||
column: i32,
|
column: i32,
|
||||||
) -> Result<JsValue, JsError> {
|
) -> Result<JsValue, JsError> {
|
||||||
self.model
|
let style = self
|
||||||
|
.model
|
||||||
.get_cell_style(sheet, row, column)
|
.get_cell_style(sheet, row, column)
|
||||||
.map_err(to_js_error)
|
.map_err(to_js_error)?;
|
||||||
.map(|x| serde_wasm_bindgen::to_value(&x).unwrap())
|
|
||||||
|
serde_wasm_bindgen::to_value(&style).map_err(|e| to_js_error(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = "onPasteStyles")]
|
#[wasm_bindgen(js_name = "onPasteStyles")]
|
||||||
pub fn on_paste_styles(&mut self, styles: JsValue) -> Result<(), JsError> {
|
pub fn on_paste_styles(&mut self, styles: JsValue) -> Result<(), JsError> {
|
||||||
let styles: &Vec<Vec<Style>> = &serde_wasm_bindgen::from_value(styles).unwrap();
|
let styles: &Vec<Vec<Style>> =
|
||||||
|
&serde_wasm_bindgen::from_value(styles).map_err(|e| to_js_error(e.to_string()))?;
|
||||||
self.model.on_paste_styles(styles).map_err(to_js_error)
|
self.model.on_paste_styles(styles).map_err(to_js_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +307,10 @@ impl Model {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I don't _think_ serializing to JsValue can't fail
|
||||||
|
// FIXME: Remove this clippy directive
|
||||||
#[wasm_bindgen(js_name = "getWorksheetsProperties")]
|
#[wasm_bindgen(js_name = "getWorksheetsProperties")]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
pub fn get_worksheets_properties(&self) -> JsValue {
|
pub fn get_worksheets_properties(&self) -> JsValue {
|
||||||
serde_wasm_bindgen::to_value(&self.model.get_worksheets_properties()).unwrap()
|
serde_wasm_bindgen::to_value(&self.model.get_worksheets_properties()).unwrap()
|
||||||
}
|
}
|
||||||
@@ -320,7 +326,10 @@ impl Model {
|
|||||||
vec![sheet as i32, row, column]
|
vec![sheet as i32, row, column]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I don't _think_ serializing to JsValue can't fail
|
||||||
|
// FIXME: Remove this clippy directive
|
||||||
#[wasm_bindgen(js_name = "getSelectedView")]
|
#[wasm_bindgen(js_name = "getSelectedView")]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
pub fn get_selected_view(&self) -> JsValue {
|
pub fn get_selected_view(&self) -> JsValue {
|
||||||
serde_wasm_bindgen::to_value(&self.model.get_selected_view()).unwrap()
|
serde_wasm_bindgen::to_value(&self.model.get_selected_view()).unwrap()
|
||||||
}
|
}
|
||||||
@@ -503,8 +512,9 @@ impl Model {
|
|||||||
let data = self
|
let data = self
|
||||||
.model
|
.model
|
||||||
.copy_to_clipboard()
|
.copy_to_clipboard()
|
||||||
.map_err(|e| to_js_error(e.to_string()));
|
.map_err(|e| to_js_error(e.to_string()))?;
|
||||||
data.map(|x| serde_wasm_bindgen::to_value(&x).unwrap())
|
|
||||||
|
serde_wasm_bindgen::to_value(&data).map_err(|e| to_js_error(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = "pasteFromClipboard")]
|
#[wasm_bindgen(js_name = "pasteFromClipboard")]
|
||||||
|
|||||||
@@ -9,17 +9,15 @@ 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
|
model.set_user_input(0, row, column, format!("{}", value))?;
|
||||||
.set_user_input(0, row, column, format!("{}", value))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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).unwrap();
|
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:{}100)", last_column);
|
||||||
model.set_user_input(1, 1, 1, formula).unwrap();
|
model.set_user_input(1, 1, 1, formula)?;
|
||||||
|
|
||||||
// evaluates
|
// evaluates
|
||||||
model.evaluate();
|
model.evaluate();
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#![allow(clippy::panic)]
|
||||||
|
#![allow(clippy::expect_used)]
|
||||||
|
|
||||||
//! Produces documentation of all the implemented IronCalc functions
|
//! Produces documentation of all the implemented IronCalc functions
|
||||||
//! and saves the result to functions.md
|
//! and saves the result to functions.md
|
||||||
//!
|
//!
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
//! Tests an Excel xlsx file.
|
//! Tests an Excel xlsx file.
|
||||||
//! Returns a list of differences in json format.
|
//! Returns a list of differences in json format.
|
||||||
//! Saves an IronCalc version
|
//! Saves an IronCalc version
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
//! Tests an Excel xlsx file.
|
//! Tests an Excel xlsx file.
|
||||||
//! Returns a list of differences in json format.
|
//! Returns a list of differences in json format.
|
||||||
//! Saves an IronCalc version
|
//! Saves an IronCalc version
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use ironcalc_base::cell::CellValue;
|
use ironcalc_base::cell::CellValue;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
mod _rels;
|
mod _rels;
|
||||||
mod doc_props;
|
mod doc_props;
|
||||||
mod escape;
|
mod escape;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
//! <sheet name="Sheet1" sheetId="1" r:id="rId1"/>
|
//! <sheet name="Sheet1" sheetId="1" r:id="rId1"/>
|
||||||
|
|
||||||
//! A workbook is composed of workbook-level properties and a collection of 1 or more sheets.
|
//! A workbook is composed of workbook-level properties and a collection of 1 or more sheets.
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
//! # A note on shared formulas
|
//! # A note on shared formulas
|
||||||
//! Although both Excel and IronCalc uses shared formulas they are used in a slightly different way that cannot be mapped 1-1
|
//! Although both Excel and IronCalc uses shared formulas they are used in a slightly different way that cannot be mapped 1-1
|
||||||
//! In IronCalc _all_ formulas are shared and there is a list of shared formulas much like there is a list of shared strings.
|
//! In IronCalc _all_ formulas are shared and there is a list of shared formulas much like there is a list of shared strings.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use core::cmp::max;
|
use core::cmp::max;
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ fn read_shared_strings_from_string(text: &str) -> Result<Vec<String>, XlsxError>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -41,29 +41,35 @@ pub(crate) fn load_table<R: Read + std::io::Seek>(
|
|||||||
// They also need to be different from any defined name
|
// They also need to be different from any defined name
|
||||||
let name = table
|
let name = table
|
||||||
.attribute("name")
|
.attribute("name")
|
||||||
.expect("Missing table name")
|
.ok_or_else(|| XlsxError::Xml("Corrupt XML structure: missing table name".to_string()))?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let display_name = table
|
let display_name = table
|
||||||
.attribute("name")
|
.attribute("name")
|
||||||
.expect("Missing table display name")
|
.ok_or_else(|| {
|
||||||
|
XlsxError::Xml("Corrupt XML structure: missing table display name".to_string())
|
||||||
|
})?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
// Range of the table, including the totals if any and headers.
|
// Range of the table, including the totals if any and headers.
|
||||||
let reference = table
|
let reference = table
|
||||||
.attribute("ref")
|
.attribute("ref")
|
||||||
.expect("Missing table ref")
|
.ok_or_else(|| XlsxError::Xml("Corrupt XML structure: missing table ref".to_string()))?
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
// Either 0 or 1, indicates if the table has a formula for totals at the bottom of the table
|
// Either 0 or 1, indicates if the table has a formula for totals at the bottom of the table
|
||||||
let totals_row_count = match table.attribute("totalsRowCount") {
|
let totals_row_count = match table.attribute("totalsRowCount") {
|
||||||
Some(s) => s.parse::<u32>().expect("Invalid totalsRowCount"),
|
Some(s) => s.parse::<u32>().map_err(|_| {
|
||||||
|
XlsxError::Xml("Corrupt XML structure: Invalid totalsRowCount".to_string())
|
||||||
|
})?,
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Either 0 or 1, indicates if the table has headers at the top of the table
|
// Either 0 or 1, indicates if the table has headers at the top of the table
|
||||||
let header_row_count = match table.attribute("headerRowCount") {
|
let header_row_count = match table.attribute("headerRowCount") {
|
||||||
Some(s) => s.parse::<u32>().expect("Invalid headerRowCount"),
|
Some(s) => s.parse::<u32>().map_err(|_| {
|
||||||
|
XlsxError::Xml("Corrupt XML structure: Invalid headerRowCount".to_string())
|
||||||
|
})?,
|
||||||
None => 1,
|
None => 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,9 +131,15 @@ pub(crate) fn load_table<R: Read + std::io::Seek>(
|
|||||||
.collect::<Vec<Node>>();
|
.collect::<Vec<Node>>();
|
||||||
let mut columns = Vec::new();
|
let mut columns = Vec::new();
|
||||||
for table_column in table_column {
|
for table_column in table_column {
|
||||||
let column_name = table_column.attribute("name").expect("Missing column name");
|
let column_name = table_column.attribute("name").ok_or_else(|| {
|
||||||
let id = table_column.attribute("id").expect("Missing column id");
|
XlsxError::Xml("Corrupt XML structure: missing column name".to_string())
|
||||||
let id = id.parse::<u32>().expect("Invalid id");
|
})?;
|
||||||
|
let id = table_column.attribute("id").ok_or_else(|| {
|
||||||
|
XlsxError::Xml("Corrupt XML structure: missing column id".to_string())
|
||||||
|
})?;
|
||||||
|
let id = id
|
||||||
|
.parse::<u32>()
|
||||||
|
.map_err(|_| XlsxError::Xml("Corrupt XML structure: invalid id".to_string()))?;
|
||||||
|
|
||||||
// style index of the header row of the table
|
// style index of the header row of the table
|
||||||
let header_row_dxf_id = if let Some(index_str) = table_column.attribute("headerRowDxfId") {
|
let header_row_dxf_id = if let Some(index_str) = table_column.attribute("headerRowDxfId") {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use colors::{get_indexed_color, get_themed_color};
|
use colors::{get_indexed_color, get_themed_color};
|
||||||
use roxmltree::{ExpandedName, Node};
|
use roxmltree::{ExpandedName, Node};
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|
||||||
use std::{collections::HashMap, io::Read, num::ParseIntError};
|
use std::{collections::HashMap, io::Read, num::ParseIntError};
|
||||||
|
|
||||||
use ironcalc_base::{
|
use ironcalc_base::{
|
||||||
@@ -1037,7 +1039,10 @@ pub(super) fn load_sheets<R: Read + std::io::Seek>(
|
|||||||
name: sheet_name.to_string(),
|
name: sheet_name.to_string(),
|
||||||
id: sheet.sheet_id,
|
id: sheet.sheet_id,
|
||||||
state: state.clone(),
|
state: state.clone(),
|
||||||
comments: comments.get(rel_id).expect("").to_vec(),
|
comments: comments
|
||||||
|
.get(rel_id)
|
||||||
|
.ok_or_else(|| XlsxError::Xml("Corrupt XML structure".to_string()))?
|
||||||
|
.to_vec(),
|
||||||
};
|
};
|
||||||
let (s, is_selected) =
|
let (s, is_selected) =
|
||||||
load_sheet(archive, &path, settings, worksheets, tables, shared_strings)?;
|
load_sheet(archive, &path, settings, worksheets, tables, shared_strings)?;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
#![allow(clippy::panic)]
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::{env, fs, io};
|
use std::{env, fs, io};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|||||||
Reference in New Issue
Block a user