FORMULATEXT and the in-cell editor keep Hidden formulas hidden (#3298)

* FORMULATEXT and the cell editor keep a hidden formula's source hidden

* address review: recalculate formulas when sheet protection changes

* address review: skip the full recalculation for a no-op unprotect

* address review: recalculate on protect/unprotect without marking the edit structural
This commit is contained in:
Dylan M. Taylor authored and GitHub committed 2026-11-11 05:48:31 -05:00
1 parent e14f783503
commit bc2dabc7ea
5 files changed
+56 -6

No files matched your search

+21 -1
View File
@@ -163,6 +163,8 @@ fn protect_sheet(s: &mut Session, p: &Json) -> Result<Json> {
let what = d.wb.sheet(sheet).map(|sh| sh.name.clone()).unwrap_or_default();
let prot = SheetProtection { password: str_param(p, "password").filter(|x| !x.is_empty()).map(|pw| new_password_hash(d, &what, pw)), ..prot };
edit(s, |cx| {
// FORMULATEXT reads a sheet's protection: its results are recalculated.
cx.recalc_all = true;
cx.sheet_mut(sheet)?.protection = Some(prot.clone());
Ok(Json::Null)
})
@@ -182,7 +184,10 @@ fn unprotect_sheet(s: &mut Session, p: &Json) -> Result<Json> {
}
}
edit(s, |cx| {
cx.sheet_mut(sheet)?.protection = None;
// Only removing protection changes what FORMULATEXT reads; a no-op unprotect skips the full recalculation.
if cx.sheet_mut(sheet)?.protection.take().is_some() {
cx.recalc_all = true;
}
Ok(Json::Null)
})
}
@@ -404,6 +409,21 @@ mod tests {
assert_eq!(at(&s), (0, "A1".to_string()));
}
#[test]
fn protecting_and_unprotecting_leave_table_headers_alone() {
let mut s = Session::new();
s.new_workbook();
s.execute("range.setValues", json!({"range": "A1", "values": [["a", "b"], [1, 2]]})).unwrap();
s.execute("insert.table", json!({"range": "A1:B2", "header": true})).unwrap();
// An imported header can hold a number: only a structural edit would turn it back into text.
let d = s.doc_mut().unwrap();
std::sync::Arc::make_mut(&mut d.wb).sheet_mut(0).unwrap().set_value(gridcraft_core::CellRef::new(0, 0), gridcraft_core::Value::Number(7.0));
s.execute("review.protectSheet", json!({})).unwrap();
s.execute("review.unprotectSheet", json!({})).unwrap();
let v = s.doc().unwrap().wb.sheet(0).unwrap().value(gridcraft_core::CellRef::new(0, 0));
assert_eq!(v, gridcraft_core::Value::Number(7.0));
}
#[test]
fn protection_that_forbids_selecting_locked_cells_is_enforced_and_kept() {
let mut s = book();