1.安裝
npm install xlsx --save
npm install xlsx-style --save
(安裝xlsx-style後會報錯,解決方案:https://blog.csdn.net/HDdgut/article/details/115356719)
2.導出並加表格樣式流程
創建excel文件
創建一個sheet
將sheet放進excel裏
將已有列表數據整理成想要的格式(如:標題 表頭 數據行)
將該數據轉成sheet格式(aoa_to_sheet)
然後用循環sheet數據(該數據就是excel表格中的沒一個單元格的列表,使用列行命名如A1)
利用單元格cells的名字區別是哪行哪列,然後設置樣式
最後將寫完樣式的sheet數據用XLSXStyle.write、下載
<template>
<div class="app-container">
<el-button type="warning" icon="el-icon-download" @click="exportClick">導出</el-button>
<vxe-table
:cell-config="{height: 70}"
:loading="listLoading"
stripe
style="width: 100%"
size="medium"
border
resizable
row-key
highlight-current-row
highlight-hover-row
:height="400"
:data="tableData"
align="center"
>
<vxe-table-column type="seq" width="60" fixed="left" title="序號" />
<vxe-table-column
field="name"
align="center"
title="名字"
min-width="130"
/>
<vxe-table-column
field="mobile"
align="center"
title="手機號碼"
min-width="110"
/>
<vxe-table-column
field="price"
align="center"
title="金額"
min-width="110"
/>
<vxe-table-column
field="team"
align="center"
title="所屬團隊"
min-width="100"
/>
</vxe-table>
</div>
</template>
<script>
import XLSX from 'xlsx'
import XLSXStyle from 'xlsx-style'
export default {
name: 'Test',
components: {},
data() {
return {
tableData: [
{ name: '張三', mobile: '13300000001', price: '623.00', team: '團隊一' },
{ name: '張思', mobile: '13300000002', price: '20.00', team: '團隊二' },
{ name: '張武', mobile: '13300000003', price: '90.00', team: '團隊三' },
{ name: '張柳', mobile: '13300000004', price: '54.00', team: '團隊四' }
],
listLoading: false
}
},
created() {
},
mounted() {
},
methods: {
// 導出按鈕方法
exportClick() {
const workbook = XLSX.utils.book_new()// 創建一個空的excel文件
const worksheet = XLSX.utils.json_to_sheet(this.tableData)// 將json數據轉成sheet格式(創建出一個sheet文件)
XLSX.utils.book_append_sheet(workbook, worksheet)// 將sheet加進excel文件裏
const tableData = this.tableData
const columnHeader = {
'name': '名字',
'mobile': '手機號碼',
'price': '金額',
'team': '所屬團隊'
} // 此處是表頭
const dealTableLine = this.transferData(tableData, columnHeader)// 用表頭和數據換取按行形式的數據
const sheetsList = XLSX.utils.aoa_to_sheet(dealTableLine)// 再將數據轉成sheet格式
// 1.設置基礎框架 列寬、合併等
sheetsList['!cols'] = [{ wch: 9 }, { wch: 20 }, { wch: 18 }, { wch: 15 }, { wch: 18 }]// 設置字段寬度;從第一列到最後
sheetsList['!merges'] = [{ s: { c: 0, r: 0 }, e: { c: 4, r: 0 }}]// 設置表標題合併。(s:開始 e:結束)從0列,0行到4列,0行合併
// 2.循環每一列,設置該列的樣式
const borderstyle = { bottom: { style: 'thin', color: 'FF0000' }, right: { style: 'thin', color: 'FF0000' }}// 右+下邊線
for (const cells in sheetsList) {
const cells_row_no = cells.replace(/[^0-9]/ig, '')// 去掉字母只留數字:數字代表行數
const cells_col_no = cells.replace(/[^a-zA-Z]/g, '')// 去掉數字只留字母:字母代表列
// cells:A1 A2 A3 B1 B2...
if (cells != '!ref' && cells != '!merges' && cells != '!cols') { // 排除幾項基礎設定
if (cells_row_no === '1') { // 第一行 標題
sheetsList[cells].s = {
font: { name: '宋體', sz: 16, bold: false },
alignment: { horizontal: 'center', vertical: 'center' },
border: { bottom: { style: 'thin', color: 'FF0000' }}
}
} else if (cells_row_no === '2') { // 第二行 表頭
sheetsList[cells].s = {
fill: { fgColor: { rgb: 'FFFF00' }},
font: { name: '宋體', sz: 14, bold: true },
alignment: { horizontal: 'left', vertical: 'center' },
border: borderstyle
}
} else { // 剩餘所有行
sheetsList[cells].s = {
font: { name: '宋體', sz: 11, bold: false },
alignment: { horizontal: 'left', vertical: 'center' },
border: borderstyle
}
if (cells_col_no == 'B') { // B列 名字
sheetsList[cells].s = {
font: { name: '宋體', sz: 12, color: { rgb: '0563C1' }, underline: false },
alignment: { horizontal: 'left', vertical: 'center' },
border: borderstyle
}
} else if (cells_col_no == 'D') { // D列 金額
sheetsList[cells].s = {
font: { name: '宋體', sz: 14, color: { rgb: 'ff0000' }, underline: true },
alignment: { horizontal: 'left', vertical: 'center' },
border: borderstyle
}
} else {}
}
// A列序號列設置居中
if (cells_col_no == 'A') {
sheetsList[cells].s.alignment.horizontal = 'center'
}
}
}
// 數據循環完畢
workbook['SheetNames'] = ['測試sheet']
workbook['Sheets'] = { '測試sheet': sheetsList }
this.exportFile(this.sheet2blob(workbook), '測試導出表格.xlsx')
},
// 把表頭和數據整理成按行的形式
transferData(data, columnHeader) {
const content = []
const otitle = '測試表格標題'
content.push([otitle])// 1.第一行 表格標題名字
const header = []
for (const i in columnHeader) {
header.push(columnHeader[i])// 生成表頭行
}
header.unshift('序號')
// header: ['序號', '名字', '手機號碼', '金額', '所屬團隊']
content.push(header)// 2.第二行 表頭行
data.forEach((item, index) => {
const arr = []
for (const i in columnHeader) {
arr.push(item[i])
}
arr.unshift(index + 1)
content.push(arr)// 3.循環 依次插入數據行
})
return content
/**
* content:
* [
* ["測試表格標題"],
* ["序號","名字","手機號碼","金額","所屬團隊"],
* [1,"張三","13300000001","623.00","團隊一"],
* ]
*/
},
// 轉xlsx-style的download
sheet2blob(workbook) {
const wbout = XLSXStyle.write(workbook, {
bookType: 'xlsx', // 要生成的文件類型
bookSST: false, // 是否生成Shared String Table,官方解釋是,如果開啓生成速度會下降,但在低版本IOS設備上有更好的兼容性
type: 'binary'
})
const blob = new Blob([s2ab(wbout)], {
type: 'application/octet-stream'
}) // 字符串轉ArrayBuffer
function s2ab(s) {
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
}
return blob
},
// 下載文件方法
exportFile(url, saveName) {
if (typeof url === 'object' && url instanceof Blob) {
url = URL.createObjectURL(url) // 創建blob地址
}
const aLink = document.createElement('a')
aLink.href = url
aLink.download = saveName || '' // HTML5新增的屬性,指定保存文件名,可以不要後綴,注意,file:///模式下不會生效
let event
if (window.MouseEvent) event = new MouseEvent('click')
else {
event = document.createEvent('MouseEvents')
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
}
aLink.dispatchEvent(event)
}
}
}
</script>
<style scoped>
</style>