Hi, no need to answer my question as I think I’ve worked it out. For info:
updateTotalIndexLabels(chart);
//—————————————————————
// — Sum visible series for each x value —
//—————————————————————
function sumVisibleColumns(chart) {
let totals = {};
chart.options.data.forEach(series => {
if (series.visible !== false && !series.isTotalSeries) {
series.dataPoints.forEach(dp => {
let key = dp.x !== undefined ? dp.x : dp.label;
if (!(key in totals)) totals[key] = 0;
totals[key] += dp.y || 0;
});
}
});
return totals;
}
//—————————————————————
// — Collect all x values across all (non-total) series —
//—————————————————————
function getAllXValues(chart) {
let xSet = new Set();
chart.options.data.forEach(series => {
if (!series.isTotalSeries) {
series.dataPoints.forEach(dp => {
xSet.add(dp.x);
});
}
});
return Array.from(xSet).sort((a, b) => a – b);
}
//—————————————————————
// — Initialize total label series if it doesn’t exist —
//—————————————————————
function initTotalSeries(chart) {
if (!chart.totalSeries) {
let totalSeries = {
type: “column”,
dataPoints: [],
showInLegend: false,
color: “transparent”,
indexLabel: “{y}”,
indexLabelPlacement: “outside”,
indexLabelFontWeight: “bold”,
indexLabelFormatter: function(e) {
// Always show the label even for 0 totals
return (e.dataPoint.y !== null && e.dataPoint.y !== undefined)
? e.dataPoint.y
: “”;
},
isTotalSeries: true
};
chart.options.data.push(totalSeries);
chart.totalSeries = totalSeries;
}
}
//—————————————————————
// — Update the total labels dynamically —
//—————————————————————
function updateTotalIndexLabels(chart) {
initTotalSeries(chart);
const totals = sumVisibleColumns(chart);
const allX = getAllXValues(chart);
// Build new total datapoints for all x values
chart.totalSeries.dataPoints = allX.map(x => ({
x: x,
y: totals[x] !== undefined ? totals[x] : 0
}));
chart.render();
}