├── .gitignore ├── README.md ├── img ├── icon.png ├── screenshot_1.png └── screenshot_2.png ├── jsconfig.json ├── main.js ├── package-lock.json ├── package.json └── panel ├── help.html ├── help.js ├── index.css ├── index.html └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Cocos Creator 插件:转换 excel 文件为 js 文件 2 | 3 | --- 4 | 5 | #### 如何使用 6 | 7 | 参考 [Cocos Creator 插件的安装与分享](https://docs.cocos.com/creator/manual/zh/extension/install-and-share.html)。 8 | 9 | #### 注意事项 10 | * excel 的读取路径为 `项目目录/excel/` 11 | * js 文件保存路径为 `项目目录/assets/data/` 12 | * 转换成功后,会以`同名`的 js 文件保存,请自行做好文件备份 13 | * 以`!`开头的 excel 文件会被忽略,以`!`开头的 excel 字段名同样会被忽略 14 | * excel 文件第一行为`字段名`,第二行起为`数据` 15 | * 每个 excel 文件只会解析`第一个`表格 16 | * 支持解析 `.xlsx` 的 excel 文件 17 | 18 | #### 转换格式 19 | * excel 20 | 21 | | id | name | num | object | array | 22 | | :-----: |:-----:| :-----:| :-----:| :-----:| 23 | | 0 | "名字0" | 0 | {a:1,b:2} | [0,1,2] | 24 | | 1 | "名字1" | 1 | {a:1,b:2} | [0,1,2] | 25 | | 2 | "名字2" | 2 | {a:"对象1",b:"对象1"} | ["数组1","数组2"] | 26 | | 3 | "名字3" | 3 | {a:"对象1",b:"对象1"} | ["数组1","数组2"] | 27 | 28 | 29 | * js 30 | 31 | ```javascript 32 | module.exports = [ 33 | {id:0, name:"名字0", num:0, object:{a:1,b:2}, array:[0,1,2]}, 34 | {id:1, name:"名字1", num:1, object:{a:1,b:2}, array:[0,1,2]}, 35 | {id:2, name:"名字2", num:2, object:{a:"对象1",b:"对象1"}, array:["数组1","数组2"]}, 36 | {id:3, name:"名字3", num:3, object:{a:"对象1",b:"对象1"}, array:["数组1","数组2"]}, 37 | ]; 38 | ``` 39 | 40 | #### 截图 41 | 42 |
43 | 44 | 45 |
46 | -------------------------------------------------------------------------------- /img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusijie/excel2js/d198b7779fe8d591f9dcdabab90a50c42a83cbf4/img/icon.png -------------------------------------------------------------------------------- /img/screenshot_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusijie/excel2js/d198b7779fe8d591f9dcdabab90a50c42a83cbf4/img/screenshot_1.png -------------------------------------------------------------------------------- /img/screenshot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusijie/excel2js/d198b7779fe8d591f9dcdabab90a50c42a83cbf4/img/screenshot_2.png -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "experimentalDecorators": true 6 | }, 7 | "exclude": [ 8 | "node_modules", 9 | ".vscode", 10 | ] 11 | } -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Fs = require('fire-fs'); 4 | const Path = require('fire-path'); 5 | 6 | module.exports = { 7 | load() { 8 | }, 9 | 10 | unload() { 11 | }, 12 | 13 | messages: { 14 | 'open'() { 15 | Editor.Panel.open('excel2js'); 16 | }, 17 | 18 | 'update-excel'(event) { 19 | let excelDir = Path.join(Editor.projectPath, 'excel'); 20 | let excelArr = []; 21 | if (Fs.existsSync(excelDir)) { 22 | excelArr = Fs.readdirSync(excelDir); 23 | } 24 | if (event.reply) { 25 | event.reply(null, excelArr); 26 | } 27 | }, 28 | 29 | 'convert-js'(event, excelFileInfo) { 30 | let jsDir = 'db://assets/data'; 31 | if (!Editor.assetdb.exists(jsDir)) { 32 | Editor.assetdb.create(jsDir); 33 | } 34 | if (Array.isArray(excelFileInfo)) { 35 | for (let i = 0; i < excelFileInfo.length; i++) { 36 | this.convertJs(excelFileInfo[i].name); 37 | } 38 | } else { 39 | this.convertJs(excelFileInfo.name); 40 | } 41 | }, 42 | }, 43 | 44 | convertJs(excelFileName) { 45 | //解析excel 46 | let xlsx = Editor.require('packages://excel2js/node_modules/xlsx'); 47 | let excelName = Path.join(Editor.projectPath, 'excel', excelFileName); 48 | const workbook = xlsx.readFile(excelName); 49 | const sheetNames = workbook.SheetNames; 50 | const worksheet = workbook.Sheets[sheetNames[0]]; 51 | const headers = {}; 52 | const data = []; 53 | const keys = Object.keys(worksheet); 54 | keys.filter(k => k[0] !== '!')// 过滤以 ! 开头的 key 55 | .forEach(k => {// 遍历所有单元格 56 | let col = k.substring(0, 1); 57 | let row = parseInt(k.substring(1)); 58 | let value = worksheet[k].v; 59 | if (row === 1) { 60 | headers[col] = value; 61 | return; 62 | } 63 | if (!data[row]) { 64 | data[row] = {}; 65 | } 66 | data[row][headers[col]] = value; 67 | }); 68 | data.splice(0, 2); 69 | 70 | //转Array为text 71 | let jsText = 'module.exports = [\n'; 72 | for (let i = 0; i < data.length; i++) { 73 | jsText += '\t{'; 74 | for (let key in data[i]) { 75 | jsText += `${key}:${data[i][key]}, `; 76 | } 77 | jsText = jsText.substr(0, jsText.length - 2); 78 | jsText += '},\n'; 79 | } 80 | jsText += '];'; 81 | 82 | //校验js文件 83 | try { 84 | eval(jsText); 85 | } catch (error) { 86 | Editor.Ipc.sendToPanel('excel2js', 'convert-failed', excelFileName); 87 | return; 88 | } 89 | 90 | //写入js文件 91 | let excelFile = excelFileName.substr(0, excelFileName.lastIndexOf('.xlsx')); 92 | let url = `db://assets/data/${excelFile}.js`; 93 | if (Editor.assetdb.exists(url)) { 94 | Editor.assetdb.saveExists(url, jsText, (err) => { 95 | if (err) { 96 | Editor.Ipc.sendToPanel('excel2js', 'convert-failed', excelFileName); 97 | } else { 98 | Editor.Ipc.sendToPanel('excel2js', 'convert-success', excelFileName); 99 | } 100 | }); 101 | } else { 102 | Editor.assetdb.create(url, jsText, (err) => { 103 | if (err) { 104 | Editor.Ipc.sendToPanel('excel2js', 'convert-failed', excelFileName); 105 | } else { 106 | Editor.Ipc.sendToPanel('excel2js', 'convert-success', excelFileName); 107 | } 108 | }); 109 | } 110 | } 111 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "excel2js", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "adler-32": { 8 | "version": "1.2.0", 9 | "resolved": "http://registry.npm.taobao.org/adler-32/download/adler-32-1.2.0.tgz", 10 | "integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=", 11 | "requires": { 12 | "exit-on-epipe": "~1.0.1", 13 | "printj": "~1.1.0" 14 | } 15 | }, 16 | "cfb": { 17 | "version": "1.1.0", 18 | "resolved": "http://registry.npm.taobao.org/cfb/download/cfb-1.1.0.tgz", 19 | "integrity": "sha1-RPsbMO7gFPpWM6DtXybIf9dleZo=", 20 | "requires": { 21 | "adler-32": "~1.2.0", 22 | "commander": "^2.16.0", 23 | "crc-32": "~1.2.0", 24 | "printj": "~1.1.2" 25 | } 26 | }, 27 | "codepage": { 28 | "version": "1.14.0", 29 | "resolved": "http://registry.npm.taobao.org/codepage/download/codepage-1.14.0.tgz", 30 | "integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=", 31 | "requires": { 32 | "commander": "~2.14.1", 33 | "exit-on-epipe": "~1.0.1" 34 | }, 35 | "dependencies": { 36 | "commander": { 37 | "version": "2.14.1", 38 | "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.14.1.tgz", 39 | "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=" 40 | } 41 | } 42 | }, 43 | "commander": { 44 | "version": "2.17.1", 45 | "resolved": "http://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz", 46 | "integrity": "sha1-vXerfebelCBc6sxy8XFtKfIKd78=" 47 | }, 48 | "crc-32": { 49 | "version": "1.2.0", 50 | "resolved": "http://registry.npm.taobao.org/crc-32/download/crc-32-1.2.0.tgz", 51 | "integrity": "sha1-yy224puIUI4y2d0OwWk+e0Ghggg=", 52 | "requires": { 53 | "exit-on-epipe": "~1.0.1", 54 | "printj": "~1.1.0" 55 | } 56 | }, 57 | "exit-on-epipe": { 58 | "version": "1.0.1", 59 | "resolved": "http://registry.npm.taobao.org/exit-on-epipe/download/exit-on-epipe-1.0.1.tgz", 60 | "integrity": "sha1-C92S6H1ShdJn2qgXHQ6wYVlolpI=" 61 | }, 62 | "frac": { 63 | "version": "1.1.2", 64 | "resolved": "http://registry.npm.taobao.org/frac/download/frac-1.1.2.tgz", 65 | "integrity": "sha1-PXT39keMiKG1AgMG10fcYxPHTQs=" 66 | }, 67 | "printj": { 68 | "version": "1.1.2", 69 | "resolved": "http://registry.npm.taobao.org/printj/download/printj-1.1.2.tgz", 70 | "integrity": "sha1-2Q3rKXWoufYA+zoclOP0xTx4oiI=" 71 | }, 72 | "ssf": { 73 | "version": "0.10.2", 74 | "resolved": "http://registry.npm.taobao.org/ssf/download/ssf-0.10.2.tgz", 75 | "integrity": "sha1-ZbK0/N/ZZ7yOg4OkE0kAmJMRWXY=", 76 | "requires": { 77 | "frac": "~1.1.2" 78 | } 79 | }, 80 | "xlsx": { 81 | "version": "0.14.1", 82 | "resolved": "http://registry.npm.taobao.org/xlsx/download/xlsx-0.14.1.tgz", 83 | "integrity": "sha1-7O31Nr0elAVUhv9IT1iI3KqJvT0=", 84 | "requires": { 85 | "adler-32": "~1.2.0", 86 | "cfb": "^1.1.0", 87 | "codepage": "~1.14.0", 88 | "commander": "~2.17.1", 89 | "crc-32": "~1.2.0", 90 | "exit-on-epipe": "~1.0.1", 91 | "ssf": "~0.10.2" 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "excel2js", 3 | "version": "0.1.0", 4 | "description": "转换xlsx文件为js文件", 5 | "author": "JackyFu", 6 | "main": "main.js", 7 | "main-menu": { 8 | "i18n:MAIN_MENU.package.title/Excel2js": { 9 | "message": "excel2js:open" 10 | } 11 | }, 12 | "panel": { 13 | "main": "panel/index.js", 14 | "type": "dockable", 15 | "title": "Excel2js", 16 | "width": 400, 17 | "height": 800, 18 | "min-width": 400 19 | }, 20 | "panel.help": { 21 | "main": "panel/help.js", 22 | "type": "dockable", 23 | "title": "Help", 24 | "width": 660, 25 | "height": 800, 26 | "min-width": 400 27 | }, 28 | "dependencies": { 29 | "xlsx": "^0.14.1" 30 | } 31 | } -------------------------------------------------------------------------------- /panel/help.html: -------------------------------------------------------------------------------- 1 |

Excel2js 帮助

2 |
3 |
4 |
5 | 6 | ### 注意事项 7 | * excel 的读取路径为 `项目目录/excel/` 8 | * js 文件保存路径为 `项目目录/assets/data/` 9 | * 转换成功后,会以`同名`的 js 文件保存,请自行做好文件备份 10 | * 以`!`开头的 excel 文件会被忽略,以`!`开头的 excel 字段名同样会被忽略 11 | * excel 文件第一行为`字段名`,第二行起为`数据` 12 | * 每个 excel 文件只会解析`第一个`表格 13 | * 支持解析 `.xlsx` 的 excel 文件 14 | 15 | ### 转换格式 16 | * excel 17 | 18 | | id | name | num | object | array | 19 | | :-----: |:-----:| :-----:| :-----:| :-----:| 20 | | 0 | "名字0" | 0 | {a:1,b:2} | [0,1,2] | 21 | | 1 | "名字1" | 1 | {a:1,b:2} | [0,1,2] | 22 | | 2 | "名字2" | 2 | {a:"对象1",b:"对象1"} | ["数组1","数组2"] | 23 | | 3 | "名字3" | 3 | {a:"对象1",b:"对象1"} | ["数组1","数组2"] | 24 | 25 | 26 | * js 27 | 28 | ```javascript 29 | module.exports = [ 30 | {id:0, name:"名字0", num:0, object:{a:1,b:2}, array:[0,1,2]}, 31 | {id:1, name:"名字1", num:1, object:{a:1,b:2}, array:[0,1,2]}, 32 | {id:2, name:"名字2", num:2, object:{a:"对象1",b:"对象1"}, array:["数组1","数组2"]}, 33 | {id:3, name:"名字3", num:3, object:{a:"对象1",b:"对象1"}, array:["数组1","数组2"]}, 34 | ]; 35 | ``` 36 | 37 |
-------------------------------------------------------------------------------- /panel/help.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Fs = require('fire-fs'); 4 | const Path = require('fire-path'); 5 | 6 | Editor.Panel.extend({ 7 | style: Fs.readFileSync( 8 | Editor.url('packages://excel2js/panel/index.css'), 9 | 'utf-8' 10 | ), 11 | 12 | template: Fs.readFileSync( 13 | Editor.url('packages://excel2js/panel/help.html'), 14 | 'utf-8' 15 | ), 16 | 17 | ready() { 18 | 19 | }, 20 | }); -------------------------------------------------------------------------------- /panel/index.css: -------------------------------------------------------------------------------- 1 | h2 { 2 | color: #f90; 3 | margin-left: 10px; 4 | } 5 | 6 | li { 7 | line-height: 30px; 8 | margin-left:10px; 9 | margin-right:10px; 10 | } 11 | 12 | ui-markdown { 13 | margin-left: 10px; 14 | } 15 | 16 | :host { 17 | display: flex; 18 | flex-direction: column; 19 | } 20 | 21 | h3 { 22 | margin-top: 0; 23 | margin-bottom: 10px; 24 | } 25 | 26 | #view { 27 | flex: 1; 28 | padding: 10px; 29 | padding-top: 0px; 30 | overflow-y: auto; 31 | overflow-x: hidden; 32 | } 33 | 34 | div.section { 35 | border-bottom: 1px solid #666; 36 | padding-bottom: 10px; 37 | margin-bottom: 10px; 38 | margin-left: 10px; 39 | } 40 | 41 | div.section:last-child { 42 | border-bottom: 0px; 43 | } 44 | 45 | div.group { 46 | min-width: 420px; 47 | margin-bottom: 5px; 48 | display: flex; 49 | flex-direction: row; 50 | align-items: center; 51 | flex-wrap: wrap; 52 | } 53 | 54 | span { 55 | margin-right: 0.25em; 56 | } -------------------------------------------------------------------------------- /panel/index.html: -------------------------------------------------------------------------------- 1 |

Excel2js

2 |
3 | {{txtUpdate}} 4 | {{txtConvert}} 5 | {{txtHelp}} 6 |
7 |
8 |
9 | 10 |
  • 11 | {{item.name}} 12 |
    13 | {{txtConvertOne}} 14 | 15 | 16 | 17 |
    18 |
  • 19 | 20 |
    21 |
    22 |
    23 |

    {{txtNoExcel}}

    24 |
    -------------------------------------------------------------------------------- /panel/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Fs = require('fire-fs'); 4 | const Path = require('fire-path'); 5 | 6 | Editor.Panel.extend({ 7 | style: Fs.readFileSync( 8 | Editor.url('packages://excel2js/panel/index.css'), 9 | 'utf-8' 10 | ), 11 | 12 | template: Fs.readFileSync( 13 | Editor.url('packages://excel2js/panel/index.html'), 14 | 'utf-8' 15 | ), 16 | 17 | ready() { 18 | this.v = new window.Vue({ 19 | el: this.shadowRoot, 20 | data: { 21 | txtUpdate: '点击更新', 22 | txtConvert: '全部生成', 23 | txtHelp: '查看帮助', 24 | txtConvertOne: '生成', 25 | txtNoExcel: '没有找到Excel', 26 | iconStatus: [ 27 | 'icon-record', 28 | 'icon-ok', 29 | 'icon-cancel' 30 | ], 31 | items: [ 32 | ] 33 | }, 34 | methods: { 35 | onClickUpdate() { 36 | Editor.Ipc.sendToMain('excel2js:update-excel', (err, data) => { 37 | if (err) { 38 | Editor.log(err); 39 | return; 40 | } 41 | this.items = []; 42 | 43 | for (let i = 0; i < data.length; i++) { 44 | if (Path.extname(data[i]) !== '.xlsx') { 45 | continue; 46 | } 47 | if (data[i].indexOf('~') === 0) { 48 | continue; 49 | } 50 | if (data[i].indexOf('!') === 0) { 51 | continue; 52 | } 53 | this.items.push({ 54 | name: data[i], 55 | status: 0, 56 | }); 57 | } 58 | }); 59 | }, 60 | 61 | onClickConvert() { 62 | if (this.items.length === 0) { 63 | return; 64 | } 65 | Editor.Ipc.sendToMain('excel2js:convert-js', this.items); 66 | }, 67 | 68 | onClickConvertOne(index) { 69 | Editor.Ipc.sendToMain('excel2js:convert-js', this.items[index]); 70 | }, 71 | 72 | onClickHelp() { 73 | Editor.Panel.open('excel2js.help'); 74 | } 75 | }, 76 | }); 77 | 78 | this.v.onClickUpdate(); 79 | }, 80 | 81 | messages: { 82 | 'convert-success'(event, excelFileName) { 83 | for (let i = 0; i < this.v.items.length; i++) { 84 | if (this.v.items[i].name === excelFileName) { 85 | this.v.items[i].status = 1; 86 | break; 87 | } 88 | } 89 | }, 90 | 91 | 'convert-failed'(event, excelFileName) { 92 | for (let i = 0; i < this.v.items.length; i++) { 93 | if (this.v.items[i].name === excelFileName) { 94 | this.v.items[i].status = 2; 95 | break; 96 | } 97 | } 98 | }, 99 | }, 100 | }); --------------------------------------------------------------------------------