-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSheetExportButton.vue
137 lines (125 loc) · 4.22 KB
/
SheetExportButton.vue
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
135
136
137
<template>
<button @click.prevent="initExport" class="btn btn-export" :disabled="disabled">
<svg width="30" height="30" viewBox="0 0 24 24"
fill="none"
stroke="#fff"
stroke-width="1.5"
stroke-linecap="round">
<path d="M8 17l4 4 4-4M12 12v9"></path>
<path d="M20.88 18.09A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.29"></path>
</svg>
</button>
</template>
<script>
/**
* SheetJS version
* @see https://cdnjs.com/libraries/xlsx
* @type {string}
*/
const VERSION = '0.15.1';
export default {
props: {
disabled: Boolean,
title: String,
file: String,
transformer: Function
},
data() {
return {
sheetTitle: this.title || 'Export',
filename: this.file || 'export'
}
},
methods: {
/**
* Launch the export flow
* @return void
*/
initExport() {
this.spin(1)
.loadScript(VERSION)
.then(() => this.exportToExcel().spin(0))
.catch(error => console.error('Script loading failed!', error))
},
/**
* Export to Excel using SheetJS
* @return this
*/
exportToExcel() {
let workBook = XLSX.utils.book_new(),
sheet = this.transformer(),
filename = this.getFileName(this.filename + '-' + this.sheetTitle);
//return this;
sheet = XLSX.utils.aoa_to_sheet(sheet);
XLSX.utils.book_append_sheet(workBook, sheet, this.sheetTitle);
XLSX.writeFile(workBook, filename);
return this;
},
/**
* Load the SheetJS script from a CDN given its version
* @param {String} version
* @param {Object} options
* @return {Promise}
*/
loadScript(version, options = {}) {
if (window.XLSX) return Promise.resolve();
return new Promise((resolve, reject) => {
let d = document,
url = `https://cdnjs.cloudflare.com/ajax/libs/xlsx/${version}/xlsx.full.min.js`,
ref = d.getElementsByTagName('script')[0],
script = d.createElement('script');
if (options.attributes) {
Object.keys(options.attributes).forEach(k => script.setAttribute(k, options.attributes[k]));
}
script.async = true;
script.onload = () => resolve();
script.onerror = error => reject(error);
script.src = url;
ref.parentNode.insertBefore(script, ref);
})
},
/**
* Setup the filename
* @param {String} name
* @param {Boolean} timestamp
* @return {string}
*/
getFileName(name, timestamp = true) {
name = name.toLowerCase().replace(' ', '-');
return name + (timestamp ? '-' + Math.round((new Date).getTime() / 1000) : '') + '.xlsx'
},
/**
* Toggle some spinning
* @param {Boolean|Number} state
* @return this
*/
spin(state) {
this.$el.classList[state ? 'add' : 'remove']('btn-spin');
return this;
}
}
}
</script>
<style>
.btn-spin:after {
content: '';
position: absolute; top: -5px; left: -5px;
width: 50px; height: 50px;
transform-origin: 50% 50%;
border: 5px solid rgba(0, 0, 0, 0);
border-top: 5px solid #fff;
border-radius: 50%;
opacity: 0;
animation: spin 1s cubic-bezier(0.46, 0.03, 0.52, 0.96) infinite;
}
@keyframes spin {
0% {
opacity: 1;
transform: rotate(0deg);
}
100% {
opacity: 1;
transform: rotate(360deg);
}
}
</style>