table数据转为excel文件下载

功能说明

本文讲解如何将table数据转为excel文件下载。亲测,当table有合并行/列时,下载的excel也会对应合并。

核心思想:

获取到table元素,根据其html组装为下载excel的文件地址,再下载

核心代码:

handleDownload() {
    // 获取table元素
    const tableElem = ReactHTMLTableToExcel.getTableElem(this.props.table);
    console.log('tableElem', tableElem)
    if(!tableElem) return;

    // 获取excel下载的url和文件名称
    const filename = `${String(this.props.filename)}.xls`;
    const tableHtml = tableElem.outerHTML;
    const url = ReactHTMLTableToExcel.getExcelUri(tableHtml, this.props.sheet);

    // 下载excel文件
    ReactHTMLTableToExcel.downloadExcel(tableHtml, filename, url);
  }

获取table元素

其中,getTableElem函数中的tableElemId参数 可以为 table元素的id ,也可以是 其父元素或其祖父元素的id,便于兼容不方便给table增加id属性时的情况。

static getTableElem(tableElemId){ // table元素的id 或者 其祖父元素的id
    if (!document || !tableElemId) {
      return null;
    }

    let tableElem = document.getElementById(tableElemId);
    
    if(tableElem){ 
      if(tableElem.nodeType !== 1 || tableElem.nodeName !== 'TABLE'){ // 不是元素类型,或者不是table
        tableElem = tableElem.getElementsByTagName('table')[0] || null; //尝试寻找内部table元素
      }
    }
    if(!tableElem){
      tableElem = document.getElementsByTagName('table')[0];
      if(!tableElem){
        console.log('未找到table元素!')
        return null;
      }
    }
    return tableElem;
  }

生成excel文件地址:

static base64(s) {
  return window.btoa(unescape(encodeURIComponent(s)));
}

static format(s, c) {
  return s.replace(/{(\w+)}/g, (m, p) => c[p]);
}

static getExcelUri(table, sheetname){
    const uri = 'data:application/vnd.ms-excel;base64,';
    const template =
      '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' +
      'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' +
      'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' +
      'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' +
      '</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' +
      'xml><![endif]--></head><body>{table}</body></html>';

    const context = {
      worksheet: String(sheetname) || 'Worksheet',
      table,
    };
    const url = uri +
      ReactHTMLTableToExcel.base64(
        ReactHTMLTableToExcel.format(template, context),
      );
    return url;
  }

下载excel文件

static downloadExcel(tableHtml, filename, url){
    // If IE11
    if (window.navigator.msSaveOrOpenBlob) {
      const fileData = [
        `${'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' + 'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' + 'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' + 'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' + '</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' + 'xml><![endif]--></head><body>'}${tableHtml}</body></html>`,
      ];
      const blobObject = new Blob(fileData);
      document.getElementById('react-html-table-to-excel').click()(() => {
        window.navigator.msSaveOrOpenBlob(blobObject, filename);
      });
      return true;
    }

    // 下载excel文件
    const element = window.document.createElement('a');
    element.href = url;
    element.download = filename;
    document.body.appendChild(element);
    element.click();
    document.body.removeChild(element);
  }

附赠完整代码:

/* global window, document, Blob */
import React, { Component } from 'react';
import PropTypes from 'prop-types';

const propTypes = {
  table: PropTypes.string.isRequired,
  filename: PropTypes.string.isRequired,
  sheet: PropTypes.string.isRequired,
  id: PropTypes.string,
  className: PropTypes.string,
  buttonText: PropTypes.string,
};

const defaultProps = {
  id: 'button-download-as-xls',
  className: 'button-download',
  buttonText: 'Download',
};

class ReactHTMLTableToExcel extends Component {
  constructor(props) {
    super(props);
    this.handleDownload = this.handleDownload.bind(this);
  }

  static base64(s) {
    return window.btoa(unescape(encodeURIComponent(s)));
  }

  static format(s, c) {
    return s.replace(/{(\w+)}/g, (m, p) => c[p]);
  }
  
