- 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]);
- }
定义方法后在浏览器中报了如下错误:
- 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 配置:
- externals: [
- {
- './cptable': 'var cptable',
- '../xlsx.js': 'var _XLSX'
- }
- ]
保存并重新编译, 浏览器又抛出如下错误:
The externals config must be Plain Object or Function, but got [object Object]
"externals 配置项必须为纯对象或函数, 但是却得到了对象形式的数组", 所以原因是 externals 的格式不对:
externals 配置支持三种形式, 分别是 Array,Object 和 Reg, 上述的配置项内容是一个对象, 所以应该为用 Object 形式, 所以只要把外面的中括号去掉就可以了:
- externals: {
- './cptable': 'var cptable',
- '../xlsx.js': 'var _XLSX'
- }
更多关于 webpack externals 配置的学习, 可以参考:[webpack externals 深入理解 https://segmentfault.com/a/1190000012113011 ]
测试
运行代码, 在浏览器中打开页面显示如下:
点击 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;
- }
来源: https://www.cnblogs.com/wx1993/p/9792716.html