Vue使用vxe-table導出和自定義Excel樣式的詳細教程
引言
vxe-table 不僅支持將表格數(shù)據(jù)導出為 .xlsx 文件,還提供了強大的自定義樣式能力。通過 exportConfig.sheetMethod 鉤子,你可以直接操作底層的 ExcelJS 工作表對象,對導出的 Excel 進行精細化樣式設置,包括邊框、字體、背景色、列寬、行高、超鏈接、圖片等。
- 前置準備:請確保已安裝并注冊 @vxe-ui/plugin-export-xlsx 和 exceljs 插件。
核心配置:sheetMethod 鉤子
在 gridOptions.exportConfig 中定義 sheetMethod 函數(shù),它會在導出過程中被調用,并接收包含 worksheet(工作表對象)、workbook(工作簿對象)等參數(shù)。在此函數(shù)內(nèi),你可以使用 ExcelJS 的 API 修改樣式。
exportConfig: {
sheetMethod(params) {
const { worksheet, workbook } = params
// 自定義樣式邏輯
}
}
示例

設置邊框
為所有單元格添加紅色細邊框:

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
sheetMethod(params) {
const { worksheet } = params
worksheet.eachRow((excelRow) => {
excelRow.eachCell((excelCell) => {
// 設置單元格邊框
excelCell.border = {
top: {
style: 'thin',
color: {
argb: 'ff0000'
}
},
left: {
style: 'thin',
color: {
argb: 'ff0000'
}
},
bottom: {
style: 'thin',
color: {
argb: 'ff0000'
}
},
right: {
style: 'thin',
color: {
argb: 'ff0000'
}
}
}
})
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
設置字體
將所有單元格字體設為紅色、粗體、16號:

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
sheetMethod(params) {
const { worksheet } = params
worksheet.eachRow((excelRow) => {
excelRow.eachCell((excelCell) => {
// 設置單元格字體
excelCell.font = {
bold: true,
size: 16,
color: {
argb: 'ff0000'
}
}
})
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
設置表頭背景
將前 3 行(表頭區(qū)域)填充為淡藍色背景

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
sheetMethod(params) {
const { worksheet } = params
worksheet.eachRow((excelRow, rowIndex) => {
if (rowIndex <= 2) {
excelRow.eachCell((excelCell) => {
// 填充單元格背景
excelCell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {
argb: 'c5d9f1'
}
}
})
}
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
設置列寬
將所有列寬設置為 16:

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
async sheetMethod(params) {
const { worksheet } = params
worksheet.columns.forEach((sheetColumn) => {
// 設置列寬
sheetColumn.width = 16
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
設置行高
將所有數(shù)據(jù)行高設置為 60(單位:磅):

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
async sheetMethod(params) {
const { worksheet } = params
worksheet.eachRow((excelRow) => {
// 設置行高
excelRow.height = 60
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
設置超鏈接
為第 2 列(Name 列)的每個數(shù)據(jù)單元格添加超鏈接:

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
sheetMethod(params) {
const { worksheet } = params
worksheet.eachRow((excelRow, rowIndex) => {
if (rowIndex > 2) {
excelRow.eachCell((excelCell, columnIndex) => {
if (columnIndex === 2) {
// 設置指定單元格為超鏈接
excelCell.value = {
text: `${excelCell.value}`,
hyperlink: 'https://vxeui.com',
tooltip: 'vxeui.com'
}
// 設置單元格字體
excelCell.font = {
color: {
argb: '0000ff'
}
}
}
})
}
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
添加圖片
在數(shù)據(jù)行的第 2 列單元格位置插入 Logo 圖片(需確保圖片服務器支持跨域):

<template>
<div>
<vxe-button @click="exportEvent">點擊導出</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
exportConfig: {
async sheetMethod(params) {
const { worksheet, workbook } = params
// 加載圖片
const buffer1 = await fetch('https://vxeui.com/logo.png').then((res) => res.arrayBuffer())
const imageId1 = workbook.addImage({
buffer: buffer1,
extension: 'png'
})
worksheet.eachRow((excelRow, rowIndex) => {
if (rowIndex > 2) {
// 設置行高
excelRow.height = 60
excelRow.eachCell((excelCell, columnIndex) => {
if (columnIndex === 2) {
// 將圖片添加到單元格
worksheet.addImage(imageId1, {
tl: { col: columnIndex - 1, row: rowIndex - 1 },
ext: { width: 40, height: 40 }
})
}
})
}
})
}
},
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{
title: '分組1',
children: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role' }
]
},
{ field: 'sex', title: 'Sex' },
{ field: 'no1', title: 'NO1' },
{ field: 'no2', title: 'NO2 String', cellType: 'string' }
],
data: [
{ id: 10001, name: '張三', role: 'Develop', sex: 'Man', no1: '028', no2: '028' },
{ id: 10002, name: '李四', role: '研發(fā)', sex: 'Women', no1: '220', no2: '220' },
{ id: 10003, name: '王五', role: '產(chǎn)品經(jīng)理', sex: 'Man', no1: '003200', no2: '003200' },
{ id: 10004, name: '老六', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' }
],
footerData: [{ seq: '合計', name: '12人', no1: '356' }]
})
const exportEvent = () => {
const $grid = gridRef.value
if ($grid) {
$grid.exportData({
type: 'xlsx'
})
}
}
</script>
說明
| 事項 | 說明 |
|---|---|
| 異步處理 | 如果 sheetMethod 中包含異步操作(如 fetch 圖片),務必使用 async 函數(shù),并等待完成。 |
| 行/列索引偏移 | worksheet.eachRow 回調中 rowIndex 從 1 開始(1 為第一行)。列索引同樣從 1 開始。 |
| 圖片跨域 | 使用 fetch 加載圖片時,需確保圖片服務器支持跨域,否則無法獲取圖片內(nèi)容。 |
| 性能考慮 | 大表格(如超過 1000 行)時,遍歷所有單元格設置樣式可能耗時較長,建議按需設置,或僅對特定區(qū)域操作。 |
| 樣式覆蓋 | 某些全局樣式(如列寬)如果在 sheetMethod 中設置,會覆蓋默認導出樣式;多步設置時注意順序。 |
| ExcelJS 版本兼容 | 插件依賴 exceljs,建議版本 ^4.3.0,不同版本 API 可能有細微差異,請查閱對應文檔。 |
以上就是Vue使用vxe-table導出和自定義Excel樣式的詳細教程的詳細內(nèi)容,更多關于Vue vxe-table導出Excel的資料請關注腳本之家其它相關文章!
相關文章
vue實現(xiàn)動態(tài)數(shù)據(jù)綁定
本篇文章主要介紹了vue實現(xiàn)動態(tài)數(shù)據(jù)綁定,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
詳解為element-ui的Select和Cascader添加彈層底部操作按鈕
這篇文章主要介紹了詳解為element-ui的Select和Cascader添加彈層底部操作按鈕,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02

