Bonsai: scheduler: draw the cell borders a schedule's spreadsheet declares - #9351
Draft
carlopav wants to merge 1 commit into
Draft
Bonsai: scheduler: draw the cell borders a schedule's spreadsheet declares#9351carlopav wants to merge 1 commit into
carlopav wants to merge 1 commit into
Conversation
schedule_ods already collects every cell style attribute from the sheet, borders included, and then draws each cell as a rectangle carrying one hardcoded `.border` class; schedule_xlsx does the same from openpyxl. The borders set in LibreOffice or Excel are therefore discarded, and a thick outline with thin inner rules cannot reach the drawing. The inline rectangle in both branches becomes draw_cell(), which takes a background color and the borders already resolved, so it is independent of the source format: get_cell_borders reads .ods style attributes and get_xlsx_cell_borders reads openpyxl Sides. A cell that declares no border keeps the `.border` class and draws as before; one that declares them gets a line per side, which a single rectangle stroke cannot express. Width, style and color are read in any order per the CSS shorthand grammar; dotted and dashed become a dash pattern scaled by the line width, while double and the relief styles draw plain. XLSX_BORDERS converts Excel's named weights into widths, since it names a weight instead of measuring one. A cell declaring `border: none` now draws no line where it used to take the stylesheet's. This is deliberate: turning a rule off from the spreadsheet is half of what per-cell borders are for. Cells declaring nothing are unaffected. Adjacent cells still each stroke the edge they share, so where neighbours differ the later one wins, as the overlapping rectangles did. Generated with the assistance of an AI coding tool. Co-authored-by: Claude Opus 5 <noreply@anthropic.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.
schedule_odsalready collects every cell style attribute from the spreadsheet — background, font size, weight, style, color, wrap — and uses them. Borders are collected too, and discarded: every cell is drawn as a rectangle carrying one hardcodedclass_="border"whose stroke comes from the stylesheet.schedule_xlsxdoes the same from openpyxl. A thick outline with thin inner rules, the usual look of an architectural schedule, cannot reach the drawing no matter what is set in LibreOffice or Excel.What changed
The inline rectangle in both branches becomes
draw_cell(), which takes a background color and the borders already resolved, so it is independent of the source format. Each branch translates its own:get_cell_borders()/parse_border()read.odsstyle attributes;get_xlsx_cell_borders()/parse_xlsx_border()read openpyxlSideobjects.A cell that declares no border keeps the
.borderclass and draws exactly as before. One that declares them gets a line per side, which a single rectangle stroke cannot express.Width, style and color are read in any order, per the CSS
bordershorthand grammar (<width> || <style> || <color>), rather than assuming the order LibreOffice happens to emit.dottedanddashedbecome a dash pattern scaled by the line width;doubleand the relief styles draw plain.XLSX_BORDERSconverts Excel's fourteen named weights into widths and dash patterns. Excel names a weight instead of measuring one, so that table is a choice rather than a reading of the file, and is commented as such.One deliberate behaviour change
A cell that declares
border: nonenow draws no line, where before it took the stylesheet's. This is intentional and is half the point of the change: a sheet that says a side has no border should not be given one.Cells that declare nothing about borders are unaffected — that is the compatibility guarantee, and it covers every schedule IfcCsv writes, since it emits no cell styles at all.
Left as it is
Adjacent cells each stroke the edge they share, so where two neighbours declare it differently the later one wins. The rectangles overlapped the same way before, with the same stroke on both sides. Spreadsheet applications resolve such conflicts by precedence, which this does not attempt.
Testing
src/bonsai/test/bim/module/drawing/test_scheduler.py— 20 tests over both translators and the drawing: the untouched-cell guarantee, theborder: nonechange, per-side overrides of the shorthand, token order, dash patterns, and the openpyxl side. One trap they pin down: asked for the ARGB of a theme color, openpyxl returns its own complaint as a string instead of raising, so the length of the value is what distinguishes a real ARGB from it.blackandruffclean on both files.Notes
schedule_odsas Bonsai: don't render spreadsheet-hidden columns in schedules (#6729) #8537 (hidden columns), a few lines apart. Whichever lands second wants a trivial rebase; this change keeps thebackground_colorlocal in place to keep the overlap as small as possible.AI disclosure
Per AGENTS.md: this contribution was written with the assistance of an AI coding tool, in whole — both the change to
scheduler.pyand the new test file, which carries the required header comment.