mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-27 04:06:52 -06:00
Recalc: clearing a distant blocker unblocks the spill
Clearing a cell re-evaluated #SPILL! anchors only within 64 rows and columns above and to the left of it, so =SEQUENCE(100) in A1 stayed #SPILL! after the blocker in A90 was cleared. Emptied cells now look for blocked anchors any distance above or to the left, with one pass over the formulas per sheet however many cells were cleared. Fixes #139.
This commit is contained in:
@@ -396,6 +396,7 @@ impl Calc {
|
||||
return;
|
||||
}
|
||||
let mut seeds: Vec<Key> = changed.to_vec();
|
||||
let mut emptied: Vec<Key> = Vec::new();
|
||||
// Typing into (or clearing) a cell a dynamic array spills over (or would spill over)
|
||||
// re-evaluates the anchor, which may now be blocked or unblocked.
|
||||
for &k in changed {
|
||||
@@ -410,6 +411,20 @@ impl Calc {
|
||||
seeds.push((k.0, c));
|
||||
}
|
||||
}
|
||||
if !sh.cells.has(k.1) {
|
||||
match emptied.iter_mut().find(|x| x.0 == k.0) {
|
||||
Some(x) => x.1 = CellRef::new(x.1.row.max(k.1.row), x.1.col.max(k.1.col)),
|
||||
None => emptied.push(k),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// An emptied cell can unblock an anchor any distance above or to the left of it.
|
||||
for (si, end) in emptied {
|
||||
for &(s, c) in self.graph.nodes.keys() {
|
||||
if s == si && c.row <= end.row && c.col <= end.col && wb.sheet(s).is_some_and(|sh| sh.value(c) == Value::Error(CellError::Spill)) {
|
||||
seeds.push((s, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Spill areas of changed anchors also change.
|
||||
|
||||
@@ -184,6 +184,16 @@ fn structural_edits_move_spills_with_their_formula() {
|
||||
assert_eq!(col(&s), [Value::Empty, Value::Empty, Value::Empty, Value::Empty]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clearing_a_distant_blocker_unblocks_the_spill() {
|
||||
let mut s = s();
|
||||
s.execute("cell.set", json!({"cell": "A1", "input": "=SEQUENCE(100)"})).unwrap();
|
||||
s.execute("cell.set", json!({"cell": "A90", "input": "x"})).unwrap();
|
||||
assert_eq!(v(&s, "A1"), Value::Error(gridcraft_core::CellError::Spill));
|
||||
s.execute("edit.clearContents", json!({"range": "A90"})).unwrap();
|
||||
assert_eq!((v(&s, "A1"), v(&s, "A100")), (Value::Number(1.0), Value::Number(100.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_command_survives_empty_params() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user