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查詢、內容包含圖表、一個工做簿中包含多個表等,使用場景更大。
相關文章
相關標籤/搜索