diff --git a/crates/calc/src/eval.rs b/crates/calc/src/eval.rs index abef54ffd..c010020a6 100644 --- a/crates/calc/src/eval.rs +++ b/crates/calc/src/eval.rs @@ -1337,6 +1337,20 @@ pub fn precedents(wb: &Workbook, sheet: usize, e: &Expr) -> (Vec, 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 = 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) diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 361fbce48..9fe3fa8fa 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -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();