-
Notifications
You must be signed in to change notification settings - Fork 1
Charts
modern-xlsx supports creating, reading, and roundtripping Excel charts with full ECMA-376 DrawingML compliance. 10 chart types with a fluent builder API.
import { initWasm, Workbook, ChartBuilder } from 'modern-xlsx'; await initWasm(); const wb = new Workbook(); const ws = wb.addSheet('Sheet1'); // Add data ws.cell('A1').value = 'Product'; ws.cell('B1').value = 'Sales'; ws.cell('A2').value = 'Widget A'; ws.cell('B2').value = 1200; ws.cell('A3').value = 'Widget B'; ws.cell('B3').value = 850; ws.cell('A4').value = 'Widget C'; ws.cell('B4').value = 2100; // Create a bar chart ws.addChart('bar', (b) => { b.title('Product Sales') .addSeries({ name: 'Sales', categories: 'Sheet1!$A2ドル:$A4ドル', values: 'Sheet1!$B2ドル:$B4ドル', }) .catAxis({ title: 'Product' }) .valAxis({ title: 'Revenue ($)' }) .legend('bottom'); }); await wb.toFile('charts.xlsx');
| Type | Description | Groupings |
|---|---|---|
bar |
Horizontal bars | clustered, stacked, percentStacked |
col |
Vertical columns | clustered, stacked, percentStacked |
line |
Line chart | standard, stacked, percentStacked |
pie |
Pie chart | (single series) |
doughnut |
Donut chart | (configurable hole size) |
scatter |
XY scatter plot | lineMarker, smoothMarker, line, smooth |
area |
Area chart | standard, stacked, percentStacked |
radar |
Radar/spider chart | radar, filled |
bubble |
Bubble chart | (bubble size series) |
stock |
Stock OHLC chart | (open-high-low-close) |
The ChartBuilder provides a fluent interface for constructing chart data models.
import { ChartBuilder } from 'modern-xlsx'; const chart = new ChartBuilder('bar') .title('My Chart') .addSeries({ name: 'Series 1', values: 'Sheet1!$B2ドル:$B5ドル' }) .build();
Two approaches:
// 1. Callback-based (recommended) ws.addChart('bar', (builder) => { builder .title('Sales') .addSeries({ name: 'Revenue', values: 'Sheet1!$B2ドル:$B5ドル' }); }); // 2. Pre-built chart data const chartData = new ChartBuilder('line').title('Trend').build(); ws.addChartData(chartData);
Set the chart title.
builder.title('Quarterly Revenue');
Add a data series. Call multiple times for multiple series.
builder.addSeries({ name: 'Revenue', // Series name (displayed in legend) categories: 'Sheet1!$A2ドル:$A5ドル', // Category labels (optional) values: 'Sheet1!$B2ドル:$B5ドル', // Data values (required) marker: 'circle', // Marker style (optional) trendline: { type: 'linear' }, // Trendline (optional) errorBars: { type: 'percentage', value: 5 }, // Error bars (optional) });
AddSeriesOptions:
| Option | Type | Description |
|---|---|---|
name |
string |
Series name for legend |
categories |
string |
Cell range for category axis labels |
values |
string |
Cell range for data values (required) |
bubbleSizes |
string |
Cell range for bubble sizes (bubble charts) |
marker |
string |
Marker style: circle, square, diamond, triangle, etc. |
trendline |
object |
Trendline configuration |
errorBars |
object |
Error bar configuration |
Configure the category and value axes.
builder .catAxis({ title: 'Month', position: 'b' }) .valAxis({ title: 'Revenue', position: 'l', min: 0, max: 10000 });
AxisOptions:
| Option | Type | Description |
|---|---|---|
title |
string |
Axis title text |
position |
'b' | 't' | 'l' | 'r' |
Axis position |
min |
number |
Minimum axis value |
max |
number |
Maximum axis value |
majorTickMark |
string |
Major tick mark style |
minorTickMark |
string |
Minor tick mark style |
tickLblPos |
string |
Tick label position |
Set legend position.
builder.legend('bottom'); // 'bottom' | 'top' | 'left' | 'right' | 'topRight'
Show data labels on chart.
builder.dataLabels({ showVal: true, showCatName: false, showSerName: false, });
Set chart grouping (bar, column, line, area).
builder.grouping('stacked'); // 'clustered' | 'stacked' | 'percentStacked' | 'standard'
Set scatter chart style.
builder.scatterStyle('smoothMarker'); // 'lineMarker' | 'smoothMarker' | 'line' | 'smooth'
Set radar chart style.
builder.radarStyle('filled'); // 'radar' | 'filled'
Set doughnut chart hole size (10-90).
builder.holeSize(50);
Set bar chart direction.
builder.barDirection('bar'); // 'bar' (horizontal) | 'col' (vertical)
Apply a chart style preset.
builder.style('colorful1'); // See Chart Style Presets below
Set chart position within the worksheet.
builder.anchor({ fromCol: 3, fromRow: 1, toCol: 10, toRow: 15, });
Enable 3D rotation.
builder.view3d({ rotX: 15, rotY: 20, perspective: 30, rAngAx: true, });
Show a data table below the chart.
builder.showDataTable();
Set manual plot area positioning (0-1 normalized coordinates).
builder.plotLayout({ x: 0.1, y: 0.1, w: 0.8, h: 0.7 });
Add trendlines to any series:
builder.addSeries({ name: 'Sales', values: 'Sheet1!$B2ドル:$B13ドル', trendline: { type: 'linear', // linear | exponential | logarithmic | polynomial | power | movingAverage order: 2, // Polynomial order (2-6, for polynomial type) period: 3, // Moving average period (for movingAverage type) forward: 2, // Forecast forward periods backward: 1, // Forecast backward periods displayEquation: true, displayRSquared: true, name: 'Linear Trend', }, });
| Type | Use Case |
|---|---|
linear |
Straight line best fit |
exponential |
Exponential growth/decay |
logarithmic |
Logarithmic curve |
polynomial |
Polynomial fit (order 2-6) |
power |
Power law relationship |
movingAverage |
Smoothing with N-period window |
Add error bars to series:
builder.addSeries({ name: 'Measurements', values: 'Sheet1!$B2ドル:$B10ドル', errorBars: { type: 'percentage', // fixed | percentage | stdDev | stdErr | custom direction: 'both', // both | plus | minus value: 10, // Error value (for fixed, percentage, stdDev) plusRef: 'Sheet1!$C2ドル:$C10ドル', // Custom plus values minusRef: 'Sheet1!$D2ドル:$D10ドル', // Custom minus values }, });
Create charts with two chart types sharing the same plot area:
const chart = new ChartBuilder('col') .title('Revenue vs Growth Rate') .addSeries({ name: 'Revenue', values: 'Sheet1!$B2ドル:$B5ドル', }) .build(); // Add secondary chart on secondary axis chart.secondaryChart = { type: 'line', series: [{ name: 'Growth %', values: { ref: 'Sheet1!$C2ドル:$C5ドル' }, }], }; chart.secondaryValAxis = { position: 'r', title: { text: 'Growth Rate (%)' }, }; ws.addChartData(chart);
modern-xlsx includes 8 color palettes:
import { getChartStylePalette, CHART_STYLE_PALETTES } from 'modern-xlsx'; // Get a palette by name const palette = getChartStylePalette('colorful1'); // Returns: ['4472C4', 'ED7D31', 'A5A5A5', 'FFC000', '5B9BD5', '70AD47'] // Apply to chart builder.style('colorful1');
Available Palettes:
| ID | Description |
|---|---|
colorful1 |
Default Office colors |
colorful2 |
Warm tones |
colorful3 |
Cool tones |
colorful4 |
Earth tones |
monochrome1 |
Blue monochrome |
monochrome2 |
Orange monochrome |
monochrome3 |
Green monochrome |
monochrome4 |
Purple monochrome |
Charts are automatically parsed when reading XLSX files:
import { readFile } from 'modern-xlsx'; const wb = await readFile('charts.xlsx'); const ws = wb.getSheet('Sheet1'); // Access all charts on the sheet const charts = ws.charts; console.log(`Found ${charts.length} chart(s)`); for (const chart of charts) { console.log('Type:', chart.chart.type); console.log('Title:', chart.chart.title?.text); console.log('Series:', chart.chart.series.length); for (const s of chart.chart.series) { console.log(` - ${s.name}: ${s.values?.ref}`); } }
interface WorksheetChartData { chart: ChartDataModel; anchor: ChartAnchorData; } interface ChartDataModel { type: ChartType; title?: ChartTitleData; series: ChartSeriesData[]; catAxis?: ChartAxisData; valAxis?: ChartAxisData; legend?: ChartLegendData; dataLabels?: DataLabelsData; grouping?: ChartGrouping; scatterStyle?: ScatterStyle; radarStyle?: RadarStyle; holeSize?: number; barDir?: string; style?: string; plotLayout?: ManualLayoutData; secondaryChart?: { type: ChartType; series: ChartSeriesData[] }; secondaryValAxis?: ChartAxisData; showDataTable?: boolean; view3d?: View3DData; }
const ws = wb.getSheet('Sheet1'); // Remove by index ws.removeChart(0);
Charts written by modern-xlsx survive a write-read roundtrip with full fidelity:
// Write const wb1 = new Workbook(); const ws1 = wb1.addSheet('Sheet1'); ws1.addChart('bar', (b) => { b.title('Test').addSeries({ name: 'S1', values: 'Sheet1!$A1ドル:$A5ドル' }); }); const buf = await wb1.toBuffer(); // Read back const wb2 = await readBuffer(buf); const ws2 = wb2.getSheet('Sheet1'); console.log(ws2.charts[0].chart.title.text); // 'Test' console.log(ws2.charts[0].chart.series[0].name); // 'S1'
All chart properties are preserved: type, title, series, categories, values, axes, legend, trendlines, error bars, 3D rotation, data labels, combo charts, and style.
ws.addChart('col', (b) => { b.title('Quarterly Revenue by Region') .addSeries({ name: 'North', categories: 'Sheet1!$A2ドル:$A5ドル', values: 'Sheet1!$B2ドル:$B5ドル', }) .addSeries({ name: 'South', categories: 'Sheet1!$A2ドル:$A5ドル', values: 'Sheet1!$C2ドル:$C5ドル', }) .addSeries({ name: 'West', categories: 'Sheet1!$A2ドル:$A5ドル', values: 'Sheet1!$D2ドル:$D5ドル', }) .grouping('clustered') .legend('bottom'); });
ws.addChart('pie', (b) => { b.title('Market Share') .addSeries({ name: 'Share', categories: 'Sheet1!$A2ドル:$A5ドル', values: 'Sheet1!$B2ドル:$B5ドル', }) .dataLabels({ showPercent: true, showCatName: true }); });
ws.addChart('scatter', (b) => { b.title('Correlation Analysis') .addSeries({ name: 'Data Points', categories: 'Sheet1!$A2ドル:$A20ドル', values: 'Sheet1!$B2ドル:$B20ドル', marker: 'circle', trendline: { type: 'linear', displayEquation: true, displayRSquared: true, }, }) .scatterStyle('lineMarker'); });
ws.addChart('area', (b) => { b.title('Cumulative Sales') .addSeries({ name: 'Online', values: 'Sheet1!$B2ドル:$B13ドル' }) .addSeries({ name: 'Retail', values: 'Sheet1!$C2ドル:$C13ドル' }) .grouping('stacked') .legend('right'); });
ws.addChart('doughnut', (b) => { b.title('Budget Allocation') .addSeries({ name: 'Budget', categories: 'Sheet1!$A2ドル:$A6ドル', values: 'Sheet1!$B2ドル:$B6ドル', }) .holeSize(60) .dataLabels({ showPercent: true }); });
ws.addChart('col', (b) => { b.title('3D Sales View') .addSeries({ name: 'Sales', values: 'Sheet1!$B2ドル:$B5ドル' }) .view3d({ rotX: 15, rotY: 20, perspective: 30 }); });
modern-xlsx v1.0.0
Getting Started
Guides
- Charts & Visualizations
- Formula Engine
- Table Layout Engine
- Tables & Print Layout
- Encryption
- Feature Comparison
Reference
Migration
Project