From 74fa69f20dc45a2261e8221da63f0318d90f337c Mon Sep 17 00:00:00 2001 From: Yonghye Kwon Date: Sat, 29 Aug 2026 14:30:27 +0700 Subject: [PATCH] fix: preserve row thickTop Signed-off-by: Yonghye Kwon --- src/structs/row.rs | 25 +++++++++++++++++++++++++ tests/integration_test.rs | 22 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/structs/row.rs b/src/structs/row.rs index 006f204b..975a056b 100644 --- a/src/structs/row.rs +++ b/src/structs/row.rs @@ -38,6 +38,7 @@ pub struct Row { row_num: UInt32Value, height: DoubleValue, descent: DoubleValue, + thick_top: BooleanValue, thick_bot: BooleanValue, custom_height: BooleanValue, hidden: BooleanValue, @@ -50,6 +51,7 @@ impl Default for Row { row_num: UInt32Value::default(), height: DoubleValue::default(), descent: DoubleValue::default(), + thick_top: BooleanValue::default(), thick_bot: BooleanValue::default(), custom_height: BooleanValue::default(), hidden: BooleanValue::default(), @@ -116,6 +118,25 @@ impl Row { self } + #[inline] + #[must_use] + pub fn thick_top(&self) -> bool { + self.thick_top.value() + } + + #[inline] + #[must_use] + #[deprecated(since = "3.0.0", note = "Use thick_top()")] + pub fn get_thick_top(&self) -> bool { + self.thick_top() + } + + #[inline] + pub fn set_thick_top(&mut self, value: bool) -> &mut Self { + self.thick_top.set_value(value); + self + } + #[inline] #[must_use] pub fn thick_bot(&self) -> bool { @@ -221,6 +242,7 @@ impl Row { ) { set_string_from_xml!(self, e, row_num, "r"); set_string_from_xml!(self, e, height, "ht"); + set_string_from_xml!(self, e, thick_top, "thickTop"); set_string_from_xml!(self, e, thick_bot, "thickBot"); set_string_from_xml!(self, e, custom_height, "customHeight"); set_string_from_xml!(self, e, hidden, "hidden"); @@ -300,6 +322,9 @@ impl Row { if self.height.value() != 0f64 { attributes.push(("ht", &height).into()); } + if self.thick_top.value() { + attributes.push(("thickTop", self.thick_top.value_string()).into()); + } if self.thick_bot.value() { attributes.push(("thickBot", self.thick_bot.value_string()).into()); } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 913973aa..37544d68 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -2372,6 +2372,28 @@ fn zip_entry_to_string(xlsx: &[u8], entry_name: &str) -> String { xml } +#[test] +fn row_thick_top_roundtrips() { + let mut book = new_file(); + let sheet = book.sheet_mut(0).unwrap(); + sheet.cell_mut("A2").set_value("thick top"); + sheet.row_dimension_mut(2).set_thick_top(true); + + let xlsx = workbook_to_xlsx_bytes(&book); + let sheet_xml = zip_entry_to_string(&xlsx, "xl/worksheets/sheet1.xml"); + assert!(sheet_xml.contains("thickTop=\"1\"")); + + let roundtrip = reader::xlsx::read_reader(std::io::Cursor::new(xlsx), true).unwrap(); + assert!( + roundtrip + .sheet(0) + .unwrap() + .row_dimension(2) + .unwrap() + .thick_top() + ); +} + fn cell_fragment(sheet_xml: &str, coordinate: &str) -> String { let start = sheet_xml .find(&format!("