mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-29 05:06:51 -06:00
Recalc: INDIRECT and OFFSET see spills laid out in the same pass
A formula whose references are only known while evaluating isn't in the
dependency graph, so when it read a spill area before the array was laid
out in the same pass, nothing evaluated it again. With the full
recalculation now laying every spill out afresh, =INDIRECT("F7") over
a spill moved by an inserted row read 0 after Calculate Now. Such
formulas are evaluated once more when a pass computed any array.
This commit is contained in:
@@ -481,6 +481,7 @@ impl Calc {
|
||||
|
||||
/// Evaluates the dirty set and writes results (and spills) back.
|
||||
fn run(&mut self, wb: &mut Workbook, mut dirty: Vec<Key>, full: bool) {
|
||||
let mut dynamic_again = !self.graph.dynamic.is_empty();
|
||||
for _round in 0..8 {
|
||||
if dirty.is_empty() {
|
||||
break;
|
||||
@@ -579,6 +580,12 @@ impl Calc {
|
||||
freed.push((k.0, o));
|
||||
}
|
||||
}
|
||||
// Formulas with references only known while evaluating (INDIRECT, OFFSET) may have read
|
||||
// a spill area before it was laid out: they are evaluated once more.
|
||||
if dynamic_again && !spills.is_empty() {
|
||||
dynamic_again = false;
|
||||
spill_changes.extend(self.graph.dynamic.iter().copied());
|
||||
}
|
||||
// An area a formula no longer spills over may unblock another formula's array.
|
||||
for (si, o) in freed {
|
||||
for &(s, c) in self.graph.nodes.keys() {
|
||||
|
||||
@@ -219,6 +219,17 @@ fn an_array_reading_another_arrays_spill_is_updated() {
|
||||
assert_eq!((v(&s, "G6"), v(&s, "G7")), (Value::Number(12.0), Value::Number(10.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn indirect_reads_a_spill_laid_out_in_the_same_pass() {
|
||||
let mut s = s();
|
||||
s.execute("cell.set", json!({"cell": "F5", "input": "=SEQUENCE(2,2,7)"})).unwrap();
|
||||
s.execute("home.insertRows", json!({"rows": "3:3"})).unwrap();
|
||||
s.execute("cell.set", json!({"cell": "E5", "input": "=INDIRECT(\"F7\")"})).unwrap();
|
||||
assert_eq!(v(&s, "E5"), Value::Number(9.0));
|
||||
s.execute("formulas.calculateNow", json!({})).unwrap();
|
||||
assert_eq!(v(&s, "E5"), Value::Number(9.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_command_survives_empty_params() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user