300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > vue中使用xlsx导出Excel 并设置样式 解决未完全合并单元格框线的BUG

vue中使用xlsx导出Excel 并设置样式 解决未完全合并单元格框线的BUG

时间:2023-03-10 00:49:04

相关推荐

vue中使用xlsx导出Excel 并设置样式 解决未完全合并单元格框线的BUG

今天有需到一个需求,需要在前端直接导出表格,将了解发现了npm上用的比较多的 xlsx 这个包,但是在使用过程中发现很多问题,下边是我将发现问题进行的汇总以及相应的解决办法。

1.安装

首先说安装问题,防止版本不对应导致运行报错,或者XLSX导入之后会出现undefined等问题,建议package.json锁以下版本:

"xlsx": "0.16.0", // 这个包是用来导出(其实不安装这个包,使用创建虚拟a标签然后click的方式也可)"file-saver": "2.0.2",// 这个包是用来设置样式"xlsx-style": "^0.8.13",

2.报错解决

在使用xlsx-style时,可能会出现以下报错

This relative module was not found:* ./cptable in ./node_modules/xlsx-style/dist/cpexcel.js

解决办法: 找到./node_modules/xlsx-style/dist/cpexcel.js文件手动修改

将 815 行var cpt = require('./cpt' + 'able'); 替换为var cpt = cptable;

3.使用

import FileSaver from 'file-saver';import XLSX from 'xlsx';import XLSXS from 'xlsx-style';// 点击事件触发的方法download() {// 首先加载 <table id='excelTable'> 标签 为 workbook对象let workbook = XLSX.utils.table_to_book(document.getElementById('excelTable'));// 先定义列宽 , 我这里文件一共有7 列 ,所以设置7列宽度相等都为 20 ,如果你有很多列建议直接 map() let wscols = [{wch: 20 },{wch: 20 },{wch: 20 },{wch: 20 },{wch: 20 },{wch: 20 },{wch: 20 }];// 获取 需要设置样式的 sheet ,我这里只有 一个 sheet 所以索引默认加载了第一个const sheet = workbook.Sheets[workbook.SheetNames[0]];// 设置列宽 sheet['!cols'] = wscols;// 定义框线样式const borderAll = {color: {auto: 1 },top: {style: "thin"},bottom: {style: "thin"},left: {style: "thin" },right: {style: "thin" }};// 这里的意思为 先默认代表表格的 7 个列 的 列号 // 比如 A2 意思是 第一列 第2行const _letterList = ['A', 'B', 'C', 'D', 'E', 'F', 'G']// 定义一个 箭头函数,接受三个参数,分别为 当前Sheet , 行列号(例如:‘A2’), 是否是新增样式const _mapCellStyle = (_sheet, _key, _type) => {const _cellStyle = {border: borderAll,alignment: {wrapText: true,horizontal: "center",vertical: "center"},font: {name: "微软雅黑",sz: 10},bold: true,numFmt: "0"}if (_type === 'append') {// 需要新增样式,说明当前加载的sheet中并不存在该单元格,可能当前单元格被前边合并,这种被合并的单元格也得设置样式,// 否则就会出现 合并单元格只有第一格带框线,后边没框线的情况出现,所以这里需要将后边的边框样式也加上。_sheet[_key] = {s: _cellStyle}} else {// 若不是新增样式 则代表sheet中已存在该表格直接修改其 s 属性即可使属性生效if (typeof _sheet[_key] === 'object') {_sheet[_key].s = _cellStyle}}}// sheet 不懂得可以单独打印一下,它其实就是一个对象,键代表行列号(‘A2’),值为该单元格的值,样式等,// 我们需要做的就是修改其值中的样式Object.keys(sheet).forEach((i, _) => {// 无用属性直接过滤if (i !== "!ref" || i !== "!cols" || i !== "!merges" || i !== "Am") {// 首先设置遍历到的 当前 key let _nowKey = i// 然后调用 _mapCellStyle 渲染当前单元格样式_mapCellStyle(sheet, _nowKey)// 我们这里先获取下一个行列号 例如当前_nowKey 是 A1 这里就是获取到 B1 ,及 当前行的 下一列数据let _nextKey = _letterList[_letterList.indexOf(_nowKey[0]) + 1] + i.slice(1)// 判断 B1 是否在 Sheet的key中,如果不存在,只可能是因为B1所在单元格已经被A1所合并,所以我们需要将B1也调用一下 _mapCellStyle // 渲染 B1 的样式,不然就会出现 A1 B1 这两格是合并的状态,只有A1有框线,而B1 没有框线的情况。// 这里用 while 就是 要把需要合并的单元格全部 渲染上样式,直到可能 B4 在 Sheet中 停止while (_nowKey[0] !== 'G' && !Object.keys(sheet).includes(_nextKey)) {_mapCellStyle(sheet, _nextKey, 'append')// 这里就是简单的交换索引_nowKey = _nextKey_nextKey = _letterList[_letterList.indexOf(_nowKey[0]) + 1] + _nowKey.slice(1)}}})let wopts = {bookType: 'xlsx',bookSST: false,type: 'buffer',}let _blob = XLSXS.write(workbook, wopts);FileSaver.saveAs(new Blob([_blob], {type: "application/octet-stream"}), "项目信息一张表.xlsx");},

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。