const exportToCsv = (data, csvFileName) => { const link = document.createElement("a"); if (undefined !== link.download) { // downloads supported? const csvRows = [], // get the key names for the CSV header (column names) headers = Object.keys(data[0]), escCsvValue = value => "string" === typeof value && (-1 !== value.indexOf('"') || -1 !== value.indexOf(",")) // escape values that contain quotes or commas ? '"' + value.replace(/"/g, '""') + '"' // Dobule quotes are double escaped : value, convertCharset = s => "string" === typeof s ? s.replace(/[—–]/g, "-") // convert long dash/tiret to the unicode .replace(/[“”„‟«»]/, '"') // quotes .replaceAll("’", "'") // apostrophes .replaceAll("×", "x") // × .replaceAll("(", "(") // TODO: make it smarter, put into array. And there are a lot more characters that really worth to convert instead of this Chinese bracket. .replaceAll(")", ")") : s; // add the column names as header csvRows.push(headers.map(escCsvValue).join(",")); // convert each JSON object into CSV row data.forEach(item => csvRows.push(headers.map(header => escCsvValue(convertCharset(item[header]))).join(","))); link.setAttribute("href", URL.createObjectURL(new Blob([csvRows.join("\n")], { type: "text/csv;charset=utf-8;" }))); // utf-8 link.setAttribute("download", csvFileName); link.style.visibility = "hidden"; document.body.appendChild(link); link.click(); // simulate native click document.body.removeChild(link); } };