Chart a spreadsheet

A live formula sheet wired to the built-in Chart panel: edit a Units or Revenue cell and the chart redraws. Customize it in-panel - change Type, swap Group by / Split by / Value, aggregate, Stack, or add data labels.

A live, editable Svelte 5 data grid example from the SvGrid gallery (Charts). See the SvGrid documentation for the full API.

What this example shows

A small editable sales sheet with the built-in chart drawer open beside it. Type a new number into any Units / Revenue cell and the chart redraws on the spot - exactly like an Excel chart bound to a table. The chart panel is the "Chart Design" surface: switch the chart Type (column / bar / line / area / pie), change what is on the axis (Group by / Split by / Value), aggregate, stack the series, or turn on data labels - all live, no code.

Imports, features and API used

Imports: @svgrid/grid

Columns: month (Month), region (Region), channel (Channel), units (Units), revenue (Revenue), cost (Cost)

Source code (356-spreadsheet-chart.svelte)

<script lang="ts">
  /**
   * 356. Spreadsheet chart (edit cells, customize the chart like Excel)
   * ------------------------------------------------------------------
   * A small editable sales sheet with the built-in chart drawer open beside it.
   * Type a new number into any Units / Revenue cell and the chart redraws on the
   * spot - exactly like an Excel chart bound to a table. The chart panel is the
   * "Chart Design" surface: switch the chart Type (column / bar / line / area /
   * pie), change what is on the axis (Group by / Split by / Value), aggregate,
   * stack the series, or turn on data labels - all live, no code.
   */
  import { SvGrid, tableFeatures, type GridColumns } from '@svgrid/grid'

  type Row = { month: string; region: string; channel: string; units: number; revenue: number; cost: number }

  const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
  const REGIONS = ['NA', 'EMEA']
  const CHANNELS = ['Online', 'Retail', 'Wholesale']
  // Seed a plausible ramp so the starting chart already looks like a real report.
  const base: Record<string, number> = { Online: 42000, Retail: 31000, Wholesale: 58000 }
  const seed: Row[] = []
  MONTHS.forEach((month, m) => {
    REGIONS.forEach((region, r) => {
      CHANNELS.forEach((channel) => {
        const revenue = Math.round((base[channel]! * (1 + m * 0.12) * (r === 0 ? 1 : 0.7)) / 500) * 500
        seed.push({ month, region, channel, units: Math.round(revenue / 120), revenue, cost: Math.round(revenue * 0.62) })
      })
    })
  })

  let rows = $state<Row[]>(seed)
  const features = tableFeatures({})

  const money = { type: 'currency', currency: 'USD', options: { maximumFractionDigits: 0 } } as const
  const columns: GridColumns<Row> = [
    { field: 'month', header: 'Month', width: 100 },
    { field: 'region', header: 'Region', width: 100 },
    { field: 'channel', header: 'Channel', width: 120 },
    { field: 'units', header: 'Units', width: 110, align: 'right', cellDataType: 'number', editorType: 'number', format: { type: 'number', options: { maximumFractionDigits: 0 } } },
    { field: 'revenue', header: 'Revenue', width: 130, align: 'right', cellDataType: 'number', editorType: 'number', format: money },
    { field: 'cost', header: 'Cost', width: 120, align: 'right', cellDataType: 'number', editorType: 'number', format: money },
  ]

  const EDITABLE = new Set(['units', 'revenue', 'cost'])
  function onCellValueChange(e: { rowIndex: number; columnId: string; newValue: unknown }) {
    if (!EDITABLE.has(e.columnId)) return
    const n = Number(e.newValue)
    if (!Number.isFinite(n)) return
    const next = rows.slice()
    next[e.rowIndex] = { ...next[e.rowIndex]!, [e.columnId]: n }
    rows = next
  }
</script>

<div class="demo-page" style="height: 620px; display: flex; flex-direction: column;">
  <p class="demo-lede">
    An editable sales sheet with a live chart - like inserting a chart in Excel. Edit any
    <strong>Units</strong> or <strong>Revenue</strong> cell and the chart redraws. Use the
    <strong>Chart</strong> panel to customize it: change the <strong>Type</strong>, swap
    <strong>Group by</strong> / <strong>Split by</strong> / <strong>Value</strong>, aggregate,
    <strong>Stack</strong>, or add <strong>Labels</strong>.
  </p>
  <div style="flex: 1; min-height: 0;">
    <SvGrid
      columnResize
      data={rows}
      columns={columns}
      features={features}
      selectionMode="cell"
      enableInlineEditing={true}
      enableCellSelection={true}
      containerHeight="100%"
      contextMenu={['copy', 'cut', 'paste', 'clear']}
      onCellValueChange={onCellValueChange}
      charting={{
        defaultOpen: true,
        width: 500,
        dimension: 'month',
        series: 'channel',
        measures: 'revenue',
        defaultType: 'bar',
        stacked: false,
      }}
    />
  </div>
</div>

View this example on GitHub

Related documentation

Related articles

More Charts examples

  • Chart a selection (context menu) - With integrated charting enabled, the right-click menu gains a Chart selected range item: select a block of cells, right-click, and the chart panel opens scoped to that range - the Excel chart-this gesture, built in. The item appears only when charting is on and is appended to the default context menu automatically.
  • Chart view of the grid - The `chart` prop turns the same <SvGrid> into a chart, driven by the grid’s filtered + sorted rows (search + sort flow through). A view of the grid like board and scheduler, but the renderer is free: the grid lazy-loads a built-in view wrapping the standalone SvChart via rowsToChartSpec. Flip Table <-> Chart (bar / line / area) over one source of truth.
  • Candlestick / OHLC - Candlestick and OHLC price marks with an ordinal date axis. ChartSeries.ohlc carries the four prices while values keeps the closes, so the CSV export, the screen-reader table and a 10-day moving average all work with no candle-specific code. Toggle the axis: a real time axis opens a gap over every weekend, an ordinal one spaces sessions evenly and still labels them by date. The strip under the plot is the chart brush: drag its window to pan, drag an edge to resize.
  • Integrated charts (no deps) - Chart the grid data with no external charting library. SvGridChart renders a ChartSpec; rowsToChartSpec aggregates the grid current (filtered/sorted) rows into one. Bar, line, area, pie - plus 100% stacked, top-N + Other, an average reference line, and double-click-to-isolate a series. Filter the grid and the chart re-aggregates live.
  • Scatter / bubble chart - A scatter plot maps two numeric measures (x vs y); a bubble chart adds a third via dot radius. type: scatter with series points [{ x, y, r }]. Spend vs revenue, sized by deals, coloured by region, with an average-revenue reference line. Filter the grid and the cloud re-plots.