js 前端实现将json格式数组下载到excel(xls、xlsx、csv)表格里

项目需求:上传文件时如果有错误信息,则上传不成功,需要提示用户下载查看错误信息。下载查看错误信息是前端根据后台返回的对象数组放到excel表格中的。

后台返回的数组:

效果如下:

在开始之前先要了解一下几个excel格式的区别:

1.后缀是xls的在2007版本之后的office打开会有提示(xls在wps上打开没有提示)

2.后缀是xlsx在2007版本之后的打开没有提示,但是在2007之前的版本会打不开

3.csv是最通用的一种文件格式,它可以非常容易的被导入各种pc表格及数据库中,此文件中一行即为数据表的一行。生成数据表字段用半角逗号隔开。但是csv不能设置样式。

第一种:生成xls

 

 可粘贴的代码如下:

// 错误信息下载
  exportEx = val => {
    let JSONData = val;
    let ShowLabel = ['序号', 'imei', '错误原因'];
    //先转化json
    let arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
    // 给数组内容换好位置
    let finalData = [];
    arrData.forEach(item => {
      let obj = {
        rowNum: item.rowNum,
        imei: item.imei ? item.imei : '',
        errorMsg: item.errorMsg,
      };
      finalData.push(obj);
    });
    let excel = '<table>';
    //设置表头
    let row = '<tr>';
    for (let i = 0; i < ShowLabel.length; i++) {
      row += '<td>' + ShowLabel[i] + '</td>';
    }
    //换行
    excel += row + '</tr>';
    //设置数据
    for (let i = 0; i < finalData.length; i++) {
      let row = '<tr>';
      for (let index in finalData[i]) {
        let value = finalData[i][index];
        if (index === 'imei') {
          // 当数字超过一定长度就科学计数法可以使用style='mso-number-format:"\@"'
          // 这个属性指定某单元格的数据格式,避免Excel自动转换格式
          row += `<td style='mso-number-format:\"\\@\"'>${value}</td>`;
        } else {
          row += '<td>' + value + '</td>';
        }
      }
      excel += row + '</tr>';
    }
    excel += '</table>';
    let excelFile =
      "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:excel' xmlns='http://www.w3.org/TR/REC-html40'>";
    excelFile +=
      '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">';
    excelFile += '<meta http-equiv="content-type" content="application/vnd.ms-excel';
    excelFile += '; charset=UTF-8">';
    excelFile += '<head>';
    excelFile += '<!--[if gte mso 9]>';
    excelFile += '<xml>';
    excelFile += '<x:ExcelWorkbook>';
    excelFile += '<x:ExcelWorksheets>';
    excelFile += '<x:ExcelWorksheet>';
    excelFile += '<x:Name>';
    excelFile += '{worksheet}';
    excelFile += '</x:Name>';
    excelFile += '<x:WorksheetOptions>';
    excelFile += '<x:DisplayGridlines/>';
    excelFile += '</x:WorksheetOptions>';
    excelFile += '</x:ExcelWorksheet>';
    excelFile += '</x:ExcelWorksheets>';
    excelFile += '</x:ExcelWorkbook>';
    excelFile += '</xml>';
    excelFile += '<![endif]-->';
    excelFile += '</head>';
    excelFile += '<body>';
    excelFile += excel;
    excelFile += '</body>';
    excelFile += '</html>';
    let uri = 'data:application/vnd.ms-excel;charset=utf-8,' + encodeURIComponent(excelFile);
    let link = document.createElement('a');
    link.href = uri;
    link.style = 'visibility:hidden';
    link.download = '错误数据文件.xls';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    message.success('下载成功!');
    this.setState({
      errorMsgVisible: false,
    });
    
  };

补充:在导出的excel中较长的数字会变成科学计数法展示,为了让过长的数字全部展示出来需要添加样式:style="mso-number-format:'\@';"

在代码中"\@"中的引号反斜杠都需要添加转义符才能使用。

 第二种:生成xlsx

需要引入js-xlsx插件

1.使用npm install xlsx

2.并在文件中引入 import XLSX from 'xlsx';

 

 

 可复制的代码如下:

// 错误信息下载
  exportEx = val => {
    let JSONData = val;
    let ShowLabel = ['序号', 'imei', '错误原因'];
    //先转化json
    let arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
    // 给数组内容换好位置
    let finalData = [];
    arrData.forEach(item => {
      let obj = {
        rowNum: item.rowNum,
        imei: item.imei ? item.imei : '',
        errorMsg: item.errorMsg,
      };
      finalData.push(obj);
    });
    let excel = '<table>';
    //设置表头
    let row = '<tr>';
    for (let i = 0; i < ShowLabel.length; i++) {
      row += '<td>' + ShowLabel[i] + '</td>';
    }
    //换行
    excel += row + '</tr>';
    //设置数据
    for (let i = 0; i < finalData.length; i++) {
      let row = '<tr>';
      for (let index in finalData[i]) {
        let value = finalData[i][index];
        if (index === 'imei') {
          // 当数字超过一定长度就科学计数法可以使用style='mso-number-format:"\@"'
          // 这个属性指定某单元格的数据格式,避免Excel自动转换格式
          row += `<td style='mso-number-format:\"\\@\"'>${value}</td>`;
        } else {
          row += '<td>' + value + '</td>';
        }
      }
      excel += row + '</tr>';
    }
    excel += '</table>';
    // 因为我们这里的数据是string格式的,但是js-xlsx需要dom格式,则先新建一个div然后把数据加入到innerHTML中,在传childNodes[0]即使dom格式的数据
    let objE = document.createElement('div');
    objE.innerHTML = excel;
    // 将一个table对象转换成一个sheet对象,raw为true的作用是把数字当成string,身份证不转换成科学计数法
    let sheet = XLSX.utils.table_to_sheet(objE.childNodes[0], { raw: true });
    this.openDownloadDialog(this.sheet2blob(sheet, '错误数据文件'), '错误数据文件.xlsx');
  };
  sheet2blob = (sheet, sheetName) => {
    sheetName = sheetName || 'sheet1'; // 不存在sheetName时使用sheet1代替
    let workbook = {
      SheetNames: [sheetName],
      Sheets: {},
    };
    workbook.Sheets[sheetName] = sheet; // 生成excel的配置项

    let wopts = {
      bookType: 'xlsx', // 要生成的文件类型
      bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
      type: 'binary', // 二进制格式
    };
    let wbout = XLSX.write(workbook, wopts);
    let blob = new Blob([this.s2ab(wbout)], {
      type: 'application/octet-stream',
    }); // 字符串转ArrayBuffer
    return blob;
  };
  s2ab = s => {
    let buf = new ArrayBuffer(s.length);
    let view = new Uint8Array(buf);
    for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
    return buf;
  };
  openDownloadDialog = (url, saveName) => {
    if (typeof url === 'object' && url instanceof Blob) {
      url = URL.createObjectURL(url); // 创建blob地址
    }
    let aLink = document.createElement('a');
    aLink.href = url;
    aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
    let 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);
    message.success('下载成功!');
    this.setState({
      errorMsgVisible: false,
    });
  };

第二种:生成csv

 

 参考链接:https://blog.csdn.net/qq_35493664/article/details/88896638?utm_medium=distribute.pc_relevant_download.none-task-blog-BlogCommendFromBaidu-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-BlogCommendFromBaidu-1.nonecas

 

posted @ 2021-02-03 10:51  棠樾  阅读(1556)  评论(0编辑  收藏  举报