mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-03 00:41:56 -06:00
Engine: Merge Across keeps only the upper-left Python code, and unmerging unblocks a Python spill
Merge Across emptied the value and formula of the other cells in each row but left their Python code, so a hidden cell stayed a Python cell with an empty value and was saved as a PY formula. It now clears their whole content, as Merge Cells and Merge & Center already did. In the same command, a merge change evaluates again the blocked arrays that could reach the area, but only formulas were picked, so a Python result blocked by a merged cell stayed #SPILL! after the cells were unmerged; Python cells are picked too.
This commit is contained in:
@@ -650,8 +650,7 @@ fn merge(s: &mut Session, p: &Json, how: &str) -> Result<Json> {
|
||||
let others: Vec<CellRef> = sh.cells.iter_range(m).map(|(c, _)| c).filter(|c| *c != m.start).collect();
|
||||
for c in others {
|
||||
if let Some(mut cell) = sh.cells.get(c).cloned() {
|
||||
cell.value = gridcraft_core::Value::Empty;
|
||||
cell.formula = None;
|
||||
cell.clear_content();
|
||||
sh.set_cell(c, cell);
|
||||
}
|
||||
touched.push((sheet, c));
|
||||
@@ -685,7 +684,10 @@ fn merge(s: &mut Session, p: &Json, how: &str) -> Result<Json> {
|
||||
let blocked = sh
|
||||
.cells
|
||||
.iter_range(reach)
|
||||
.filter(|(_, x)| x.formula.is_some() && x.value == gridcraft_core::Value::Error(gridcraft_core::CellError::Spill));
|
||||
// A Python cell's result is blocked and unblocked like a formula's.
|
||||
.filter(|(_, x)| {
|
||||
(x.formula.is_some() || x.py.is_some()) && x.value == gridcraft_core::Value::Error(gridcraft_core::CellError::Spill)
|
||||
});
|
||||
touched.extend(blocked.map(|(c, _)| (sheet, c)));
|
||||
}
|
||||
cx.changed.extend(touched);
|
||||
|
||||
@@ -316,3 +316,36 @@ fn a_hidden_python_cell_on_a_protected_sheet_hides_its_code() {
|
||||
assert!(s.execute("python.set", json!({"cell": "A1", "code": "2"})).is_err());
|
||||
assert_eq!(code(&s, 0, "A1").as_deref(), Some("secret = 1\nsecret"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_merge_keeps_only_the_upper_left_cells_python_code() {
|
||||
let mut s = s();
|
||||
for (cmd, row) in [("home.mergeAcross", 1), ("home.mergeCells", 2), ("home.mergeCenter", 3)] {
|
||||
plant(&mut s, 0, &format!("A{row}"), "'kept'");
|
||||
plant(&mut s, 0, &format!("B{row}"), "'merged away'");
|
||||
s.execute(cmd, json!({"range": format!("A{row}:B{row}")})).unwrap();
|
||||
assert_eq!(code(&s, 0, &format!("A{row}")).as_deref(), Some("'kept'"), "{cmd}");
|
||||
assert_eq!(code(&s, 0, &format!("B{row}")), None, "{cmd}: the hidden cell is no Python cell");
|
||||
assert_eq!(super::v(&s, &format!("B{row}")), Value::Empty, "{cmd}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unmerging_lets_a_blocked_python_result_spill_again() {
|
||||
let mut s = s();
|
||||
s.execute("python.set", json!({"cell": "A1", "code": "[5, 6]"})).unwrap();
|
||||
{
|
||||
let d = s.doc_mut().unwrap();
|
||||
let wb = Arc::make_mut(&mut d.wb);
|
||||
let cell = wb.sheet_mut(0).unwrap().cells.get_mut(CellRef::parse("A1").unwrap()).unwrap();
|
||||
let value = Value::Array(Arc::new(gridcraft_core::Array::new(2, 1, vec![Value::Number(5.0), Value::Number(6.0)]).unwrap()));
|
||||
Arc::make_mut(cell.py.as_mut().unwrap()).output =
|
||||
Some(gridcraft_model::PyOutput { value, type_name: "list".into(), preview: String::new(), convertible: true });
|
||||
}
|
||||
s.execute("formulas.calculateNow", json!({})).unwrap();
|
||||
assert_eq!(super::v(&s, "A2"), Value::Number(6.0));
|
||||
s.execute("home.mergeCells", json!({"range": "A2:B2"})).unwrap();
|
||||
assert_eq!(super::v(&s, "A1"), Value::Error(gridcraft_core::CellError::Spill), "a merged cell blocks the spill");
|
||||
s.execute("home.unmergeCells", json!({"range": "A2:B2"})).unwrap();
|
||||
assert_eq!((super::v(&s, "A1"), super::v(&s, "A2")), (Value::Number(5.0), Value::Number(6.0)), "it spills again");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user