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

时间:2024-02-22 08:22:52

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