Looking for a way to add an "Export to CSV" button to a react-table which is an npmjs package ().
I need to add a custom button for exporting the table data to an excel sheet in the csv or xls format?
34 Answers
Take a look at this npm library -
For example -
import {CSVLink, CSVDownload} from 'react-csv'; const csvData =[ ['firstname', 'lastname', 'email'] , ['John', 'Doe' , ''] , ['Jane', 'Doe' , ''] ]; <CSVLink data={csvData} >Download me</CSVLink> // or <CSVDownload data={csvData} target="_blank" /> 2Here is how integration will look like
import React from "react"; import "react-dropdown/style.css"; import "react-table/react-table.css"; import ReactTable from "react-table"; import { CSVLink } from "react-csv"; const columns = [ { Header: "name", accessor: "name", // String-based value accessors! }, { Header: "age", accessor: "age", }, ]; class AllPostPage extends React.Component { constructor(props) { super(props); this.download = this.download.bind(this); this.state = { tableproperties: { allData: [ { name: "ramesh", age: "12" }, { name: "bill", age: "13" }, { name: "arun", age: "9" }, { name: "kathy", age: "21" }, ], }, dataToDownload: [], }; } download(event) { const currentRecords = this.reactTable.getResolvedState().sortedData; var data_to_download = []; for (var index = 0; index < currentRecords.length; index++) { let record_to_download = {}; for (var colIndex = 0; colIndex < columns.length; colIndex++) { record_to_download[columns[colIndex].Header] = currentRecords[index][columns[colIndex].accessor]; } data_to_download.push(record_to_download); } this.setState({ dataToDownload: data_to_download }, () => { // click the CSVLink component to trigger the CSV download this.csvLink.link.click(); }); } render() { return ( <div> <div> <button onClick={this.download}>Download</button> </div> <div> <CSVLink data={this.state.dataToDownload} filename="data.csv" className="hidden" ref={(r) => (this.csvLink = r)} target="_blank" /> </div> <div> <ReactTable ref={(r) => (this.reactTable = r)} data={this.state.tableproperties.allData} columns={columns} filterable defaultFilterMethod={(filter, row) => String(row[filter.id]) .toLowerCase() .includes(filter.value.toLowerCase()) } /> </div> </div> ); } } export default AllPostPage; This will work with filters as well.
7I have it implemented like this in React + Typescript (no dependency):
/** * @desc get table data as json * @param data * @param columns */ const getTableDataForExport = (data: any[], columns: any[]) => data?.map((record: any) => columns .reduce((recordToDownload, column) => ( { ...recordToDownload, [column.Header]: record[column.accessor] } ), {})); /** * @desc make csv from given data * @param rows * @param filename */ const makeCsv = async (rows: any[], filename: string) => { const separator: string = ';'; const keys: string[] = Object.keys(rows[0]); const csvContent = `${keys.join(separator)}\n${ rows.map((row) => keys.map((k) => { let cell = row[k] === null || row[k] === undefined ? '' : row[k]; cell = cell instanceof Date ? cell.toLocaleString() : cell.toString().replace(/"/g, '""'); if (cell.search(/("|,|\n)/g) >= 0) { cell = `"${cell}"`; } return cell; }).join(separator)).join('\n')}`; const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); if (navigator.msSaveBlob) { // In case of IE 10+ navigator.msSaveBlob(blob, filename); } else { const link = document.createElement('a'); if (link.download !== undefined) { // Browsers that support HTML5 download attribute const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', filename); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } }; the table:
<Table data={data} columns={columns} /> and the button:
<button type="button" onClick={() => makeCsv(getTableDataForExport(data, columns), `${filename}.csv`)} > Download table data CSV </button> 1I thought I'd piggyback on best wishes' extremely valuable answer with a simplified download implementation.
export = e => { const currentRecords = this.ReactTable.getResolvedState().sortedData; this.setState({ dataToDownload: this.dataToDownload(currentRecords, columns) }, () => this.csvLink.link.click() ); } dataToDownload = (data, columns) => data.map(record => columns.reduce((recordToDownload, column) => { recordToDownload[column.Header] = record[column.accessor]; return recordToDownload; }, {}) ); I used this to allow multiple table exports in one component by adding additional export functions.