Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing CSV and Excel Export Functionality for Highcharts

Tech 1

1. Chart Initialization

First, configure the basic Highcharts instance with the desired dataset. In this example, we visualize annual revenue trends across different product lines.

const salesChart = Highcharts.chart('chart-wrapper', {
    chart: {
        type: 'area',
        zoomType: 'x'
    },
    title: {
        text: 'Annual Revenue Growth'
    },
    subtitle: {
        text: 'Source: Internal Sales Records'
    },
    xAxis: {
        categories: ['2018', '2019', '2020', '2021', '2022', '2023'],
        title: { text: 'Fiscal Year' }
    },
    yAxis: {
        title: { text: 'Revenue (USD)' },
        labels: { formatter: function () { return '$' + this.value / 1000 + 'k'; } }
    },
    plotOptions: {
        area: { stacking: 'normal', lineColor: '#666666', lineWidth: 1, marker: { lineWidth: 1, lineColor: '#666666' } }
    },
    series: [{
        name: 'Services',
        data: [45000, 49000, 52000, 61000, 75000, 88000]
    }, {
        name: 'Hardware',
        data: [30000, 35000, 32000, 40000, 42000, 55000]
    }, {
        name: 'Licensing',
        data: [15000, 18000, 22000, 28000, 35000, 41000]
    }]
});

2. Implementing the Export Plugin

To enable data extraction, extend the Highcharts prototype. This script defines methods to convert the chart data into a 2D array, formats it as a CSV or HTML table string, and triggers a browser download using Blob objects.

(function(H) {
    'use strict';

    // Helper: Convert chart data to a 2D array structure
    H.Chart.prototype.getDataMatrix = function() {
        const xAxis = this.xAxis[0];
        const rows = [];
        const headers = [];

        // 1. Extract Headers
        const xLabel = xAxis.options.title && xAxis.options.title.text;
        headers.push(xLabel || (xAxis.isDatetimeAxis ? 'DateTime' : 'Category'));
        
        this.series.forEach(series => {
            if (series.visible && series.options.includeInCSVExport !== false) {
                headers.push(series.name);
            }
        });
        rows.push(headers);

        // 2. Extract Data Points
        // Assuming all series share the same X axis points
        if (this.series.length > 0) {
            const baseSeries = this.series.find(s => s.visible && s.options.includeInCSVExport !== false) || this.series[0];
            
            baseSeries.points.forEach(point => {
                const currentRow = [];
                
                // Add X value
                if (xAxis.categories) {
                    currentRow.push(xAxis.categories[point.x]);
                } else if (xAxis.isDatetimeAxis) {
                    currentRow.push(H.dateFormat('%Y-%m-%d %H:%M:%S', point.x));
                } else {
                    currentRow.push(point.x);
                }

                // Add Y values for each visible series
                this.series.forEach(series => {
                    if (series.visible && series.options.includeInCSVExport !== false) {
                        const pt = series.points.find(p => p.x === point.x);
                        currentRow.push(pt ? pt.y : '');
                    }
                });
                rows.push(currentRow);
            });
        }
        return rows;
    };

    // Helper: Generate CSV String
    H.Chart.prototype.getCSVString = function() {
        const matrix = this.getDataMatrix();
        const csvRows = matrix.map(row => row.map(val => {
            const str = String(val);
            // Quote strings containing commas or quotes
            if (str.indexOf(',') > -1 || str.indexOf('"') > -1) {
                return `"${str.replace(/"/g, '""')}"`;
            }
            return str;
        }).join(','));
        return csvRows.join('\r\n');
    };

    // Helper: Generate HTML Table String (for Excel)
    H.Chart.prototype.getHTMLTable = function() {
        const matrix = this.getDataMatrix();
        let html = '';
        
        // Header
        matrix[0].forEach(cell => html += ``);
        html += '';

        // Body
        for (let i = 1; i < matrix.length; i++) {
            html += '';
            matrix[i].forEach(cell => html += ``);
            html += '';
        }
        html += '
${cell}
${cell}
'; return html; }; // Function to handle file download const initiateDownload = function(url, filename) { const anchor = document.createElement('a'); anchor.href = url; anchor.download = filename; anchor.style.display = 'none'; document.body.appendChild(anchor); anchor.click(); setTimeout(() => { document.body.removeChild(anchor); }, 100); }; // Export to CSV H.Chart.prototype.saveAsCSV = function() { const csv = this.getCSVString(); const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' }); // Add BOM for Excel const url = URL.createObjectURL(blob); const filename = (this.title.textStr || 'export').replace(/ /g, '_') + '.csv'; initiateDownload(url, filename); }; // Export to XLS (HTML-based) H.Chart.prototype.saveAsExcel = function() { const htmlTable = this.getHTMLTable(); const excelTemplate = ` ${htmlTable} `; const blob = new Blob([excelTemplate], { type: 'application/vnd.ms-excel' }); const url = URL.createObjectURL(blob); const filename = (this.title.textStr || 'export').replace(/ /g, '_') + '.xls'; initiateDownload(url, filename); }; // Add buttons to the default exporting menu if (H.getOptions().exporting) { H.getOptions().exporting.buttons.contextButton.menuItems.push({ textKey: 'downloadCSV', onclick: function() { this.saveAsCSV(); } }, { textKey: 'downloadXLS', onclick: function() { this.saveAsExcel(); } }); } }(Highcharts));

3. Triggering the Export

Bind the export methods to UI elements using standard DOM event listeners.

document.getElementById('export-csv-btn').addEventListener('click', function() {
    if (salesChart) {
        salesChart.saveAsCSV();
    }
});

document.getElementById('export-xls-btn').addEventListener('click', function() {
    if (salesChart) {
        salesChart.saveAsExcel();
    }
});
Tags: Highcharts

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.