前端解析excel文件

905 阅读2分钟

前端有时就会遇见明明是后端的活,却一定要前端来完成。就比如下面的

需求:前端解析excel文件中的内容,加工成json传给后端,后端加工完json再传给前端,然后前端以excel的形式下载到本地。

下面就分两部分来封装方法

一、解析excel文件

import * as XLSX from 'xlsx';

const getExcelFile=()=>{

    let list=[]; // 存储解析出来的excel内容

    let titleList=[]; // 存储excel的title
   
    let files = e.target.files;   // e为input为file时 点击之后传过来的参数。
   
    let fileReader = new FileReader(); // 创建解析文件流的实例 
    
    fileReader.onload = function (ev) {
        try {
          let data = ev.target.result;
          let workbook = XLSX.read(data, {
            type: 'binary',
          }); // 以二进制流方式读取得到整份excel表格对象
          let persons = []; // 存储获取到的数据
        } catch (e) {
          alert('文件类型不正确');
          console.log('文件类型不正确');
          return;
        }
        
        // 表格的表格范围,可用于判断表头是否数量是否正确
        let fromTo = '';
        
        for (let sheet in workbook.Sheets) { 
            if (workbook.Sheets.hasOwnProperty(sheet)) {
                fromTo = workbook.Sheets[sheet]['!ref']; 
                list =persons.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); 
                //break; // 如果只取第一张表,就取消注释这行 
            } 
        } 
    }
    titleList = Object.keys(list[0] || {});
    
    //然后我们在以二进制的方式打开文件 
    fileReader.readAsBinaryString(files[0]);

}

下载excel文件到本地

/**
 *  注: ! outlist中数据中对象的顺序要和 titleList数组中的字段顺序一样,不然会导致导出的数据混乱
 * @param {*} titleList type Array  excel的表头列表  titleList=['one,‘two']
 * @param {*} outlist  type Array excel内容  outlist=[{},{},{}]
 * @param {*} name  导出文件的名字 string
 */
const downloadExcel=(titleList, outlist, name)=>{
    
    let str = ''; 
    titleList.forEach(element => { 
        str += `<td>${element}</td>`; 
    }); 
    str = `<tr>${str}</tr>`; //具体数值 遍历 
    for (let i = 0; i < outlist.length; i++) { 
        str += '<tr>'; 
        for (const item in outlist[i]) { 
            let cellvalue = outlist[i][item]; //不让表格显示科学计数法或者其他格式 
            //方法1 tr里面加 style="mso-number-format:'\@';"  方法2 是改为 = 'XXXX'格式 
            //如果纯数字且超过15位 /*let reg = /^[0-9]+.?[0-9]*$/; 
            if ((cellvalue.length>15) && (reg.test(cellvalue))){ 
                // cellvalue = '="' + cellvalue + '"'; }*/ 
                //此处用 `取代',具体用法搜索模板字符串 ES6特性 
                str += `<td style="mso-number-format:'\@';">${cellvalue}</td>`; 
                // str+=`<td>${cellvalue}</td>`; } 
                str += '</tr>'; 
             } 
             const worksheet = '导出结果' 
             const uri = 'data:application/vnd.ms-excel;base64,';
         }
    }
    // 下载的表格模板数据
    const template = `<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">
      <head>
        <!--[if gte mso 9]>
        <xml>
          <x:ExcelWorkbook>
            <x:ExcelWorksheets>
              <x:ExcelWorksheet>
                <x:Name>${worksheet}</x:Name>
                <x:WorksheetOptions>
                  <x:DisplayGridlines/>
                </x:WorksheetOptions>
              </x:ExcelWorksheet>
            </x:ExcelWorksheets>
          </x:ExcelWorkbook>
        </xml>
        <![endif]-->
      </head>
      <body>
        <table>${str}</table>
      </body>
    </html>`;

    // 下载模板
    function base64(s) {
      return window.btoa(unescape(encodeURIComponent(s)));
    }

    // 自定义文件名
    const dlink = document.createElement('a');
    dlink.href = uri + base64(template);
    dlink.download = `${name}.xls`;
    document.body.appendChild(dlink);
    dlink.click();

    // 默认使用“下载”为文件名
    // window.location.href = uri + base64(template);
}