feat(xlsx): print worksheet gridlines when printOptions asks for them - #721
Merged
Conversation
<printOptions gridLines="1"/> tells Excel to rule every cell boundary of the printed range, independently of border styling. The attribute was never read, so sheets that rely on printed gridlines for their structure came out with no rules at all. Measured off the native Excel GT of NumberFormatTests (both sheets set the flag; traces cited in the code): gridlines are 1pt pure-black boundary-anchored [B, B+1] bands — the same convention as #619 thin borders, and not the gray usually assumed — covering exactly the printed range and closed on all four sides at every page break. An explicit border of any style owns its boundary over the gridline (a hair border replaces the black rule with its dotted band), and a cell fill suppresses all four adjacent segments: Excel truncates the verticals at a filled row and omits the horizontal at its bottom edge, because fills paint last and bleed over the bands. Implementation seeds gridline declarations into the #619 boundary-resolution pass on every boundary that carries no explicit border from either neighbour and is not adjacent to a fill, so the bands ride the existing emission (offsets, run extension, repeating headers, width splits). The flag is read by a raw-XML scanner that skips customSheetViews subtrees (a custom view's nested printOptions must not shadow the sheet-level element) and honours the ECMA-376 gridLines AND gridLinesSet conjunction. umya models neither attribute. Verified against GT: every rule 1.0pt black at the boundary bands, fill suppression mirrored, pages closed top and bottom; conversion time on the 337-row fixture rises 474ms -> 547ms with the ~5,400 extra bands. Related: #622 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<printOptions gridLines="1"/>prints Excel's worksheet gridlines across the printed range; the attribute was never read, so grid-structured sheets came out with no rules at all.Measured off the native Excel GT of NumberFormatTests (traces cited in the code): printed gridlines are 1pt pure-black boundary-anchored [B, B+1] bands — the #619 thin-border convention, not the commonly assumed gray — covering exactly the printed range, closed on all four sides at every page break. An explicit border of any style owns its boundary over the gridline (a hair border replaces the black rule with its dotted band), and a cell fill suppresses all four adjacent segments (Excel truncates verticals at a filled row and omits the horizontal at its bottom edge).
Implementation seeds gridline declarations into the #619 boundary-resolution pass (lowest precedence, both-neighbour seeding so grids close at page breaks), riding the existing band emission including repeating headers and width splits. The flag is read by a raw-XML scanner that skips
customSheetViewssubtrees (a custom view's nested printOptions must not shadow the sheet-level element) and honours the ECMA-376gridLines AND gridLinesSetconjunction; umya models neither attribute.Known limitation (TODO in code): a background-filled row that lands as the first row of a page leaves the previous page's grid open at that one boundary — kept because the alternative paints a black rule over the fill's top edge on every within-page filled row, the far more common case.
Related issue
Fixes #622
Testing
cargo test --workspace— green (red-first tests: measured band geometry on all four sides, both-neighbour interior seeding, explicit-border precedence incl. hair, fill suppression, repeating-header carry, flag-off negatives; scanner tests for customSheetViews shadowing both directions, gridLinesSet veto, "true" spelling)cargo +1.97 clippy --workspace --all-targets— clean;cargo fmt --check— clean#000000at boundary bands matching GT's fills; fill suppression mirrored; pages closed top and bottom; Flags-sheet variable-height rows match GT offsetsVisual impact
Visual audit
fixassets/bugfixes/issue-622/gt.jpgassets/bugfixes/issue-622/before.jpgassets/bugfixes/issue-622/after.jpgVisual comparison
Required inspection
Deviation audit
Checklist
Signed-off-byline🤖 Generated with Claude Code