From 85c22dd27bb46dbd3a7e3dae9c12c44fe0875fd2 Mon Sep 17 00:00:00 2001 From: prxnvt <53838599+prxnvt@users.noreply.github.com> Date: Sat, 31 Oct 2026 16:38:18 -0400 Subject: [PATCH] XLSX: control properties parts use the ctrlProp relationship type Excel uses The sheet related each control properties part with http://schemas.microsoft.com/office/2006/relationships/ctrlProp. MS-XLSX defines the relationship in the officeDocument namespace, http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp, which Excel writes and looks the part up by. GridCraft's own reader matched either (it goes by the last segment and the r:id), so its round trips passed; Excel would not have found the parts. --- crates/xlsx/src/controls.rs | 3 ++- crates/xlsx/src/tests/controls_tests.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/xlsx/src/controls.rs b/crates/xlsx/src/controls.rs index 37765dd19..0a3d57bf3 100644 --- a/crates/xlsx/src/controls.rs +++ b/crates/xlsx/src/controls.rs @@ -25,7 +25,8 @@ use crate::write::{Out, Rels}; use crate::xml::{El, esc, esc_attr}; pub const CT_CTRL_PROP: &str = "application/vnd.ms-excel.controlproperties+xml"; -pub const REL_CTRL_PROP: &str = "http://schemas.microsoft.com/office/2006/relationships/ctrlProp"; +/// The worksheet relationship to a control properties part (MS-XLSX), as Excel writes it. +pub const REL_CTRL_PROP: &str = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp"; const NS_X14: &str = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"; const NS_MC: &str = "http://schemas.openxmlformats.org/markup-compatibility/2006"; const NS_XDR: &str = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"; diff --git a/crates/xlsx/src/tests/controls_tests.rs b/crates/xlsx/src/tests/controls_tests.rs index 8825e040a..f94be0e3a 100644 --- a/crates/xlsx/src/tests/controls_tests.rs +++ b/crates/xlsx/src/tests/controls_tests.rs @@ -303,3 +303,15 @@ fn many_listed_controls_read_in_linear_time() { // About 0.4 s here; scanning every shape for every control took over 8 s. assert!(took < std::time::Duration::from_secs(3), "{took:?}"); } + +/// The sheet relates each control properties part with the relationship type MS-XLSX defines and +/// Excel writes (in the officeDocument namespace); Excel finds the part by that type. +#[test] +fn the_properties_parts_use_the_ctrl_prop_relationship_type() { + let bytes = write_xlsx(&book()).unwrap(); + let mut pkg = Package::open(&bytes).unwrap(); + let rels = text(&mut pkg, "xl/worksheets/_rels/sheet1.xml.rels"); + let types: Vec<&str> = rels.split("Type=\"").skip(1).filter_map(|r| r.split('"').next()).filter(|t| t.ends_with("/ctrlProp")).collect(); + assert_eq!(types.len(), 4, "{rels}"); + assert!(types.iter().all(|t| *t == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/ctrlProp"), "{types:?}"); +}