React 中的“导出到 CSV”按钮 table

Export to CSV button in react table

正在寻找将 "Export to CSV" 按钮添加到 react-table 的方法,它是一个 npmjs 包 (https://www.npmjs.com/package/react-table)。

我需要添加自定义按钮以将 table 数据导出到 csv 或 xls 格式的 excel sheet?

看看这个 npm 库 - https://www.npmjs.com/package/react-csv

例如-

import {CSVLink, CSVDownload} from 'react-csv';

const csvData =[
  ['firstname', 'lastname', 'email'] ,
  ['John', 'Doe' , 'john.doe@xyz.com'] ,
  ['Jane', 'Doe' , 'jane.doe@xyz.com']
];
<CSVLink data={csvData} >Download me</CSVLink>
// or
<CSVDownload data={csvData} target="_blank" />

这是集成的样子

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;

这也适用于过滤器。

我想我可以通过简化的 download 实施来获得最美好的祝福的极其有价值的答案。

  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;
      }, {})
    );

我使用它通过添加额外的 export 函数允许在一个组件中进行多个 table 导出。

我在 React + Typescript 中这样实现了它(无依赖):

  /**
   * @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);
    }
  }
};

table:

<Table data={data} columns={columns} />

和按钮:

  <button
    type="button"
    onClick={() => makeCsv(getTableDataForExport(data, columns), `${filename}.csv`)}
  >
    Download table data CSV
  </button>