Summary
empty_sheet_context() (crates/office2pdf/src/parser/xlsx.rs:264-280) hands drawing-only
sheets a context with column_widths: Vec::new() and col_start: 1, col_end: 0. The
column_width_at closure in anchored_image (crates/office2pdf/src/parser/xlsx.rs:180-190)
therefore misses the col_start..=col_end window for every column and prices each one at
column_width_to_pt(DEFAULT_COLUMN_WIDTH, …) (xlsx.rs:188). Unlike
prepare_sheet_context, which reads sheet.get_column_dimension_by_number() per column
(crates/office2pdf/src/parser/xlsx_cells.rs:802-808), the empty-sheet path never consults
the sheet's <cols> entries — declared column widths on a drawing-only sheet are ignored
wholesale.
Measured
Probe workbook: one sheet, empty <sheetData>, <col min=i max=i width="20"> for columns
1-10, one picture anchored C1→F9. Local Excel-for-Mac GT export vs the #620 fix build:
|
GT (Excel) |
office2pdf |
| column width |
120.0pt ((294 − 54) / 2) |
50.58pt (8.43-char default) |
| picture x |
294.0pt (54pt margin + 2 cols) |
155.16pt (−138.84pt) |
| picture width |
360.0pt (3 cols) |
151.74pt (−57.9%) |
| pages |
2 (splits at the printable edge) |
1 |
(Row heights drift too — GT resolves 17pt rows against our 15pt — but that is independent
of <cols> and reproduces on sheets with no <cols> at all; tracked separately.)
Reproduction
# probe: empty sheetData, cols 1-10 width=20, picture C1→F9 (build with openpyxl)
cargo run -p office2pdf-cli -- cols_probe.xlsx -o out.pdf
mutool draw -F trace -o - out.pdf | grep fill_image
# ours: x=155.16 w=151.74 — Excel: x=294 w=360 across 2 pages
Expected
Anchors on a drawing-only sheet resolve against the sheet's declared <cols> widths,
exactly as they do when the sheet has cells.
Actual
empty_sheet_context leaves column_widths empty and column_width_at falls back to
DEFAULT_COLUMN_WIDTH for every column, so <cols> is ignored: the picture renders 2.37×
too narrow and 138.84pt left of Excel's placement, and the sheet loses its second page.
Related: #620 #713
Found in: the #620 fix-PR adversarial review + one-factor probe (local Excel-for-Mac GT, 150 DPI, 2026-07-30). Visual comparison below.
Visual comparison
| Compare |
 |
GT left, office2pdf right, 150 DPI, page 1.
Summary
empty_sheet_context()(crates/office2pdf/src/parser/xlsx.rs:264-280) hands drawing-onlysheets a context with
column_widths: Vec::new()andcol_start: 1, col_end: 0. Thecolumn_width_atclosure inanchored_image(crates/office2pdf/src/parser/xlsx.rs:180-190)therefore misses the
col_start..=col_endwindow for every column and prices each one atcolumn_width_to_pt(DEFAULT_COLUMN_WIDTH, …)(xlsx.rs:188). Unlikeprepare_sheet_context, which readssheet.get_column_dimension_by_number()per column(
crates/office2pdf/src/parser/xlsx_cells.rs:802-808), the empty-sheet path never consultsthe sheet's
<cols>entries — declared column widths on a drawing-only sheet are ignoredwholesale.
Measured
Probe workbook: one sheet, empty
<sheetData>,<col min=i max=i width="20">for columns1-10, one picture anchored C1→F9. Local Excel-for-Mac GT export vs the #620 fix build:
(Row heights drift too — GT resolves 17pt rows against our 15pt — but that is independent
of
<cols>and reproduces on sheets with no<cols>at all; tracked separately.)Reproduction
Expected
Anchors on a drawing-only sheet resolve against the sheet's declared
<cols>widths,exactly as they do when the sheet has cells.
Actual
empty_sheet_contextleavescolumn_widthsempty andcolumn_width_atfalls back toDEFAULT_COLUMN_WIDTHfor every column, so<cols>is ignored: the picture renders 2.37×too narrow and 138.84pt left of Excel's placement, and the sheet loses its second page.
Related: #620 #713
Found in: the #620 fix-PR adversarial review + one-factor probe (local Excel-for-Mac GT, 150 DPI, 2026-07-30). Visual comparison below.
Visual comparison
GT left, office2pdf right, 150 DPI, page 1.