☀️学习系列:React实现excel导入导出

10,805 阅读4分钟

说实话 公司 闲着很无聊 不知道干嘛 写写博客记录一下

一、环境搭建

环境搭建暂时不多说本人是使用自己的简易脚手架搭建的,与excel无关的代码很多,建议大家还是使用自己搭建的脚手架好一点。这是我的github项目地址掘金Demo。自行百度create-react-app等官方推荐的脚手架吧。这里只对excel核心功能进行讲解。

二、excel导入

1.新建tsx文件

其实本人不太熟悉ts,所以对于tsx就当做乐呵乐呵。空有ts的后缀,实际上是js(语法)。总共就一个页面,页面地址tsx文件

2.引用antd部分组件

为了简洁大方明了 我们这里直接引用了antd的部分组件

import { Button,Table,Upload } from 'antd';

<Upload {...uploadProps}>
    <Button type="primary" >Excel导入</Button>
</Upload>

<Button type="primary" onClick={this.handleExportAll}>Excel导出数据</Button>

<Button type="primary" onClick={this.handleExportDocument}>Excel导出格式文件</Button>

<Table columns={columns} dataSource={data} bordered></Table>

3.核心插件xlsx介绍

1.安装

npm install xlsx --save-dev

2.使用api介绍

1.XLSX.read(data,type)

尝试解析data数据 解析的类型

2.workbook.Sheets[workbook.SheetNames[0]]

是工作簿中的工作表的有序列表

3.XLSX.utils.sheet_to_json(first_worksheet, { header: 1 });

将工作簿对象转换为JSON对象数组

更多api可查看 xlsx git 官网

3.导入实现

1.首先react render部分写入antd组件

/*组件部分*/
<Upload {...uploadProps}>
    <Button type="primary" >Excel导入</Button>
</Upload>
/*js部分*/
const uploadProps={
    onRemove: file => {
        this.setState(state => ({
            data:[],
            fileList:[]
        }));
    },
    accept: ".xls,.xlsx,application/vnd.ms-excel",
    beforeUpload: (file) => {
        const _this=this;
        const f = file;
        const reader = new FileReader();
        reader.onload = function (e) {
        const datas = e.target.result;
        const workbook = XLSX.read(datas, {
            type: 'binary'
        });//尝试解析datas
        const first_worksheet = workbook.Sheets[workbook.SheetNames[0]];//是工作簿中的工作表的有序列表
        const jsonArr = XLSX.utils.sheet_to_json(first_worksheet, { header: 1 });//将工作簿对象转换为JSON对象数组
         _this.handleImpotedJson(jsonArr, file);
        };
        reader.readAsBinaryString(f);
        return false;
    },
    fileList,
};
  1. onRemove是当移除文件时触发的操作,这里的操作就是清除数据。
  2. accept是接受上传的文件类型。
  3. beforeUpload是上传文件之前的钩子,参数为上传的文件,若返回 false 则停止上传,此处只是进行数据的转化,没有真实上传。
  4. fileList是文件列表。

更多api请看antd upload官网

2.核心代码理解

总共就那么几行

const f = file;
const reader = new FileReader();
reader.onload = function (e) {
    const datas = e.target.result;
    const workbook = XLSX.read(datas, {
        type: 'binary'
    });//尝试解析datas

    const first_worksheet = workbook.Sheets[workbook.SheetNames[0]];//是工作簿中的工作表的有序列表
    const jsonArr = XLSX.utils.sheet_to_json(first_worksheet, { header: 1 });//将工作簿对象转换为JSON对象数组
    _this.handleImpotedJson(jsonArr, file);
};
reader.readAsBinaryString(f);

1 .首先FileReader对象实例化一个file对象

2 .在file对象onload事件里进行处理

3 .使用XLSX.read解析data

4 .first_worksheet是解析的数据

5 .XLSX.utils.sheet_to_json(first_worksheet, { header: 1 });将工作簿对象转化为JSON对象

6 .handleImpotedJson方法可以将json对象进行一系列操作 转化到表格里

handleImpotedJson = (array, file) => {
       
        const header = array[0];//头部数据 ["姓名",...]
        const entozh = this.formatTitleOrFileld('title', 'dataIndex');//将表字段数组形式转化为对象形式,如:{"姓名":"name",...}
        const firstRow = header.map(item => entozh[item]);//可以获取到行属性 ["name",...]

        const newArray = [...array];

        newArray.splice(0, 1);//去除表头

        const json = newArray.map((item, index) => {
            const newitem = {};
            item.forEach((im, i) => {
                const newKey = firstRow[i] || i;
                newitem[newKey] = im
            })
            return newitem;
        });//将存在表头定义字段的值赋值

        const formatData = json.map(item => ({
            name: item.name,
            age: item.age,
            address: item.address,
        }))//筛选出自己需要的属性

        this.setState({ data: formatData, fileList: [file] });

        return formatData;
}

formatTitleOrFileld = (a, b) => {
        const entozh = {};
        this.state.columns.forEach(item => {
            entozh[item[a]] = item[b]
        })
        return entozh;
}

3.效果图

三、excel导出

1.excel导出表格数据

1.先上代码

<Button type="primary" onClick={this.handleExportAll}>Excel导出数据</Button>

handleExportAll = (e) => {
        const entozh = {
          "name":"姓名",
          "age":"年龄",
          "address":"地址"
        }

        const nowdata = this.state.data;

        const json = nowdata.map((item) => {
          return Object.keys(item).reduce((newData, key) => {
            const newKey = entozh[key] || key
            newData[newKey] = item[key]
            return newData
          }, {})
        });
  
  
        const sheet = XLSX.utils.json_to_sheet(json);
 
        this.openDownloadDialog(this.sheet2blob(sheet,undefined), `全部信息.xlsx`);
   
}
openDownloadDialog = (url, saveName) => {
        if (typeof url == 'object' && url instanceof Blob) {
          url = URL.createObjectURL(url); // 创建blob地址
        }
        var aLink = document.createElement('a');
        aLink.href = url;
        aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
        var event;
        if (window.MouseEvent) event = new MouseEvent('click');
        else {
          event = document.createEvent('MouseEvents');
          event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        }
        aLink.dispatchEvent(event);
}
sheet2blob = (sheet, sheetName) => {
        sheetName = sheetName || 'sheet1';
        var workbook = {
          SheetNames: [sheetName],
          Sheets: {}
        };
        workbook.Sheets[sheetName] = sheet; // 生成excel的配置项
  
        var wopts = {
          bookType: 'xlsx', // 要生成的文件类型
          bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
          type: 'binary'
        };
        var wbout = XLSX.write(workbook, wopts);
        var blob = new Blob([s2ab(wbout)], {
          type: "application/octet-stream"
        }); // 字符串转ArrayBuffer
        function s2ab(s) {
          var buf = new ArrayBuffer(s.length);
          var view = new Uint8Array(buf);
          for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
          return buf;
        }
  
        return blob;
}

2.核心代码讲解

1.XLSX.utils.json_to_sheet

字面意思,可以将工作簿对象转化为json对象

2.openDownloadDialog

此方法创建了a标签 利用a标签的download属性进行下载文件

3.sheet2blob

可以将工作簿对象转化为我们需要的

3.效果图

2.表格导出标准格式文件

其实和上面一样 唯独把表头数据保存下来就行唯一的区别就是

let nowdata = [
            {"name":""},
            {"age":""},
            {"address":""},
            
];

将state中的data对象转化为空数组形式即可。

有不懂的可以加我微信询问我