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

问题描述 投票:0回答:5

寻找一种方法将“导出到 CSV”按钮添加到反应表(npmjs 包)(https://www.npmjs.com/package/react-table)。

我需要添加一个自定义按钮,用于将表数据导出到 csv 或 xls 格式的 Excel 工作表?

javascript reactjs frontend react-table
5个回答
58
投票

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

例如-

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

const csvData =[
  ['firstname', 'lastname', 'email'] ,
  ['John', 'Doe' , '[email protected]'] ,
  ['Jane', 'Doe' , '[email protected]']
];
<CSVLink data={csvData} >Download me</CSVLink>
// or
<CSVDownload data={csvData} target="_blank" />

56
投票

集成如下:

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;

这也适用于过滤器。


12
投票

我在 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 data={data} columns={columns} />

和按钮:

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

4
投票

我想我会通过简化的

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
函数来允许在一个组件中导出多个表。


0
投票

首先添加参考:

const tabRef = useRef(0);

下一个:

<div className="table_widget">
     <span onClick={goCSV} >CSV</span>
</div>                     
<table className="table"  ref={tabRef}>
    <tr><td>TEXT</td></tr>
</table>

并复制我的功能:

const goCSV = () =>
    {
 
        var txtBuffer  = "";
        
        const rows = tabRef.current?.rows;
        if(!rows)
        {
            return; 
        }

        Array.from(rows).forEach(row => {

        
            var clsName = row.className;
           
            const cells = Array.from(row.cells);
            cells.forEach(cell => {

                  console.log(cell);

                  var txt = cell.innerHTML;
                  var tdClsName = cell.className;
                  var childElementCount = cell.childElementCount; //

        

                  if(childElementCount == 0) 
                  {
                    txtBuffer = txtBuffer +   txt + ";";
                  }else
                  {
                    txtBuffer = txtBuffer       + ";";
                  }


            });

            txtBuffer = txtBuffer + "\r\n";

          });

          
          txtBuffer = "\ufeff"+txtBuffer; //code utf 

          var encodedString = utf8_to_b64(txtBuffer);
    
          document.location.href = "data:text/csv;base64," + encodedString;
    }
© www.soinside.com 2019 - 2024. All rights reserved.