use super::common::arrow_eval_config;
use crate::engine::Engine;
use crate::test_workbook::TestWorkbook;
use crate::traits::{ArgumentHandle, DefaultFunctionContext, FunctionProvider};
use formualizer_common::LiteralValue;
use formualizer_parse::parser::{ASTNode, ASTNodeType, ReferenceType};
fn range_ref(sheet: &str, sr: u32, sc: u32, er: u32, ec: u32) -> ASTNode {
let r = ReferenceType::Range {
sheet: Some(sheet.to_string()),
start_row: Some(sr),
start_col: Some(sc),
end_row: Some(er),
end_col: Some(ec),
start_row_abs: false,
start_col_abs: false,
end_row_abs: false,
end_col_abs: false,
};
ASTNode::new(
ASTNodeType::Reference {
original: String::new(),
reference: r,
},
None,
)
}
fn lit_text(s: &str) -> ASTNode {
ASTNode::new(ASTNodeType::Literal(LiteralValue::Text(s.into())), None)
}
#[test]
fn sumifs_arrow_edits_start_mid_end() {
let config = arrow_eval_config();
let mut engine = Engine::new(TestWorkbook::new(), config.clone());
let sheet = "SheetEdits";
let mut ab = engine.begin_bulk_ingest_arrow();
ab.add_sheet(sheet, 3, 1024);
let rows = 100;
for i in 0..rows {
let val = LiteralValue::Int((i + 1) as i64);
let group = if i % 2 == 0 { "A" } else { "B" };
let num = LiteralValue::Int(if i % 3 == 0 { 20 } else { 5 }); ab.append_row(sheet, &[val, LiteralValue::Text(group.into()), num])
.unwrap();
}
ab.finish().unwrap();
let sum_rng = range_ref(sheet, 1, 1, rows as u32, 1);
let c1_rng = range_ref(sheet, 1, 2, rows as u32, 2);
let c1 = lit_text("A");
let c2_rng = range_ref(sheet, 1, 3, rows as u32, 3);
let c2 = lit_text(">10");
let eval = |eng: &Engine<TestWorkbook>| -> LiteralValue {
let fun = eng.get_function("", "SUMIFS").expect("SUMIFS available");
let interp = crate::interpreter::Interpreter::new(eng, sheet);
let args = vec![
ArgumentHandle::new(&sum_rng, &interp),
ArgumentHandle::new(&c1_rng, &interp),
ArgumentHandle::new(&c1, &interp),
ArgumentHandle::new(&c2_rng, &interp),
ArgumentHandle::new(&c2, &interp),
];
let fctx = DefaultFunctionContext::new_with_sheet(eng, None, eng.default_sheet_name());
fun.dispatch(&args, &fctx).unwrap().into_literal()
};
let res = eval(&engine);
println!("Initial: {:?}", res);
assert_eq!(res, LiteralValue::Number(833.0), "Initial Sum failed");
engine
.set_cell_value(sheet, 1, 2, LiteralValue::Text("B".into()))
.unwrap();
let res = eval(&engine);
println!("After Start Edit: {:?}", res);
assert_eq!(res, LiteralValue::Number(832.0), "Edit Start failed");
engine
.set_cell_value(sheet, 50, 2, LiteralValue::Text("A".into()))
.unwrap();
engine
.set_cell_value(sheet, 50, 3, LiteralValue::Int(30))
.unwrap();
let res = eval(&engine);
println!("After Mid Edit: {:?}", res);
assert_eq!(res, LiteralValue::Number(882.0), "Edit Middle failed");
engine
.set_cell_value(sheet, 100, 2, LiteralValue::Text("A".into()))
.unwrap();
let v1 = engine.get_cell_value(sheet, 1, 2).unwrap();
println!("Read Row 1 Col 2: {:?}", v1); let v50 = engine.get_cell_value(sheet, 50, 2).unwrap();
println!("Read Row 50 Col 2: {:?}", v50); let v100 = engine.get_cell_value(sheet, 100, 2).unwrap();
println!("Read Row 100 Col 2: {:?}", v100);
let res = eval(&engine);
println!("After End Edit: {:?}", res);
assert_eq!(res, LiteralValue::Number(982.0), "Edit End failed");
}