vue + vue-json-excel 制作导出excel
项目场景:
项目场景:我目前有一个列表,功能可以筛选时间以及渠道,筛选出来的数据包含订单号字段,渲染在列表中,我需要把所有的订单号,根据时间渠道筛选后,把筛选后的所有订单号导出只Excel中。
这个功能一开始也是在网上找办法,但是也是不是很适用,这里就分享一下我的解决方案。
注:这里只提供思路及方法,直接复制就无法使用的,因为涉及到其他的组件(时间,渠道)就没有放全代码了,建议参考一下思路,然后用自己的方法来实现会比复制粘贴更好,授人以鱼不如授人以渔这个道理相信大家都懂。
效果
当点击导出则直接下载对应的数据,这里表头为Hader(可自定义),TrackingNo(必须)为订单号下面的为导出的数据,Startime(必须):开始时间,Endtime(必须):结束时间,LabelType:渠道:当为空时显示空。
1.安装并引入vue-json-excel:
我这里是通过npm的包管理器,并且进行全局引入的方式。
1.下载vue-json-excel
npm i vue-json-excel
2.全局引入
在main.js中
//导入导出excel表格组件
import JsonExcel from 'vue-json-excel'
Vue.component('downloadExcel', JsonExcel)
2.页面中使用
1.HTML
<download-excel
class="export-excel-wrapper"
:data = "print"
:fields = "json_fields"
type="csv"
header = "Header"
name = "filename"
style="width:100px;float: left;"
>
<el-button style="margin-left:20px" type="primary">{{$t('export')}}</el-button>
</download-excel>
2.JS
export default {
data(){
return{
print:[],
json_fields:{}
}
},
methods(){
GetJsonFileds(val){ //导出
let params={
TrackingNo : this.photoinfo.waybill_number,
StockID : this.StockInfovalue,
LabelType : this.photoinfo.LabelType,
Startime : this.photoinfo.starttime[0],
Endtime : this.photoinfo.starttime[1],
}
if (val == 2) {
if (this.photoinfo.starttime.length == 0) {
return
}
}
if (this.photoinfo.starttime.length == 0) {
this.$message.warning(this.$t('Unselected_time'))
}
if (params.LabelType == '') {
params.LabelType = ''
}else{
params.LabelType = params.LabelType.join(',')
}
this.$api.post('/Shipment/DownTrackingNoPhotodata',params).then((res) => {
if(res.return_codes==0){
this.print = res.return_data[0].Date
if (this.print.length == 0) {
this.$message.error(this.$t('Data_in_this_time_range_is_null'))
return
}
if (val != 1 && val != 2) {
this.$message.success(this.$t('exporting'))
}
this.print[0].Startime = res.return_data[0].Startime || 'empty'
this.print[0].Endtime = res.return_data[0].Endtime || 'empty'
this.print[0].LabelType = this.photoinfo.LabelType || 'empty'
this.json_fields={
TrackingNo:'TrackingNo',
Startime:'Startime',
Endtime:'Endtime',
LabelType:'LabelType'
}
}else{
this.$message.error(this.$t('operation_failed'))
}
})
},
}
}
字段说明
- class:类
- data:这个data是需要打印的数据
- fields:打印格式
- type:导出的类型
- header:头
- name:导出的文件名
- style:样式
实现逻辑
首先我这里有一个时间选择控件和渠道控件将这些控件的值改变时就会触发GetJsonFileds
函数,并且会带值,证明是渠道或者时间,这个后面会用到。
先说一下为什么要这样子做,因为我在做完之后发现一个很严重的问题,就是这个导出的逻辑是,通过读取data
里面的值,通过fields
导出来的,这样子就会出现一个问题,就是数据的更新是在导出的后面的所以导出的数据要么为空导不出来,要么是上一次的数据。
所以这里就想到这个办法,在选择时间控件的时候,就先去触发函数进行预处理,先把数据处理好,因为时间这里是必选,所以放在时间上没有问题,如果不选择时间的话,这里this.photoinfo.starttime.length
便会直接跳出提示需要输入时间。
但是这样子又还有一个问题就是先选完时间之后再去选择渠道最后打印渠道又是慢一步的,按照同样的方法的话,渠道又不是必选的,所以这里又要在判断一次,通过渠道传入的2在判断,这里的话就分两种情况来处理,一时先选择时间,二是先选择渠道,如果先选择渠道则不需要动直接return,但是如果先选择的是时间的话,在选择渠道就需要重新更新数据,使用直接拿时间的值就好了,能拿到到就说明是先选择的时间。
这里注意一个重要的逻辑,导出的事件是放在按钮上的,而导出的数据是放在时间控件值改变上的。
处理好这个之后便可以去调用后台接口去拿数据,拿到数据之后直接传给print
,并且判断是不是为空,如果为空就是证明这个时间段是没有数据的一样跳出,这里的话也可以直接判断后端的返回数据都一样的。
现在拿到后端数据并且确定有数据之后将数据写入到print里面,并且修改它的格式。
总结
这里要注意一个坑:目前我看到网上其他的都没有说到这一点,当导出的数据为动态数据的时候,如果fields在data中定义的话那么最终导出的数据都是上一次的数据,所以我这里的方法是在选择完对应筛选信息后先去更新一遍数据,在后续导出时保证导出的是最新的筛选数据。
这个导出的流程为:
先选择渠道
- 选择渠道
- 渠道值改变触发函数,但是函数并没有什么操作
- 选择时间
- 时间值改变更新数据,这里会将渠道的值一起更新过去
- 导出
先选择时间
- 选择时间
- 时间的值改变,更新数据,但是此时渠道的值为空
- 选择渠道
- 渠道值改变,重新更新数据,此时会带上渠道的值,时间的值一致
- 导出
以上就是我解决这个方法的思路