好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

React如何接收excel文件下载导出功能封装

React接收excel文件下载导出功能封装

因为最近项目又需求要导出excel,所以封装了这部分的功能,对fetch的封装做了修改,使之后的调用导出功能更为方便

首先这个项目请求是对fetch进行过封装的 ,如果对fetch有了解的话,我们知道fetch种response返回的是一个实现了Body接口的对象, 所以可以使用Body接口中的方法 json()处理json,blob ()处理成blob文件对象 方法, 所以要先对封装的请求方法做如下修改

export default function request(url, option,noToken = false,type = 'json') { ?
//这是封装request方法 noToken判断是否写代token ?type用来区别 json/blob 这里我们需要下载文件所以传入blob
?? ?...
?? ?.then(response => {
? ? ? ? ? if (newOptions.method === 'DELETE' || response.status === 204) {
? ? ? ? ? ? return response.text();
? ? ? ? ? }
? ? ? ? ? if(type == 'blob') {
? ? ? ? ? ?return ?response.blob(); ?//处理成blob文件类型
? ? ? ? ? }
? ? ? ? ? return response.json();
? ? ? ? })
? ? ?.then(response => {
? ? ? ? if(type == 'blob') {
? ? ? ? return URL.createObjectURL(response); //使用URL.createObjectURL将blob放入一个object'
? ? ? ? ...
? ? ? ? }
? ? ? ?}
?? ?}
}

上面我们通过一个参数,将blob文件处理成url

export async function exportExcel(params) {
? return request(`/api/xxxxx/${params}`,{method: 'GET'} ,false ,'blob' );
} ?

上面就是我们导出文件的请求接口,获得的是一个url,然后我们在effect中接受url

* exportExcel({payload}, {call,put}) {
? try {
? ? const url = yield call(exportExcel, payload); //收到一个url
?? ? let link = document.createElement('a') //创建一个a标签
? ? ?link.style.display = 'none' //不显示
? ? ?link.href = url ?//将地址填入
? ? ?link.setAttribute('download', '表格.xlsx') //设置下载属性,取个文件名
? ? ?document.body.appendChild(link) //添加到页面上
? ? ?link.click() //点击触发下载
? } catch (e) {
? }
},

到这里就是实现了文件的导出,基本原理就是将接受的文件处理成url,用a标签触发下载

其实本来到这里就应该结束了,但是作为一个有原则的程序员, 反复添加a标签显示让我们觉得很不规范, 所以我们来改写成一直复用一个a标签来下载,动态修改url\\现在BasicLayout里加个a标签,因为这个是登陆都最先加载的,保证每个模块都能使用

? ?<a ?
? ?style={{display: 'none'}}?
? ?ref={(link)=> {this.props.dispatch({type: 'global/saveLink', payload: link})}} //这个是用来讲a标签的ref存到redux里,随时可以调用
? ?></a>

**然后我们在modes/global里写两个reducer** 

? reducers: {
? ? saveLink(state, { payload }) {
? ? //保存a标签
? ? ? return {
? ? ? ? ...state,
? ? ? ? link: payload,
? ? ? }
? ? },
? ? exportFile(state, { payload }) {
? ? //设置a标签的地址并触发点击下载
? ? ? state.link.href = payload.url
? ? ? state.link.setAttribute('download',payload.name)
? ? ? state.link.click()
? ? ? return {
? ? ? ? ...state,
? ? ? };
? ? },
}

然后我们在普通的模块中effect调用时只需要这么写

* exportExcel({payload}, {call,put}) {
? try {
? ? const url = yield call(exportExcel, payload); //收到一个url
?? ?yield put({type: 'global/exportFile',payload: {url,name: `表格.xlsx`}}) //设置地址并触发下载?
? } catch (e) {
? }
},

这样写方便了很多 ,其实最好的方式是将这部分代码封装到一个组件中,单独调用,这里就不演示了,写法差不多 

react导出excel文件的几种方式

一共总结了四种方法  前两种适用范围比较广泛 可以适用导出多级表头合并等,第三种方法导出的文件比较中规中矩,但是支持导出多张sheet表。第四种方法导出不推荐使用

1.原生js导出 (带样式)

       

