vue项目中,纯前端实现jexcel导出(样式+单元格格式)

        免费开源的框架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)

                            },

                        },

        报表原来的页面展示:


        导出效果(背景色及单元格格式都有):


你可能感兴趣的:(vue项目中,纯前端实现jexcel导出(样式+单元格格式))