mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-25 19:26:50 -06:00
Recalc: a range ending in INDEX depends on the cells it spans
=SUM(C3:INDEX(B9:C11,2,2)) adds C3:C10, but only C3 and B9:C11 were recorded as its precedents, so typing into C5 left the total unchanged until a full recalculation. A range whose ends are function results now depends on the box spanned by the references inside it, which contains any cell those functions can return.
This commit is contained in:
@@ -1337,6 +1337,20 @@ pub fn precedents(wb: &Workbook, sheet: usize, e: &Expr) -> (Vec<Area>, bool) {
|
||||
}
|
||||
Expr::Name(_) | Expr::Struct(_) => dynamic = true,
|
||||
Expr::Call(n, _) if gridcraft_functions::lookup(n).is_none() && !is_special(n) => dynamic = true,
|
||||
// A range ending in a function's result (`A1:INDEX(B1:B9,n)`) covers the cells between
|
||||
// the references inside it, not only those references.
|
||||
Expr::Binary(BinOp::Range, a, b) if !matches!((&**a, &**b), (Expr::Ref(_), Expr::Ref(_))) => {
|
||||
let mut inner = precedents(wb, sheet, a).0;
|
||||
inner.extend(precedents(wb, sheet, b).0);
|
||||
let mut boxes: Vec<Area> = Vec::new();
|
||||
for area in inner {
|
||||
match boxes.iter_mut().find(|x| x.sheet == area.sheet) {
|
||||
Some(x) => x.range = x.range.union(&area.range),
|
||||
None => boxes.push(area),
|
||||
}
|
||||
}
|
||||
out.extend(boxes);
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
(out, dynamic)
|
||||
|
||||
@@ -165,6 +165,14 @@ fn replacing_a_spilling_formula_clears_its_spill() {
|
||||
assert_eq!((v(&s, "A2"), v(&s, "B1")), (Value::Empty, Value::Number(0.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn range_ending_in_index_recalculates() {
|
||||
let mut s = s();
|
||||
s.execute("cell.set", json!({"cell": "B6", "input": "=SUM(C3:INDEX(B9:C11,2,2))"})).unwrap();
|
||||
s.execute("cell.set", json!({"cell": "C5", "input": "2"})).unwrap();
|
||||
assert_eq!(v(&s, "B6"), Value::Number(2.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_command_survives_empty_params() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user