From 7dcb3bd2fae0631990a189baf889c7832a870fdc Mon Sep 17 00:00:00 2001 From: Leandro Marceddu Date: Fri, 28 Aug 2026 17:54:38 +0200 Subject: [PATCH] fix: keep worksheet drawing r:id in sync with its rels write_print_settings bumped the relationship id whenever PageSetup had any page-setup attribute (paperSize/orientation), but the rels writer only emits a printerSettings relationship when PageSetup::object_data is present. For a sheet with a page setup but no printer-settings binary this wrote while the rels only defined the drawing at rId1, a dangling reference that made Excel strip the drawing. Read the mutable counter back from PageSetup::write_to so the id only advances when a printerSettings relationship is actually written. --- src/writer/xlsx/worksheet.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/writer/xlsx/worksheet.rs b/src/writer/xlsx/worksheet.rs index 229e36cc..d3cd2b74 100644 --- a/src/writer/xlsx/worksheet.rs +++ b/src/writer/xlsx/worksheet.rs @@ -447,10 +447,9 @@ fn write_print_settings(writer: &mut InternalWriter, worksheet: &Worksheet, r_id worksheet.page_margins().write_to(writer); if worksheet.page_setup().has_param() { - worksheet - .page_setup() - .write_to(writer, &mut num_traits::cast(r_id).unwrap()); - r_id += 1; + let mut r_id_write: usize = num_traits::cast(r_id).unwrap(); + worksheet.page_setup().write_to(writer, &mut r_id_write); + r_id = num_traits::cast(r_id_write).unwrap(); } worksheet.header_footer().write_to(writer); @@ -658,6 +657,31 @@ mod tests { assert_eq!(r_id, 1); } + #[test] + fn test_write_print_settings_with_params_no_object_data_keeps_rid_stable() { + // `write_print_settings` must NOT advance the relationship id for a + // pageSetup that carries only attributes (paper size, orientation, ...) + // but has no printer-settings `object_data`. The rels writer only emits a + // printerSettings relationship when `object_data` is present, so failing + // to keep the two in sync emits a `` that points at a + // non-existent relationship, which Excel then uses to strip the drawing. + let mut writer = setup_test_writer(); + let mut worksheet = setup_test_worksheet(); + worksheet.page_setup_mut().set_paper_size(9); + + assert!(worksheet.page_setup().has_param()); + assert!(worksheet.page_setup().object_data().is_none()); + + let r_id = write_print_settings(&mut writer, &worksheet, 1); + + let result = String::from_utf8(writer.into_inner().into_inner()).unwrap(); + assert!(result.contains("pageSetup")); + assert!(!result.contains("r:id")); + // No printerSettings relationship was written, so the next relationship + // id (e.g. the drawing's) must remain unchanged. + assert_eq!(r_id, 1); + } + #[test] fn test_write_drawings() { let mut writer = setup_test_writer();