From 2a9f40c65ef9ddc4e280adf5f2ae7efdcc1afdb5 Mon Sep 17 00:00:00 2001 From: tisca26 Date: Fri, 16 Oct 2026 16:38:11 -0600 Subject: [PATCH] Rows: a big font isn't counted twice when the sheet's default height already fits it auto_row_height estimated a line of a bigger font by scaling the sheet's default row height by size / 11. When the sheet's default already fits that font, the font counted twice: Excel for Mac saves rows of 16pt text with defaultRowHeight="21" (28px) and no ht, and opening such a file fitted every row to 40.7px, 1.45 times Excel's height. Rows mixing Middle and Bottom aligned cells then looked misaligned. The estimate now scales an 11pt row's height (DEFAULT_ROW_HEIGHT), so those rows open at 29px, and rows on a 15pt-default sheet still grow to their font (#833). Co-Authored-By: Claude Opus 5.5 (1M context) --- crates/engine/src/cmd/mod.rs | 4 +++- crates/engine/src/tests.rs | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/mod.rs b/crates/engine/src/cmd/mod.rs index 50865a2b7..6eb0ceb63 100644 --- a/crates/engine/src/cmd/mod.rs +++ b/crates/engine/src/cmd/mod.rs @@ -484,7 +484,9 @@ pub fn auto_row_height(wb: &mut Workbook, si: usize, row: u32) { for (c, cell) in sh.cells.row(row, 0, gridcraft_core::MAX_COLS - 1) { let st = wb.styles.get(cell.style); let size = st.font.size; - let line = (size * 1.8).round().max(default * size / gridcraft_model::DEFAULT_FONT_SIZE); + // Scaled from an 11pt row's height, not the sheet's default: a sheet whose default + // already fits a bigger font (21pt rows for 16pt text) would otherwise scale it twice. + let line = (size * 1.8).round().max(gridcraft_model::DEFAULT_ROW_HEIGHT * size / gridcraft_model::DEFAULT_FONT_SIZE); let mut lines = 1.0f32; if !cell.value.is_empty() || cell.formula.is_some() { let text = crate::display::cell_text(wb, sh, CellRef::new(row, c)); diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index ae499a189..9c04ef2dc 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -1150,6 +1150,26 @@ fn open_leaves_plain_workbooks_untouched() { assert!(sh.rows.values().all(|i| i.size.is_none()), "no row gains a height entry"); } +#[test] +fn open_fits_big_font_rows_from_the_font_not_the_sheet_default() { + // Excel saves a sheet whose rows hold 16pt text with a 21pt (28px) default row height and no + // `ht` on rows of that height. Those rows already fit their font: they open at about 28px, + // not scaled up again by 16/11 to 41px. + let mut wb = gridcraft_model::Workbook::new(); + let big = wb.styles.derive(gridcraft_model::StyleId::DEFAULT, |s| s.font.size = 16.0); + let sh = wb.sheet_mut(0).unwrap(); + sh.default_row_height = 28.0; + sh.set_value(CellRef::new(4, 0), Value::text("SANTANDER")); + sh.set_style(CellRef::new(4, 0), big); + let bytes = gridcraft_xlsx::write_xlsx(&wb).unwrap(); + let mut s = Session::new(); + s.execute("file.open", json!({"name": "tall-default.xlsx", "base64": crate::io::base64_encode(&bytes)})).unwrap(); + let sh = s.doc().unwrap().wb.active().unwrap(); + assert_eq!(sh.default_row_height, 28.0); + let h = sh.row_height(4); + assert!((28.0..30.0).contains(&h), "a 16pt row on a 28px-default sheet opens at about 28px, got {h}"); +} + #[test] fn tables_and_structured_refs() { let mut s = s();