HTML Table to CSV on the Client

There’s nothing that makes me want to thrash a bureaucrat more than the HTML-table-to-Excel request. But if you’ve gotta…

Turn table into CSV
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Send in a unique identifier for a table, like #myStupidTable
export default function table2csv(theTable){
let rows = document.querySelectorAll(`${theTable} tr`);
let csvData = "";

for (let i = 0; i < rows.length; i++) {
let cells = rows[i].querySelectorAll('th, td');
let dataArray = [];
for (let n = 0; n < cells.length; n++) {
dataArray.push(cells[n].innerText);
}
csvData += dataArray.map(val => `"${val.replace(/"/g, '')}"`).join(",") + '\n';
}

return csvData;
}

Next, suppose you have a download button like this. Note the download attribute - we can give this sucker a useful name rather than ‘download’ with no extension.

1
2
3
<a download="data.csv" id="download" onclick="downloadTable('#myStupidTable')">
Download
</a>

Your downloadTable handler needs to check for IE/Edge, because they’re shite when it comes to data URI’s. You have to use a crappy MS thing instead.

1
2
3
4
5
6
7
8
9
10
11
function downloadTable(theTable) {
let csvData = table2csv(theTable);
if (window.navigator.msSaveBlob) {
// i hate you ie
let blob = new Blob([csvData],{ type: "application/csv;charset=utf-8;"});
navigator.msSaveBlob(blob, 'data.csv');
} else {
// fix button href
document.querySelector('#download').href = 'data:text/csv;charset=utf-8;base64,' + btoa(csvData);
}
}