網站首頁 編程語言 正文
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;
原文鏈接:https://blog.csdn.net/deng1456694385/article/details/89517591
相關推薦
- 2022-05-03 使用EF的Code?First模式操作數據庫_實用技巧
- 2022-08-21 使用?DataAnt?監控?Apache?APISIX的原理解析_Linux
- 2022-04-18 python?如何讀取列表中字典的value值_python
- 2022-12-07 python中的eval函數使用實例_python
- 2022-04-11 圖文詳解C#中的協變與逆變_C#教程
- 2022-07-19 mybatis plus 代碼生成器配置
- 2022-11-25 使用openssl實現私有CA的搭建和證書的頒發_相關技巧
- 2022-08-30 Springcloud--Nacos服務治理
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支