Engine: writing a stash item checks for a clashing visible name in one pass over the names

The check ran once per chunk, each a scan of every defined name: an item of many chunks in a workbook with thousands of names compared every pair. One pass now parses each visible workbook-scope name and refuses when it is a chunk of this key below the chunk count. The behaviour and its test are unchanged.
This commit is contained in:
prxnvt
2026-10-23 16:21:48 -04:00
parent 524826687c
commit 5ca886507c
+11 -8
View File
@@ -65,14 +65,17 @@ pub fn set(wb: &mut Workbook, key: &str, text: &str) -> Result<()> {
}
let formulas = chunk_formulas(text);
// A visible name of the item's shape is someone's own (see `item_of`); a hidden name beside
// it with the same name would be the one an xlsx file drops. Refuse before changing anything.
for i in 0..formulas.len() {
let name = format!("{PREFIX}{key}_{i}");
if wb.names.iter().any(|n| n.scope.is_none() && !n.hidden && n.name.eq_ignore_ascii_case(&name)) {
return Err(EngineError::Other(format!(
"The workbook has a defined name '{name}', which GridCraft needs for its own data. Rename it first."
)));
}
// it with the same name would be the one an xlsx file drops. Refuse before changing anything,
// in one pass over the names (a file can carry many thousands).
let chunks = formulas.len() as u64;
let taken = |n: &&DefinedName| {
n.scope.is_none() && !n.hidden && parse_name(&n.name).is_some_and(|(k, i)| k.eq_ignore_ascii_case(key) && i.is_some_and(|i| i < chunks))
};
if let Some(n) = wb.names.iter().find(taken) {
return Err(EngineError::Other(format!(
"The workbook has a defined name '{}', which GridCraft needs for its own data. Rename it first.",
n.name
)));
}
remove(wb, key);
for (i, formula) in formulas.into_iter().enumerate() {