30 lines
885 B
TypeScript
30 lines
885 B
TypeScript
export type CsvColumn<T> = {
|
|
title: string;
|
|
value: (row: T) => unknown;
|
|
};
|
|
|
|
function csvCell(value: unknown) {
|
|
if (value == null) return '';
|
|
const text = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
return `"${text.replace(/"/g, '""')}"`;
|
|
}
|
|
|
|
export function buildCsv<T>(columns: CsvColumn<T>[], rows: T[]) {
|
|
return [
|
|
columns.map((item) => csvCell(item.title)).join(','),
|
|
...rows.map((row) => columns.map((column) => csvCell(column.value(row))).join(','))
|
|
].join('\n');
|
|
}
|
|
|
|
export function downloadCsv(filename: string, csv: string) {
|
|
const blob = new Blob(['\uFEFF', csv], { type: 'text/csv;charset=utf-8' });
|
|
const url = URL.createObjectURL(blob);
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.download = filename;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
link.remove();
|
|
URL.revokeObjectURL(url);
|
|
}
|