Skip to content

fix(xlsx): cell alignment, column width, borders, page setup#186

Open
nikith-18161 wants to merge 7 commits into
developer0hye:mainfrom
nikith-18161:main
Open

fix(xlsx): cell alignment, column width, borders, page setup#186
nikith-18161 wants to merge 7 commits into
developer0hye:mainfrom
nikith-18161:main

Conversation

@nikith-18161

@nikith-18161 nikith-18161 commented Jun 5, 2026

Copy link
Copy Markdown

Summary

Fix XLSX conversion: cell alignment, column width, borders, and page setup.

Changes

1. Cell alignment (xlsx_style.rs, xlsx_cells.rs, ir/elements.rs, typst_gen_tables.rs)

  • Parse and render horizontal alignment: Left, Center, Right, Justify
  • Distributed alignment approximated as Justify
  • Numeric cells auto right-aligned using cell.get_value_number() instead of parsing the formatted string (avoids false positives on text like 0050 and missing currency/percentage values)

2. Column width (xlsx_cells.rs)

  • Corrected formula to OOXML spec: (char_width * 7.0 + 5.0) * 0.75
  • Accounts for 5px padding Excel adds before converting pixels to points

3. Double border rendering (typst_gen.rs, typst_gen_table_border_tests.rs)

  • BorderLineStyle::Double now renders as solid stroke at 2.5× width
  • Added test coverage for format_border_side Double arm

4. Page setup (xlsx.rs)

  • Read paper size from pageSetup; corrected OOXML codes:
  • Read orientation (portrait/landscape) from pageSetup
  • Read margins from pageMargins; fall back to Excel defaults (0.75in top/bottom, 0.7in left/right) when element is absent

Testing

  • cargo test -p office2pdf --lib — 1076 passed, 0 failed
  • cargo fmt --all -- --check — clean

Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
…sheet

Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
markany-yhkwon

This comment was marked as low quality.

@developer0hye developer0hye left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution — the issues this PR targets are real (cell alignment, page setup, and double-border rendering are genuine gaps), and the overall approach fits the codebase architecture. However, I verified this branch locally and there are several blockers, so I'm requesting changes before it can be merged.

Blockers

1. cargo test fails (1 failing test)

border_line_style_to_typst now maps BorderLineStyle::Double to "solid", but the existing test expectation was not updated:

---- render::typst_gen::tests::table_codegen_tests::border_tests::test_border_line_style_to_typst_mapping ----
assertion `left == right` failed
  left: "solid"
 right: "dashed"
  • Failing test: crates/office2pdf/src/render/typst_gen_table_border_tests.rs:185
  • Change site: border_line_style_to_typst in crates/office2pdf/src/render/typst_gen.rs

Please update the expectation, and add coverage for the new Double arm in format_border_side (2.5x thickness) — per this repo's conventions (see CLAUDE.md, TDD section) every behavior change needs a corresponding test. This PR currently adds no new tests.

Note: the PR description says "All 86 existing tests pass", but cargo test --workspace runs 1,100+ tests on this branch and exactly one fails. Please run the full workspace suite before pushing.

2. cargo fmt --all -- --check fails

Formatting violations in xlsx.rs, xlsx_cells.rs, xlsx_style.rs, typst_gen.rs (manually aligned match arms, non-rustfmt signature/import wrapping). CI enforces this — please run cargo fmt --all.

3. Incorrect entries in the paper_size_pts table (crates/office2pdf/src/parser/xlsx.rs)

