新增excel导出

This commit is contained in:
zouzhibing 2022-05-18 15:53:43 +08:00
parent 1c6d61da6b
commit a6abe9ced8
7 changed files with 186 additions and 26 deletions

View File

@ -42,20 +42,5 @@ vue3.0 + Typescript + vuex + vue-router + Element-Plus scss
- 退出
- 其他各组件
## 开发
```
# 克隆项目
git clone https://github.com/zouzhibin/vue-admin-perfect.git
# 安装依赖
yarn install
# 本地开发 启动项目
yarn serve
```
### 发布
```
yarn build
```

View File

@ -32,6 +32,12 @@ const excelRouter = {
name: 'upload-excel',
meta: { title: '上传 Excel', noCache: true }
},
{
path: 'upload-style-excel',
component: () => import('@/views/excel/export-style-excel.vue'),
name: 'upload-style-excel',
meta: { title: '自定义样式导出 Excel', noCache: true }
},
]
}

View File

@ -8,7 +8,7 @@ const othersRouter = {
redirect: 'noRedirect',
name: 'other',
meta: {
title: '扩展',
title: '扩展组件',
icon: 'management'
},
children: [

View File

@ -63,6 +63,88 @@ export const exportExcel = async ({column,data,filename,autoWidth,format})=>{
window.URL.revokeObjectURL(link.href); // 释放内存
}
}
export function addCellStyle(cell, attr) {
const {color, fontSize, horizontal, bold} = attr || {};
// eslint-disable-next-line no-param-reassign
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: {argb: color},
};
// eslint-disable-next-line no-param-reassign
cell.font = {
bold: bold ?? true,
size: fontSize ?? 11,
// italic: true,
// name: '微软雅黑',
color: {argb: 'ff0000'},
};
// eslint-disable-next-line no-param-reassign
cell.alignment = {vertical: 'middle', wrapText: true, horizontal: horizontal ?? 'left'};
}
export const exportStyleExcel =async ({column,data,filename,autoWidth,format})=>{
// 创建excel
const workbook = new ExcelJS.Workbook();
// 设置信息
workbook.creator = "Me";
workbook.title = filename;
workbook.created = new Date();
workbook.modified = new Date();
// 创建工作表
const worksheet = workbook.addWorksheet(filename);
// 设置列名
let columnsName = [];
column.forEach((item,index)=>{
let obj = {
header: item.label, key:item.name, width: null
}
if(autoWidth){
let maxArr = [autoWidthAction(item.label)]
data.forEach(ite=>{
let str = ite[item.name] ||''
if(str){
maxArr.push(autoWidthAction(str))
}
})
obj.width = Math.max(...maxArr)+5
}
// 设置列名、键和宽度
columnsName.push(obj);
})
worksheet.columns = columnsName;
// 添加行
worksheet.addRows(data);
// 写入文件
// 设置表头颜色
// 给表头添加背景色。因为表头是第一行,可以通过 getRow(1) 来获取表头这一行
const headerRow = worksheet.getRow(1);
// 通过 cell 设置样式,更精准
headerRow.eachCell((cell) => addCellStyle(cell, {color: 'dff8ff', fontSize: 12, horizontal: 'left'}));
const uint8Array =
format === "xlsx"
? await workbook.xlsx.writeBuffer()
: await workbook.csv.writeBuffer();
const blob = new Blob([uint8Array], { type: "application/octet-binary" });
if (window.navigator.msSaveOrOpenBlob) {
// msSaveOrOpenBlob方法返回boolean值
navigator.msSaveBlob(blob, filename + `.${format}`);
// 本地保存
} else {
const link = document.createElement("a"); // a标签下载
link.href = window.URL.createObjectURL(blob); // href属性指定下载链接
link.download = filename + `.${format}`; // dowload属性指定文件名
link.click(); // click()事件触发下载
window.URL.revokeObjectURL(link.href); // 释放内存
}
}
// 默认的列宽
export const DEFAULT_COLUMN_WIDTH = 20;

View File

@ -0,0 +1,96 @@
<template>
<div>
<div style="margin-bottom: 15px;display: flex;align-items: center">
<el-input v-model="input" placeholder="请输入文件名" style="width: 200px;margin-right: 10px"/>
<el-button @click="exportExcelAction" type="primary">
<el-icon style="margin-right: 10px"><document-remove /></el-icon> Excel
</el-button>
</div>
<el-table :data="list" style="width: 100%" border>
<template v-for="item,index in column" :key="index">
<el-table-column :prop="item.name" :label="item.label" :width="item.width" />
</template>
</el-table>
</div>
</template>
<script lang="ts" setup>
import {ref,reactive} from "vue";
import * as dayjs from 'dayjs'
import { ElMessage,ElMessageBox } from 'element-plus'
import {exportStyleExcel} from '@/utils/exprotExcel'
const data = []
for(let i=0;i<10;i++){
data.push({
date: '2016-05-02',
name: '王五'+i,
price: 1+i,
province: '上海',
admin:"admin",
sex:i%2?1:0,
checked:true,
id:i+1,
age:0,
city: '普陀区',
address: '上海市普上海',
zip: 200333
})
}
const column = [
{ name: 'id', label: 'id', },
{ name: 'name',
label: '姓名',
inSearch:true,
valueType:'input',
},
{ name: 'age',
label: '年龄',
align:'right',
},
{ name: 'sex',
label: '性别',
slot:true,
inSearch:true,
options:[{
value:1,
label:'男'
},{
value:0,
label:'女'
}],
valueType:'select',
},
{
name: 'price',
label: '价格',
inSearch:true,
valueType:'input',
},
{ name: 'admin', label: '账号', inSearch:true,
valueType:'input',},
{ name: 'address', label: '地址', inSearch:true,
valueType:'input', },
{ name: 'date', label: '日期',sorter:true, inSearch:true,
valueType:'input', },
{ name: 'province', label: '省份' },
{ name: 'city', label: '城市' },
{ name: 'zip', label: '邮编' },
]
const list = ref(data)
const input = ref('')
const format = ref('xlsx')
const exportExcelAction = ()=>{
exportStyleExcel({
column,
data,
filename:input.value||'导出 excel',
format:format.value,
autoWidth:true
})
}
</script>
<style>
</style>

View File

@ -4,6 +4,7 @@
style="width: 100%"
class="upload-demo"
drag
action="/"
:before-upload="beforeUploadAction"
type="file" accept=".xlsx, .xls"
>

View File

@ -1,15 +1,5 @@
<template>
<div class="login-container">
<!-- <video-->
<!-- poster="@/assets/mp4/3.jpeg"-->
<!-- loop-->
<!-- autoplay-->
<!-- muted-->
<!-- >-->
<!-- <source src="@/assets/mp4/2.mp4">-->
<!-- </video>-->
<!-- <img src="@/assets/3.png" class="bg"/>-->
<div class="login-box">
<!--登录功能-->
<div style="color: white;text-align: center;margin-bottom: 15px">登录系统-密码账号随便填 admin admin</div>