├── .babelrc ├── .github └── workflows │ └── release.yml ├── .gitignore ├── .releaserc.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── _blob.js ├── _csv.js ├── _export-csv.js ├── _export2Excel.js └── index.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | publish: 10 | if: "! contains(github.event.head_commit.message, '[skip ci]')" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v1 14 | - uses: bahmutov/npm-install@v1 15 | - name: Build 16 | run: npm run build 17 | - name: Semantic Release 18 | uses: cycjimmy/semantic-release-action@v2 19 | with: 20 | extra_plugins: | 21 | @semantic-release/changelog@3.0.6 22 | @semantic-release/git@7.0.18 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | 7 | # Editor directories and files 8 | .idea 9 | *.suo 10 | *.ntvs* 11 | *.njsproj 12 | *.sln 13 | -------------------------------------------------------------------------------- /.releaserc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branch: 'master', 3 | plugins: [ 4 | [ '@semantic-release/commit-analyzer' ], 5 | [ '@semantic-release/release-notes-generator' ], 6 | [ '@semantic-release/changelog', { changelogFile: 'CHANGELOG.md' } ], 7 | [ '@semantic-release/npm', { npmPublish: true } ], 8 | [ '@semantic-release/github' ], 9 | [ '@semantic-release/git', { assets: ['CHANGELOG.md', 'package.json'] } ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.1.3](https://github.com/d2-projects/vue-table-export/compare/v1.1.2...v1.1.3) (2021-01-19) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * :bug: 补充 merges 参数 ([634af3f](https://github.com/d2-projects/vue-table-export/commit/634af3fbe3455afacd4a753e28d602c2bb2bf1b0)) 7 | 8 | ## [1.1.2](https://github.com/d2-projects/vue-table-export/compare/v1.1.1...v1.1.2) (2020-11-25) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * :package: 移除多余的 module 配置 ([345dfb4](https://github.com/d2-projects/vue-table-export/commit/345dfb497137bf2d8ec860ada361751b4e21b078)) 14 | 15 | ## [1.1.1](https://github.com/d2-projects/vue-table-export/compare/v1.1.0...v1.1.1) (2020-11-25) 16 | 17 | 18 | ### Bug Fixes 19 | 20 | * 由于会引起问题,暂时取消列宽设置 ([f3d7f05](https://github.com/d2-projects/vue-table-export/commit/f3d7f051f2ee74294e6f4b7229492bd560b73245)) 21 | 22 | # [1.1.0](https://github.com/d2-projects/vue-table-export/compare/v1.0.1...v1.1.0) (2020-11-02) 23 | 24 | 25 | ### Features 26 | 27 | * 测试CI ([a0aa96c](https://github.com/d2-projects/vue-table-export/commit/a0aa96c1fb79be3b8475f2324f2776c18259614f)) 28 | 29 | 30 | ### Performance Improvements 31 | 32 | * 支持设置列宽 ([adbd7c3](https://github.com/d2-projects/vue-table-export/commit/adbd7c35aa172d0b7e9eda9455bdda2d3db466e3)) 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 FairyEver 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-table-export 2 | 3 | ## externals 4 | 5 | VueTableExport 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@d2-projects/vue-table-export", 3 | "description": "vue plugin to export data to csv | xlsx | txt file", 4 | "version": "1.1.3", 5 | "author": "liyang <1711467488@qq.com>", 6 | "private": false, 7 | "license": "MIT", 8 | "main": "dist/vue-table-export.js", 9 | "files": [ 10 | "dist/", 11 | "src/" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/d2-projects/vue-table-export.git" 16 | }, 17 | "scripts": { 18 | "build": "webpack" 19 | }, 20 | "dependencies": { 21 | "file-saver": "^2.0.0", 22 | "xlsx": "^0.14.1" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/d2-projects/vue-table-export/issues" 26 | }, 27 | "homepage": "https://github.com/d2-projects/vue-table-export#readme", 28 | "devDependencies": { 29 | "@babel/cli": "^7.10.4", 30 | "@babel/core": "^7.10.4", 31 | "@babel/preset-env": "^7.10.4", 32 | "babel-loader": "^8.1.0", 33 | "clean-webpack-plugin": "^3.0.0", 34 | "terser-webpack-plugin": "^3.0.6", 35 | "webpack": "^4.43.0", 36 | "webpack-cli": "^3.3.12" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/_blob.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* Blob.js 3 | * A Blob implementation. 4 | * 2014-05-27 5 | * 6 | * By Eli Grey, http://eligrey.com 7 | * By Devin Samarin, https://github.com/eboyjr 8 | * License: X11/MIT 9 | * See LICENSE.md 10 | */ 11 | 12 | /*global self, unescape */ 13 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 14 | plusplus: true */ 15 | 16 | /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ 17 | 18 | (function (view) { 19 | "use strict"; 20 | 21 | view.URL = view.URL || view.webkitURL; 22 | 23 | if (view.Blob && view.URL) { 24 | try { 25 | new Blob; 26 | return; 27 | } catch (e) {} 28 | } 29 | 30 | // Internally we use a BlobBuilder implementation to base Blob off of 31 | // in order to support older browsers that only have BlobBuilder 32 | var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { 33 | var 34 | get_class = function(object) { 35 | return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; 36 | } 37 | , FakeBlobBuilder = function BlobBuilder() { 38 | this.data = []; 39 | } 40 | , FakeBlob = function Blob(data, type, encoding) { 41 | this.data = data; 42 | this.size = data.length; 43 | this.type = type; 44 | this.encoding = encoding; 45 | } 46 | , FBB_proto = FakeBlobBuilder.prototype 47 | , FB_proto = FakeBlob.prototype 48 | , FileReaderSync = view.FileReaderSync 49 | , FileException = function(type) { 50 | this.code = this[this.name = type]; 51 | } 52 | , file_ex_codes = ( 53 | "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " 54 | + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" 55 | ).split(" ") 56 | , file_ex_code = file_ex_codes.length 57 | , real_URL = view.URL || view.webkitURL || view 58 | , real_create_object_URL = real_URL.createObjectURL 59 | , real_revoke_object_URL = real_URL.revokeObjectURL 60 | , URL = real_URL 61 | , btoa = view.btoa 62 | , atob = view.atob 63 | 64 | , ArrayBuffer = view.ArrayBuffer 65 | , Uint8Array = view.Uint8Array 66 | ; 67 | FakeBlob.fake = FB_proto.fake = true; 68 | while (file_ex_code--) { 69 | FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; 70 | } 71 | if (!real_URL.createObjectURL) { 72 | URL = view.URL = {}; 73 | } 74 | URL.createObjectURL = function(blob) { 75 | var 76 | type = blob.type 77 | , data_URI_header 78 | ; 79 | if (type === null) { 80 | type = "application/octet-stream"; 81 | } 82 | if (blob instanceof FakeBlob) { 83 | data_URI_header = "data:" + type; 84 | if (blob.encoding === "base64") { 85 | return data_URI_header + ";base64," + blob.data; 86 | } else if (blob.encoding === "URI") { 87 | return data_URI_header + "," + decodeURIComponent(blob.data); 88 | } if (btoa) { 89 | return data_URI_header + ";base64," + btoa(blob.data); 90 | } else { 91 | return data_URI_header + "," + encodeURIComponent(blob.data); 92 | } 93 | } else if (real_create_object_URL) { 94 | return real_create_object_URL.call(real_URL, blob); 95 | } 96 | }; 97 | URL.revokeObjectURL = function(object_URL) { 98 | if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { 99 | real_revoke_object_URL.call(real_URL, object_URL); 100 | } 101 | }; 102 | FBB_proto.append = function(data/*, endings*/) { 103 | var bb = this.data; 104 | // decode data to a binary string 105 | if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { 106 | var 107 | str = "" 108 | , buf = new Uint8Array(data) 109 | , i = 0 110 | , buf_len = buf.length 111 | ; 112 | for (; i < buf_len; i++) { 113 | str += String.fromCharCode(buf[i]); 114 | } 115 | bb.push(str); 116 | } else if (get_class(data) === "Blob" || get_class(data) === "File") { 117 | if (FileReaderSync) { 118 | var fr = new FileReaderSync; 119 | bb.push(fr.readAsBinaryString(data)); 120 | } else { 121 | // async FileReader won't work as BlobBuilder is sync 122 | throw new FileException("NOT_READABLE_ERR"); 123 | } 124 | } else if (data instanceof FakeBlob) { 125 | if (data.encoding === "base64" && atob) { 126 | bb.push(atob(data.data)); 127 | } else if (data.encoding === "URI") { 128 | bb.push(decodeURIComponent(data.data)); 129 | } else if (data.encoding === "raw") { 130 | bb.push(data.data); 131 | } 132 | } else { 133 | if (typeof data !== "string") { 134 | data += ""; // convert unsupported types to strings 135 | } 136 | // decode UTF-16 to binary string 137 | bb.push(unescape(encodeURIComponent(data))); 138 | } 139 | }; 140 | FBB_proto.getBlob = function(type) { 141 | if (!arguments.length) { 142 | type = null; 143 | } 144 | return new FakeBlob(this.data.join(""), type, "raw"); 145 | }; 146 | FBB_proto.toString = function() { 147 | return "[object BlobBuilder]"; 148 | }; 149 | FB_proto.slice = function(start, end, type) { 150 | var args = arguments.length; 151 | if (args < 3) { 152 | type = null; 153 | } 154 | return new FakeBlob( 155 | this.data.slice(start, args > 1 ? end : this.data.length) 156 | , type 157 | , this.encoding 158 | ); 159 | }; 160 | FB_proto.toString = function() { 161 | return "[object Blob]"; 162 | }; 163 | FB_proto.close = function() { 164 | this.size = this.data.length = 0; 165 | }; 166 | return FakeBlobBuilder; 167 | }(view)); 168 | 169 | view.Blob = function Blob(blobParts, options) { 170 | var type = options ? (options.type || "") : ""; 171 | var builder = new BlobBuilder(); 172 | if (blobParts) { 173 | for (var i = 0, len = blobParts.length; i < len; i++) { 174 | builder.append(blobParts[i]); 175 | } 176 | } 177 | return builder.getBlob(type); 178 | }; 179 | }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); 180 | -------------------------------------------------------------------------------- /src/_csv.js: -------------------------------------------------------------------------------- 1 | /* 2 | inspired by https://www.npmjs.com/package/react-csv-downloader 3 | now removed from Github 4 | inspired by https://github.com/iview/iview 5 | */ 6 | 7 | /* eslint-disable */ 8 | 9 | const newLine = '\r\n'; 10 | const appendLine = (content, row, { separator, quoted }) => { 11 | const line = row.map(data => { 12 | if (!quoted) return data; 13 | // quote data 14 | data = typeof data === 'string' ? data.replace(/"/g, '"') : data; 15 | return `"${data}"`; 16 | }); 17 | content.push(line.join(separator)); 18 | }; 19 | 20 | const defaults = { 21 | separator: ',', 22 | quoted: false 23 | }; 24 | 25 | export default function csv(columns, datas, options, noHeader = false) { 26 | options = Object.assign({}, defaults, options); 27 | let columnOrder; 28 | const content = []; 29 | const column = []; 30 | 31 | if (columns) { 32 | columnOrder = columns.map(v => { 33 | if (typeof v === 'string') return v; 34 | if (!noHeader) { 35 | column.push(typeof v.label !== 'undefined' ? v.label : v.prop); 36 | } 37 | return v.prop; 38 | }); 39 | if (column.length > 0) appendLine(content, column, options); 40 | } else { 41 | columnOrder = []; 42 | datas.forEach(v => { 43 | if (!Array.isArray(v)) { 44 | columnOrder = columnOrder.concat(Object.keys(v)); 45 | } 46 | }); 47 | if (columnOrder.length > 0) { 48 | columnOrder = columnOrder.filter((value, index, self) => self.indexOf(value) === index); 49 | if (!noHeader) appendLine(content, columnOrder, options); 50 | } 51 | } 52 | 53 | if (Array.isArray(datas)) { 54 | datas.forEach(row => { 55 | if (!Array.isArray(row)) { 56 | row = columnOrder.map(k => (typeof row[k] !== 'undefined' ? row[k] : '')); 57 | } 58 | appendLine(content, row, options); 59 | }); 60 | } 61 | return content.join(newLine); 62 | } 63 | -------------------------------------------------------------------------------- /src/_export-csv.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | /* 4 | 此代码来源于iview表格组件的CSV导出部分 5 | https://github.com/iview/iview 6 | */ 7 | 8 | function has (browser) { 9 | const ua = navigator.userAgent; 10 | if (browser === 'ie') { 11 | const isIE = ua.indexOf('compatible') > -1 && ua.indexOf('MSIE') > -1; 12 | if (isIE) { 13 | const reIE = new RegExp('MSIE (\\d+\\.\\d+);'); 14 | reIE.test(ua); 15 | return parseFloat(RegExp['$1']); 16 | } else { 17 | return false; 18 | } 19 | } else { 20 | return ua.indexOf(browser) > -1; 21 | } 22 | } 23 | 24 | const csv = { 25 | _isIE11 () { 26 | let iev = 0; 27 | const ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent)); 28 | const trident = !!navigator.userAgent.match(/Trident\/7.0/); 29 | const rv = navigator.userAgent.indexOf('rv:11.0'); 30 | 31 | if (ieold) { 32 | iev = Number(RegExp.$1); 33 | } 34 | if (navigator.appVersion.indexOf('MSIE 10') !== -1) { 35 | iev = 10; 36 | } 37 | if (trident && rv !== -1) { 38 | iev = 11; 39 | } 40 | 41 | return iev === 11; 42 | }, 43 | 44 | _isEdge () { 45 | return /Edge/.test(navigator.userAgent); 46 | }, 47 | 48 | _getDownloadUrl (text) { 49 | const BOM = '\uFEFF'; 50 | // Add BOM to text for open in excel correctly 51 | if (window.Blob && window.URL && window.URL.createObjectURL) { 52 | const csvData = new Blob([BOM + text], { type: 'text/csv' }); 53 | return URL.createObjectURL(csvData); 54 | } else { 55 | return 'data:attachment/csv;charset=utf-8,' + BOM + encodeURIComponent(text); 56 | } 57 | }, 58 | 59 | download (filename, text) { 60 | if (has('ie') && has('ie') < 10) { 61 | // has module unable identify ie11 and Edge 62 | const oWin = window.top.open('about:blank', '_blank'); 63 | oWin.document.charset = 'utf-8'; 64 | oWin.document.write(text); 65 | oWin.document.close(); 66 | oWin.document.execCommand('SaveAs', filename + '.csv'); 67 | oWin.close(); 68 | } else if (has('ie') === 10 || this._isIE11() || this._isEdge()) { 69 | const BOM = '\uFEFF'; 70 | const csvData = new Blob([BOM + text], { type: 'text/csv' }); 71 | navigator.msSaveBlob(csvData, filename + '.csv'); 72 | } else { 73 | const link = document.createElement('a'); 74 | link.download = filename + '.csv'; 75 | link.href = this._getDownloadUrl(text); 76 | document.body.appendChild(link); 77 | link.click(); 78 | document.body.removeChild(link); 79 | } 80 | } 81 | }; 82 | 83 | export default csv; -------------------------------------------------------------------------------- /src/_export2Excel.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | // 来源于网络 有细微改动 4 | 5 | import './_blob' 6 | import FileSaver from 'file-saver' 7 | import XLSX from 'xlsx' 8 | 9 | function generateArray(table) { 10 | var out = []; 11 | var rows = table.querySelectorAll('tr'); 12 | var ranges = []; 13 | for (var R = 0; R < rows.length; ++R) { 14 | var outRow = []; 15 | var row = rows[R]; 16 | var columns = row.querySelectorAll('td'); 17 | for (var C = 0; C < columns.length; ++C) { 18 | var cell = columns[C]; 19 | var colspan = cell.getAttribute('colspan'); 20 | var rowspan = cell.getAttribute('rowspan'); 21 | var cellValue = cell.innerText; 22 | if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue; 23 | 24 | //Skip ranges 25 | ranges.forEach(function (range) { 26 | if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) { 27 | for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null); 28 | } 29 | }); 30 | 31 | //Handle Row Span 32 | if (rowspan || colspan) { 33 | rowspan = rowspan || 1; 34 | colspan = colspan || 1; 35 | ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}}); 36 | } 37 | ; 38 | 39 | //Handle Value 40 | outRow.push(cellValue !== "" ? cellValue : null); 41 | 42 | //Handle Colspan 43 | if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null); 44 | } 45 | out.push(outRow); 46 | } 47 | return [out, ranges]; 48 | }; 49 | 50 | function datenum(v, date1904) { 51 | if (date1904) v += 1462; 52 | var epoch = Date.parse(v); 53 | return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); 54 | } 55 | 56 | function sheet_from_array_of_arrays(data, opts) { 57 | var ws = {}; 58 | var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; 59 | for (var R = 0; R != data.length; ++R) { 60 | for (var C = 0; C != data[R].length; ++C) { 61 | if (range.s.r > R) range.s.r = R; 62 | if (range.s.c > C) range.s.c = C; 63 | if (range.e.r < R) range.e.r = R; 64 | if (range.e.c < C) range.e.c = C; 65 | var cell = {v: data[R][C]}; 66 | if (cell.v == null) continue; 67 | var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); 68 | 69 | if (typeof cell.v === 'number') cell.t = 'n'; 70 | else if (typeof cell.v === 'boolean') cell.t = 'b'; 71 | else if (cell.v instanceof Date) { 72 | cell.t = 'n'; 73 | cell.z = XLSX.SSF._table[14]; 74 | cell.v = datenum(cell.v); 75 | } 76 | else cell.t = 's'; 77 | 78 | ws[cell_ref] = cell; 79 | } 80 | } 81 | if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); 82 | return ws; 83 | } 84 | 85 | function Workbook() { 86 | if (!(this instanceof Workbook)) return new Workbook(); 87 | this.SheetNames = []; 88 | this.Sheets = {}; 89 | } 90 | 91 | function s2ab(s) { 92 | var buf = new ArrayBuffer(s.length); 93 | var view = new Uint8Array(buf); 94 | for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; 95 | return buf; 96 | } 97 | 98 | export function export_table_to_excel(id) { 99 | var theTable = document.getElementById(id); 100 | console.log('a') 101 | var oo = generateArray(theTable); 102 | var ranges = oo[1]; 103 | 104 | /* original data */ 105 | var data = oo[0]; 106 | var ws_name = "SheetJS"; 107 | console.log(data); 108 | 109 | var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); 110 | 111 | /* add ranges to worksheet */ 112 | // ws['!cols'] = ['apple', 'banan']; 113 | ws['!merges'] = ranges; 114 | 115 | /* add worksheet to workbook */ 116 | wb.SheetNames.push(ws_name); 117 | wb.Sheets[ws_name] = ws; 118 | 119 | var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); 120 | 121 | FileSaver.saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") 122 | } 123 | 124 | function formatJson(jsonData) { 125 | console.log(jsonData) 126 | } 127 | export function export_json_to_excel(th, jsonData, defaultTitle, options = { merges: [], header: null }) { 128 | 129 | /* original data */ 130 | 131 | var data = jsonData; 132 | data.unshift(th); 133 | if (options.header) data.unshift([options.header]); 134 | var ws_name = "SheetJS"; 135 | 136 | var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); 137 | 138 | /* add merges area to worksheet */ 139 | let { merges } = options; 140 | if (typeof merges[0] == 'string' && merges.length == 2) merges = [merges] // just one # ['A1', 'C1'] = > [['A1', 'C1']] 141 | merges = merges.map(i => i instanceof Array ? { s: i[0], e: i[1] } : i); // be sort :) # ['A1', 'C1'] => { s: 'A1', e: 'C3' } 142 | ws['!merges'] = merges; 143 | 144 | /* add worksheet to workbook */ 145 | wb.SheetNames.push(ws_name); 146 | wb.Sheets[ws_name] = ws; 147 | 148 | var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); 149 | var title = defaultTitle || '列表' 150 | FileSaver.saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx") 151 | } 152 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import Csv from './_csv' 3 | import ExportCsv from './_export-csv' 4 | import FileSaver from 'file-saver' 5 | import * as Excel from './_export2Excel' 6 | 7 | const vueTableExport = { 8 | install (Vue, options) { 9 | Vue.prototype.$export = { 10 | // 导出 csv 11 | csv (params) { 12 | return new Promise((resolve, reject) => { 13 | // 默认值 14 | const paramsDefault = { 15 | columns: [], 16 | data: [], 17 | title: 'table', 18 | noHeader: false 19 | } 20 | // 合并参数 21 | const _params = Object.assign({}, paramsDefault, params) 22 | // 生成数据 23 | const data = Csv(_params.columns, _params.data, params, _params.noHeader) 24 | // 下载数据 25 | ExportCsv.download(_params.title, data) 26 | // 完成 27 | resolve() 28 | }) 29 | }, 30 | // 导出 excel 31 | excel (params) { 32 | return new Promise((resolve, reject) => { 33 | // 默认值 34 | const paramsDefault = { 35 | columns: [], 36 | data: [], 37 | merges: [], 38 | title: 'table', 39 | header: null 40 | } 41 | // 合并参数 42 | const _params = Object.assign({}, paramsDefault, params) 43 | // 从参数中派生数据 44 | const header = _params.columns.map(e => e.label) 45 | const data = _params.data.map(row => _params.columns.map(col => row[col.prop])) 46 | // 导出 47 | Excel.export_json_to_excel(header, data, _params.title, { merges: _params.merges, header: _params.header }) 48 | // 完成 49 | resolve() 50 | }) 51 | }, 52 | // 导出 文本文档 53 | txt (params) { 54 | return new Promise((resolve, reject) => { 55 | // 默认值 56 | const paramsDefault = { 57 | text: '', 58 | title: '文本' 59 | } 60 | // 合并参数 61 | const _params = Object.assign({}, paramsDefault, params) 62 | // 导出 63 | const blob = new Blob([_params.text], {type: 'text/plain;charset=utf-8'}) 64 | FileSaver.saveAs(blob, _params.title + '.txt') 65 | // 完成 66 | resolve() 67 | }) 68 | } 69 | } 70 | } 71 | } 72 | 73 | if (typeof window !== 'undefined' && window.Vue) { 74 | window.Vue.use(vueTableExport) 75 | } 76 | 77 | export default vueTableExport 78 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const TerserPlugin = require('terser-webpack-plugin') 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 4 | 5 | module.exports = { 6 | mode: 'production', 7 | entry: './src/index.js', 8 | output: { 9 | filename: 'vue-table-export.js', 10 | path: path.resolve(__dirname, 'dist'), 11 | // library指定的就是你使用require时的模块名,这里便是require("VueTableExport") 12 | library: 'VueTableExport', 13 | // libraryTarget会生成不同umd的代码,可以只是commonjs标准的,也可以是指amd标准的,也可以只是通过script标签引入的 14 | libraryTarget: 'umd', 15 | // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define 16 | umdNamedDefine: true 17 | }, 18 | module:{ 19 | rules: [ 20 | { 21 | test: /\.js$/, 22 | exclude: /node_modules/, 23 | use: { 24 | loader: 'babel-loader' 25 | } 26 | } 27 | ] 28 | }, 29 | plugins: [ 30 | new CleanWebpackPlugin() 31 | ], 32 | optimization: { 33 | minimize: true, 34 | minimizer: [ 35 | new TerserPlugin({ 36 | sourceMap: true 37 | }) 38 | ] 39 | } 40 | } 41 | --------------------------------------------------------------------------------