From 6312c7cb4067842838e0dd970b1809b5769eef4f Mon Sep 17 00:00:00 2001 From: prxnvt <53838599+prxnvt@users.noreply.github.com> Date: Thu, 22 Oct 2026 02:01:32 -0400 Subject: [PATCH] Engine: only hidden names are read as macro storage A visible workbook-scope name such as `_gc_macro_0_0` matched the storage key and was read as a macro and removed when the workbook opened. Macro storage is written hidden, so only hidden names are read back; a person's own name of that shape stays a name. --- crates/engine/src/macros/mod.rs | 4 +++- crates/engine/src/macros/tests.rs | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/macros/mod.rs b/crates/engine/src/macros/mod.rs index 9a580c791..38016049d 100644 --- a/crates/engine/src/macros/mod.rs +++ b/crates/engine/src/macros/mod.rs @@ -177,7 +177,9 @@ pub fn load(wb: &mut Workbook) -> Vec { /// The item key (`macro_`, lower-cased) of a hidden macro name, and `n` when it is a number. fn macro_item(n: &DefinedName) -> Option<(String, Option)> { - let key = stash::item_key(&n.name).filter(|k| n.scope.is_none() && k.starts_with(MACRO_KEY))?; + // Only a hidden workbook-scope name is macro storage: a person's own visible name that + // happens to look like one stays a name. + let key = stash::item_key(&n.name).filter(|k| n.hidden && n.scope.is_none() && k.starts_with(MACRO_KEY))?; let i = key.strip_prefix(MACRO_KEY).and_then(|i| i.parse().ok()); Some((key, i)) } diff --git a/crates/engine/src/macros/tests.rs b/crates/engine/src/macros/tests.rs index 4bd2ac1bc..9a28f14f9 100644 --- a/crates/engine/src/macros/tests.rs +++ b/crates/engine/src/macros/tests.rs @@ -127,6 +127,19 @@ fn hidden(name: &str, text: &str) -> DefinedName { DefinedName { name: name.into(), scope: None, formula: format!("\"{}\"", text.replace('"', "\"\"")), comment: String::new(), hidden: true } } +#[test] +fn a_visible_name_that_looks_like_macro_storage_is_left_alone() { + // Macro storage is hidden workbook-scope names; a visible `_gc_macro_0_0` someone defined + // is neither read as a macro nor removed when the workbook opens. + let mut wb = Workbook::new(); + let name = DefinedName { hidden: false, ..hidden("_gc_macro_0_0", "x") }; + wb.names.push(name.clone()); + let warnings = load(&mut wb); + assert!(warnings.is_empty(), "{warnings:?}"); + assert!(wb.macros.is_empty()); + assert_eq!(wb.names, vec![name]); +} + #[test] fn scripts_and_vba_stay_as_they_are() { // Automate scripts keep their own storage, and a VBA project is carried through unchanged.