美文网首页
前端将表格导出Excel -react项目

前端将表格导出Excel -react项目

作者: jack_rofer | 来源:发表于2020-01-03 14:21 被阅读0次

    前言:主要用到的东西是:xlsx-style,之后进行二次封装,再引入使用
    (代码实现并没有获取页面什么东西,是直接拿数据源进行处理出来,注释都在代码中!!!)
    npm地址

    一。将xlsx-style引入项目
    npm install xlsx-style --save
    
    二。将xlsx-style封装一下
    /* eslint-disable */
    import FileSaver from 'file-saver'
    import XLSX from 'xlsx-style'
    
    function generateArray(table) {
      var out = [];
      var rows = table.querySelectorAll('tr');
      var ranges = [];
      for (var R = 0; R < rows.length; ++R) {
        var outRow = [];
        var row = rows[R];
        var columns = row.querySelectorAll('td');
        for (var C = 0; C < columns.length; ++C) {
          var cell = columns[C];
          var colspan = cell.getAttribute('colspan');
          var rowspan = cell.getAttribute('rowspan');
          var cellValue = cell.innerText;
          if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
    
          //Skip ranges
          ranges.forEach(function (range) {
            if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
              for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
            }
          });
    
          //Handle Row Span
          if (rowspan || colspan) {
            rowspan = rowspan || 1;
            colspan = colspan || 1;
            ranges.push({
              s: {
                r: R,
                c: outRow.length
              },
              e: {
                r: R + rowspan - 1,
                c: outRow.length + colspan - 1
              }
            });
          }
          ;
    
          //Handle Value
          outRow.push(cellValue !== "" ? cellValue : null);
    
          //Handle Colspan
          if (colspan)
            for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
        }
        out.push(outRow);
      }
      return [out, ranges];
    };
    
    function datenum(v, date1904) {
      if (date1904) v += 1462;
      var epoch = Date.parse(v);
      return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
    }
    
    function sheet_from_array_of_arrays(data, opts) {
      var ws = {};
      var range = {
        s: {
          c: 10000000,
          r: 10000000
        },
        e: {
          c: 0,
          r: 0
        }
      };
      for (var R = 0; R != data.length; ++R) {
        for (var C = 0; C != data[R].length; ++C) {
          if (range.s.r > R) range.s.r = R;
          if (range.s.c > C) range.s.c = C;
          if (range.e.r < R) range.e.r = R;
          if (range.e.c < C) range.e.c = C;
          var cell = {
            v: data[R][C]
          };
          if (cell.v == null) continue;
          var cell_ref = XLSX.utils.encode_cell({
            c: C,
            r: R
          });
    
          if (typeof cell.v === 'number') cell.t = 'n';
          else if (typeof cell.v === 'boolean') cell.t = 'b';
          else if (cell.v instanceof Date) {
            cell.t = 'n';
            cell.z = XLSX.SSF._table[14];
            cell.v = datenum(cell.v);
          } else cell.t = 's';
    
          ws[cell_ref] = cell;
        }
      }
      if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
      return ws;
    }
    
    function Workbook() {
      if (!(this instanceof Workbook)) return new Workbook();
      this.SheetNames = [];
      this.Sheets = {};
    }
    
    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;
    }
    
    export function export_table_to_excel(id) {
      var theTable = document.getElementById(id);
      var oo = generateArray(theTable);
      var ranges = oo[1];
    
      /* original data */
      var data = oo[0];
      var ws_name = "SheetJS";
    
      var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);
    
      /* add ranges to worksheet */
      // ws['!cols'] = ['apple', 'banan'];
      ws['!merges'] = ranges;
    
      /* add worksheet to workbook */
      wb.SheetNames.push(ws_name);
      wb.Sheets[ws_name] = ws;
    
      var wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: false,
        type: 'binary'
      });
    
      saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
      }), "test.xlsx")
    }
    
    export function export_json_to_excel({
      // title,
      multiHeader = [],
      header,
      data,
      filename,
      merges = [],
      autoWidth = true,
      bookType = 'xlsx'
    } = {}) {
      /* original data */
      filename = filename || 'excel-list'
      data = [...data]
      data.unshift(header);
      // data.unshift(title);
      for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i])
      }
    
      var ws_name = "SheetJS";
      var wb = new Workbook(),
        ws = sheet_from_array_of_arrays(data);
    
      if (merges.length > 0) {
        if (!ws['!merges']) ws['!merges'] = [];
        merges.forEach(item => {
          ws['!merges'].push(XLSX.utils.decode_range(item))
        })
      }
    
      if (autoWidth) {
        /*设置worksheet每列的最大宽度*/
        const colWidth = data.map(row => row.map(val => {
          /*先判断是否为null/undefined*/
          if (val == null) {
            return {
              'wch': 200
            };
          }
          /*再判断是否为中文*/
          else if (val.toString().charCodeAt(0) > 255) {
            return {
              'wch': val.toString().length * 5
            };
          } else {
            return {
              'wch': val.toString().length * 3
            };
          }
        }))
        /*以第一行为初始值*/
        let result = colWidth[0];
        for (let i = 1; i < colWidth.length; i++) {
          for (let j = 0; j < colWidth[i].length; j++) {
            if (result[j] < colWidth[i][j]) {
              result[j]['wch'] = colWidth[i][j]['wch'];
            }
          }
        }
        ws['!cols'] = result;
      }
    
      /* add worksheet to workbook */
      wb.SheetNames.push(ws_name);
      wb.Sheets[ws_name] = ws;
      var dataInfo = wb.Sheets[wb.SheetNames[0]];
    
      const borderAll = {  //单元格外侧框线
        top: {
          style: 'thin'
        },
        bottom: {
          style: 'thin'
        },
        left: {
          style: 'thin'
        },
        right: {
          style: 'thin'
        }
      };
      //给所以单元格加上边框
      for (var i in dataInfo) {
        if (i == '!ref' || i == '!merges' || i == '!cols' || i == 'A1') {
    
        } else {
          dataInfo[i + ''].s = {
            border: borderAll
          }
        }
      }
    
      var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: 'binary'
      });
      saveAs(new Blob([s2ab(wbout)], {
        type: "application/octet-stream"
      }), `${filename}.${bookType}`);
    }
    
    三。将封装好的xlsx-style进行使用
    //-------------------引入封装的组件------------------------------------------------
    import * as excelExport from '../../utils/Export2Excel'   
    
    
    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          data: [],
          source:[],
         //TA数据分红导出
          DetailColumns:[],
          DetailtableData:[],
          DTexcelHeader: [],  //
          DTexcelBody: [],  //
          DTfilterVal: [],  // 
          DTdate:'',
       
        }
      }
    //----------------处理数据的函数 --------------------------------------------------
      dealwithDetailData(){
        const DetailColumns = [  //需要展示的表头
          {
            title: '第一列', //表头名字
            dataIndex: 'F_CODE',//对应的后端返回字段
            key: 'F_CODE',//react渲染的key值,可以和dataIndex一样
          },
          {
            title: '第二列',
            dataIndex: 'F_NAME',
            key: 'F_NAME',
          },
          {
            title: '第三列',
            dataIndex: 'R_DATE',
            key: 'R_DATE',
          },  
        ];    
        let DTexcelHeader = []
        let DTexcelBody = []
        let DTfilterVal = []
    
        DetailColumns.map(item => {
          if (!item.children) {
            DTexcelHeader.push(item.title)
            DTfilterVal.push(item.dataIndex)
          } else {
            item.children.map(itm => {
                DTexcelHeader.push(item.title + itm.title)
                DTfilterVal.push(itm.dataIndex)
            })
          }
        })
    
        this.state.DetailtableData.map(item => {
          for (const i in item) {
            if (item.hasOwnProperty(i) && item[i] == null) {
              item[i] = ''
            }
          }
          DTexcelBody.push(item)
        })        
        this.setState({
            DetailColumns,DTexcelHeader, DTexcelBody,DTfilterVal
        })
      };
    
      //excel导出数据进行格式化函数
      formatJson(DTfilterVal, jsonData) {
          return jsonData.map(v => DTfilterVal.map(j => v[j]));
      };
    
    
    //---------------因为xlsx-style,比较大,所以在点击的时候再调用--------- 
        render(){
            return (
                <div>
                    <Button icon="file-excel" key="confim" type="primary" size="large"
                            onClick={ ()=>excelExport.export_json_to_excel({
                            header:this.state.DTexcelHeader,  //表头
                            data:this.formatJson(this.state.DTfilterVal,this.state.DTexcelBody), //数据格式化
                            filename:`某某文件(${this.state.DTdate})`, //导出的名字
                            autoWidth: true,
                            bookType: "xlsx"
                        })
                    }>
                            导出Excel
                    </Button> 
                </div>
            )
    
    
    
        }
    }
    

    相关文章

      网友评论

          本文标题:前端将表格导出Excel -react项目

          本文链接:https://www.haomeiwen.com/subject/glyzoctx.html