React項目中,如何把數據導出到Excel文件

寫在前面

不管是作項目仍是本身學習過程當中,咱們可能會遇到導出數據的需求,好比導出數據到Excel文件。react

爲了方便你們的學習和開發,這裏介紹一種導出數據到Excel文件的方法。git

方法簡介

我在這裏使用 exceljs 包來導出數據,若是你有興趣,能夠閱讀一下他們的文檔:github

英文文檔:github.com/exceljs/exc…數組

中文文檔:github.com/exceljs/exc…markdown

若是你想直接看Demo和源碼,能夠直接訪問我在codesandbox部署的代碼:codesandbox.io/s/react-exp…app

導出後的數據以下:oop

方法代碼詳解

1. 引入依賴包和須要導出的數據

首先咱們須要引入依賴包,定義導出Excel文件須要的數據,這裏提供一個對象數組便可,後面的代碼會從該數組中提取須要的數據。實例代碼以下:學習

import ExcelJs from "exceljs";

const mockData = [
  {
    Name: "Allen",
    Gender: "Male",
    Height: "175"
  },
  {
    Name: "Tom",
    Gender: "Male",
    Height: "180"
  },
  {
    Name: "Jane",
    Gender: "Female",
    Height: "170"
  }
];
複製代碼

2. 使用依賴包定義一個對象,後期使用該對象設置參數和導出數據

// 獲取sheet對象,設置當前sheet的樣式
// showGridLines: false 表示不顯示錶格邊框
let workbook = new ExcelJs.Workbook();
let sheetName = "Allen_test.xlsx";
let sheet = workbook.addWorksheet(sheetName, {
	views: [{ showGridLines: false }]
});
// 每個sheet對象對應一個Excel文件中的表,若是你想子一個Excel中顯示多個表,能夠定義多個sheet
// let sheet2 = workbook.addWorksheet("Second sheet", { views: [{ showGridLines: false }] });
複製代碼

3. 獲取表格數據的header信息

咱們在製做Excel表格的時候,通常都須要給每一列設置一個表頭,用來講明這一列展現的是什麼信息,咱們以前只定義了表格數據(前面的對象數組),這裏根據表格數據,獲取對應的表頭信息:優化

let columnArr = [];
for (let i in mockData[0]) {
  let tempObj = { name: "" };
  tempObj.name = i;
  columnArr.push(tempObj);
}
複製代碼

4. 設置表格頂部的信息及樣式

在表格中,頂部能夠展現該表格的標題,說明,注意事項等信息。如上圖中的「This is the header text」 和「As of: 07/09/2021」。spa

咱們可使用以下代碼進行設置頂部信息,設置過程當中,能夠定義一個起始單元格,而後從該單元格開始,根據columns和rows數組,以此向右和向下的單元格中進行繪製。

sheet.addTable({
  name: `Header`,
  ref: "A1", // 頭部信息從A1單元格開始顯示
  headerRow: true,
  totalsRow: false,
  style: {
    theme: "",
    showRowStripes: false,
    showFirstColumn: true,
    width: 200
  },
  columns: [{ name: "This is the header text" }],  // 若是傳遞多個數組元素,會以此在B1, C3...單元格中繪製
  rows: [[`As of: 07/09/2021`]]   // 若是傳遞多個數組元素,會以此在A2, A3...單元格中繪製
});
複製代碼

5. 設置表格的主要數據部分

頂部數據繪製完成以後,下面繼續繪製主題的數據部分,這是最關鍵的,咱們導出Excel文件就是爲了導出這些數據嘛。

// 設置表格的主要數據部分
let headerName = "RequestsList";
sheet.addTable({
  name: headerName,
  ref: "A5", // 主要數據從A5單元格開始
  headerRow: true,
  totalsRow: false,
  style: {
    theme: "TableStyleMedium2",
    showRowStripes: false,
    width: 200
  },
  columns: columnArr ? columnArr : [{ name: "" }],  // 把以前定義的表頭數據傳遞進來
  rows: mockData.map((e) => {
    let arr = [];
    for (let i in e) {
      arr.push(e[i]);
    }
    return arr;
  })
});
複製代碼

6. 美化數據部分的樣式

如今數據能夠正常導出了,可是導出的數據樣式是比較醜的,能夠參考一下代碼,優化這部分的樣式。對代碼不明白能夠閱讀註釋。

// 設置單元格的文字樣式
sheet.getCell("A1").font = { size: 20, bold: true };

// 設置每一列的寬度
sheet.columns = sheet.columns.map((e) => {
  const expr = e.values[5];
  switch (expr) {
    case "Name":
      return { width: 50 };
    case "Gender":
      return { width: 40 };
    case "Height":
      return { width: 30 };
    default:
      return { width: 20 };
  }
});

const table = sheet.getTable(headerName);
for (let i = 0; i < table.table.columns.length; i++) {
  // 表格主體數據是從A5開始繪製的,一共有三列。這裏是獲取A5到,B5,C5單元格,定義表格的頭部樣式
  sheet.getCell(`${String.fromCharCode(65 + i)}5`).font = { size: 12 };
  sheet.getCell(`${String.fromCharCode(65 + i)}5`).fill = {
    type: "pattern",
    pattern: "solid",
    fgColor: { argb: "c5d9f1" }
  };

  // 獲取表格數據部分,定義其樣式
  for (let j = 0; j < table.table.rows.length; j++) {
    let rowCell = sheet.getCell(`${String.fromCharCode(65 + i)}${j + 6}`);
    rowCell.alignment = { wrapText: true };
    rowCell.border = {
      bottom: {
        style: "thin",
        color: { argb: "a6a6a6" }
      }
    };
  }
}
table.commit();
複製代碼

