? ? ? ? 免費開源的框架jexcel(jexcel文檔),他自帶的導(dǎo)出沒什么問題,就是格式和單元格的格式不太好,報表中的背景色等都沒有,所以決定找個方法做導(dǎo)出報表功能。廢話不多說,直接上代碼。
? ? ? ? 首先,先把封裝的導(dǎo)出js文件中引用的方法奉上:
// 去除千分位 num -> 字符串格式
export function delCommafy(num) {
? ? if ((num + '').trim() === '') {
? ? ? ? return ''
? ? }
? ? if (isType(num, 'string')) {
? ? ? ? num = num.replace(/,/gi, '')
? ? }
? ? return num
}
// 把reg(255,255,255)轉(zhuǎn)為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
? ? }
}
? ? ? ? 其次就是封裝的導(dǎo)出方法了:
import { colorHex, delCommafy } from '@/utils/index'
import XLSX from 'xlsx-style'
/**
?*
?* @param {string} fileNames 導(dǎo)出文件名
?* @param {string} exportType 導(dǎo)出類型(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 = [] //用來保存轉(zhuǎn)換好的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 = {
? ? ? ? ? ? ? ? //單元格外側(cè)框線
? ? ? ? ? ? ? ? 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,
? ? ? ? ? ? ? ? },
? ? ? ? ? ? }
? ? ? ? ? ? // 設(shè)置單元格類型(n:數(shù)值,s:字符串)
? ? ? ? ? ? let judgeCondition =
? ? ? ? ? ? ? ? (String(exportData[key].v).includes('.') && Number(exportData[key].v)) || !exportData[key].v
? ? ? ? ? ? exportData[key].t = judgeCondition ? 'n' : 's'
? ? ? ? ? ? // 數(shù)值格式(二選一)
? ? ? ? ? ? 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) //設(shè)置區(qū)域,比如表格從A1到D10
? ? ? ? var tmpWB = {
? ? ? ? ? ? SheetNames: ['mySheet'], //保存的表標(biāo)題
? ? ? ? ? ? Sheets: {
? ? ? ? ? ? ? ? mySheet: Object.assign(
? ? ? ? ? ? ? ? ? ? {},
? ? ? ? ? ? ? ? ? ? exportData, //內(nèi)容
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? '!ref': outputPos[3] + ':' + outputPos[outputPos.length - 1], //設(shè)置填充區(qū)域
? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ),
? ? ? ? ? ? },
? ? ? ? }
? ? ? ? let tmpDown = new Blob(
? ? ? ? ? ? [
? ? ? ? ? ? ? ? s2ab(
? ? ? ? ? ? ? ? ? ? XLSX.write(
? ? ? ? ? ? ? ? ? ? ? ? tmpWB,
? ? ? ? ? ? ? ? ? ? ? ? { bookType: type == undefined ? 'xlsx' : type, bookSST: false, type: 'binary' }, //這里的數(shù)據(jù)是用來定義導(dǎo)出的格式類型
? ? ? ? ? ? ? ? ? ? ),
? ? ? ? ? ? ? ? ),
? ? ? ? ? ? ],
? ? ? ? ? ? {
? ? ? ? ? ? ? ? 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中引入傳參調(diào)用就可以了:
????????????????????? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? type: 'i',
? ? ? ? ? ? ? ? ? ? ? ? ? ? content: 'cloud_download',
? ? ? ? ? ? ? ? ? ? ? ? ? ? onclick: (element, instance) => {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? let fileNames = '導(dǎo)出'
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? exportReports(fileNames, 'xlsx', jexcel, instance)
? ? ? ? ? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? ? ? },
? ? ? ? 報表原來的頁面展示:

? ? ? ? 導(dǎo)出效果(背景色及單元格格式都有):
