mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
Move PivotTables with their cells on row/column insert and delete
Found while testing crates/engine/src/cmd/sheet.rs:115 (shift_sheet_features; it never touches sh.pivots) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
f1894c6da6
commit
a6aa53cbff
@@ -2308,4 +2308,53 @@ mod tests {
|
||||
// 64 Sub items under the collapsed "g" show as one column group: (1 + grand total) x 256 columns fit.
|
||||
s.execute("pivot.addField", json!({"field": "Sub", "area": "columns"})).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inserting_or_deleting_lines_moves_the_pivot_with_its_cells() {
|
||||
let mut s = sales();
|
||||
s.execute("insert.pivotTable", json!({"source": "Sheet1!A1:E13", "destination": "Sheet1!H10", "rows": ["Region"], "values": ["Sales"]}))
|
||||
.unwrap();
|
||||
assert_eq!(pt(&s).last_range.unwrap().a1(), "H10:I14");
|
||||
// Rows above the report (and below the source) move the report only.
|
||||
s.execute("home.insertRows", json!({"rows": "16:17"})).unwrap();
|
||||
s.execute("home.insertRows", json!({"rows": "6:7"})).unwrap();
|
||||
assert_eq!(text(&s, "H12"), "Row Labels");
|
||||
let l = s.execute("pivot.list", json!({})).unwrap();
|
||||
assert_eq!(l[0]["anchor"], "H12");
|
||||
assert_eq!(l[0]["range"], "H12:I16");
|
||||
assert_eq!(l[0]["source"], "Sheet1!A1:E15");
|
||||
// A row above the source moves both.
|
||||
s.execute("home.insertRows", json!({"rows": "1:1"})).unwrap();
|
||||
let p = pt(&s);
|
||||
assert_eq!(p.source, "Sheet1!A2:E16");
|
||||
assert_eq!(p.anchor.a1(), "H13");
|
||||
s.execute("pivot.refresh", json!({})).unwrap();
|
||||
assert_eq!(pt(&s).last_range.unwrap().a1(), "H13:I17");
|
||||
assert_eq!(text(&s, "H13"), "Row Labels");
|
||||
assert_eq!(val(&s, "I17"), Value::Number(TOTAL));
|
||||
// Deleting a column left of the report moves it left.
|
||||
s.execute("home.deleteColumns", json!({"cols": "F:F"})).unwrap();
|
||||
let p = pt(&s);
|
||||
assert_eq!(p.anchor.a1(), "G13");
|
||||
assert_eq!(p.last_range.unwrap().a1(), "G13:H17");
|
||||
// Deleting rows above moves it up.
|
||||
s.execute("home.deleteRows", json!({"rows": "1:1"})).unwrap();
|
||||
assert_eq!(pt(&s).source, "Sheet1!A1:E15");
|
||||
assert_eq!(pt(&s).anchor.a1(), "G12");
|
||||
s.execute("pivot.refresh", json!({})).unwrap();
|
||||
assert_eq!(text(&s, "G12"), "Row Labels");
|
||||
assert_eq!(val(&s, "H16"), Value::Number(TOTAL));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inserting_rows_on_the_source_sheet_moves_another_sheets_pivot_source() {
|
||||
let mut s = sales();
|
||||
s.execute("insert.pivotTable", json!({"source": "Sheet1!A1:E13", "rows": ["Region"], "values": ["Sales"]})).unwrap();
|
||||
s.execute("sheet.activate", json!({"sheet": "Sheet1"})).unwrap();
|
||||
s.execute("home.insertRows", json!({"rows": "1:2"})).unwrap();
|
||||
let l = s.execute("pivot.list", json!({})).unwrap();
|
||||
assert_eq!(l[0]["source"], "Sheet1!A3:E15");
|
||||
assert_eq!(l[0]["anchor"], "A3");
|
||||
s.execute("pivot.refresh", json!({"pivot": "PivotTable1"})).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,15 @@ fn shift_sheet_features(sh: &mut Sheet, axis: Axis, at: u32, count: u32, insert:
|
||||
if let Some(pa) = sh.print.print_area {
|
||||
sh.print.print_area = map_range(pa);
|
||||
}
|
||||
// PivotTables follow their report cells. A deleted anchor line collapses onto the line that
|
||||
// takes its place; a report deleted entirely has no last area until the next refresh.
|
||||
for pt in sh.pivots.iter_mut() {
|
||||
pt.anchor = map_cell(pt.anchor).unwrap_or_else(|| match axis {
|
||||
Axis::Rows => CellRef::new(at, pt.anchor.col),
|
||||
Axis::Cols => CellRef::new(pt.anchor.row, at),
|
||||
});
|
||||
pt.last_range = pt.last_range.and_then(map_range);
|
||||
}
|
||||
}
|
||||
|
||||
/// Rewrites every formula reference (and chart series) for a structural edit on `target`.
|
||||
@@ -235,6 +244,18 @@ fn rewrite(wb: &mut gridcraft_model::Workbook, target: &str, e: &Edit) {
|
||||
for sp in sh.sparklines.iter_mut() {
|
||||
sp.source = fix(&sp.source);
|
||||
}
|
||||
// PivotTable sources (a range, table or defined name) are only rewritten when the edit
|
||||
// moves them, so table and name sources keep their text.
|
||||
for pt in sh.pivots.iter_mut() {
|
||||
let body = pt.source.trim().trim_start_matches('=');
|
||||
if let Ok(expr) = gridcraft_formula::parse(body) {
|
||||
let before = gridcraft_formula::print(&expr);
|
||||
let after = gridcraft_formula::print(&gridcraft_formula::adjust::adjust(expr, &host, target, e));
|
||||
if after != before {
|
||||
pt.source = after;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user