react 导出Excel

1,054 阅读2分钟

1.利用XLSX插件和Blob对象

该方法最终还是转换成blob进行下载,适用于数据量较少,不需要和后端进行交互的情况。eg:导出模板、导出少量统计数据情况
import * as XLSX from "xlsx";
 const util = {
 // 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
  sheet2blob(sheet, sheetName) {
    sheetName = sheetName || "sheet1";
    var workbook = {
      SheetNames: [sheetName],
      Sheets: {}
    };
    workbook.Sheets[sheetName] = sheet;
    // 生成excel的配置项
    var wopts = {
      bookType: "xlsx", // 要生成的文件类型
      bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
      type: "binary"
    };
    var wbout = XLSX.write(workbook, wopts);
    var blob = new Blob([s2ab(wbout)], { type: "application/octet-stream" });
    // 字符串转ArrayBuffer
    function s2ab(s) {
      var buf = new ArrayBuffer(s.length);
      var view = new Uint8Array(buf);
      for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
      return buf;
    }
    return blob;
  },

  openDownloadDialog(url, saveName) {
    if (typeof url == "object" && url instanceof Blob) {
      url = URL.createObjectURL(url); // 创建blob地址
    }
    var aLink = document.createElement("a");
    aLink.href = url;
    aLink.download = saveName || ""; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    var event;
    if (window.MouseEvent) event = new MouseEvent("click");
    else {
      event = document.createEvent("MouseEvents");
      event.initMouseEvent(
        "click",
        true,
        false,
        window,
        0,
        0,
        0,
        0,
        0,
        false,
        false,
        false,
        false,
        0,
        null
      );
    }
    aLink.dispatchEvent(event);
  },
 }
 
 export default util

调用以下方法进行下载

    downLoadExcel = () => {
    const aoa = [
      ["姓名", "年龄""年级],
      ["小明", "18","高二"],
      ["小张", "19","高三"],
    ];
    var sheet = XLSX.utils.aoa_to_sheet(aoa);
    util.openDownloadDialog(
      util.sheet2blob(sheet),
      "学生信息导入模板.xlsx"
    );
  };

2. react + antd table + react-html-table-to-excel 直接对表格导出

下载依赖
yarn add react-html-table-to-excel
import React,{ useState } from 'react';
import { Table } from 'antd';
import ReactHTMLTableToExcel from 'react-html-table-to-excel';

class exportExcelTable extend React.component {
    constructor(props){
      super(props)
      this.state={
        selectId:''
      }
    }

    componentDidMount(){
        const tableCon = ReactDOM.findDOMNode(this.refs['tables']); // 通过ref属性找到该table
        const table = tableCon.querySelector('table');  //获取table
        table.setAttribute('id', 'table-to-xls')     //给该table设置属性
    }



// 导出前可做相应判断
   handleExportable = (e) => {
        if (!this.state.selectId) {
            e.stopPropagation()
            console.log('请先选择需要导出的模板')
        }
    }
    
    return (
       <>
           <div className={s.conditionWrap} onClick={handleExportable}>
                <ReactHTMLTableToExcel
                    className="download-table-xls-button exportBtn"
                    filename={selectCard ? ccxiIndustryName + '行业打分卡' : '评级打分卡'}
                    sheet="sheet1"
                    buttonText="导出Excel"
                    id="test-table-xls-button"
                    table="table-to-xls"
                />
           </div>
           
           <Table
               ref='tables' 
               dataSource={dataSource}
               columns={columns}
               bordered
               pagination={false}
               className='exportTableWrap'
            />
       
       </>
        
    )
}

export default exportExcelTable

3. 请求后端接口使用Blob进行导出

通过接口获取 src/actions
import axios from 'axios';
import util  from '@src/util';

// 导出excel
export const exportExcel = (params, callback) => async (dispatch) => {
  const result = await axios({
    url: HOST_NAME_EXPORT_URL,// 接口地址....
    method: 'POST',
    data: JSON.stringify(params),
    headers: {// 可携带token等
      'Content-Type': 'application/json;charset=UTF-8',
    },
    responseType: 'blob',// 接收类型指定为blob
  })

  const response = await util.judgeErrorByResponseType(result) // 对返回内容进行校验,捕获错误
  if (callback) callback(response)
};

src/util

const util = {
  // 导出excel(response响应结果,fileName文件名)
  exportExcel(response,fileName) {
    const data = response.data
    const blob = new Blob([data], {type: 'application/octet-stream'});
    const url = URL.createObjectURL(blob);
    const exportLink = document.createElement('a');
    // 文件名可自行指定 或从响应头中获取
    const exportName =  fileName || decodeURIComponent(
      response.headers['content-disposition'].split(';')[1].split('=')[1]
    )
    exportLink.setAttribute('download',exportName);
    exportLink.href = url;
    document.body.appendChild(exportLink);
    exportLink.click();
  },
  
  // 捕捉导出错误
  judgeErrorByResponseType(response) {
    return new Promise((resolve, reject) => {
      if (response.headers['content-type'] && response.headers['content-type'].includes('json')) {
        // 此处拿到的data才是blob
        const { data } = response
        const reader = new FileReader()
        reader.onload = () => {
          const { result } = reader
          const errorInfos = JSON.parse(result)
          const { msg } = errorInfos
          reject(new Error(msg))
          message.error(msg,1.5)
        }
        reader.onerror = err => {
          reject(err)
        }
        reader.readAsText(data)
      } else {
        resolve(response)
      }
    })
  },
}

export default util

导出

import util from '@src/util';
const ExportPage = (props) => {
    const exportData = () => {
        this.props.exportExcel(searchParams, (res) => {
          util.exportExcel(res)
        })
    }
    return (
     <div onClick={exportData} className='exportBtn'>导出</div>
    )
}