ExcelJS 在前端浏览器中读取 Excel 文件内容 #142

@Dream4ever

Description

需求描述

实现基本功能

Google 关键字 exceljs parse xlsx browser ,第一个链接 how to read xlsx file in browser with exceljs? · Issue #832 中就有具体的代码。

handleChange(e) {
  this.file = e.target.files[0]
handleImport() {
  const wb = new Excel.Workbook();
  const reader = new FileReader()
  reader.readAsArrayBuffer(this.file)
  reader.onload = () => {
    const buffer = reader.result;
    wb.xlsx.load(buffer).then(workbook => {
      console.log(workbook, 'workbook instance')
      workbook.eachSheet((sheet, id) => {
        sheet.eachRow((row, rowIndex) => {
          console.log(row.values, rowIndex)

注意:在官方文档中,有下面这么一段代码:

// read from a file
const workbook = new Excel.Workbook();
await workbook.xlsx.readFile(filename);
// ... use workbook

上面这段代码会用到 Node.js 的专属 API,前端无法使用,如果要在前端加载 Excel 文件的内容,就得像再之前那段代码那样,用 workbook.xlsx.load() 方法而不是 readFile() 方法。

相关讨论见官方 issue:[BUG] readFile error #1168

异步回调同步化

上面的代码不够优雅,于是 Google promisify filereader onload,Stack Overflow 果然再次没有让我失望,Javascript Promises with FileReader() 这个链接中给出了下面的代码:

function readFile(file){
  return new Promise((resolve, reject) => {
    var fr = new FileReader();  
    fr.onload = () => {
      resolve(fr.result);
    fr.onerror = reject;
    fr.readAsText(file.blob);
  });

但是上面的代码似乎有误,修改之后用如下代码:

readFile (file) {
  return new Promise((resolve, reject) => {
    var fr = new FileReader()
    fr.onload = () => {
      resolve(fr.result)
    fr.onerror = reject
    fr.readAsArrayBuffer(file)

将其引入 Vue 中之后,只需要下面三行代码,就可以用同步的形式来异步读取 Excel 文件内容了:

const buffer = await this.readFile(this.fileList[0])
const workbook = new ExcelJS.Workbook()
await workbook.xlsx.load(buffer)