Vue+xlsx+xlsx-style修改表格样式并导出

参考:(可根据此参考 解决Can't resolve './cptable' in '...' 的问题,我只是对他的方法进行了封装)使用Vue+xlsx+xlsx-style实现导出自定义样式的Excel文件

版本:

"xlsx": "^0.18.5",

 "xlsx-style": "^0.8.13"

"vue": "^2.5.10",

删除了一些代码,只保留了表头和边框,顺便加了个合计,合计在页面调用中直接插入到数据中

在libs里创建excel2.js


import * as XLSX from 'xlsx'
import * as XLSX_STYLE from 'xlsx-style' // Vue2 + Webpack
//thList 表头,keyList 对应的字段名
/**
 * 导出数据
 */
export function handelExportExcelClick(title,data,thList,keyList) {
    // 一、准备数据
    const list = getExportDataList(data,thList,keyList)
    // yLength用于设置列宽
    const yLength = thList.length;
    console.log('list =>', list)

    // 二、新建一个工作簿
    const workBook = XLSX.utils.book_new()

    // 三、使用二维数组生成一个工作表
    const workSheet = sheet_from_array_of_arrays(list)

    // 四、将 "A1" 到 "M1" 的单元格合并为 "A1"
    workSheet['!merges'] = [
        {
            s: { // s ("start"): c = 0 r = 0 -> "A1"
                r: 0,
                c: 0
            },
            e: { // e ("end"):   c = 0 r = 9 -> "J1"
                r: 0,
                c: yLength-1
            }
        }
    ]

    // 五、设置每列的宽度(单位:px)
    
    // const wsCols = [
    //     { wch: 15 },
    //     { wch: 15 },
    //     { wch: 15 },
    //     { wch: 15 },
    //     { wch: 15 }
    // ]
    // 上面的是固定写法
    let wsCols = []
    for (let i = 0; i < yLength; i++) {
        wsCols.push({ wch: 15 })
    }
    workSheet['!cols'] = wsCols

    // 六、设置每行的高度(单位:px)
    let wsRows = []
    for (let i in list) {
        if (i == 0) {
            wsRows.push({ hpx: 100 }) // 首行高度为 100px
        } else {
            // wsRows.push({ hpx: 30 }) // 其他行高度为 30px
        }
    }
    workSheet['!rows'] = wsRows

    // 七、设置单元格样式
    for (let key in workSheet) {
        if (key == '!ref' || key == '!merges' || key == '!cols' || key == '!rows') {
            continue
        } else {
            // 匹配表格第一行(注意 A1 单元已合并为一个单元),设置其样式
            if (key == 'A1') {
                workSheet[key] = {
                    t: 's', // 设置单元格类型(type: b Boolean, e Error, n Number, d Date, s Text, z Stub)
                    v: title, // 这里设置了表头!
                    // l: { Target: "https://sheetjs.com", Tooltip: "Find us @ SheetJS.com!" }, // 单元格超链接 cell hyperlink / tooltip (More Info)
                    s: { // 设置单元格样式
                        fill: { // 设置背景色
                            fgColor: { rgb: 'ffffff' },
                        },
                        font: { // 设置字体
                            name: '等线', // 字体名称
                            sz: 35, // 字体大小
                            bold: true, // 字体是否加粗
                            color: { rgb: '5e7ce0' }, // 文字颜色
                        },
                        alignment: { // 设置居中
                            horizontal: 'center', // 水平(向左、向右、居中)
                            vertical: 'center', // 上下(向上、向下、居中)
                            wrapText: false, // 设置单元格自动换行,目前仅对非合并单元格生效
                            indent: 0 // 设置单元格缩进
                        },
                    },
                }
            }
            else {
                workSheet[key].s = {
                    border: {
                        top: {
                            style: 'thin',
                        },
                        bottom: {
                            style: 'thin',
                        },
                        left: {
                            style: 'thin',
                        },
                        right: {
                            style: 'thin',
                        },
                    },
                    fill: { // 设置背景色
                        fgColor: { rgb: 'ffffff' },
                    },
                    font: { // 设置字体
                        name: '微软雅黑', // 字体名称
                        sz: 10, // 字体大小
                    },
                    alignment: {
                        horizontal: 'center', // 水平(向左、向右、居中)
                        vertical: 'center', // 上下(向上、向下、居中)
                        wrapText: false, // 设置单元格自动换行,目前仅对非合并单元格生效
                        indent: 0 // 设置单元格缩进
                    }
                }
            }
        }
    }
    // console.log('workSheet =>', workSheet)

    // 八、在工作簿中添加工作表
    XLSX.utils.book_append_sheet(workBook, workSheet, 'sheet')

    // 九、使用 xlsx-style 写入文件方式,使得自定义样式生效
    const tmpDown = new Blob([
        s2ab(
            XLSX_STYLE.write(workBook, {
                bookType: 'xlsx',
                bookSST: true,
                type: 'binary',
                cellStyles: true,
            })
        ),
    ])

    // 十、导出 Excel 文件
    // const date = new Date()
    // const formattedDate =
    //     `` +
    //     `${date.getFullYear()}` + // 年
    //     `${(date.getMonth() + 1).toString().padStart(2, '0')}` + // 月
    //     `${date.getDate().toString().padStart(2, '0')}` + // 日
    //     `${date.getHours().toString().padStart(2, '0')}` + // 时
    //     `${date.getMinutes().toString().padStart(2, '0')}` + // 分
    //     `${date.getSeconds().toString().padStart(2, '0')}` + // 秒
    //     ``.trim()
    downloadExcelFile(tmpDown, title + '.xlsx')
}

/**
 * 准备数据
 */
function getExportDataList(data,thList,keyList) {
    // const thList = [
    //     '商品ID',
    //     '商品名称',
    //     '商品描述',
    //     '规格',
    //     '库存'
    // ]

    // const keyList = [
    //     'id',
    //     'name',
    //     'desc',
    //     'spec',
    //     'num'
    // ]

   

    const tdList = formatJson(keyList, data) // 过滤字段以及转换数据格式,即:表格数据
    tdList.unshift(thList) // 将 thList 数组添加到 tdList 数组开头,即:表格头部
    tdList.unshift(['']) // 将空字符串数组添加到 tdList 数组开头,即:表格首行
    const list = tdList
    return list
}

/**
 * 过滤字段以及转换数据格式
 */
function formatJson(filterVal, jsonData) {
    return jsonData.map(v => filterVal.map(item => {
        if (item === 'name') {
            if (v['name'] != null && v['name'] != '') {
                return v[item].split(';').join('\n')
            } else {
                return '-'
            }
        }
        // else if (item === 'status') {
        //     if (v['status'] != null && v['status'] == 0) {
        //         return '正常'
        //     } else if (v['status'] != null && v['status'] == 1) {
        //         return '待上架'
        //     } else if (v['status'] != null && v['status'] == 2) {
        //         return '已下架'
        //     } else {
        //         return '-'
        //     }
        // }
        else {
            return v[item]
        }
    }))
}

/**
 * 使用二维数组生成一个工作表
 */
function sheet_from_array_of_arrays(data, opts) {
    var ws = {};
    var range = {
        s: {
            c: 10000000,
            r: 10000000
        },
        e: {
            c: 0,
            r: 0
        }
    }

    for (var R = 0; R != data.length; ++R) {
        for (var C = 0; C != data[R].length; ++C) {
            if (range.s.r > R) range.s.r = R;
            if (range.s.c > C) range.s.c = C;
            if (range.e.r < R) range.e.r = R;
            if (range.e.c < C) range.e.c = C;
            var cell = {
                v: data[R][C]
            };
            if (cell.v == null) continue;
            var cell_ref = XLSX.utils.encode_cell({
                c: C,
                r: R
            })

            if (typeof cell.v === 'number') cell.t = 'n';
            else if (typeof cell.v === 'boolean') cell.t = 'b';
            else if (cell.v instanceof Date) {
                cell.t = 'n';
                cell.z = XLSX.SSF._table[14];
                cell.v = date_num(cell.v);
                // cell.z = 'YYYY-MM-DD'
                cell.z = 'YYYY-MM-DD HH:mm:ss'
            } else cell.t = 's'

            ws[cell_ref] = cell
        }
    }

    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
    return ws
}

/**
 * 日期转换
 */
function date_num(v, date1904) {
    if (date1904) {
        v += 1462;
    }
    var epoch = Date.parse(v);
    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}

/**
 * 文件流转换
 */
function s2ab(s) {
    if (typeof ArrayBuffer !== 'undefined') {
        const buf = new ArrayBuffer(s.length)
        const view = new Uint8Array(buf);
        for (let i = 0; i != s.length; ++i) {
            view[i] = s.charCodeAt(i) & 0xff
        }
        return buf
    } else {
        const buf = new Array(s.length)
        for (let i = 0; i != s.length; ++i) {
            buf[i] = s.charCodeAt(i) & 0xff
        }
        return buf
    }
}

/**
 * 使用 a 标签下载文件
 */
function downloadExcelFile(obj, fileName) {
    const a_node = document.createElement('a')
    a_node.download = fileName
    if ('msSaveOrOpenBlob' in navigator) {
        window.navigator.msSaveOrOpenBlob(obj, fileName)
    } else {
        a_node.href = URL.createObjectURL(obj)
    }
    a_node.click()
    setTimeout(() => {
        URL.revokeObjectURL(obj)
    }, 2000)
}

在页面中调用:

exportExcel(title) {
            if (this.list.length) {

                this.exportLoading = true
                const { thList, keyList } = this.getThList()
                let data=JSON.parse(JSON.stringify(this.list));
       
                 // 初始化sumObj,所有key对应值设为空字符串
                 let sumObj = {};
                keyList.forEach(key => {
                    sumObj[key] = '';
                });
                // 设置第一个item的key值为'合计'
                sumObj[keyList[0]]='合计'
                // 遍历data并累加数字类型的item[key]
                data.forEach(item => {
                    keyList.forEach(key => {
                        if (typeof item[key] === 'number') {
                            sumObj[key] = Number(sumObj[key]) + item[key];
                        }
                    });
                });

                // 将汇总对象推入data数组
                data.push(sumObj);
                handelExportExcelClick(title, data, thList, keyList)
            }else{
                this.$Message.info('表格数据不能为空!')
            }
        },
        getThList() {
            let thList = []
            let keyList = []
            this.columns.forEach(item => {
                if (item.title) {
                    thList.push(item.title)
                    keyList.push(item.key)
                }
            })
            // 将 thList 和 keyList 包装成一个对象返回
            return { thList, keyList }
        },

运行结果:

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
修改导出的 Excel 表格的字体颜色,你可以使用 xlsx-style 库提供的 `XLSXStyle` 类的 `createStyle` 方法来创建自定义样式,然后将其应用到单元格中。 下面是一个使用 Vue 3 + TypeScript 和 xlsx-style-vite 库的示例代码: ```typescript <template> <div> <button @click="exportExcel">导出 Excel</button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { utils, writeFile } from 'xlsx-style-vite'; import { XLSXStyle } from 'xlsx-style-vite/xlsx-style'; export default defineComponent({ methods: { exportExcel() { const data = [ ['姓名', '年龄', '性别'], ['张三', 18, '男'], ['李四', 20, '女'], ['王五', 22, '男'] ]; const workbook = utils.book_new(); const worksheet = utils.aoa_to_sheet(data); // 创建自定义样式 const style = XLSXStyle.createStyle({ font: { color: '#FF0000' } }); // 将样式应用到单元格 utils.sheet_set_cell_style(worksheet, 'A1:C1', style); utils.book_append_sheet(workbook, worksheet, 'Sheet1'); writeFile(workbook, 'example.xlsx'); } } }); </script> ``` 在上面的代码中,我们首先创建了一个包含一些数据的数组 `data`。然后,我们使用 `utils.aoa_to_sheet` 方法将该数组转换为一个工作表对象。接着,我们使用 `XLSXStyle.createStyle` 方法创建了一个包含字体颜色为红色的自定义样式,并使用 `utils.sheet_set_cell_style` 方法将该样式应用到了表头行的所有单元格上。最后,我们将工作表对象添加到工作簿中,使用 `writeFile` 方法将工作簿导出为一个 Excel 文件。 需要注意的是,在使用 xlsx-style-vite 库时,要使用 `XLSXStyle` 类来创建自定义样式,这与原生的 xlsx-style 库有所不同,所以要引入 `xlsx-style-vite/xlsx-style` 模块。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值