Repository navigation
Show a tabular file as a picture, drawn the way the export writes it - #1
Closed
JackTelford wants to merge 2 commits into
Closed
JackTelford wants to merge 2 commits into
JackTelford wants to merge 2 commits into
Conversation
A reader handed a spreadsheet had no way to see it without downloading it first. Each worksheet is now drawn as a figure in the answer: a header band, a lettered column strip, a numbered row gutter, and a caption saying plainly what was left out of the window. The picture is drawn from the same formatting the workbook is written with. Resolving that in two places is how a preview ends up showing a different header colour, or a raw 74612.15999999999 where the file shows $74,612.16, so the resolution both tools need now lives in TabularFormattingResolver and the export delegates to it. Column formats inherited from the uploaded file are applied to the drawing too, which is what makes a column that was currency in the upload read as currency in the preview. The value a workbook stores is a number and a format code, and the presenting is left to whatever opens it, so the codes are read here. Currency, accounting, plain number, percent and date are covered; a code outside that vocabulary falls back to the general presentation rather than being guessed at. That general presentation now rounds to the significant digits a spreadsheet shows instead of printing a double to full binary precision. Two faults found while building it: The figures were addressed before the rows that back them were committed, so every picture arrived at an address that did not resolve yet. The document is now committed before its address is handed out. The model would not write the markers that place the pictures, through three rounds of asking. The host now appends a marker for any servable image the answer did not name, which is the rule this codebase already applies to a generated file: it is surfaced even when the model does not cite it. A picture is bounded to a fraction of its drawn size so a stack of sheets does not push the conversation off screen, which leaves a spreadsheet grid at about half size. Clicking one enlarges it. The download sits over the picture's corner rather than on a line of its own, and saves a PNG converted from the picture the page has already loaded, so nothing is fetched twice and nothing is converted for a picture nobody saves.
…f its name The check reads back which element a figure is wrapped in, because a marker is often written mid-sentence and a <div> tears the paragraph apart. It located that element by the first mention of the class name in the file, which is the markup only for as long as no rule or selector is written above it. Adding a stylesheet for the figures moved the first mention into CSS and the check started reading a selector, so it failed on a file whose markup it had never looked at. It now searches for the opening tag itself, and checks every figure the file emits rather than only the one that happens to come first.
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.
Previews a spreadsheet in the answer instead of making the reader download it first. Each worksheet is drawn as a figure — header band, lettered column strip, numbered row gutter, and a caption saying what was left out of the window.
The picture is drawn from the formatting the file is written with
Resolving formatting in two places is how a preview ends up showing a different header colour, or a raw
74612.15999999999where the file shows$74,612.16. The resolution both tools need now lives inTabularFormattingResolver, andExportTabularDataTooldelegates to it — so the two cannot drift. Column formats inherited from the uploaded workbook are applied to the drawing too, which is what makes a column that was currency in the upload read as currency in the preview.A workbook stores a number and a format code and leaves the presenting to whatever opens it, so the codes are read in
TabularPreviewValueFormat. Currency, accounting, plain number, percent and date are covered; anything outside that vocabulary falls back to the general presentation rather than being guessed at.The general presentation now rounds to the significant digits a spreadsheet shows, instead of printing a double to full binary precision —
74612.15999999999was wrong even with no format applied.Two faults found while building it
Read-your-own-write. Figures were addressed before the rows backing them were committed, so every picture arrived at an address that did not resolve yet. The document is now committed before its address is handed out.
The model would not write the markers that place the pictures, through three rounds of prompt hardening. The host now appends a marker for any servable image the answer did not name — the rule this codebase already applies to generated files, which are surfaced even when the model does not cite them.
Reading the picture
A figure is bounded to a fraction of its drawn size so a stack of sheets does not push the conversation off screen, which leaves a grid at roughly half size. Clicking one enlarges it (~45% → ~72%, undistorted).
The download sits over the picture's corner rather than on a line of its own — that band cost a row of vertical space per sheet. It saves a PNG, converted in the browser from the picture already loaded: no second fetch, and nothing converted for a picture nobody saves. Every failure path falls back to the SVG the server holds.
Verification
TabularPreviewValueFormatcovered by 15 cases against the format codes this corpus actually carries, including the values from a real workbook:$74,612.16,$0.00,-$81,065.04,(1,234.50),12.3%,09-01-26— all pass..xlsxvalidated withOpenXmlValidator— 0 errors; bytes served match bytes on disk by SHA-256.Not included
appsettings.jsonis deliberately left out of this branch — it carries live credentials in the working tree.Known gaps: the SQL-query preview path gets the correct header colour and rounding but not per-column formats; and
ai-chat.js/chat-interaction.jsrender the same markup for the other chat surfaces and still need the zoom/download treatment, which requires an asset rebuild.🤖 Generated with Claude Code