vue3使用 xlsx-js-style导出Exce 动态合并表头

安装插件
xlsx-js-style相当于xlsx的生基本,xlsx导出不能对单元格样式进行调整
安装了xlsx-js-style 就不需要安装 xlsx了

npm install xlsx-js-style

引入插件

import XLSXS from 'xlsx-js-style'

示例数据

  // 示例数据 data
            const data = [
                { transactionDate: '2024-01-01', '17lowerPriceDisplay': 100, '17upperPriceDisplay': 150, '17averagePriceDisplay': 120, xxxxx2: '12', xxxxx1: '11' },
                { transactionDate: '2024-01-02', '17lowerPriceDisplay': 110, '17upperPriceDisplay': 160, '17averagePriceDisplay': 125, xxxxx2: '12', xxxxx1: '11' },
            ]
// 示例 表格列

            const columns = [
                { title: '日期', dataIndex: 'transactionDate', width: 100, fixed: 'left' },
                { title: 'ssss', dataIndex: '17lowerPriceDisplay', colSpan: 0, width: 120 },
                { title: 'ssss', dataIndex: '17upperPriceDisplay', colSpan: 3, width: 120 },
                { title: 'ssss', dataIndex: '17averagePriceDisplay', colSpan: 0, width: 120 },
                { title: 'xxxxx', dataIndex: 'xxxxx1', colSpan: 0, width: 120 },
                { title: 'xxxxx', dataIndex: 'xxxxx2', colSpan: 0, width: 120 },
            ] 

表格头
表格头对应的key

 const headers = columns.map(item => { return item.title })  
 const fields = columns.map(item => { return item.dataIndex })

数据转换 二维数组

let dataCopy = data.map((obj) => {
                return fields.map((field) => {
                    return obj[field]
                })
            })
            if (headers.length > 0) {
                dataCopy.splice(0, 0, headers)
            } else {
                dataCopy.splice(0, 0, fields)
            }

生成工作表

  const ws = XLSX.utils.aoa_to_sheet(dataCopy) // 创建工作表

单元格格式设置


            // 设置列宽度自适应
            const colWidths = columns.map(col => col.width || 100);
            ws['!cols'] = colWidths.map(width => ({ wpx: width }));

            // 设置内容居中
            // 设置单元格公共样式
            let borderAll = { //单元格外侧框线
                top: {
                    style: 'thin',
                },
                bottom: {
                    style: 'thin',
                },
                left: {
                    style: 'thin',
                },
                right: {
                    style: 'thin',
                }
            };

            for (let key in ws) {
                // 单元格公共样式设置
                if (ws[key] instanceof Object) {
                    ws[key].s = {
                        border: borderAll,
                        alignment: {
                            horizontal: 'center', //水平居中对齐
                            vertical: 'center',//垂直居中
                            wrapText: 1,//自动换行
                        },
                        // fill: { //背景色
                        //     fgColor: { rgb: 'dbf3f2' }
                        // },
                        font: {
                            sz: 12,//单元格中字体的样式与颜色设置
                            color: {
                                rgb: '000000'
                            }
                        },
                        bold: true,
                        numFmt: 0
                    }
                }
            }

动态合并列 导出excel

 // 记录合并单元格的信息
            const merges = [];
            let startCol = 0;
            let currentTitle = columns[0].title;

            // 确定合并区域
            columns.forEach((col, index) => {
                if (col.title === currentTitle) {
                    // 继续合并
                } else {
                    if (index - startCol > 1) {
                        // 如果需要合并的区域大于1列
                        merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: index - 1 } });
                    }
                    // 更新标题和起始列
                    currentTitle = col.title;
                    startCol = index;
                }
            });

            // 处理最后一个区域
            if (columns.length - startCol > 1) {
                merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: columns.length - 1 } });
            }

            // 应用合并区域到工作表
            ws['!merges'] = merges;

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            console.log(wb, '创建工作簿')
            XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

            // 导出 Excel 文件
            XLSX.writeFile(wb, 'export.xlsx');

