【第一个Vue上手小项目Day6】导出Excel表格(解决分页矛盾+导出指定内容)
目录
- 一、初级版
- 二、中级篇(导出指定内容)
- 2.1 需求
- 2.2 重写文件导出方法
- 2.3 后端结合
- 三、高级篇(解决分页问题)
- 四、源码
- 4.1 项目源码
- 4.2 本节全部源码
一、初级版
【目标】导出页面上存在的表格
-
安装依赖(-S === --save、 -D === --save-dev)
cnpm install -S file-saver xlsx
cnpm install -D script-loader -
静态数据导出测试
<template><div><div class="toexcel"><el-button @click="exportExcel" type="primary" class="button" style="width:70px;position:absolute;top:0;right:30px">导出el-button>div><el-table class="table" :data="tableData" border style="width: 100%"><el-table-column prop="date" label="日期" width="180">el-table-column><el-table-column prop="name" label="姓名" width="180">el-table-column><el-table-column prop="address" label="地址">el-table-column>el-table>div> template><script>import FileSaver from "file-saver";import XLSX from "xlsx";//需要导出的位置才引入,不必要配置在main.js中export default {data() {return {tableData: [{date: '2016-05-02',name: '王小虎',address: '上海市普陀区金沙江路 1518 弄'}, {date: '2016-05-04',name: '王小虎',address: '上海市普陀区金沙江路 1517 弄'}, {date: '2016-05-01',name: '王小虎',address: '上海市普陀区金沙江路 1519 弄'}, {date: '2016-05-03',name: '王小虎',address: '上海市普陀区金沙江路 1516 弄'}]};},methods: {// 导出表格所用exportExcel() {// 设置当前日期let time = new Date();let year = time.getFullYear();let month = time.getMonth() + 1;let day = time.getDate();let name = year + "" + month + "" + day;// console.log(name)/* generate workbook object from table */// .table要导出的是哪一个表格var wb = XLSX.utils.table_to_book(document.querySelector(".table"));//没有明确具体表名,因为一个vue钩子只有一张表/* get binary string as output */var wbout = XLSX.write(wb, {bookType: "xlsx",bookSST: true,type: "array"});try {// name+'.xlsx'表示导出的excel表格名字FileSaver.saveAs(new Blob([wbout], {type: "application/octet-stream"}),name + ".xlsx");} catch (e) {if (typeof console !== "undefined") console.log(e, wbout);}return wbout;}}}; script> <style scoped>/* 导出按钮 */.toexcel {cursor: pointer;cursor: hand;width: 70px;height: 34px;} style>测试结果:(简单表格读取打印ok~)

二、中级篇(导出指定内容)
2.1 需求
【原因】上面这样的打印是页面上的内容title和内容全部打印出来,
如果是翻页加自定义动态表格,还会打印出btn名称???? ?
这就不对了,需要特别处理!

【分析】打印时不应该提取页面显示内容打印,应该对请求返回的list进行打印,即打印ajax返回的内容
【扩展需求】打印时,增加只打印勾选行和列进行打印功能。
2.2 重写文件导出方法
封装表格打印方法,实现可重写标题和内容;
-
创建src/vendor,并创建两个文件
Blob.js(File格式流转换)和Export2Excel.js(表格重写方法声明)

Blob.js:快速链接Github-Blob.js
Export2Excel.js: 快速链接 -
实现原理:
<template><el-button @click="handleDownload" type="primary" class="button">导出2el-button> template><script>// import FileSaver from "file-saver";// import XLSX from "xlsx";//因为重写了,可省略export default {methods: {// 下载handleDownload() {//数据导出方法require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel');//Export2Excel的地址const tHeader = ['序号', '文章标题', '作者', '阅读数', '发布时间'];//表头const filterVal = ['id', 'title', 'author', 'views', 'display_time'];//list里面的对应数据const list = [//将导出数据赋值{id: 1,title: 2,author: 3,pageviews: 4,display_time: 5},{id: 6,title: 7,author: 8,pageviews: 9,display_time: 10},{id: 11,title: 12,author: 13,pageviews: 14,display_time: 15},];const data = this.formatJson(filterVal, list);//参数过滤方法export_json_to_excel(tHeader, data, '列表excel');//表名,方法封装在在Export2Excel中})},// 参数过滤formatJson(filterVal, jsonData) {return jsonData.map(v => filterVal.map(j => v[j]))},}}; script><style scoped> style>测试结果:

