Skip to content

feat(xlsx): radar, bubble, stock and surface charts - #15

Closed
mkroemer wants to merge 7 commits into
p10node:mainfrom
mkroemer:xlsx-chart-types
Closed

mkroemer wants to merge 7 commits into
p10node:mainfrom
mkroemer:xlsx-chart-types

Conversation

@mkroemer

Copy link
Copy Markdown

Builds on the chart looks PR (#14), which builds on #12. Until those are merged this PR shows their commits too; this part is the last commit.

The four chart kinds that still showed a placeholder are now drawn:

  • Radar: lines, lines with markers, or filled; a spoke per category from 12 o'clock, rings at the value axis' ticks.
  • Bubble: the sizes are read from the cells like the other values, by area or by width (sizeRepresents), scaled by bubbleScale, the largest a quarter of the plot's smaller side at 100 % as in Excel. Negative bubbles are outlines where showNegBubbles is set. The axes leave the bubbles room without crossing zero for it.
  • Stock: high-low lines and up-down bars between the first and the last series, with the series drawn over them. A volume stock chart is a bar group plus a stock group, which the combination code already handles.
  • Surface, 2D and 3D: drawn from above, as Excel's contour chart, with a band per step of the value axis and the bands in the legend; a wireframe surface as its mesh of lines. A 3D surface is drawn flat, as the other 3D kinds are.

Only the newer chartex kinds (waterfall, treemap, sunburst, ...) keep the placeholder; they live in a separate part.

test/xlsx-chart.test.ts reads and draws each kind: a radar's spokes and markers, bubble sizes and their order, a stock chart's high-low lines and falling bars, and a surface chart's bands. bun run typecheck, bun test and the e2e suite pass in CI.

🤖 Generated with Claude Code

markus-kroemer and others added 7 commits November 14, 2026 07:58
A sheet's drawing part (xl/drawings/drawingN.xml) is read for its
pictures and charts with their anchors: two cells, one cell and a size,
or a position and a size. The new `xlsx.drawings(sheet)` call returns
them; the grid lays them over the cells, placed by the row and column
axes, so a picture moves and grows with resized or hidden rows and
columns, and the sheet extends far enough to reach every drawing.

A picture the browser can draw (PNG, JPEG, GIF, SVG, ...) is shown as
itself, through the client's media URLs. A chart, and a picture in a
format the browser cannot draw (EMF, WMF), is shown as a box of its
size naming what is there: the chart's kind (column, bar, line, pie,
...) and title. Shapes and text boxes are left out. Clicks go through
to the cells below.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sheet's charts were placeholders. Now src/core/xlsx/chart.ts reads a
chart part into a model in the worker, and src/core/xlsx/chart-svg.ts
draws it as a self-contained SVG (DOM-free), shown over the cells like a
picture.

- Kinds: bar and column (clustered, stacked, 100%, upright or
  horizontal), line (markers, smoothing, gaps for empty cells), area,
  pie and doughnut (exploded slices, first-slice angle), scatter, and
  combinations on primary and secondary axes; 3D charts as their flat
  form. Radar, bubble, stock, surface and chartex keep the placeholder.
- Values: series references are read from the workbook's cells, loading
  a sheet not shown yet, so charts follow edits (the view reads them
  again after an edit result). A defined name, another workbook or an
  unreadable reference falls back to the chart's numCache / strCache.
  Hidden rows and columns are left out when plotVisOnly is set.
- Look: Excel-like automatic axis bounds (zero kept, steps of 1/2/5),
  fixed min/max/major unit, reversed and log axes, gridlines, tick and
  data labels in their number formats, tilted category labels where they
  do not fit flat, title (Excel's automatic one included), legend
  (positions, overlay, deleted entries), theme accents for series
  without colors of their own, manual plot layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pie negatives, cell titles

- scatter: a point whose X value is missing is not drawn (it was placed at
  its ordinal position); value labels follow their own points when a Y
  value is missing
- bars, areas, lines and points are clipped to the plot area, so a fixed
  axis range does not let them run over the title and legend
- pie and doughnut: a negative value is a slice of its magnitude, as in
  Excel; its value label keeps the sign
- a title whose text is a cell (`c:tx/c:strRef`) shows that cell's text,
  else its cached text, before the automatic title

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… row stays in it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The automatic bounds add a step above a maximum that falls on a
gridline, so a 100% stacked axis ran to 120%. An axis carrying only
100% stacks now ends at 100% (and -100% with negatives), as Excel's does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- gradient fills (linear and radial) and pattern fills (DrawingML presets)
  for series, points, the chart area and the plot area
- the text size, weight and color of axis labels, legend and data labels
- gridline and axis lines: color, width, dash, or none
- the plot area's fill and border
- the built-in chart style (c:style, c14:style): gray, accent and
  one-accent palettes, tinted plot areas, dark backgrounds
- default grays (text, gridlines, axis lines) as shades of the theme's
  text color rather than fixed values

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kinds that were placeholders until now:
- radar: lines, lines with markers, filled; a spoke per category, rings
  at the value axis' ticks
- bubble: sizes read from the cells, by area or by width, scaled by
  bubbleScale; negative bubbles as outlines where the chart shows them;
  the axes leave the bubbles room
- stock: high-low lines and up-down bars, the series over them
- surface (2D and 3D): seen from above as Excel's contour chart, its
  value bands in the legend; or the wireframe

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mkroemer

Copy link
Copy Markdown
Author

Folded into #12, which now carries these commits, so the charts can be reviewed in one place.

@mkroemer mkroemer closed this Nov 15, 2026
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.

2 participants