完整代码 vue3

<template>
    <div>
        <button @click="exportExcel">导出 Excel</button>
    </div>
</template>

<script>
// import * as XLSX from 'xlsx'
import XLSX from 'xlsx-js-style'
export default {
    methods: {
        exportExcel() {
            // 示例数据
            const data = [
                { transactionDate: '2024-01-01', '17lowerPriceDisplay': 100, '17upperPriceDisplay': 150, '17averagePriceDisplay': 120, xxxxx2: '12', xxxxx1: '11' },
                { transactionDate: '2024-01-02', '17lowerPriceDisplay': 110, '17upperPriceDisplay': 160, '17averagePriceDisplay': 125, xxxxx2: '12', xxxxx1: '11' },
            ]

            // 列配置
            const columns = [
                { title: '日期', dataIndex: 'transactionDate', width: 100, fixed: 'left' },
                { title: 'ssss', dataIndex: '17lowerPriceDisplay', colSpan: 0, width: 120 },
                { title: 'ssss', dataIndex: '17upperPriceDisplay', colSpan: 3, width: 120 },
                { title: 'ssss', dataIndex: '17averagePriceDisplay', colSpan: 0, width: 120 },
                { title: 'xxxxx', dataIndex: 'xxxxx1', colSpan: 0, width: 120 },
                { title: 'xxxxx', dataIndex: 'xxxxx2', colSpan: 0, width: 120 },
            ]

            const fields = columns.map(item => { return item.dataIndex })
            const headers = columns.map(item => { return item.title })
            let dataCopy = data.map((obj) => {
                return fields.map((field) => {
                    return obj[field]
                })
            })
            if (headers.length > 0) {
                dataCopy.splice(0, 0, headers)
            } else {
                dataCopy.splice(0, 0, fields)
            }
            // 生成工作表
            // const ws = XLSX.utils.json_to_sheet(data, { header: columns.map(col => col.dataIndex) });
            const ws = XLSX.utils.aoa_to_sheet(dataCopy) // 创建工作表


            // 设置列宽度自适应
            const colWidths = columns.map(col => col.width || 100);
            ws['!cols'] = colWidths.map(width => ({ wpx: width }));

            // 设置内容居中
            // 设置单元格公共样式
            let borderAll = { //单元格外侧框线
                top: {
                    style: 'thin',
                },
                bottom: {
                    style: 'thin',
                },
                left: {
                    style: 'thin',
                },
                right: {
                    style: 'thin',
                }
            };

            for (let key in ws) {
                // 单元格公共样式设置
                if (ws[key] instanceof Object) {
                    ws[key].s = {
                        border: borderAll,
                        alignment: {
                            horizontal: 'center', //水平居中对齐
                            vertical: 'center',//垂直居中
                            wrapText: 1,//自动换行
                        },
                        // fill: { //背景色
                        //     fgColor: { rgb: 'dbf3f2' }
                        // },
                        font: {
                            sz: 12,//单元格中字体的样式与颜色设置
                            color: {
                                rgb: '000000'
                            }
                        },
                        bold: true,
                        numFmt: 0
                    }
                }
            }

            // 记录合并单元格的信息
            const merges = [];
            let startCol = 0;
            let currentTitle = columns[0].title;

            // 确定合并区域
            columns.forEach((col, index) => {
                if (col.title === currentTitle) {
                    // 继续合并
                } else {
                    if (index - startCol > 1) {
                        // 如果需要合并的区域大于1列
                        merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: index - 1 } });
                    }
                    // 更新标题和起始列
                    currentTitle = col.title;
                    startCol = index;
                }
            });

            // 处理最后一个区域
            if (columns.length - startCol > 1) {
                merges.push({ s: { r: 0, c: startCol }, e: { r: 0, c: columns.length - 1 } });
            }

            // 应用合并区域到工作表
            ws['!merges'] = merges;

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            console.log(wb, '创建工作簿')
            XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');

            // 导出 Excel 文件
            XLSX.writeFile(wb, 'export.xlsx');
        }
    }
};
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值