基于xlsx-populate实现的前端埋点导出

实现excel导出功能的三种情景

  • 后端生成excel并封装好,直接将文件地址通过接口返回给前端。前端拿到文件地址后通过js创建a标签,将文件地址赋值给a标签的href属性,调用a标签的click方法,最后移除a标签即可

    const link = document.createElement('a')
    link.download = fileName // 赋值文件名
    link.style.display = 'none'
    link.href = path
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    
  • 后端生成excel,但接口返回生成excel的二进制流

    const content = res.blob // 首先获取文件流
    const blob = new Blob([content], {
          
          type: 'application/octet-stream'}) // 创建blob实例 将文件流转化为类文件对象
    const url = URL.createObjectURL(blob) // 生成文件下载url 后面的操作和第一类相同生成a标签并点击
    
  • 前端生成excel,后端只提供excel内部填充数据

    下面将详细描述埋点导出的原理,前端如何生成excel以及如何进行数据填充

埋点导出的原理

埋点导出一般使用于比较个性化的模板,数据比较规则的表格可以直接使用xlsx-populate这个库通过遍历填充数据并导出,这里不多赘述。

埋点导出的原理即根据自定义的模板,在模板中需要填充的地方埋点,埋点常规是这样的

在这里插入图片描述

上面的姓名和员工编号是模板自带的,#name##jobNum#即为我们埋的点,这里埋点的格式可以自定义,主要用于后面通过正则捕获要填充的单元格。#号中的属性名也是自定义的,用于到数据源中寻找对应的属性值

埋下点后,一份用于解析的模板就造好了,接下来我们通过xlsx-populate这个库对该文件进行解析,解析后通过遍历获取到内容区域的单元格以及单元格中的值,这时候我们之前所埋的点就派上用场了,我们可以通过正则表达式捕获到埋点单元格,读取其属性,然后到数据源去寻找该属性对应的值,再拿找到的值替换我们最初埋下的点。最后将更新后的excel表格通过xlsx-populate进行导出。

实现

这里需要提前声明一下我们要用到的一些工具,首先肯定是xlsx-populate这个库,其次我使用lodash库中的get方法用来在数据源中搜索指定字段的值,最后还使用到了file-saver这个库用于实现生成excel表的下载。大家可以先去这几个库的官网下载包。

// 导入工具 
import XLSX from "xlsx-populate";
import {
    
     saveAs } from "file-saver";
import _ from "lodash";

这里需要提一下,我们先前埋好点的模板,一般可以放在项目中的静态资源目录下public/static。而且浏览器使用xlsx-populate这个库时,只能使用fromDataAsync 这个api来解析文件。官方给出的示例是这样的

在这里插入图片描述

// 第一步 定义一个解析模板的方法
const getExcelTemplate = url => {
    
    
    return new Promise(resolve => {
    
    
        const req = new XMLHttpRequest();
        req.open("GET", url, true);
        req.responseType = "arraybuffer";
        req.onreadystatechange = async () => {
    
    
            if (req.readyState === 4 && req.status === 200) {
    
    
                // 这里解析模板,并将解析好的数据resolve出去
                const workbook = await XLSX.fromDataAsync(req.response);
                resolve(workbook);
            }
        };
        req.send();
    });
};

// 第二步 数据填充 data为数据源
async function fill(data) {
    
    
    // 先获取解析后的模板 url即为你存模板的路径
    const BOOK = await getExcelTemplate("/static/performance-temp/probation-temp.xlsx");

    // 获取sheet
    const sheet = BOOK.sheet("Sheet1");
    for (let row = 3; row < 29; row++) 
        // 这里row和col的遍历范围根据自己模板的内容范围定
        for (let col = 1; col <= 16; col++) {
    
    
            // 获取每个单元格的值
            const val = sheet.row(row).cell(col).value();

            const rule = /^#.+#$/;
            if (rule.test(val)) {
    
    
                    // 这里获取到了埋点单元格
                    // 从数据源中找到我们要填充的值 注意找的时候要把我们之前埋点加的特殊符号去掉
                	const target = _.get(data, val.replace(/#/g,''))
                    // 填充
                    sheet.row(row).cell(col).value(target);
            }
        }
    }
	return BOOK
}

// 最后一步 下载填充好的excel
const blob = await fill(data).outputAsync();
saveAs(blob, `fileName.xlsx`);

猜你喜欢

转载自blog.csdn.net/m0_64023259/article/details/124827541