From e8c6fcb8b0fc65deedf245000bef859657bd4d77 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo Date: Fri, 16 Oct 2026 05:11:07 +0200 Subject: [PATCH] XLSX: keep custom column widths that round to the default width (fixes #1607) --- crates/xlsx/src/sheet_read.rs | 4 ++-- crates/xlsx/src/tests/fixtures.rs | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/xlsx/src/sheet_read.rs b/crates/xlsx/src/sheet_read.rs index 0194d2268..83f8d0d91 100644 --- a/crates/xlsx/src/sheet_read.rs +++ b/crates/xlsx/src/sheet_read.rs @@ -324,8 +324,8 @@ fn read_cols(cx: &Ctx<'_>, e: &El, sheet: &mut Sheet) { info.style = Some(id); } } - // A width equal to the default with nothing else set is noise. - if info == LineInfo::default() || (info.size == Some(sheet.default_col_width) && LineInfo { size: None, ..info } == LineInfo::default()) { + // A custom width equal to the default still pins the column (Standard Width leaves it alone). + if info == LineInfo::default() { continue; } for col in (min - 1)..max { diff --git a/crates/xlsx/src/tests/fixtures.rs b/crates/xlsx/src/tests/fixtures.rs index 39ea30951..4ca580a5b 100644 --- a/crates/xlsx/src/tests/fixtures.rs +++ b/crates/xlsx/src/tests/fixtures.rs @@ -577,3 +577,25 @@ fn user_defined_function_prefix_round_trips() { assert_eq!(cell.child("f").unwrap().text, f, "written {a}"); } } + +/// `customWidth="1"` pins a column even when its width rounds to the default: Standard Width does not +/// move it, and a save must keep its `` (openpyxl writes 9.08 for Excel's 8.43, #1607). +#[test] +fn custom_widths_equal_to_the_default_round_trip() { + let body = r#" + + "#; + let (wb, _) = read_xlsx(&minimal(body, &[], "", "")).unwrap(); + let s = wb.sheet(0).unwrap(); + assert_eq!(s.default_col_width, 64.0); + for c in 3..=6 { + assert_eq!(s.cols.get(&c).and_then(|i| i.size), Some(64.0), "read col {c}"); + } + assert_eq!(s.cols.get(&7), None, "a width without customWidth equal to the default stays the default"); + let bytes = crate::write_xlsx(&wb).unwrap(); + let mut pkg = crate::package::Package::open(&bytes).unwrap(); + let sheet = pkg.read_xml("xl/worksheets/sheet1.xml").unwrap().unwrap(); + let cols: Vec<_> = + sheet.child("cols").unwrap().kids("col").map(|c| (c.attr_u32("min"), c.attr_u32("max"), c.flag("customWidth", false))).collect(); + assert_eq!(cols, [(Some(4), Some(7), true)]); +}