-
Bjarke Madsen authoredBjarke Madsen authored
DownloadDataButton.tsx 3.38 KiB
import React from 'react';
import * as XLSX from "xlsx";
import { ExportType } from "../../helpers/constants";
import { FaDownload } from 'react-icons/fa';
import { NrenAndYearDatapoint } from '../../Schema';
interface DownloadProps {
data: NrenAndYearDatapoint[];
filename: string;
exportType: ExportType;
}
function createCSVRows(jsonData: NrenAndYearDatapoint[], header: string[]): string[] {
return jsonData.map(obj => {
return header.map(fieldName => {
const value = obj[fieldName];
if (value === null) {
return "";
}
// Always wrap strings in double quotes and escape internal double quotes
if (typeof value === 'string') {
return `"${value.replace(/"/g, '""')}"`;
}
return value;
}).join(',');
});
}
function convertToCSV(jsonData: NrenAndYearDatapoint[]): string {
if (!jsonData.length) return "";
const header = Object.keys(jsonData[0]);
const rows = createCSVRows(jsonData, header);
// Combine header and rows with newline characters
return [header.join(','), ...rows].join('\r\n');
}
function convertToExcel(jsonData: NrenAndYearDatapoint[], sheetName = "Sheet1"): Blob {
const ws = XLSX.utils.json_to_sheet(jsonData);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, sheetName);
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
const buffer = new ArrayBuffer(wbout.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < wbout.length; i++) {
// Convert each character of the binary workbook string to an 8-bit integer and store in the Uint8Array 'view' for blob creation.
view[i] = wbout.charCodeAt(i) & 0xFF;
}
return new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
}
const DownloadDataButton: React.FC<DownloadProps> = ({ data, filename, exportType }) => {
const downloadData = () => {
let convertedData;
let fileType;
let contentType;
switch (exportType) {
case ExportType.EXCEL: {
convertedData = convertToExcel(data);
fileType = 'xlsx';
contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
break;
}
case ExportType.CSV:
default: {
convertedData = convertToCSV(data);
fileType = 'csv';
contentType = 'text/csv;charset=UTF-8';
break;
}
}
const blob = new Blob([convertedData], { type: contentType });
filename = filename.endsWith(fileType) ? filename : `${filename}.${fileType}`;
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
let classname = 'downloadbutton';
if (exportType === ExportType.CSV) {
classname += ' downloadcsv';
}
else if (exportType === ExportType.EXCEL) {
classname += ' downloadexcel';
}
return (
<button className={classname} onClick={downloadData}>{exportType} <FaDownload /></button>
);
}
export default DownloadDataButton;