/**
?* ?原生JS导出为excel文件
?*/
export const jsToExcel = (id, name) => {
? ? //window.location.href='<%=basePath%>pmb/excelShowInfo.do';
? ? //获取表格
? ? var exportFileContent = document.getElementById(id).outerHTML;
? ? //设置格式为Excel,表格内容通过btoa转化为base64,此方法只在文件较小时使用(小于1M)
? ? //exportFileContent=window.btoa(unescape(encodeURIComponent(exportFileContent)));
? ? //var link = "data:"+MIMEType+";base64," + exportFileContent;
? ? //使用Blob
? ? var blob = new Blob([exportFileContent], { type: "text/plain;charset=utf-8" }); ? ? ? ? //解决中文乱码问题
? ? blob = new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type });
? ? //设置链接
? ? var link = window.URL.createObjectURL(blob);
? ? var a = document.createElement("a"); ? ?//创建a标签
? ? a.download = name; ?//设置被下载的超链接目标(文件名) ? 建议文件后缀为 .xls
? ? a.href = link; ? ? ? ? ? ? ? ? ? ? ? ? ? ?//设置a标签的链接
? ? document.body.appendChild(a); ? ? ? ? ? ?//a标签添加到页面
? ? a.click(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//设置a标签触发单击事件
? ? document.body.removeChild(a); ? ? ? ? ? ?//移除a标签
}

使用方式   

  

<table id='table_report'>...</table>
?
<div onClick={() => jsToExcel('table_report', '现券交易异常日报.xls')}>导出</div>

如果想导出xlsx格式请参考方法2,方法1仅改文件后缀 不会被Excel识别  但是wps可以

2.使用xlsx导出(此方法导出的excel文件无样式,但导出的文件格式是 xlsx格式) 

首先安装xlsx  : yarn add xlsx

import XLSX from "xlsx"
?
?
/**
?* ?用XLSX导出 (导出无样式)
?*/
export const exportExcel = (id, name) => {
? ? var exportFileContent = document.getElementById(id).cloneNode(true);
? ? var wb = XLSX.utils.table_to_book(exportFileContent, { sheet: "sheet1" });
? ? XLSX.writeFile(wb, name);
}
? ? 

使用方式

  

<table id='table_report'>...</table>
?
<div onClick = {() => exportExcel('table_report', '现券交易异常日报.xlsx')}>导出</div>

3.使用 js-export-excel (可以导出多张sheet表)

首先安装 js-export-excel  : yarn add js-export-excel 

import { Table } from 'antd';
import { columns } from './config';
import ExportJsonExcel from "js-export-excel";
import { PlusCircleOutlined } from '@ant-design/icons';
?
function Tables(props) {
? const { isLoading, viewData, data } = props;
? // data格式
? const data1 = [
? ? {
? ? ? adID: "张三",
? ? ? leaveCount: 26,
? ? ? leaveDuration: 82,
? ? ? leaveType: "调休",
? ? ? name: "张三"
? ? },
? ? {
? ? ? adID: "张三1",
? ? ? leaveCount: 526,
? ? ? leaveDuration: 82,
? ? ? leaveType: "调休",
? ? ? name: "张三1"
? ? },
? ? {
? ? ? adID: "张三1",
? ? ? leaveCount: 26,
? ? ? leaveDuration: 852,
? ? ? leaveType: "调休",
? ? ? name: "张三1"
? ? },
? ? {
? ? ? adID: "张三1",
? ? ? leaveCount: 256,
? ? ? leaveDuration: 82,
? ? ? leaveType: "调休",
? ? ? name: "张三1"
? ? },
? ]
? /**
? ?* ?导出数据
? ?*/
? const handleExportCurrentExcel = (data) => {
? ? let sheetFilter = ["name", "leaveType", "leaveCount", "leaveDuration"];
? ? let sheetFilter2 = ["name", "leaveType", "leaveCount", "leaveDuration"];
? ? let option = {};
? ? option.fileName = '考勤分析结果';
? ? option.datas = [
? ? ? {
? ? ? ? sheetData: data1,
? ? ? ? sheetName: '考勤分析结果',
? ? ? ? sheetFilter: sheetFilter,
? ? ? ? sheetHeader: ['姓名', '类型', '次数', '时长'],
? ? ? ? columnWidths: [10, 10, 10, 10]
? ? ? },
? ? ? {
? ? ? ? sheetData: data1, ?//比较懒得造数据了 ?跟表1数据一样
? ? ? ? sheetName: '考勤分析结果222',
? ? ? ? sheetFilter: sheetFilter2,
? ? ? ? sheetHeader: ['姓名22', '类型22', '次数22', '时长22'],
? ? ? ? columnWidths: [10, 10, 10, 10]
? ? ? },
? ? ];
? ? var toExcel = new ExportJsonExcel(option); //new
? ? toExcel.saveExcel(); //保存
? }
?
? return (
? ? <div>
? ? ? <div className='exportButton' onClick={() => handleExportCurrentExcel(data)}>
? ? ? ? <PlusCircleOutlined className='icon-but' />
? ? ? ? 导出当前数据
? ? ? </div>
? ? ? <Table
? ? ? ? loading={isLoading}
? ? ? ? columns={columns}
? ? ? ? dataSource={viewData}
? ? ? ? pagination={false}
? ? ? />
? ? </div>
? )
}
export default Tables;