2.3 后端结合
先获取数据,再下载内容:
<template><div><el-button @click="exportExcel" type="primary" class="button">导出2el-button>div>
template><script>export default {data() {return {userList: [],}},methods: {exportExcel(){this.getUserList();//先获取后端全部内容this.handleDownload();//再导出excel},//获取数据getUserList() {this.$ajax.get('/user/aop/list').then((res) => { //axios发送get请求if (res.data) {console.log(res.data)this.userList = res.data.data;} else {this.$message({type: 'error',message: '查询失败',showClose: true})}})},// 下载handleDownload() {//数据导出方法require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel');//Export2Excel的地址,与配置路径相对应const tHeader = ['序号', '姓名', '年龄', '地址', '密码'];//表头const filterVal = ['id', 'name', 'age', 'address', 'password'];//list里面的对应数据const list = this.userList; //将导出数据赋值const data = this.formatJson(filterVal, list);//参数过滤方法export_json_to_excel(tHeader, data, '列表excel');//表名,方法封装在在Export2Excel中})},// 参数过滤formatJson(filterVal, jsonData) {return jsonData.map(v => filterVal.map(j => v[j]))},}};
script>
<style scoped>
style>
测试结果:

这里是跳过了分页,用以上得到全部list和自定义header的方法,直接下载数据库全部内容。
三、高级篇(解决分页问题)
【思路】
- 得到多选框内容,在
multipleSelection存放将要导出的内容; - 全部导出为
userList内容(get请求获取内容),部分导出为multipleSelection的手动勾选内容; - 把内容传给Excel导出的body中,导出 ?。
【用法】
-
data中设置集合存储,
userList、multipleSelection; -
在批量导出Btn加上:
@selection-change="handleSelectionChange"监听;【前提:】
在前面文章中,我用到了element对数据进行翻页和多选设置,不是本篇重点,这里稍稍略过。
参考:【第一个Vue上手小项目Day4】Element-table表格<el-button @click="exportToExcel" @selection-change="handleSelectionChange" type="primary" class="button" size="mini">批量导出el-button> <el-button @click="exportAllToExcel" type="warning" class="button" size="mini">全部导出el-button> <script> ....data() {return {userList: [],multipleSelection: [], //标记选中的集合}} ..method中..handleSelectionChange(val) { //选中的内容,监听状态@selection-change="handleSelectionChange"this.multipleSelection = val;},// ======================部分下载======================exportToExcel() {if (this.multipleSelection.length) { //根据选中的某条数据进行导出require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel'); //Export2Excel的地址,与配置路径相对应const tHeader = ['序号', '姓名', '年龄', '地址', '密码']; //表头const filterVal = ['id', 'name', 'age', 'address', 'password']; //userList里面的对应的全部数据const list = this.multipleSelection; //将导出数据赋值const data = this.formatJson(filterVal, list); //参数过滤方法export_json_to_excel(tHeader, data, '列表excel'); //表名,方法封装在在Export2Excel中})}else {this.$message({message: '请选择至少一项内容',type: 'warning',showClose: true})}},// ===================全部下载==================exportAllToExcel() { //数据导出方法require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel'); //Export2Excel的地址,与配置路径相对应const tHeader = ['序号', '姓名', '年龄', '地址', '密码']; //表头const filterVal = ['id', 'name', 'age', 'address', 'password']; //userList里面的对应的全部数据const list = this.userList; //将导出数据赋值const data = this.formatJson(filterVal, list); //参数过滤方法export_json_to_excel(tHeader, data, '列表excel'); //表名,方法封装在在Export2Excel中})},// 参数过滤formatJson(filterVal, jsonData) {return jsonData.map(v => filterVal.map(j => v[j]))},//导出完毕script>
导出测试:(勾选成功!)

【遇见问题】:翻页之后会刷新之前的勾选状态!
【解决方法】:element table 保持勾选解决方案
- 在
el-table加上:row-key="getRowKeys" - 在第一个勾选状态框加上:
reserve-selection="true"(这是element专门提供翻页,且保持勾选状态)

- 在method中加上:记录方法
getRowKeys(row){//翻页也保存勾选状态return row.id;},
测试结果:大功告成!(翻页、选中内容、导出到表格!)

多页选中导出效果 ?

四、源码
4.1 项目源码
前端:cungudafa–VueDay6
后端:cungudafa–SpringbootDay8
4.2 本节全部源码
userList.vue
<template><div><el-row type="flex" class="row-bg" justify="space-around"><el-col :span="6"><el-button @click="toggleSelection([userList[1], userList[2]])" size="mini">切换第二、第三行的选中状态el-button><el-button @click="toggleSelection()" size="mini">取消选择el-button>el-col><el-col :span="6">el-col><el-col :span="6"><el-button @click="clearFilter" type="success" size="mini"><i class="el-icon-refresh-right">i>刷新el-button><el-button @click="exportToExcel" @selection-change="handleSelectionChange" type="primary" class="button" size="mini"><i class="el-icon-download">i>批量导出el-button><el-button @click="exportAllToExcel" type="warning" class="button" size="mini"><i class="el-icon-download">i>全部导出el-button>el-col>el-row><el-table class="table" ref="filterTable" v-loading="loading" :data="userList.slice((currentPage-1)*pagesize,currentPage*pagesize).filter(data => !search || data.name.toLowerCase().includes(search.toLowerCase()))":default-sort="{prop: 'id', order: 'ascending'}" border tooltip-effect="dark" style="width: 100%"@selection-change="handleSelectionChange" :row-key="getRowKeys"><el-table-column type="selection" reserve-selection="true" width="55">el-table-column><el-table-column prop="id" label="id" sortable width="180">el-table-column><el-table-column prop="name" label="姓名" width="180">el-table-column><el-table-column prop="age" label="年龄" width="180" :formatter="formatter">el-table-column><el-table-column prop="address" label="地址" width="180" :filters="[{ text: '重庆', value: '重庆' }, { text: '北京', value: '北京' },{ text: '上海', value: '上海' }]":filter-method="filterTag" filter-placement="bottom-end"><template slot-scope="scope"><el-tag :type="scope.row.address === '重庆' ? 'primary' : 'success'" disable-transitions>{{scope.row.address}}el-tag>template>el-table-column><el-table-column align="right"><template slot="header" slot-scope="scope"><el-input v-model="search" size="mini" placeholder="输入姓名关键字搜索" />template><template slot-scope="scope"><el-button size="mini" @click="handleEdit(scope.$index, scope.row)">Editel-button><el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">Deleteel-button>template>el-table-column>el-table><div class="block"><el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage":page-sizes="[10, 20, 30, 40]" :page-size="pagesize" layout="total, sizes, prev, pager, next, jumper" :total="userList.length"background>el-pagination>div>div>
template><script>import FileSaver from 'file-saver'import XLSX from 'xlsx'export default {data() {return {userList: [],loading: false, //加载效果multipleSelection: [], //标记选中的集合search: '', //关键词查找currentPage: 1, //最初显示默认要跳转的一页pagesize: 10}},created() {this.getUserList();},methods: {//多行全选和反选toggleSelection(rows) {if (rows) {rows.forEach(row => {this.$refs.filterTable.toggleRowSelection(row);});} else {this.$refs.filterTable.clearSelection(); //反选}},handleSelectionChange(val) { //选中的内容,监听状态@selection-change="handleSelectionChange"this.multipleSelection = val;},getRowKeys(row){//翻页也保存勾选状态return row.id;},//地址排序formatter(row, column) {return row.age;//排序},//标签查找和清除标签resetDateFilter() {this.$refs.filterTable.clearFilter('address');},clearFilter() {this.$refs.filterTable.clearFilter();},filterTag(value, row) {return row.address === value;},filterHandler(value, row, column) {const property = column['property'];return row[property] === value;},//编辑handleEdit(index, row) {console.log(index, row);},//删除handleDelete(index, row) {console.log(index, row);},//分页handleSizeChange(size) {console.log(`每页 ${size} 条`);this.pagesize = size;},handleCurrentChange(currentPage) {console.log(`当前页: ${currentPage}`);this.currentPage = currentPage;},getUserList() {this.loading = true;this.$ajax.get('/user/aop/list').then((res) => { //axios发送get请求if (res.data) {this.loading = false;//console.log(res.data)this.userList = res.data.data;} else {this.loading = false;this.$message({type: 'error',message: '查询失败',showClose: true})}})},// 部分下载exportToExcel() {if (this.multipleSelection.length) { //根据选中的某条数据进行导出require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel'); //Export2Excel的地址,与配置路径相对应const tHeader = ['序号', '姓名', '年龄', '地址', '密码']; //表头const filterVal = ['id', 'name', 'age', 'address', 'password']; //userList里面的对应的全部数据const list = this.multipleSelection; //将导出数据赋值const data = this.formatJson(filterVal, list); //参数过滤方法export_json_to_excel(tHeader, data, '列表excel'); //表名,方法封装在在Export2Excel中})}else {this.$message({message: '请选择至少一项内容',type: 'warning',showClose: true})}},// 全部下载exportAllToExcel() { //数据导出方法require.ensure([], () => {const {export_json_to_excel} = require('@/vendor/Export2Excel'); //Export2Excel的地址,与配置路径相对应const tHeader = ['序号', '姓名', '年龄', '地址', '密码']; //表头const filterVal = ['id', 'name', 'age', 'address', 'password']; //userList里面的对应的全部数据const list = this.userList; //将导出数据赋值const data = this.formatJson(filterVal, list); //参数过滤方法export_json_to_excel(tHeader, data, '列表excel'); //表名,方法封装在在Export2Excel中})},// 参数过滤formatJson(filterVal, jsonData) {return jsonData.map(v => filterVal.map(j => v[j]))},//导出完毕}}
script>
<style scoped>.el-row {margin-bottom: 20px;&:last-child {margin-bottom: 0;}}.el-col {border-radius: 4px;}.row-bg {padding: 10px 0;background-color: #f9fafc;}
style>
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
