React读取Excel——js-xlsx 插件的使用

介绍

SheetJS js-xlsx 是一款可以读写多种格式表格的插件,浏览器支持良好,而且能在多个语言平台上使用,目前在 github 上有 12602 个 star,前端

恰好项目中遇到了前端解析 excel 的需求,因此就尝试使用了一下,这里将使用方法和遇到的问题简单记录一下。node

插件地址: GitHub地址react

使用

1. 安装依赖

进入项目文件夹,安装 xlsxwebpack

npm install xlsx
复制代码

2. 在项目中引入

import * as XLSX from 'xlsx';
复制代码

3. 定义上传 input

<input type='file' accept='.xlsx, .xls' onChange={this.onImportExcel} />
复制代码

accept 属性定义了上传文件支持的类型,onChange 操做中的 importExcel 方法定义了上传文件时执行的操做。git

4. 定义获取和解析 excel 对象的方法

onImportExcel = file => {
	    // 获取上传的文件对象
	    const { files } = file.target;
	    // 经过FileReader对象读取文件
	    const fileReader = new FileReader();
	    fileReader.onload = event => {
	      try {
	        const { result } = event.target;
	        // 以二进制流方式读取获得整份excel表格对象
	        const workbook = XLSX.read(result, { type: 'binary' });
	        let data = []; // 存储获取到的数据
	        // 遍历每张工做表进行读取(这里默认只读取第一张表)
	        for (const sheet in workbook.Sheets) {
	          if (workbook.Sheets.hasOwnProperty(sheet)) {
	            // 利用 sheet_to_json 方法将 excel 转成 json 数据
	            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
	            // break; // 若是只取第一张表,就取消注释这行
	          }
	        }
	        console.log(data);
	      } catch (e) {
	        // 这里能够抛出文件类型错误不正确的相关提示
	        console.log('文件类型不正确');
	        return;
	      }
	    };
	    // 以二进制方式打开文件
	    fileReader.readAsBinaryString(files[0]);
	  }
复制代码

定义方法后在浏览器中报了以下错误: github

Failed to compile
./node_modules/xlsx/dist/cpexcel.js
Module not found: Can't resolve './cptable' in '/Users/wangxi/Desktop/Code/admin/node_modules/xlsx/dist'
复制代码

大意是说在 cpexcel.js 文件中找不到 ./captable 模块,因而在 github 上的 issue 中输入问题,发现问题仍是挺广泛的,官方给出的解决方案以下: 即在 webpack 配置文件中添加以下 external 配置:web

externals: [
    {
        './cptable': 'var cptable',
        '../xlsx.js': 'var _XLSX'
    }
] 
复制代码

保存并从新编译,浏览器又抛出以下错误:npm

The externals config must be Plain Object or Function, but got [object Object]
复制代码

"externals 配置项必须为纯对象或函数,可是却获得了对象形式的数组",因此缘由是 externals 的格式不对:json

externals 配置支持三种形式,分别是 Array、Object 和 Reg,上述的配置项内容是一个对象,因此应该为用 Object 形式,因此只要把外面的中括号去掉就能够了:segmentfault

externals: {
    './cptable': 'var cptable',
    '../xlsx.js': 'var _XLSX'
 }
复制代码

更多关于 webpack externals 配置的学习,能够参考:【webpack externals 深刻理解】

测试

运行代码,在浏览器中打开页面显示以下: 点击 Choose File,在本地选择一个内容以下的 excel 文件: 点击肯定,上传后在浏览器控制台查看打印信息: 能够发现,excel 已经读取成功而且转换成了 json 格式的数据,以后就能够对 json 数据进行分析和处理啦。

完善

  1. 使用原生 input 标签显示效果比较粗糙,由于对组件简单地进行了样式上的美化,效果以下:

  2. 针对文件上传和读取结果分别作了对应的提示(这里使用 ant design 中的 message 组件)

demo 完整代码以下:

// excel.js
import React, { Component } from 'react';
import { Button, Icon, message } from 'antd';
import * as XLSX from 'xlsx';
import styles from './index.less';

class Excel extends Component {
  onImportExcel = file => {
    // 获取上传的文件对象
    const { files } = file.target;
    // 经过FileReader对象读取文件
    const fileReader = new FileReader();
    fileReader.onload = event => {
      try {
        const { result } = event.target;
        // 以二进制流方式读取获得整份excel表格对象
        const workbook = XLSX.read(result, { type: 'binary' });
         // 存储获取到的数据
        let data = [];
        // 遍历每张工做表进行读取(这里默认只读取第一张表)
        for (const sheet in workbook.Sheets) {
          // esline-disable-next-line
          if (workbook.Sheets.hasOwnProperty(sheet)) {
            // 利用 sheet_to_json 方法将 excel 转成 json 数据
            data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
            // break; // 若是只取第一张表,就取消注释这行
          }
        }
        // 最终获取到而且格式化后的 json 数据
        message.success('上传成功!')
        console.log(data);
      } catch (e) {
        // 这里能够抛出文件类型错误不正确的相关提示
        message.error('文件类型不正确!');
      }
    };
    // 以二进制方式打开文件
    fileReader.readAsBinaryString(files[0]);
  }
  render() {
    return (
      <div style={{ marginTop: 100 }}>
        <Button className={styles['upload-wrap']}>
          <Icon type='upload' />
          <input className={styles['file-uploader']} type='file' accept='.xlsx, .xls' onChange={this.onImportExcel} />
          <span className={styles['upload-text']}>上传文件</span>
        </Button>
        <p className={styles['upload-tip']}>支持 .xlsx、.xls 格式的文件</p>
      </div >
    );
  }
}

export default Excel;
复制代码
// index.less
.upload-wrap {
  display: inline-block;
  position: relative;
  width: 124px;
  padding: 3px 5px;
  overflow: hidden;
}

.file-uploader {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  outline: none;
  opacity: 0;
  background-color: transparent;
}

.upload-text {
  display: inline-block;
  margin-left: 5px;
}

.upload-tip {
  display: inline-block;
  margin-left: 10px;
  color: #999;
}
复制代码
相关文章
相关标签/搜索