csv與xlsx導出


一.csv與xlsx格式基本介紹
 
    csv即comma seperate values - 逗號分隔值,文件以純文本形式來存儲表格數據,它可以由任意數目的記錄組成,記錄之間通過某種換行符來分隔如 ’\r\n’,而每條記錄由字段組成,字段之間的分隔符一般通過逗號來分隔即  ’,’,因此csv是一種比較簡單的文件格式,在編輯器中打開如下所示
   
    
    xlsx是Microsoft Excel 2007之后的擴展名,其本身是一種新的基於XML的壓縮文件,相對於傳統的xls文件占用空間更小,在后綴名之后添加.zip即可解壓縮,如下所示:
 
二. 前端導出csv格式文件
 
     csv格式 - csv格式本身比較簡單,所以前端只需要對數據按照格式(記錄之間通過換行符分隔,記錄中的字段之間通過逗號分隔)進行處理即可,一般不需要引入額外的庫,基本的使用方法如下:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
<button id="btn">下載</button>
<a id="downloadCsv"></a>
<script>
const btn = document.getElementById('btn');
btn.addEventListener('click', function () {
  let headers = ['時段', '2018-08-01', '2018-08-01', '2018-08-01'];
  let dataSource = [
    ['00時', 345, 65, 8],
    ['06時', 23, 56, 89],
    ['12時', 21, 4, 7],
    ['18時', 67, 9, 34],
  ];
  let csv = '\uFEFF';
  csv += headers.join(',') + '\r\n';
  dataSource.forEach( (record) => {
    csv += (record.join(',') + '\r\n');
  });
  const blob = new window.Blob([csv], { type: 'text/csv,charset=UTF-8' });
  const downloadCsv = document.getElementById('downloadCsv');
  downloadCsv.href = window.URL.createObjectURL(blob);
  downloadCsv.click();
  window.URL.revokeObjectURL(blob);
})
</script>
</body>
</html>
 
值得注意的有以下幾點:
  1. 在csv文件的開頭需要添加BOM,這里使用\uFEFF表示此文件使用UTF-16進行編碼
  2. 在創建Blob時,第一個參數必須是數組
  3. 在下載完成最后,需要及時清除Blob占用的內存
可以在 https://jsfiddle.net/veh7asqk/1/查看效果
 
 
 
三.前端導出excel格式文件
    excel格式文件比較復雜,在實現上一般可以引用第三方庫 https://github.com/sheetjs/js-xlsx,它可以簡化xlsx文件的各種操作:讀取、預覽、web sql查詢、編輯、導出,可以訪問 https://sheetjs.com/opensource查看更多;這里主要陳述如何導出xlsx類型的文件
    打開一個excel表,可以發現其主要的格式如下:
      A     B      C     D      E
1    A1   B1    C1   D1    E1
2    A2   B2    C2   D2    E2
3    A3   B3    C3   D3    E3
4    A4   B4    C4   D4    E4
    所以前端對於數據的處理過程就是將數據按照上面的格式進行匹配,一個簡單的例子如下所示:
 
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <!-- XLSX -->
  <script src=" https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
  <!-- fileSaver saveAs -->
</head>
<body>
  <button id="btn"/>下載</button>
  <script>
  function createWorkSheet (XLSX, tableCols, tableData) {
    var EMPTY_XSLX_BASE64 = '';
    var workbook = XLSX.read(EMPTY_XSLX_BASE64, { type: 'base64' });
    var sheets = {
    Sheet1: {},
    };
    var sheetNames = ['Sheet1'];
    var idx = 0;
    var colNum = tableCols.length;
    var rowNum = tableData.length;
    // 輸入表頭
    for (idx = 0; idx < colNum; idx++) {
      var title = tableCols[idx];
      sheets.Sheet1[String.fromCharCode(65 + idx) + '1'] = {
        t: 's',
        v: title.name,
      };
    }
    // 插入每行的數據值
    for (let n = 0; n < rowNum; n++) {
      let key = tableCols[0].key;
      let v = tableData[n][key] + '';
      sheets.Sheet1[String.fromCharCode(65) + (n + 2)] = {
        t: 'n',
        v: v,
      };
    }
    for (let n = 0; n < rowNum; n++) {
      let key = tableCols[1].key;
      let v = tableData[n][key] + '';
      sheets.Sheet1[String.fromCharCode(65 + 1) + (n + 2)] = {
        t: 's ,  
        v: v,
      }
    }
    for (let n = 0; n < rowNum; n++) {
      for (idx = 2; idx < colNum; idx++) {
        let key = tableCols[idx].key;
        let v = tableData[n][key];
          sheets.Sheet1[String.fromCharCode(65 + idx) + (n + 2)] = {
            t: 'n',
            v: v,
        };
      }
    }
    sheets.Sheet1['!ref'] = 'A1:' + String.fromCharCode(65 + colNum - 1) + (rowNum + 1);
    workbook.Sheets = sheets;
    workbook.SheetNames = sheetNames;
    return workbook;
  }
 
  function a2ab (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;
  }
 
  const headers = [
    {
      name: '序號',
      key: 'No',
    },
    {
      name: '應用名稱',
      key: 'AppName',
    },
    {
      name: '日活躍用戶數(萬)',
      key: 'DAU',
    },
    {
      name: '月數(萬)',
      key: 'MAU',
    }
  ];
 
  const dataSource = [
    {
      No: 1,
      AppName:   ‘a',
      DAU: 17900,
      MAU: 50000,
    },
    {
      No: 2,
      AppName:   ‘b',
      DAU: 12500,
      MAU: 40000,
    },
    {
      No: 3,
      AppName:   ‘c',
      DAU: 4400,
      MAU: 15000,
    },
    {
      No: 4,
      AppName:   ‘d',
      DAU: 4800,
      MAU: 17000,
    },
  ];
 
  function download (fileName) {
    let wb = createWorkSheet(XLSX, headers, dataSource);
    let wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: true, type: 'binary'});
    saveAs(new Blob([a2ab(wbout)], {type: 'application/octet-stream'}), fileName);
  }
  let btn = document.getElementById('btn');
  btn.addEventListener('click', function () {
  const fileName = 'example.xlsx';
    download(fileName);
  })
</script>
</body>
</html>
這里導出的是一個工作簿,工作簿中包含多個表,所以通過這種方式可以輸出多個表從而方便用戶查看;另外,在格式化過程中可以針對導出表格式需要來規定每個字段的type來做類型的限定,保證類型的確定性以及減少前端相應工作量;
可以在 https://jsfiddle.net/q8dgvL3w/2/查看效果
 
 
四. 總結
    csv文件格式簡單,在前端實現上相對簡單,無需引入額外的庫文件,對於一般的表格導出均可滿足需求;xlsx文件格式復雜,需要引用第三方庫文件進行處理,其可以文件預覽、類型限定、SQL查詢、內容包含圖表、一個工作簿中包含多個表等,使用場景更大。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM