前端实现导出excel文件流_xlsx表格

前端实现导出excel文件流_xlsx表格最近写管理端的需求,发现有一个excel导出的需求,本来是后端同学负责,但是因为他们太忙了,把这块任务交给前端了,起初产品觉得前端实现不了,一听这话,这我哪里受得了,赶紧写了个demo给她看,前端是可以实现的

前端实现导出excel文件流_xlsx表格"

点击在线阅读,体验更好 链接
现代JavaScript高级小册 链接
深入浅出Dart 链接
现代TypeScript高级小册 链接
linwu的算法笔记📒 链接

前言

最近写管理端的需求,发现有一个excel导出的需求,本来是后端同学负责,但是因为他们太忙了,把这块任务交给前端了,起初产品觉得前端实现不了,一听这话,这我哪里受得了,赶紧写了个demo给她看,前端是可以实现的。enen,产品看了直夸牛逼

接下来,我来分享导出excel文件的三种实现方式

url下载

在这种方式中,我们的目标是后端生成Excel文件并提供一个地址,前端通过访问这个地址来下载导出的Excel文件。

  • 后端根据前端的请求,生成需要导出的数据,并将数据转换为Excel格式的文件。

  • 后端将生成的Excel文件保存到服务器的某个临时目录,并为该文件生成一个临时的访问地址。

  • 后端将生成的临时地址返回给前端作为响应。

  • 前端收到后端返回的地址后,可以通过创建一个隐藏的 <a> 标签,并设置其 href 属性为后端返回的地址,然后触发点击该标签的操作,从而实现文件下载。

  • 前端完成下载后,可以根据需求决定是否删除服务器上的临时文件。

// 后端接口:/api/export/excel // 请求方式:GET // 假设后端接口返回导出地址的数据格式为 { url: "https://example.com/excel_exports/exported_file.xlsx" } export const exportExcelViaURL = () => { 
    // 发起后端接口请求获取导出地址 fetch('/api/export/excel') .then((response) => response.json()) .then((data) => { 
    const { 
    url } = data; // 创建一个隐藏的<a>标签并设置href属性为后端返回的地址 const link = document.createElement('a'); link.href = url; link.target = '_blank'; link.download = `exported_data_${ 
     dayjs().format('YYYY-MM-DD_hh.mm.ss_a')}.xlsx`; // 触发点击操作,开始下载文件 link.click(); }) .catch((error) => { 
    console.error('导出Excel失败:', error); }); }; 

Blob文件流

后端直接返回Blob文件流数据,前端通过接收到的Blob数据进行文件下载。

  • 后端根据前端的请求,生成需要导出的数据,并将数据转换为Excel格式的文件。

  • 后端将生成的Excel数据以Blob文件流的形式返回给前端,通常是通过设置响应的Content-Type和Content-Disposition头,使其以文件下载的方式呈现给用户。

  • 前端通过接收到的Blob数据,可以创建一个Blob URL,然后创建一个隐藏的 <a> 标签,并将其 href 属性设置为Blob URL,再触发点击该标签的操作,从而实现文件下载。

// 后端接口:/api/export/excel/blob // 请求方式:GET export const exportExcelViaBlob = () => { 
    // 发起后端接口请求获取Blob文件流数据 fetch('/api/export/excel/blob') .then((response) => response.blob()) .then((blobData) => { 
    // 创建Blob URL const blobUrl = URL.createObjectURL(blobData); // 创建一个隐藏的<a>标签并设置href属性为Blob URL const link = document.createElement('a'); link.href = blobUrl; link.target = '_blank'; link.download = `exported_data_${ 
     dayjs().format('YYYY-MM-DD_hh.mm.ss_a')}.xlsx`; // 触发点击操作,开始下载文件 link.click(); // 释放Blob URL URL.revokeObjectURL(blobUrl); }) .catch((error) => { 
    console.error('导出Excel失败:', error); }); }; 

基于XLSX

XLSX是一款功能强大的JavaScript库,用于在浏览器和Node.js中读取、解析、处理和写入Excel文件。

1. 安装XLSX

首先,你需要在你的项目中安装XLSX库。你可以通过npm或yarn来安装:

npm install xlsx 

或者

yarn add xlsx 

2. 引入XLSX

在你的代码中,你需要引入XLSX库,以便使用其中的功能:

import * as XLSX from 'xlsx'; 

3. 读取Excel文件

使用XLSX库,你可以读取现有的Excel文件,提取其中的数据和元数据。例如,假设你有一个名为”data.xlsx”的Excel文件,你可以通过以下方式读取它:

import * as XLSX from 'xlsx'; const file = 'data.xlsx'; // 文件路径或URL const workbook = XLSX.readFile(file); const sheetName = workbook.SheetNames[0]; // 假设我们读取第一个工作表 const worksheet = workbook.Sheets[sheetName]; const data = XLSX.utils.sheet_to_json(worksheet, { 
    header: 1 }); console.log(data); 

4. 写入Excel文件

除了读取现有的Excel文件,XLSX库还允许你将数据写入到新的Excel文件中。例如,你可以将一个二维数组的数据写入到一个新的Excel文件:

import * as XLSX from 'xlsx'; const data = [ ['Name', 'Age', 'City'], ['John Doe', 30, 'New York'], ['Jane Smith', 25, 'San Francisco'], ]; const worksheet = XLSX.utils.aoa_to_sheet(data); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); const fileName = 'output.xlsx'; // 导出的文件名 XLSX.writeFile(workbook, fileName); 

项目实践

下面代码是我在项目中封装好的代码,有需要的同学直接copy使用就行

为了实现前述两种方式的前端导出Excel功能,我们将使用XLSX库来处理数据并导出Excel文件。

// 基于XLSX的前端导出Excel实现 import dayjs from 'dayjs'; import * as XLSX from 'xlsx'; /** * eg: .columns = [ * { header: 'Id', key: 'id', wpx: 10 }, * { header: 'Name', key: 'name', wch: 32 }, * { header: 'D.O.B.', key: 'dob', width: 10, hidden: true } * ] * data: [{id: 1, name: 'John Doe', dob: new Date(1970,1,1)}] * @param columns 定义列属性数组 * @param data 数据 * @param name 文件名 */ export const generateExcel = (columns = [], data = [], name = '') => { 
    const headers = columns.map((item) => item.header); // https://docs.sheetjs.com/docs/csf/features/#row-and-column-properties const otherConfigs = columns.map(({ 
     key, header, ...item }) => item); const dataList = data.map((item) => { 
    let obj = { 
   }; columns.forEach((col) => { 
    obj[col.header] = item[col.key]; }); return obj; }); const workbook = XLSX.utils.book_new(); workbook.SheetNames.push(name); const worksheet = XLSX.utils.json_to_sheet(dataList, { 
    header: headers, }); worksheet['!cols'] = otherConfigs; workbook.Sheets[name] = worksheet; // 生成Blob数据 const excelData = XLSX.write(workbook, { 
    type: 'array', bookType: 'xlsx' }); const blobData = new Blob([excelData], { 
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); // 创建Blob URL const blobUrl = URL.createObjectURL(blobData); // 创建一个隐藏的<a>标签并设置href属性为Blob URL const link = document.createElement('a'); link.href = blobUrl; link.target = '_blank'; link.download = `${ 
     name}-${ 
     dayjs().format('YYYY-MM-DD_hh.mm.ss_a')}.xlsx`; // 触发点击操作,开始下载文件 link.click(); // 释放Blob URL URL.revokeObjectURL(blobUrl); }; 

下载全部

我们可能需要一键下载所有表格的数据,这时候前端需要轮询后端的接口,拿到所有的数据,所以我们需要实现一个loopReuqest函数

export default function awaitRequest(limit = 5) { 
    let awaitTask = []; let currentTaskNum = 0; function run(event, ...args) { 
    return new Promise((resolve, reject) => { 
    function callbackEvent() { 
    currentTaskNum++; event(...args) .then((res) => { 
    if (awaitTask.length) { 
    const nextTask = awaitTask.shift(); nextTask(); } resolve(res); }) .catch((e) => { 
    console.error(e); reject(e); }) .finally(() => { 
    currentTaskNum--; }); } if (currentTaskNum >= limit) { 
    awaitTask.push(callbackEvent); } else { 
    callbackEvent(); } }); } Object.defineProperties(run, { 
    clear: { 
    value: () => { 
    awaitTask = []; }, }, }); return run; } /** * 循环分页请求,获取全部数据 * @param {Function} request 请求 * @param {Number} size 页大小 * @param {Object} params 其余参数 * @param {String} listLabel.pageLable 当前页字段名。默认page * @param {String} listLabel.sizeLabel 页大小字段名。默认page_size * @param {String} listLabel.totalLabel 总条数字段名。默认total * @param {String} listLabel.itemsLabel 数据列表字段名。默认list * @returns */ export async function loopRequest( request, size, params, listLabel = { 
    totalLabel: 'total', pageLable: 'page', sizeLabel: 'page_size', itemsLabel: 'list', }, ) { 
    const { 
    totalLabel = 'total', pageLable = 'page', sizeLabel = 'page_size', itemsLabel = 'list' } = listLabel; try { 
    const firstRes = await request({ 
    ...params, [sizeLabel]: size, [pageLable]: 1, }); let list = firstRes.data[itemsLabel] || []; const total = firstRes.data[totalLabel]; if (total > size) { 
    const limit = awaitRequest(); const restRequest = Array.from({ 
    length: Math.floor(total / size), }).map((_, index) => limit(() => request({ 
    ...params, [sizeLabel]: size, [pageLable]: index + 2, }), ), ); const resetRes = await Promise.all(restRequest); resetRes.forEach((res) => { 
    if (res.code === 0 && res.data[itemsLabel]) { 
    list.push(...res.data[itemsLabel]); } }); } return list; } catch (e) { 
    console.error(e); } return []; } 

今天的文章
前端实现导出excel文件流_xlsx表格分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/80841.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注