Skip to content

Commit d235e22

Browse files
committed
#112 Convert JSON to CSV and export as CSV
1 parent 4750e95 commit d235e22

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

src/lib/components/Table/TableContent.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import {
3131
cellStyle,
3232
exportAsCsv,
33+
jsonToCsv,
3334
fixedWidth,
3435
normalizeFilters,
3536
resetResize,
@@ -580,7 +581,7 @@
580581
type="button"
581582
class="btn btn-sm variant-filled-primary rounded-full order-last"
582583
aria-label="Export table data as CSV"
583-
on:click|preventDefault={() => exportAsCsv(tableId, $exportedData)}
584+
on:click|preventDefault={() => exportAsCsv(tableId, jsonToCsv($exportedData))}
584585
>Export as CSV</button
585586
>
586587
{/if}

src/lib/components/Table/shared.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,37 @@ export const exportAsCsv = (tableId: string, exportedData: string) => {
6363
document.body.removeChild(anchor);
6464
};
6565

66+
export const jsonToCsv = (data: string): string => {
67+
const json = JSON.parse(data);
68+
69+
if (json.length === 0) return '';
70+
71+
// Extract headers (keys)
72+
const headers = Object.keys(json[0]);
73+
74+
// Escape and format a single cell
75+
const escapeCsvCell = (value: any): string => {
76+
if (value === null || value === undefined) return '';
77+
let cell = String(value);
78+
// Escape quotes by doubling them, and wrap the value in quotes if it contains special characters
79+
if (/[",\n]/.test(cell)) {
80+
cell = `"${cell.replace(/"/g, '""')}"`;
81+
}
82+
return cell;
83+
};
84+
85+
// Create CSV rows
86+
const rows = [
87+
headers.join(','), // Header row
88+
...json.map((row) =>
89+
headers.map(header => escapeCsvCell(row[header])).join(',')
90+
) // Data rows
91+
];
92+
93+
// Join rows with newlines
94+
return rows.join('\n');
95+
}
96+
6697
// Resetting the resized columns and/or rows
6798
export const resetResize = (
6899
headerRows: any,
@@ -114,15 +145,15 @@ export const missingValuesFn = (
114145
const foundKey =
115146
typeof key === 'number' && key.toString().includes('e')
116147
? Object.keys(missingValues).find((item) => {
117-
return (item as string).toLowerCase() === key.toString().toLowerCase();
118-
})
148+
return (item as string).toLowerCase() === key.toString().toLowerCase();
149+
})
119150
: typeof key === 'string' && parseInt(key).toString().length !== key.length && new Date(key)
120-
? Object.keys(missingValues).find(
151+
? Object.keys(missingValues).find(
121152
(item) => new Date(item).getTime() === new Date(key).getTime()
122-
)
123-
: key in missingValues
124-
? key
125-
: undefined;
153+
)
154+
: key in missingValues
155+
? key
156+
: undefined;
126157

127158
return foundKey ? missingValues[foundKey] : key;
128159
};

0 commit comments

Comments
 (0)