From d5c892f23874f20b105f16a9cee8b1c23eb5d75d Mon Sep 17 00:00:00 2001 From: Hector Villarreal Date: Tue, 3 Nov 2026 00:37:00 -0600 Subject: [PATCH] #2630: mark the checkbox mapping bag with its extRef A workbook with checkboxes saved by GridCraft made Excel repair it ("Repaired records: Format from /xl/styles.xml (Styles)") and drop every checkbox. The feature property bag part GridCraft writes for checkboxes left out extRef="XFComplementsMapperExtRef" on the XFComplements bag, the bag the cell formats' xfComplement indexes into. With it, Excel opens the file without repairing and shows the checkboxes. Co-Authored-By: Claude Opus 5.5 --- crates/xlsx/src/feature_bags.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/xlsx/src/feature_bags.rs b/crates/xlsx/src/feature_bags.rs index 71a6514a5..db2e73e91 100644 --- a/crates/xlsx/src/feature_bags.rs +++ b/crates/xlsx/src/feature_bags.rs @@ -25,10 +25,13 @@ pub const XF_EXT_URI: &str = "{C7286773-470A-42A8-94C5-96B5CB345126}"; /// The bags for one checkbox cell control, referenced as `xfComplement i="0"`: Checkbox (0), /// XFControls → 0 (1), XFComplement → 1 (2), XFComplements mapping index 0 → 2 (3). Every -/// reference points to an earlier bag, as [MS-XLSX] 2.6.230 requires. +/// reference points to an earlier bag, as [MS-XLSX] 2.6.230 requires. The XFComplements bag is +/// the one `xfComplement` indexes into, and Excel finds it by its `extRef`: without +/// `extRef="XFComplementsMapperExtRef"` it repairs the workbook ("Format from /xl/styles.xml") +/// and drops every checkbox (#2630). pub fn checkbox_part() -> String { format!( - "\n012" + "\n012" ) } @@ -73,6 +76,9 @@ mod tests { fn written_chain_resolves_and_hostile_chains_do_not() { let root = crate::xml::parse(checkbox_part().as_bytes()).unwrap_or_default(); assert_eq!(checkbox_complements(&root), vec![true]); + // #2630: Excel repairs the file unless the mapping bag carries this extRef. + let mapper = root.kids("bag").find(|b| b.attr("type") == Some("XFComplements")); + assert_eq!(mapper.and_then(|b| b.attr("extRef")), Some("XFComplementsMapperExtRef")); // Out-of-range, wrong-type and self references resolve to false without panicking. let bad = format!( "99114294967295x"