mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-31 14:17:12 -06:00
Recalc: structural edits don't leave old spills behind
Inserting or deleting rows and columns moved formula cells but not the values they had spilled, and the full recalculation that follows reconciled spills only at the formulas' new positions. =SEQUENCE(3) in A5 with row 1 deleted showed #SPILL! in A4 (blocked by its own old values in A6:A7); deleting the anchor's row left 2 and 3 behind. A full recalculation now drops all spills and lays them out again from the formulas. Fixes #133.
This commit is contained in:
@@ -345,6 +345,16 @@ impl Calc {
|
||||
/// Recalculates every formula (F9 / Ctrl+Alt+F9, and after loading).
|
||||
pub fn recalc_all(&mut self, wb: &mut Workbook) {
|
||||
self.rebuild(wb);
|
||||
// Spills are laid out again from the formulas where they are now (a structural edit moves
|
||||
// or deletes the formulas, not the values they spilled).
|
||||
for i in 0..wb.sheets.len() {
|
||||
if wb.sheet(i).is_some_and(|s| !s.spill_ranges.is_empty() || !s.spill.is_empty())
|
||||
&& let Some(sh) = wb.sheet_mut(i)
|
||||
{
|
||||
sh.spill.clear();
|
||||
sh.spill_ranges.clear();
|
||||
}
|
||||
}
|
||||
let all: Vec<Key> = self.graph.nodes.keys().copied().collect();
|
||||
self.run(wb, all, true);
|
||||
}
|
||||
|
||||
@@ -173,6 +173,17 @@ fn range_ending_in_index_recalculates() {
|
||||
assert_eq!(v(&s, "B6"), Value::Number(2.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structural_edits_move_spills_with_their_formula() {
|
||||
let mut s = s();
|
||||
s.execute("cell.set", json!({"cell": "A5", "input": "=SEQUENCE(3)"})).unwrap();
|
||||
s.execute("home.deleteRows", json!({"rows": "1:1"})).unwrap();
|
||||
let col = |s: &Session| (4..=7).map(|r| v(s, &format!("A{r}"))).collect::<Vec<_>>();
|
||||
assert_eq!(col(&s), [Value::Number(1.0), Value::Number(2.0), Value::Number(3.0), Value::Empty]);
|
||||
s.execute("home.deleteRows", json!({"rows": "4:4"})).unwrap();
|
||||
assert_eq!(col(&s), [Value::Empty, Value::Empty, Value::Empty, Value::Empty]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_command_survives_empty_params() {
|
||||
let mut s = Session::new();
|
||||
|
||||
Reference in New Issue
Block a user