-
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!$A$2:$A$4',
values: 'Sheet1!$B$2:$B$4',
})
.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!$B$2:$B$5' })
.build();Two approaches:
// 1. Callback-based (recommended)
ws.addChart('bar', (builder) => {
builder
.title('Sales')
.addSeries({ name: 'Revenue', values: 'Sheet1!$B$2:$B$5' });
});
// 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!$A$2:$A$5', // Category labels (optional)
values: 'Sheet1!$B$2:$B$5', // 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 belowSet 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!$B$2:$B$13',
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!$B$2:$B$10',
errorBars: {
type: 'percentage', // fixed | percentage | stdDev | stdErr | custom
direction: 'both', // both | plus | minus
value: 10, // Error value (for fixed, percentage, stdDev)
plusRef: 'Sheet1!$C$2:$C$10', // Custom plus values
minusRef: 'Sheet1!$D$2:$D$10', // 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!$B$2:$B$5',
})
.build();
// Add secondary chart on secondary axis
chart.secondaryChart = {
type: 'line',
series: [{
name: 'Growth %',
values: { ref: 'Sheet1!$C$2:$C$5' },
}],
};
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!$A$1:$A$5' });
});
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!$A$2:$A$5',
values: 'Sheet1!$B$2:$B$5',
})
.addSeries({
name: 'South',
categories: 'Sheet1!$A$2:$A$5',
values: 'Sheet1!$C$2:$C$5',
})
.addSeries({
name: 'West',
categories: 'Sheet1!$A$2:$A$5',
values: 'Sheet1!$D$2:$D$5',
})
.grouping('clustered')
.legend('bottom');
});ws.addChart('pie', (b) => {
b.title('Market Share')
.addSeries({
name: 'Share',
categories: 'Sheet1!$A$2:$A$5',
values: 'Sheet1!$B$2:$B$5',
})
.dataLabels({ showPercent: true, showCatName: true });
});ws.addChart('scatter', (b) => {
b.title('Correlation Analysis')
.addSeries({
name: 'Data Points',
categories: 'Sheet1!$A$2:$A$20',
values: 'Sheet1!$B$2:$B$20',
marker: 'circle',
trendline: {
type: 'linear',
displayEquation: true,
displayRSquared: true,
},
})
.scatterStyle('lineMarker');
});ws.addChart('area', (b) => {
b.title('Cumulative Sales')
.addSeries({ name: 'Online', values: 'Sheet1!$B$2:$B$13' })
.addSeries({ name: 'Retail', values: 'Sheet1!$C$2:$C$13' })
.grouping('stacked')
.legend('right');
});ws.addChart('doughnut', (b) => {
b.title('Budget Allocation')
.addSeries({
name: 'Budget',
categories: 'Sheet1!$A$2:$A$6',
values: 'Sheet1!$B$2:$B$6',
})
.holeSize(60)
.dataLabels({ showPercent: true });
});ws.addChart('col', (b) => {
b.title('3D Sales View')
.addSeries({ name: 'Sales', values: 'Sheet1!$B$2:$B$5' })
.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