Form controls: a linked cell's formula survives a write of the value it already shows

write_link skipped the write only when the linked cell held a constant equal to the value; a cell
with a formula was always written, so Format Control's OK (which sends the value back every
time) replaced the formula with a constant even when the formula showed that value, and on a
protected sheet with the linked cell locked a rename was refused. The value the cell shows is now
compared whether or not it holds a formula: a write that changes nothing is skipped, and a real
change still replaces the formula with the constant, as in Excel.

Test: a_formula_in_the_linked_cell_survives_a_write_of_the_value_it_shows (insert and Format
Control with the value the formula shows keep the formula, also on a protected sheet with the
cell locked; a changed value writes the constant).
This commit is contained in:
prxnvt
2026-11-02 05:13:55 -05:00
parent d09694ff61
commit 112a9c78b9
2 changed files with 41 additions and 2 deletions
+5 -2
View File
@@ -276,11 +276,14 @@ fn linked_number(wb: &Workbook, host: usize, c: &FormControl) -> Option<f64> {
wb.sheet(si)?.cell(cell)?.value.as_f64()
}
/// Writes `value` to the linked cell through `cell.set` (nothing without a link).
/// Writes `value` to the linked cell through `cell.set` (nothing without a link, or when the cell
/// already shows `value`, formula or not: Format Control's OK sends the value back every time, and
/// a write that changes nothing must not turn a formula into a constant or fail on a locked cell
/// of a protected sheet; a real change replaces a formula with the constant, as in Excel).
fn write_link(s: &mut Session, host: usize, link: Option<&str>, value: u32) -> Result<()> {
let Some(link) = link else { return Ok(()) };
let Some((si, cell)) = link_target(&s.doc()?.wb, host, link) else { return Ok(()) };
let holds = s.doc()?.wb.sheet(si).and_then(|sh| sh.cell(cell)).and_then(|c| if c.formula.is_none() { c.value.as_f64() } else { None });
let holds = s.doc()?.wb.sheet(si).and_then(|sh| sh.cell(cell)).and_then(|c| c.value.as_f64());
if holds == Some(value as f64) {
return Ok(());
}