前端js實現導出大量數據的excel文件


文章原文: https://www.cnblogs.com/yalong/p/15095651.html

前端導出excel文件,最開始使用xlsx, react 環境下代碼如下所示

import XLSX from 'xlsx';
const exportExcel = (headers, data, fileName) => {
  const _headers = headers
    .map((item, i) =>
      Object.assign(
        {},
        {  
          key: item.key || item.dataIndex,
          title: item.title,
          position: String.fromCharCode(65 + i) + 1,
        },
      ),
    )
    .reduce(
      (prev, next) =>
        Object.assign({}, prev, {
          [next.position]: { key: next.key, v: next.title },
        }),
      {},
    );

  const _data = data
    .map((item, i) =>
      headers.map((key, j) =>
        Object.assign(
          {},
          {
            content: item[key.key || key.dataIndex],
            position: String.fromCharCode(65 + j) + (i + 2),
          },
        ),
      ),
    )
    // 對剛才的結果進行降維處理(二維數組變成一維數組)
    .reduce((prev, next) => prev.concat(next))
    // 轉換成 worksheet 需要的結構
    .reduce(
      (prev, next) =>
        Object.assign({}, prev, {
          [next.position]: { v: next.content, t: typeof next.content === 'number' ? 'n' : undefined },
        }),
      {},
    );

  // 合並 headers 和 data
  const output = Object.assign({}, _headers, _data);
  // 獲取所有單元格的位置
  const outputPos = Object.keys(output);
  // 計算出范圍 ,["A1",..., "H2"]
  const ref = `${outputPos[0]}:${outputPos[outputPos.length - 1]}`;

  // 構建 workbook 對象
  // TODO: 這里固定設置了前8個col的寬度,不太適用於通用util
  const wb: WorkBook = {
    SheetNames: ['mySheet'],
    Sheets: {
      mySheet: Object.assign({}, output, {
        '!ref': ref,
        '!cols': [
          { wpx: 45 },
          { wpx: 100 },
          { wpx: 200 },
          { wpx: 80 },
          { wpx: 150 },
          { wpx: 100 },
          { wpx: 300 },
          { wpx: 300 },
        ],
      }),
    },
  };

  // 導出 Excel
  XLSX.writeFile(wb, fileName, {
    ignoreEC: true,
  });
};

使用方式如下:

const initalColumns = [
  {
      title: '名字',
      dataIndex: 'name',
      key: 'name',
    },
   
      title: '年齡',
      dataIndex: 'age',
      key: 'age',
    },
 ]
 const initList = [
    {
      name: '張三',
      age: 18,
    },
    {
      name: '李四',
      age: 20,
    },
  ];
 exportExcel(initalColumns, initList, '統計表格.xlsx')

上面這種方式在數據量比較少的時候,沒問題, 300條以內都可以接受, 但是數據量大了以后,比如上千條數據,這時候,就很卡,有時候瀏覽器會崩潰
為了解決大量數據的導出excel問題,通過查閱資料,發現可以把文件導出成csv格式的文件,這時候導出時間就降低了很多

excel 跟csv文件格式對比如下:


簡單來說,就是

  1. csv格式的文件是文本格式,體積更小,文件解析快,可以通過記事本、office excel等打開
  2. excel格式的文件功能多,但是體積大,文件解析慢
  3. 同樣的數據,excel格式體積是280KB, csv格式體積只有80KB
  4. csv格式的文件用office excel 打開 跟 excel 文件效果是一樣的

導出csv格式文件代碼如下:

const exportExcel2 = (initColumns: any, initList: any, name: string) => {
  let str: string = '';
  let arr: string[] = [];
  let keyArr: string[] = [];
  initColumns.forEach((item) => {
    arr.push(item['title']);
    keyArr.push(item['key']);
  });
  str = arr.join(',') + '\n';
  for (let i = 0; i < initList.length; i++) {
    let subArr = keyArr.map((item) => {
      let temp = initList[i][item] === undefined ? '' : initList[i][item] + ''; // 轉成字符串
      // 下面解決中文亂碼問題 會把空格轉成 #, 這里把空格轉成 \xa0 就不會有這個問題了
      return temp ? temp.replaceAll(/\s+/g, '\xa0') : '';
    });
    let subStr = subArr.join('\t,');
    subStr += '\n';
    str += subStr;
  }
  // \ufeff 解決中文亂碼問題
  var blob = new Blob(['\ufeff', str], { type: 'text/plain' });
  let object_url = window.URL.createObjectURL(blob);
  let link = document.createElement('a');
  link.href = object_url;
  link.download = `${name}.csv`;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
};

使用方式如下:

const initalColumns = [
  {
      title: '名字',
      dataIndex: 'name',
      key: 'name',
    },
   
      title: '年齡',
      dataIndex: 'age',
      key: 'age',
    },
 ]
 const initList = [
    {
      name: '張三',
      age: 18,
    },
    {
      name: '李四',
      age: 20,
    },
  ];
 exportExcel2(initalColumns, initList, '統計表格')

經測試 1萬條數據可以在3秒內下載完畢,速度還可以了。

最后可以考慮把該函數封裝成npm包,以后用的時候更方便了, 怎么把js函數封裝成npm包教程看這里: https://www.cnblogs.com/yalong/p/15214644.html


免責聲明!

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



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