  static getTableElem(tableElemId){ // table元素的id 或者 其祖父元素的id
    if (!document || !tableElemId) {
      return null;
    }

    let tableElem = document.getElementById(tableElemId);
    
    if(tableElem){ 
      if(tableElem.nodeType !== 1 || tableElem.nodeName !== 'TABLE'){ // 不是元素类型,或者不是table
        tableElem = tableElem.getElementsByTagName('table')[0] || null; //尝试寻找内部table元素
      }
    }
    if(!tableElem){
      tableElem = document.getElementsByTagName('table')[0];
      if(!tableElem){
        console.log('未找到table元素!')
        return null;
      }
    }
    return tableElem;
  }

  static getExcelUri(table, sheetname){
    const uri = 'data:application/vnd.ms-excel;base64,';
    const template =
      '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' +
      'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' +
      'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' +
      'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' +
      '</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' +
      'xml><![endif]--></head><body>{table}</body></html>';

    const context = {
      worksheet: String(sheetname) || 'Worksheet',
      table,
    };
    const url = uri +
    ReactHTMLTableToExcel.base64(
      ReactHTMLTableToExcel.format(template, context),
    );
    return url;
  }

  static downloadExcel(tableHtml, filename, url){
    // If IE11
    if (window.navigator.msSaveOrOpenBlob) {
      const fileData = [
        `${'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-mic' + 'rosoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta cha' + 'rset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:Exce' + 'lWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/>' + '</x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></' + 'xml><![endif]--></head><body>'}${tableHtml}</body></html>`,
      ];
      const blobObject = new Blob(fileData);
      document.getElementById('react-html-table-to-excel').click()(() => {
        window.navigator.msSaveOrOpenBlob(blobObject, filename);
      });
      return true;
    }

    // 下载excel文件
    const element = window.document.createElement('a');
    element.href = url;
    element.download = filename;
    document.body.appendChild(element);
    element.click();
    document.body.removeChild(element);
  }

  handleDownload() {
    // 获取table元素
    const tableElem = ReactHTMLTableToExcel.getTableElem(this.props.table);
    console.log('tableElem', tableElem)
    if(!tableElem) return;

    // 获取excel下载的url和文件名称
    const filename = `${String(this.props.filename)}.xls`;
    const tableHtml = tableElem.outerHTML;
    const url = ReactHTMLTableToExcel.getExcelUri(tableHtml, this.props.sheet);

    // 下载excel文件
    ReactHTMLTableToExcel.downloadExcel(tableHtml, filename, url);
  }

  render() {
    return (
      <button
        id={this.props.id}
        className={this.props.className}
        type="button"
        onClick={this.handleDownload}
      >
        {this.props.buttonText}
      </button>
    );
  }
}

ReactHTMLTableToExcel.propTypes = propTypes;
ReactHTMLTableToExcel.defaultProps = defaultProps;

export default ReactHTMLTableToExcel;

使用:

兼容不方便给table增加id属性时的情况:

<div id="table-to-xls">
      <ReactHTMLTableToExcel
          id="test-table-xls-button"
          className="download-table-xls-button"
          table="table-to-xls"
          filename="tablexls"
          sheet="tablexls"
          buttonText="Download as XLS"/>
      <Mytable>//封装好的table,table上没有透传id</Mytable>
  </div>

直接在table上增加id的情况:

<div>
                <ReactHTMLTableToExcel
                    id="test-table-xls-button"
                    className="download-table-xls-button"
                    table="table-to-xls"
                    filename="tablexls"
                    sheet="tablexls"
                    buttonText="Download as XLS"/>
                <table id="table-to-xls">
                    <tr>
                        <th>Firstname</th>
                        <th>Lastname</th>
                        <th>Age</th>
                    </tr>
                    <tr>
                        <td>Jill</td>
                        <td>Smith</td>
                        <td>50</td>
                    </tr>
                    <tr>
                        <td>Eve</td>
                        <td>Jackson</td>
                        <td>94</td>
                    </tr>
                </table>
            </div>

参考代码

ReactHTMLTableToExcel:https://www.npmjs.com/package/react-html-table-to-excel

本文在这个基础上,进行了代码抽离和获取table元素功能增强(兼容不方便给table增加id属性时的情况)。目的不是重复造轮子,是能够满足尽量多的业务场景。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值