mirror of
https://github.com/storytold/gridcraft.git
synced 2026-11-04 01:20:34 -06:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b1ff015ea | ||
|
|
79a4cbac57 |
@@ -52,13 +52,16 @@ impl<'h> Evaluator<'h> {
|
||||
"ISFORMULA" | "FORMULATEXT" => {
|
||||
let Some(Ev::R(a)) = args.first().map(|a| self.eval(a)) else { return err(CellError::NA) };
|
||||
let Some(a) = a.first() else { return err(CellError::NA) };
|
||||
let f = self.host.workbook().sheet(a.sheet).and_then(|s| s.cell(a.range.start)).and_then(|c| c.formula.clone());
|
||||
let wb = self.host.workbook();
|
||||
let f = wb.sheet(a.sheet).and_then(|s| s.cell(a.range.start)).and_then(|c| c.formula.clone());
|
||||
// A formula formatted Hidden on a protected sheet stays hidden from FORMULATEXT too.
|
||||
let hidden = wb.sheet(a.sheet).is_some_and(|s| s.is_protected() && wb.styles.get(s.style_id(a.range.start)).protection.hidden);
|
||||
if name == "ISFORMULA" {
|
||||
Ev::V(Value::Bool(f.is_some()))
|
||||
} else {
|
||||
match f {
|
||||
Some(f) => Ev::V(Value::text(format!("={}", f.text))),
|
||||
None => err(CellError::NA),
|
||||
Some(f) if !hidden => Ev::V(Value::text(format!("={}", f.text))),
|
||||
_ => err(CellError::NA),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.structural = true;
|
||||
cx.sheet_mut(sheet)?.protection = Some(prot.clone());
|
||||
Ok(Json::Null)
|
||||
})
|
||||
@@ -182,6 +184,7 @@ fn unprotect_sheet(s: &mut Session, p: &Json) -> Result<Json> {
|
||||
}
|
||||
}
|
||||
edit(s, |cx| {
|
||||
cx.structural = true;
|
||||
cx.sheet_mut(sheet)?.protection = None;
|
||||
Ok(Json::Null)
|
||||
})
|
||||
|
||||
@@ -5572,3 +5572,20 @@ fn clearing_links_and_notes_keeps_allow_edit_ranges() {
|
||||
let sh = s.doc().unwrap().wb.active().unwrap().clone();
|
||||
assert!(sh.hyperlinks.is_empty() && sh.comments.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formulatext_does_not_reveal_a_hidden_formula() {
|
||||
let mut s = s();
|
||||
s.execute("cell.set", json!({"cell": "A1", "input": "=1+1"})).unwrap();
|
||||
s.execute("home.formatCells", json!({"range": "A1", "style": {"protection": {"locked": false, "hidden": true}}})).unwrap();
|
||||
s.execute("home.formatCells", json!({"range": "B1", "style": {"protection": {"locked": false}}})).unwrap();
|
||||
s.execute("cell.set", json!({"cell": "B1", "input": "=FORMULATEXT(A1)"})).unwrap();
|
||||
assert_eq!(v(&s, "B1"), Value::from("=1+1"), "not protected yet");
|
||||
s.execute("review.protectSheet", json!({})).unwrap();
|
||||
// Without entering the formula again: protecting recalculates what reads the protection.
|
||||
assert_eq!(v(&s, "B1"), Value::Error(gridcraft_core::CellError::NA));
|
||||
s.execute("cell.set", json!({"cell": "B1", "input": "=FORMULATEXT(A1)"})).unwrap();
|
||||
assert_eq!(v(&s, "B1"), Value::Error(gridcraft_core::CellError::NA));
|
||||
s.execute("review.unprotectSheet", json!({})).unwrap();
|
||||
assert_eq!(v(&s, "B1"), Value::from("=1+1"), "unprotecting shows it again without re-entering");
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ impl SheetApp {
|
||||
self.session.mode = gridcraft_engine::Mode::Edit;
|
||||
return;
|
||||
}
|
||||
// A hidden formula's source isn't loaded into an edit (a blank edit would also write over
|
||||
// it on commit): no edit starts. Typing still replaces the cell.
|
||||
if text.is_none() && gridcraft_engine::display::formula_hidden(&d.wb, sh, at) {
|
||||
return;
|
||||
}
|
||||
let locale = self.ui.language.formula_locale();
|
||||
let current = if sh.cell_pictures.contains_key(&at) {
|
||||
String::new()
|
||||
|
||||
Reference in New Issue
Block a user