From 214b8ea106ab2285a7ca11c0c568d03b79e6ffa9 Mon Sep 17 00:00:00 2001 From: Stanislav Popov Date: Sat, 18 Apr 2020 00:28:00 +0500 Subject: [PATCH] feat: xlsx export --- package-lock.json | 88 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- pages/index.scss | 8 +++++ pages/index.vue | 69 +++++++++++++++++++++++++++++++++++-- 4 files changed, 164 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24adc9b..8668502 100644 --- a/package-lock.json +++ b/package-lock.json @@ -273,6 +273,15 @@ "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", "dev": true }, + "adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", + "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -1799,6 +1808,17 @@ "lazy-cache": "^1.0.3" } }, + "cfb": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.1.4.tgz", + "integrity": "sha512-rwFkl3aFO3f+ljR27YINwC0x8vPjyiEVbYbrTCKzspEf7Q++3THdfHVgJYNUbxNcupJECrLX+L40Mjm9hm/Bgw==", + "requires": { + "adler-32": "~1.2.0", + "commander": "^2.16.0", + "crc-32": "~1.2.0", + "printj": "~1.1.2" + } + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -2025,6 +2045,22 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "codepage": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz", + "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", + "requires": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==" + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2484,6 +2520,15 @@ } } }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -3607,6 +3652,11 @@ "strip-eof": "^1.0.0" } }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==" + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -4187,6 +4237,11 @@ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==" + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -9771,6 +9826,11 @@ "utila": "~0.4" } }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==" + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -10841,6 +10901,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "ssf": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.3.tgz", + "integrity": "sha512-pRuUdW0WwyB2doSqqjWyzwCD6PkfxpHAHdZp39K3dp/Hq7f+xfMwNAWIi16DyrRg4gg9c/RvLYkJTSawTPTm1w==", + "requires": { + "frac": "~1.1.2" + } + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -12293,6 +12361,11 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, + "wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==" + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -12359,6 +12432,21 @@ "safe-buffer": "~5.1.0" } }, + "xlsx": { + "version": "0.15.6", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.15.6.tgz", + "integrity": "sha512-7vD9eutyLs65iDjNFimVN+gk/oDkfkCgpQUjdE82QgzJCrBHC4bGPH7fzKVyy0UPp3gyFVQTQEFJaWaAvZCShQ==", + "requires": { + "adler-32": "~1.2.0", + "cfb": "^1.1.4", + "codepage": "~1.14.0", + "commander": "~2.17.1", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.3", + "wmf": "~1.0.1" + } + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/package.json b/package.json index 29df6c9..4af718b 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "style-loader": "^0.23.1", "vue-awesome": "^3.2.0", "vue-style-loader": "^4.1.2", - "vue-tables-2": "^1.4.70" + "vue-tables-2": "^1.4.70", + "xlsx": "^0.15.6" }, "devDependencies": { "babel-eslint": "^8.2.1", diff --git a/pages/index.scss b/pages/index.scss index 88b4daf..5e04d2b 100644 --- a/pages/index.scss +++ b/pages/index.scss @@ -108,6 +108,14 @@ } } +.table-actions { + float: right; + margin-bottom: -100px; + .btn-excel { + color: #008000; + } +} + .VueTables { margin-top: 15px; diff --git a/pages/index.vue b/pages/index.vue index 5f567aa..5a00e4c 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -4,6 +4,12 @@ +
+ +
+ { + return { width: key.length + 2 }; // plus 2 to account for short object keys + }); + for (let i = 0; i < json.length; i++) { + let value = Object.values(json[i]); + for (let j = 0; j < value.length; j++) { + if (value[j] !== null && widthArr[j] !== undefined && value[j].length > widthArr[j].width) { + widthArr[j].width = value[j].length; + } + } + } + return widthArr; + }, + + buildXlsx() { + const table = this.$el.querySelector(".VueTables__table"); + const wb = XLSX.utils.table_to_book(table); + const ws = wb.Sheets[wb.SheetNames[0]]; + + const lastCell = ws['!ref'].split(':')[1]; + const range = XLSX.utils.decode_range('B1:'+lastCell); + + const cols = [1]; + + for(let r = 0; r <= range.e.r; r++){ + // delete first col + const firstAddr = XLSX.utils.encode_cell({r:r, c:0}); + delete(ws[firstAddr]); + + // count columns width + for(let c = 1; c <= range.e.c; c++) { + const addr = XLSX.utils.encode_cell({r:r, c:c}); + const length = Object.values(ws[addr].v).length + 2; + if(!cols[c]) cols[c] = length; + else cols[c] = Math.max(cols[c], length); + } + } + const colsObj = cols.map(length => { return {width: length} }); + + ws['!cols'] = colsObj; + ws['!autofilter'] = { ref: 'B1:'+lastCell }; + + // console.log('wb: ', wb); + return wb; + }, + + getXlsx() { + const wb = this.buildXlsx(); + const suffix = this.q ? "--" + this.q.replace(/&/g, ",") : ""; + const filename = `viasite-projects${suffix}.xlsx`; + XLSX.writeFile(wb, filename, {}); + }, + // переключает поле в таблице по клику toggleField(field, add) { this.$store.dispatch("toggleField", { field, add }); @@ -240,8 +303,8 @@ export default { const sitesJson = await this.$axios.$get(this.$store.state.sitesJsonUrl); this.$store.commit("tests", sitesJson.tests); this.$store.dispatch("sites", sitesJson.sites); - if(!this.$route.query["q"]){ - this.$route.query["q"] = 'prod=1'; + if (!this.$route.query["q"]) { + this.$route.query["q"] = "prod=1"; } this.$store.dispatch("q", this.$route.query["q"]);