您现在的位置是:首页 > 技术教程 正文

vue3前端excel导出;组件表格,自定义表格导出;Vue3 + xlsx + xlsx-style

admin 阅读: 2024-04-01
后台-插件-广告管理-内容页头部广告(手机)

当画面有自定义的表格或者样式过于复杂的表格时,导出功能可以由前端实现

1. 使用的插件 : sheet.js-xlsx

文档地址:https://docs.sheetjs.com/
中文地址:https://geekdaxue.co/read/SheetJS-docs-zh/README.md
xlsx-style:https://www.npmjs.com/package/xlsx-style
在这里插入图片描述

2. 安装引用

安装插件-vue3

yarn add xlsx yarn add xlsx-style-vite (有样式需求才需要安装;背景色等)
  • 1
  • 2

引用插件

import * as XLSX from 'xlsx'; import * as XLSX_STYLE from 'xlsx-style-vite'
  • 1
  • 2

3. 组件表格的导出(无样式)

以ant design vue 表格为例,只导出表格内容

<a-table :columns="columns" :dataSource="detaildata" :scroll="{ x: 'max-content',y:700 }" >table?> <a-button @click="exportData">导出a-button> <script> //数据处理为数组 const transData=(columns, tableList)=> { const obj = columns.reduce((acc, cur) => { if (!acc.titles && !acc.keys) { acc.titles = []; acc.keys = []; } acc.titles.push(cur.title); acc.keys.push(cur.dataIndex); return acc; }, {}); const tableBody = tableList.map((item,i) => { return obj.keys.map((key,index) => item[key]); }); return [ obj.titles, ...tableBody ]; } const exportData=()=>{ const tableData = transData( columns.value, detaildata.value ); // 将数据数组转换为工作表 const ws = XLSX.utils.aoa_to_sheet(tableData); // 创建 workbook const wb = XLSX.utils.book_new(); ws['!ref'] = `A1:AI${tableData.length}`; //设置列宽 ws["!cols"] = [ {wpx: 120}, {wpx: 100}, {wpx: 110}, {wpx: 110},]; //合并单元格 ws['!merges'] = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 1 } }] // 将 工作表 添加到 workbook XLSX.utils.book_append_sheet(wb, ws, 'Sheet1'); // 将 workbook 写入文件 XLSX.writeFile(wb, 'tablename.xlsx'); } script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

3. 自定义表格的导出 (div拼成的表格)

比如这种前端拼成的,又附带各种样式的表格
在这里插入图片描述
一些常用的格式:
(1):合并单元格
(2):列宽
(3):背景色
(4):字体相关-大小粗细颜色字体等
(5):表格线,边框
详细的格式可以参考:
https://www.jianshu.com/p/869375439fee
https://www.npmjs.com/package/xlsx-style

数据处理就不写了,数据处理为数组就可以了 const toExcel=()=>{ const data = [ ['左上表头','','','右上',''], ['标题1','','','',''], ['标题','测试合并','','',''], ['固定标题','123','123','',''], ['左下表头','','','右下',''], ['2021','¥28337','测试数据','北京','黑龙江'], ...... ] const worksheet = XLSX.utils.aoa_to_sheet([headers, ...data]) const workbook = XLSX.utils.book_new() worksheet['!ref'] = `A1:AI${data.length}` //列宽 按excel的列顺序排列,对应A列,B列, C列...... worksheet["!cols"] = [ {wpx: 200}, {wpx: 80}, {wpx: 80}, {wpx: 110}, {wpx: 110}, ]; /* 合并单元格 默认合并当前格的右侧格子 { s: { r: 0, c: 0 }, e: { r: 0, c: 1 } } A1 与 B1 合并 内容为 A1 的内容 s:start 合并开始 e:end 合并结束 r:row 行 c:col 列 */ worksheet['!merges'] = [ { s: { r: 0, c: 0 }, e: { r: 0, c: 1 } }, { s: { r: 0, c: 4 }, e: { r: 0, c: 5 } }, { s: { r: 4, c: 0 }, e: { r: 4, c: 1 } }, ...... ]; //表格详细样式 for (let key in worksheet) { if (key == '!ref' || key == '!merges' || key == '!cols' || key == '!rows') { continue } else { //通过key值来选择筛选想要的设置样式的单元格 if (key.substring(1)=='1'||key.substring(1)=='5'|| key == 'A2') { worksheet[key].s = { // 设置单元格样式 fill: { // 设置背景色 fgColor: { rgb: 'F2F3F7' }, }, font: { // 设置字体 name: '等线', // 字体名称 sz: 16, // 字体大小 bold: true, // 字体是否加粗 color:{ //字体颜色 rgb:'ed263d' } }, border:{ //设置边框 top: { style: 'thin', color:{ rgb:'e5e7eb' } }, bottom: { style: 'thin', color:{ rgb:'e5e7eb' } } }, alignment: { horizontal: 'center', // 横向(向左、向右、居中) vertical: 'center', // 纵向(向上、向下、居中) wrapText: true, // 设置单元格自动换行,目前仅对非合并单元格生效 indent: 0 // 设置单元格缩进 } } }else if(key == 'B1'){ ...... } } } XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') const tmpDown = new Blob([ s2ab( XLSX_STYLE.write(workbook, { bookType: 'xlsx', bookSST: false, type: 'binary', cellStyles: true, }) ), ]) downloadExcelFile(tmpDown, 'excelname' + '.xlsx') } /*用到的方法*/ export 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 标签下载文件 */ export 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) }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134

参考文章:https://blog.csdn.net/Cai181191/article/details/131130926

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索