Per the OOXML pageSetup paper-size table (reference: https://c-rex.net/samples/ooxml/e1/part4/OOXML_P4_DOCX_pageSetup_topic_ID0EHZ54.html):

  • Code 6 = Statement, 5.5 x 8.5 in → should be (396.0, 612.0). The code currently has Executive's size (522 x 756).
  • Code 7 = Executive, 7.25 x 10.5 in → should be (522.0, 756.0). The code currently has 10 x 14 in (that is code 16).
  • Code 19 is #9 Envelope (3.875 x 8.875 in), not "Note" — Note is code 18. Grouping 19 with Letter is incorrect.

4. PR description does not match the diff

  • Fix #2 (umya-spreadsheet inlineStr fix): not in this PR. The dependency is pinned to a git fork in Cargo.toml/Cargo.lock, and neither file changed here.
  • Fix #3 (column width formula): not in this PR. column_width_to_pt (crates/office2pdf/src/parser/xlsx_cells.rs:33) is still char_width * 7.0.
  • Fix #7 (wrap text): wrap_text is parsed and stored on TableCell but never read by the renderer, so behavior is unchanged. Either implement it or drop the field from this PR (dead code).
  • Fix #1 mentions justify/distributed, but only Left/Center/Right are mapped (justify/distributed fall through to None).

Please update the description to describe what the diff actually changes.

Correctness issues to address

5. Zero margins for files without pageMargins

umya's PageMargins getters return 0.0 when the element is absent, so such files now render with 0pt margins (previously the 72pt default). Excel always writes pageMargins, but files from other generators may omit it. Please fall back to sensible defaults when the element is absent / all values are zero.

6. Partial vertical-alignment application causes mixed rows

umya's Alignment::get_vertical() returns Bottom (the OOXML default) whenever an alignment element exists, even if the vertical attribute was not specified. So a cell with only horizontal="center" now renders bottom-aligned while neighboring cells without any alignment element stay top-aligned — inconsistent within the same row. Excel's default for all cells is bottom; consider applying that uniformly (fine as a follow-up, but worth a TODO).

7. Numeric right-align heuristic operates on the formatted string

value.parse::<f64>() misses 1,234.56 / $5.00 / 50% (which Excel right-aligns) and false-positives text cells like 0050 or NaN. Base the check on the cell's underlying type instead, e.g. cell.get_value_number().is_some() (backed by CellRawValue::Numeric).

8. get_formatted_value()get_value() fallback

In umya, get_formatted_value() formats the result of get_value(), so when the raw value is empty the fallback is a no-op — it cannot fix the claimed inlineStr case without the upstream fix, which is not part of this PR. When the fallback does fire, it is for number formats that intentionally produce empty output (e.g. ;;; hidden cells, 0;-0;""), which this change would un-hide — a regression. Please drop this hunk, or include a fixture/test demonstrating the concrete bug it fixes.

Verification performed

Check Result
gh pr checks DCO ✅ (CI workflows pending first-time-contributor approval)
cargo check -p office2pdf ✅ pass
cargo clippy --workspace --all-targets -- -D warnings ✅ pass
cargo test ❌ 1 failed (test_border_line_style_to_typst_mapping)
cargo fmt --all -- --check ❌ fail

Happy to re-review once the above are addressed — the alignment and page-setup work in particular is worth landing.

@developer0hye developer0hye dismissed markany-yhkwon’s stale review June 6, 2026 04:46

Dismissing — posted from the wrong account by mistake. See the review from @developer0hye instead.

- Fix failing test: update Double border style expectation to 'solid'
- Fix cargo fmt violations across xlsx.rs, xlsx_cells.rs, xlsx_style.rs,
  typst_gen.rs
- Fix incorrect paper size table: Statement (code 6) = 5.5x8.5in,
  Executive (code 7) = 7.25x10.5in, remove developer0hye#9 Envelope (code 19)
  from Letter grouping
- Add zero-margins fallback: when pageMargins element is absent umya
  returns 0.0 for all sides; fall back to Excel defaults (0.75in
  top/bottom, 0.7in left/right)
- Fix numeric right-align heuristic: use cell.get_value_number()
  instead of parsing the formatted string, avoiding false positives
  on text like '0050' and missing currency/percentage values
- Revert get_formatted_value fallback to get_value: the fallback
  cannot fix the inlineStr case without an upstream fix and risks
  un-hiding intentionally hidden cells
- Add TODO for vertical-align default inconsistency

Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
@nikith-18161 nikith-18161 changed the title fix(xlsx): cell alignment, column width, borders, page setup, wrap text fix(xlsx): cell alignment, column width, borders, page setup Jun 8, 2026
- Drop wrap_text field from TableCell IR — rendering not implementable
  in Typst without significant complexity; remove from ir/elements.rs,
  xlsx_cells.rs, xlsx_style.rs, docx_tables.rs, pptx_tables.rs and
  pptx_table_style_tests.rs
- Add Justify variant to CellHorizontalAlign; map Distributed to Justify
  in xlsx_style.rs; render as 'justify' in typst_gen_tables.rs
- Fix column width formula: (char_width * 7.0 + 5.0) * 0.75 per OOXML
  spec, accounting for 5px padding Excel adds before pixel-to-point
  conversion; update test range accordingly
- Add test_double_border_uses_2_5x_thickness covering format_border_side
  Double arm at 2.5x thickness as requested by reviewer

Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
@nikith-18161

Copy link
Copy Markdown
Author

All review feedback has been addressed in the latest commits:

  1. ✅ Failing test fixed — updated Double border expectation to "solid" + added new test for format_border_side 2.5x thickness
  2. ✅ cargo fmt clean
  3. ✅ Paper size table corrected — Statement (code 6), Executive (code 7), feat: [US-043] PPTX parser - SmartArt diagrams (basic) #9 Envelope (code 19) separated from Letter
  4. ✅ PR description updated to match the actual diff
  5. ✅ Zero margins fallback added — falls back to Excel defaults when pageMargins is absent
  6. ✅ Vertical alignment TODO added
  7. ✅ Numeric right-align uses cell.get_value_number() instead of parsing formatted string
  8. ✅ get_formatted_value → get_value fallback reverted
  9. ✅ wrap_text dropped from the PR entirely (field removed from IR, parsers, and tests)
  10. ✅ Justify/Distributed alignment implemented
  11. ✅ Column width formula corrected: (char_width * 7.0 + 5.0) * 0.75

cargo test -p office2pdf --lib — 1076 passed, 0 failed
cargo fmt --all -- --check — clean

Typst has no native justify alignment for table cells. Map
CellHorizontalAlign::Justify to 'left' as the closest approximation.

Signed-off-by: nikith-18161 <nikith.molaka@progentys.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants