免费开源的框架jexcel(jexcel文档),他自带的导出没什么问题,就是格式和单元格的格式不太好,报表中的背景色等都没有,所以决定找个方法做导出报表功能。废话不多说,直接上代码。
首先,先把封装的导出js文件中引用的方法奉上:
// 去除千分位 num -> 字符串格式
export function delCommafy(num) {
if ((num + '').trim() === '') {
return ''
}
if (isType(num, 'string')) {
num = num.replace(/,/gi, '')
}
return num
}
// 把reg(255,255,255)转为16进制颜色(无#号)
export function colorHex(color) {
// RGB颜色值的正则
var reg = /^(rgb|RGB)/
if (reg.test(color)) {
// var strHex = "#";
var strHex = ''
var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
for (var i = 0; i < colorArr.length; i++) {
var hex = Number(colorArr[i]).toString(16)
if (hex === '0') {
hex += hex
}
strHex += hex
}
return strHex
} else {
return color
}
}
其次就是封装的导出方法了:
import { colorHex, delCommafy } from '@/utils/index'
import XLSX from 'xlsx-style'
/**
*
* @param {string} fileNames 导出文件名
* @param {string} exportType 导出类型(xlsx...)
* @param {object} jexcel jexcel对象
* @param {object} jexcelSpread jexcel的spread对象
*/
export function exportReports(fileNames, exportType, jexcel, jexcelSpread) {
function saveAs(obj, fileName) {
var tmpa = document.createElement('a')
tmpa.download = fileName || '下载'
tmpa.href = URL.createObjectURL(obj)
tmpa.click()
setTimeout(function() {
URL.revokeObjectURL(obj)
}, 100)
}
const wopts = { bookType: 'xlsx', bookSST: true, type: 'binary', cellStyles: true }
function downloadExl(fileName, type) {
let datas = jexcelSpread.getData()
let merges = jexcelSpread.getMerge()
let styles = jexcelSpread.getStyle()
let exportData = [] //用来保存转换好的json
exportData['!merges'] = []
exportData['!cols'] = []
exportData['!rows'] = []
datas.forEach((rowData, rowIndex) => {
rowData.forEach((colData, colIndex) => {
exportData[jexcel.getColumnNameFromId([colIndex, rowIndex])] = {
v: Number(delCommafy(colData)) ? delCommafy(colData) : colData,
}
})
})
for (const key in merges) {
let startMergeId = jexcel.getIdFromColumnName(key).split('-')
let startCol = Number(startMergeId[0])
let startRow = Number(startMergeId[1])
let endCol = startCol + (merges[key][0] - 1)
let endRow = startRow + (merges[key][1] - 1)
exportData['!merges'].push({
s: {
r: startRow,
c: startCol,
},
e: {
r: endRow,
c: endCol,
},
})
}
for (const key in styles) {
let styleArr = styles[key].split(';').map(item => item.replaceAll(' ', ''))
let fgRgb = styleArr.filter(item => item.indexOf('background-color') === 0).length
? colorHex(
styleArr
.filter(item => item.indexOf('background-color') === 0)[0]
.replace('background-color:', ''),
)
: 'FFFFFF'
const borderAll = {
//单元格外侧框线
top: {
style: 'thin',
color: { rgb: colorHex('rgb(204,204,204)') },
},
bottom: {
style: 'thin',
color: { rgb: colorHex('rgb(204,204,204)') },
},
left: {
style: 'thin',
color: { rgb: colorHex('rgb(204,204,204)') },
},
right: {
style: 'thin',
color: { rgb: colorHex('rgb(204,204,204)') },
},
}
exportData[key].s = {
border: borderAll,
fill: {
bgColor: { indexed: 64 },
fgColor: { rgb: fgRgb },
},
alignment: {
vertical: 'center',
wrapText: true,
},
}
// 设置单元格类型(n:数值,s:字符串)
let judgeCondition =
(String(exportData[key].v).includes('.') && Number(exportData[key].v)) || !exportData[key].v
exportData[key].t = judgeCondition ? 'n' : 's'
// 数值格式(二选一)
exportData[key].z = judgeCondition ? '#,##0.00;-#,##0.00' : ''
}
let colsLen = jexcelSpread.colgroup.length
for (let j = 0; j < colsLen; j++) {
exportData['!cols'].push({ wpx: Number(jexcelSpread.getWidth()[j]) })
}
exportData['!cols'].push({ wpx: 100 })
let outputPos = Object.keys(exportData) //设置区域,比如表格从A1到D10
var tmpWB = {
SheetNames: ['mySheet'], //保存的表标题
Sheets: {
mySheet: Object.assign(
{},
exportData, //内容
{
'!ref': outputPos[3] + ':' + outputPos[outputPos.length - 1], //设置填充区域
},
),
},
}
let tmpDown = new Blob(
[
s2ab(
XLSX.write(
tmpWB,
{ bookType: type == undefined ? 'xlsx' : type, bookSST: false, type: 'binary' }, //这里的数据是用来定义导出的格式类型
),
),
],
{
type: '',
},
)
saveAs(tmpDown, fileName + '.' + (wopts.bookType == 'biff2' ? 'xlsx' : wopts.bookType))
}
function s2ab(s) {
if (typeof ArrayBuffer !== 'undefined') {
let buf = new ArrayBuffer(s.length)
let view = new Uint8Array(buf)
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
return buf
} else {
let buf = new Array(s.length)
for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xff
return buf
}
}
downloadExl(fileNames, exportType)
}
vue中引入传参调用就可以了:
{
type: 'i',
content: 'cloud_download',
onclick: (element, instance) => {
let fileNames = '导出'
exportReports(fileNames, 'xlsx', jexcel, instance)
},
},
报表原来的页面展示:
导出效果(背景色及单元格格式都有):