7. 將數據導出Excel,自動下載到本地

如今Excel已經繪製完成了,咱們須要把數據導出到本地,代碼以下,很是簡單:

// 定義下載文件的方法
const writeFile = (fileName, content) => {
  const link = document.createElement("a");
  const blob = new Blob([content], {
    type: "application/vnd.ms-excel;charset=utf-8;"
  });
  link.download = fileName;
  link.href = URL.createObjectURL(blob);
  link.click();
};

// 表格的數據繪製完成,定義下載方法,將數據導出到Excel文件
workbook.xlsx.writeBuffer().then((buffer) => {
  writeFile(sheetName, buffer);
});
複製代碼

代碼總覽

到這裏就完成了導出Excel的全部工做,這裏列出全部代碼,方便你進一步參考。

若是你想設置表格的其餘屬性,能夠查看官方文檔,我認爲是很是詳細的。

英文文檔:github.com/exceljs/exc…

中文文檔:github.com/exceljs/exc…

import React from "react";
import ExcelJs from "exceljs";

const mockData = [
  {
    Name: "Allen",
    Gender: "Male",
    Height: "175"
  },
  {
    Name: "Tom",
    Gender: "Male",
    Height: "180"
  },
  {
    Name: "Jane",
    Gender: "Female",
    Height: "170"
  }
];

const ExportToExcel = () => {
  const exportToExcel = (data) => {
    let sheetName = "Allen_test.xlsx";
    let headerName = "RequestsList";

    // 獲取sheet對象,設置當前sheet的樣式
    // showGridLines: false 表示不顯示錶格邊框
    let workbook = new ExcelJs.Workbook();
    let sheet = workbook.addWorksheet(sheetName, {
      views: [{ showGridLines: false }]
    });
    // let sheet2 = workbook.addWorksheet("Second sheet", { views: [{ showGridLines: false }] });

    // 獲取每一列的header
    let columnArr = [];
    for (let i in data[0]) {
      let tempObj = { name: "" };
      tempObj.name = i;
      columnArr.push(tempObj);
    }

    // 設置表格的頭部信息,能夠用來設置標題,說明或者注意事項
    sheet.addTable({
      name: `Header`,
      ref: "A1", // 頭部信息從A1單元格開始顯示
      headerRow: true,
      totalsRow: false,
      style: {
        theme: "",
        showRowStripes: false,
        showFirstColumn: true,
        width: 200
      },
      columns: [{ name: "This is the header text" }, { name: "Hahaha" }],
      rows: [[`As of: 07/09/2021`], [`Allen`]]
    });

    // 設置表格的主要數據部分
    sheet.addTable({
      name: headerName,
      ref: "A5", // 主要數據從A5單元格開始
      headerRow: true,
      totalsRow: false,
      style: {
        theme: "TableStyleMedium2",
        showRowStripes: false,
        width: 200
      },
      columns: columnArr ? columnArr : [{ name: "" }],
      rows: data.map((e) => {
        let arr = [];
        for (let i in e) {
          arr.push(e[i]);
        }
        return arr;
      })
    });

    sheet.getCell("A1").font = { size: 20, bold: true }; // 設置單元格的文字樣式

    // 設置每一列的寬度
    sheet.columns = sheet.columns.map((e) => {
      const expr = e.values[5];
      switch (expr) {
        case "Name":
          return { width: 50 };
        case "Gender":
          return { width: 40 };
        case "Height":
          return { width: 30 };
        default:
          return { width: 20 };
      }
    });

    const table = sheet.getTable(headerName);
    for (let i = 0; i < table.table.columns.length; i++) {
      // 表格主體數據是從A5開始繪製的,一共有三列。這裏是獲取A5到,B5,C5單元格,定義表格的頭部樣式
      sheet.getCell(`${String.fromCharCode(65 + i)}5`).font = { size: 12 };
      sheet.getCell(`${String.fromCharCode(65 + i)}5`).fill = {
        type: "pattern",
        pattern: "solid",
        fgColor: { argb: "c5d9f1" }
      };

      // 獲取表格數據部分,定義其樣式
      for (let j = 0; j < table.table.rows.length; j++) {
        let rowCell = sheet.getCell(`${String.fromCharCode(65 + i)}${j + 6}`);
        rowCell.alignment = { wrapText: true };
        rowCell.border = {
          bottom: {
            style: "thin",
            color: { argb: "a6a6a6" }
          }
        };
      }
    }
    table.commit();

    const writeFile = (fileName, content) => {
      const link = document.createElement("a");
      const blob = new Blob([content], {
        type: "application/vnd.ms-excel;charset=utf-8;"
      });
      link.download = fileName;
      link.href = URL.createObjectURL(blob);
      link.click();
    };

    // 表格的數據繪製完成,定義下載方法,將數據導出到Excel文件
    workbook.xlsx.writeBuffer().then((buffer) => {
      writeFile(sheetName, buffer);
    });
  };

  return (
    <button
      onClick={() => {
        exportToExcel(mockData);
      }}
    >
      Export to Excel
    </button>
  );
};

export default ExportToExcel;
複製代碼
相關文章
相關標籤/搜索