UPDATE: Implement Insert/Delete Cells

This commit is contained in:
Nicolás Hatcher
2024-05-09 07:13:51 +02:00
parent f752c90058
commit fd12881972
49 changed files with 830 additions and 172 deletions

View File

@@ -1,31 +1,29 @@
/*!
# GRAMAR
<pre class="rust">
opComp => '=' | '<' | '>' | '<=' } '>=' | '<>'
opFactor => '*' | '/'
unaryOp => '-' | '+'
expr => concat (opComp concat)*
concat => term ('&' term)*
term => factor (opFactor factor)*
factor => prod (opProd prod)*
prod => power ('^' power)*
power => (unaryOp)* range '%'*
range => primary (':' primary)?
primary => '(' expr ')'
=> number
=> function '(' f_args ')'
=> name
=> string
=> '{' a_args '}'
=> bool
=> bool()
=> error
f_args => e (',' e)*
</pre>
*/
//! # GRAMMAR
//!
//! <pre class="rust">
//! opComp => '=' | '<' | '>' | '<=' } '>=' | '<>'
//! opFactor => '*' | '/'
//! unaryOp => '-' | '+'
//!
//! expr => concat (opComp concat)*
//! concat => term ('&' term)*
//! term => factor (opFactor factor)*
//! factor => prod (opProd prod)*
//! prod => power ('^' power)*
//! power => (unaryOp)* range '%'*
//! range => primary (':' primary)?
//! primary => '(' expr ')'
//! => number
//! => function '(' f_args ')'
//! => name
//! => string
//! => '{' a_args '}'
//! => bool
//! => bool()
//! => error
//!
//! f_args => e (',' e)*
//! </pre>
use std::collections::HashMap;
@@ -44,21 +42,15 @@ use super::utils::number_to_column;
use token::OpCompare;
pub mod move_formula;
pub(crate) mod move_formula;
pub(crate) mod walk;
/// Produces a string representation of a formula from the AST.
pub mod stringify;
pub mod walk;
#[cfg(test)]
mod test;
#[cfg(test)]
mod test_ranges;
#[cfg(test)]
mod test_move_formula;
#[cfg(test)]
mod test_tables;
pub(crate) fn parse_range(formula: &str) -> Result<(i32, i32, i32, i32), String> {
let mut lexer = lexer::Lexer::new(
formula,

View File

@@ -1,43 +1,75 @@
#![deny(missing_docs)]
use super::{super::utils::quote_name, Node, Reference};
use crate::constants::{LAST_COLUMN, LAST_ROW};
use crate::expressions::token::OpUnary;
use crate::{expressions::types::CellReferenceRC, number_format::to_excel_precision_str};
/// Displaced data
pub enum DisplaceData {
/// Displaces columns (inserting or deleting columns)
Column {
/// Sheet in which the displace data applies
sheet: u32,
/// Column from which the data is displaced
column: i32,
/// Number of columns displaced (might be negative, e.g. when deleting columns)
delta: i32,
},
/// Displaces rows (Inserting or deleting rows)
Row {
/// Sheet in which the displace data applies
sheet: u32,
/// Row from which the data is displaced
row: i32,
/// Number of rows displaced (might be negative, e.g. when deleting rows)
delta: i32,
},
CellHorizontal {
/// Displaces cells horizontally
ShiftCellsRight {
/// Sheet in which the displace data applies
sheet: u32,
/// Row of the to left corner
row: i32,
/// Column of the top left corner
column: i32,
delta: i32,
/// Number of rows to be displaced
row_delta: i32,
/// Number of columns to be displaced (might be negative)
column_delta: i32,
},
CellVertical {
/// Displaces cells vertically
ShiftCellsDown {
/// Sheet in which the displace data applies
sheet: u32,
/// Row of the to left corner
row: i32,
/// Column of the top left corner
column: i32,
delta: i32,
/// Number of rows displaced (might be negative)
row_delta: i32,
/// Number of columns to be displaced
column_delta: i32,
},
/// Displaces data due to a column move from column to column + delta
ColumnMove {
/// Sheet in which the displace data applies
sheet: u32,
/// Column that is moved
column: i32,
/// The position of the new column is column + delta (might be negative)
delta: i32,
},
/// Doesn't do any cell displacement
None,
}
/// Stringifies the AST formula in its internal R1C1 format
pub fn to_rc_format(node: &Node) -> String {
stringify(node, None, &DisplaceData::None, false)
}
/// Stringifies the formula applying the _displace_data_.
pub fn to_string_displaced(
node: &Node,
context: &CellReferenceRC,
@@ -46,10 +78,12 @@ pub fn to_string_displaced(
stringify(node, Some(context), displace_data, false)
}
/// Stringifies a formula from the AST
pub fn to_string(node: &Node, context: &CellReferenceRC) -> String {
stringify(node, Some(context), &DisplaceData::None, false)
}
/// Stringifies the formula for Excel compatibility
pub fn to_excel_string(node: &Node, context: &CellReferenceRC) -> String {
stringify(node, Some(context), &DisplaceData::None, true)
}
@@ -116,41 +150,49 @@ pub(crate) fn stringify_reference(
}
}
}
DisplaceData::CellHorizontal {
DisplaceData::ShiftCellsRight {
sheet,
row: displace_row,
column: displace_column,
delta,
column_delta,
row_delta,
} => {
if sheet_index == *sheet && displace_row == &row {
if *delta < 0 {
if sheet_index == *sheet
&& displace_row >= &row
&& *displace_row < row + *row_delta
{
if *column_delta < 0 {
if &column >= displace_column {
if column < displace_column - *delta {
if column < displace_column - *column_delta {
return "#REF!".to_string();
}
column += *delta;
column += *column_delta;
}
} else if &column >= displace_column {
column += *delta;
column += *column_delta;
}
}
}
DisplaceData::CellVertical {
DisplaceData::ShiftCellsDown {
sheet,
row: displace_row,
column: displace_column,
delta,
row_delta,
column_delta,
} => {
if sheet_index == *sheet && displace_column == &column {
if *delta < 0 {
if sheet_index == *sheet
&& displace_column >= &column
&& *displace_column < column + *column_delta
{
if *row_delta < 0 {
if &row >= displace_row {
if row < displace_row - *delta {
if row < displace_row - *row_delta {
return "#REF!".to_string();
}
row += *delta;
row += *row_delta;
}
} else if &row >= displace_row {
row += *delta;
row += *row_delta;
}
}
}

View File

@@ -0,0 +1,4 @@
mod test_genertal;
mod test_move_formula;
mod test_ranges;
mod test_tables;

View File

@@ -1,17 +1,12 @@
use std::collections::HashMap;
use crate::expressions::lexer::LexerMode;
use crate::expressions::parser::stringify::DisplaceData;
use super::super::types::CellReferenceRC;
use super::Parser;
use super::{
super::parser::{
stringify::{to_rc_format, to_string},
Node,
},
stringify::to_string_displaced,
use crate::expressions::parser::stringify::{to_string_displaced, DisplaceData};
use crate::expressions::parser::{
stringify::{to_rc_format, to_string},
Node, Parser,
};
use crate::expressions::types::CellReferenceRC;
struct Formula<'a> {
initial: &'a str,

View File

@@ -1,10 +1,8 @@
use std::collections::HashMap;
use crate::expressions::parser::move_formula::{move_formula, MoveContext};
use crate::expressions::types::Area;
use super::super::types::CellReferenceRC;
use super::Parser;
use crate::expressions::parser::Parser;
use crate::expressions::types::{Area, CellReferenceRC};
#[test]
fn test_move_formula() {

View File

@@ -2,9 +2,9 @@ use std::collections::HashMap;
use crate::expressions::lexer::LexerMode;
use super::super::parser::stringify::{to_rc_format, to_string};
use super::super::types::CellReferenceRC;
use super::Parser;
use crate::expressions::parser::stringify::{to_rc_format, to_string};
use crate::expressions::parser::Parser;
use crate::expressions::types::CellReferenceRC;
struct Formula<'a> {
formula_a1: &'a str,

View File

@@ -6,8 +6,8 @@ use crate::expressions::parser::stringify::to_string;
use crate::expressions::utils::{number_to_column, parse_reference_a1};
use crate::types::{Table, TableColumn, TableStyleInfo};
use super::super::types::CellReferenceRC;
use super::Parser;
use crate::expressions::parser::Parser;
use crate::expressions::types::CellReferenceRC;
fn create_test_table(
table_name: &str,