4.第四种 使用react-html-table-to-excel   不推荐使用

安装   react-html-table-to-excel : yarn add react-html-table-to-excel

import React, { ?useRef, useEffect } from 'react';
import { Table } from "antd";
import { ?columns } from './config';
import ReactHTMLTableToExcel from 'react-html-table-to-excel';
import styles from './index.module.less';
function StudyExcel() {
?
? ? const data = [
? ? ? ? {
? ? ? ? ? ? key: '0',
? ? ? ? ? ? name: '张三'
? ? ? ? },
? ? ? ? {
? ? ? ? ? ? key: '1',
? ? ? ? ? ? name: '赵四'
? ? ? ? },
? ? ? ? {
? ? ? ? ? ? key: '2',
? ? ? ? ? ? name: '王五'
? ? ? ? },
? ? ? ? {
? ? ? ? ? ? key: '3',
? ? ? ? ? ? name: '齐六'
? ? ? ? }
? ? ];
?
? ? // 用ref来获取组件按钮实例,使用里面的方法
? ? const buttonRef = useRef(null);
?
? ? // 禁止组件按钮的默认点击事件
? ? useEffect(() => {
? ? ? ? const button = document.querySelector('#test-table-xls-button');
? ? ? ? button.style['pointer-events'] = ('none');
? ? }, []);
?
?
? ? // 导出表格
? ? const exportTable = (e) => {
? ? ? ? e.stopPropagation();
? ? ? ? const table = document.getElementsByTagName('table');
? ? ? ? const container = document.querySelector('#hiddenBox');
? ? ? ? const tempTable = document.createElement('table');
? ? ? ? tempTable.appendChild(table[0]);
? ? ? ? tempTable.setAttribute('id', 'table-to-xls'); ? ? ? ? ? ? ? ? ? ?// 给table添加id,值与按钮上的table字段对应
? ? ? ? container.appendChild(tempTable); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 把创建的节点添加到页面容器中
? ? ? ? buttonRef.current.handleDownload(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 手动触发下载
? ? };
? ? return (
? ? ? ? <div style={{ backgroundColor: '#fff' }} className={styles.container}>
? ? ? ? ? ? <span onClick={(e) => exportTable(e)}>
? ? ? ? ? ? ? ? <ReactHTMLTableToExcel
? ? ? ? ? ? ? ? ? ? width={1900}
? ? ? ? ? ? ? ? ? ? ref={buttonRef}
? ? ? ? ? ? ? ? ? ? table="table-to-xls"
? ? ? ? ? ? ? ? ? ? id='test-table-xls-button'
? ? ? ? ? ? ? ? ? ? filename='回购日报'
? ? ? ? ? ? ? ? ? ? sheet='表1'
? ? ? ? ? ? ? ? ? ? buttonText='导出Excel'
? ? ? ? ? ? ? ? />
? ? ? ? ? ? </span>
? ? ? ? ? ? <Table
? ? ? ? ? ? ? ? columns={columns}
? ? ? ? ? ? ? ? dataSource={data}
? ? ? ? ? ? ? ? bordered
? ? ? ? ? ? ? ? pagination={false}
? ? ? ? ? ? />
? ? ? ? ? ? <div id='hiddenBox' style={{ position: 'absolute', zIndex: -1, top: 0, left: 0 }} />
? ? ? ? </div>
? ? )
}
export default StudyExcel;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

查看更多关于React如何接收excel文件下载导出功能封装的详细内容...

  阅读:50次