Browse Source

基础功能

HonorLee 11 months ago
commit
b0d426eb45
7 changed files with 412 additions and 0 deletions
  1. 4 0
      .gitignore
  2. 0 0
      README.md
  3. 197 0
      convert.js
  4. BIN
      excel/example.xlsx
  5. BIN
      excel/standalone.xlsx
  6. 196 0
      package-lock.json
  7. 15 0
      package.json

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+node_modules/
+output/
+
+.DS_Store

+ 0 - 0
README.md


+ 197 - 0
convert.js

@@ -0,0 +1,197 @@
+const FILE = require('fs-extra');
+const XLSX = require('node-xlsx');
+
+//读取excel目录所有excel文件
+const files = FILE.readdirSync('./excel');
+const outputDir = './output';
+
+//清除输出目录
+FILE.emptyDirSync(outputDir);
+
+//创建JSON目录
+FILE.ensureDirSync(outputDir + '/json');
+//创建C#目录
+FILE.ensureDirSync(outputDir + '/cs');
+
+let Head = `using System;\nusing System.Collections.Generic;\nusing UnityEngine;\n`;
+let NameSpaceHead = `namespace {NAMESPACE} {\n`;
+let NameSpaceEnd = `}\n`;
+let NameSpaceCombine = {};
+
+//遍历所有excel文件
+for (let i = 0; i < files.length; i++) {
+    const filePath = './excel/' + files[i];
+    const result = convert(filePath);
+}
+Object.keys(NameSpaceCombine).forEach((key)=>{
+    let namespace = key;
+    let content = NameSpaceCombine[key].join('\n');
+    let NameSpace = NameSpaceHead.replace('{NAMESPACE}',namespace);
+    let ret = Head + NameSpace + content + NameSpaceEnd;
+    FILE.writeFileSync(outputDir + '/cs/' + namespace + '.cs', ret);
+});
+console.log('转换完成');
+
+function convert(filePath) {
+    //获取文件名,删除后缀并大写首字符
+    let fileName = filePath.split('/')[2].split('.')[0];
+    // const className = fileName.charAt(0).toUpperCase() + fileName.slice(1);
+    fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1);
+    
+    const workSheetsFromFile = XLSX.parse(filePath);
+    const data = workSheetsFromFile[0].data;
+    // console.log(data)
+    let tableStartIndexs = [];
+
+    for (let i = 0; i < data.length; i++) {
+        for (let j = 0; j < data[i].length; j++) {
+            if(data[i][j] === '###') {
+                let startX = i;
+                let startY = j;
+                let endX = data.length-1;
+                tableStartIndexs.push({startX,startY,endX});
+                if(tableStartIndexs.length>1){
+                    tableStartIndexs[tableStartIndexs.length-2].endX = i-1;
+                }
+            }
+        }
+    }
+    
+    for (let i = 0; i < tableStartIndexs.length; i++) {
+        parse(data,tableStartIndexs[i],fileName);
+    }
+    
+}
+
+
+function parse(data,tableInfo,fileName){
+    let varTypes = [];
+    let dataList = [];
+    let NAMESPACE = '';
+    let CLASSNAME = '';
+    let FILECOMMENT = '';
+    let CLASSCOMMENT = '';
+    let Combine = false;
+
+    let varStartX = tableInfo.startX + 1;
+
+    //处理定义行
+    let defineRow = data[tableInfo.startX].slice(tableInfo.startY);
+        NAMESPACE    = defineRow[2]||'Default';
+        CLASSNAME    = defineRow[4]||fileName;
+        CLASSCOMMENT = defineRow[6]||'';
+        Combine      = defineRow[8]?true:false;
+    
+    //处理注释行
+    if(data[tableInfo.startX+1][tableInfo.startY]=='## CCMT'){
+        let prefix = Combine?'    ':'';
+        FILECOMMENT = `\n${prefix}/**\n`
+        for(let i=tableInfo.startX+1;i<tableInfo.endX;i++){
+            if(data[i][tableInfo.startY]=='## VAR'){
+                varStartX = i;
+                break;
+            }
+            let FILECOMMENTArr = data[i].slice(tableInfo.startY+1);
+            if(FILECOMMENTArr.length==0) continue;
+            FILECOMMENT += `${prefix} * `;
+            let head = FILECOMMENTArr.shift();
+            FILECOMMENT += head;
+            if(FILECOMMENTArr.length){
+                FILECOMMENT += `\n${prefix} *     ` + FILECOMMENTArr.join(' ');
+            }
+            FILECOMMENT += `\n`;
+        }
+        FILECOMMENT += `${prefix} */\n\n`;
+    }
+
+    let keyStatus = {};
+    //处理Var变量行
+    let varRow = data[varStartX].slice(tableInfo.startY+1);
+    for (let i = 0; i < varRow.length; i++) {
+        let value = varRow[i];
+        if(value==undefined) break;
+        
+        if(value.includes('#')){
+            keyStatus[i] = false;
+        }else{
+            keyStatus[i] = true;
+        }
+        if(!keyStatus[i]) continue;
+        let type = {
+            vname:value,
+            type:'',
+            comment:''
+        }
+
+        varTypes[i] = type;
+    }
+    // //处理Var变量类型行
+    for (let i = 0; i < varTypes.length; i++) {
+        if(!keyStatus[i]) continue;
+        let value = data[varStartX+1][tableInfo.startY+1+i];
+        varTypes[i].type = value;
+    }
+    //处理Var变量注释行
+    for (let i = 0; i < varTypes.length; i++) {
+        if(!keyStatus[i]) continue;
+        let value = data[varStartX+2][tableInfo.startY+1+i];
+        if(value!=undefined && value!='') value = value.replace(/\n/g,'  ');
+        varTypes[i].comment = value;
+    }
+    //处理数据多行
+    if(data[varStartX+3] && data[varStartX+3][tableInfo.startY]=='## DATA'){
+        for (let x = varStartX+3; x <= tableInfo.endX; x++) {
+            if(data[x].length==0) continue;
+            let obj = {};
+            for(let i = 0; i < varTypes.length; i++) {
+                if(!keyStatus[i]) continue;
+                let value = data[x][tableInfo.startY+1+i];
+                if(varTypes[i].type.includes('List')) {
+                    value = value.toString().split(',');
+                    if(varTypes[i].type.includes('int') || varTypes[i].type.includes('float')){
+                        value = value.map((item)=>{
+                            return item * 1;
+                        })
+                    }
+                }
+                obj[varTypes[i].vname] = value;
+            }
+            dataList.push(obj);
+        }
+        //写入JSON文件
+        if(dataList.length){
+            const json = JSON.stringify({dataList});
+            const jsonPath = outputDir + '/json/' + fileName + '.json';
+            FILE.writeFileSync(jsonPath, json);
+        }
+    }
+    //生成C#类
+    let ListClass = '';
+    ListClass += `    [Serializable]\n    public class ${CLASSNAME}s {\n`;
+    ListClass += `        public List<${CLASSNAME}> dataList;\n`;
+    ListClass += `    }\n\n`;
+
+    let Class = `    [Serializable]\n    public class ${CLASSNAME} {\n`;
+    let ClassComment = CLASSCOMMENT?`    /// <summary>${CLASSCOMMENT}</summary>\n`:'';
+    let ClassVar = '';
+    for (let i = 0; i < varTypes.length; i++) {
+        if(!varTypes[i]) continue;
+        ClassVar += `        /// <summary>${varTypes[i].comment}</summary>\n`;
+        // ClassVar += `        public ${varTypes[i].type} ${varTypes[i].vname} { get; set; }\n`;
+        ClassVar += `        public ${varTypes[i].type} ${varTypes[i].vname};\n`;
+    }
+    let ClassEnd = `    }\n`;
+    let result;
+    if(Combine){
+        result = `\n    //----------------------# ${fileName} #----------------------\n`;
+        result += FILECOMMENT + ClassComment + ListClass + Class + ClassVar + ClassEnd;
+        if(!NameSpaceCombine[NAMESPACE]) NameSpaceCombine[NAMESPACE] = [];
+        NameSpaceCombine[NAMESPACE].push(result);
+    }else{
+        NameSpace = NameSpaceHead.replace('{NAMESPACE}',NAMESPACE);
+        result = Head + FILECOMMENT + NameSpace + ClassComment + ListClass + Class + ClassVar + ClassEnd + NameSpaceEnd;
+        //写入C#文件
+        const csPath = outputDir + '/cs/' + fileName + '.cs';
+        FILE.writeFileSync(csPath, result);
+    }
+}

BIN
excel/example.xlsx


BIN
excel/standalone.xlsx


+ 196 - 0
package-lock.json

@@ -0,0 +1,196 @@
+{
+  "name": "x2jc-unity",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "x2jc-unity",
+      "version": "1.0.0",
+      "license": "GPL-3.0-or-later",
+      "dependencies": {
+        "fs-extra": "^11.1.1",
+        "node-xlsx": "^0.21.2"
+      }
+    },
+    "node_modules/adler-32": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.2.0.tgz",
+      "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==",
+      "dependencies": {
+        "exit-on-epipe": "~1.0.1",
+        "printj": "~1.1.0"
+      },
+      "bin": {
+        "adler32": "bin/adler32.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "dependencies": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/cfb/node_modules/adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+      "bin": {
+        "crc32": "bin/crc32.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/exit-on-epipe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
+      "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/fs-extra": {
+      "version": "11.1.1",
+      "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.1.1.tgz",
+      "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=14.14"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+    },
+    "node_modules/jsonfile": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
+      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/node-xlsx": {
+      "version": "0.21.2",
+      "resolved": "https://registry.npmmirror.com/node-xlsx/-/node-xlsx-0.21.2.tgz",
+      "integrity": "sha512-Hx/AQ+IEoNgiq8rjEOPtvv3F+KZ5iHZLmEO5Cf7oB6mrpzXsaLNTQvyZvJ3sEOMQ2HfGXwyks18ZVTI6+WmuQA==",
+      "dependencies": {
+        "xlsx": "^0.17.4"
+      },
+      "bin": {
+        "node-xlsx": "lib/bin/cli.js"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/printj": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/printj/-/printj-1.1.2.tgz",
+      "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==",
+      "bin": {
+        "printj": "bin/printj.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "dependencies": {
+        "frac": "~1.1.2"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz",
+      "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/xlsx": {
+      "version": "0.17.5",
+      "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.17.5.tgz",
+      "integrity": "sha512-lXNU0TuYsvElzvtI6O7WIVb9Zar1XYw7Xb3VAx2wn8N/n0whBYrCnHMxtFyIiUU1Wjf09WzmLALDfBO5PqTb1g==",
+      "dependencies": {
+        "adler-32": "~1.2.0",
+        "cfb": "^1.1.4",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.0",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      },
+      "bin": {
+        "xlsx": "bin/xlsx.njs"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    }
+  }
+}

+ 15 - 0
package.json

@@ -0,0 +1,15 @@
+{
+  "name": "x2jc-unity",
+  "version": "1.0.0",
+  "description": "Convert excel to unity json data & class struct",
+  "main": "convert.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "HonorLee",
+  "license": "GPL-3.0-or-later",
+  "dependencies": {
+    "fs-extra": "^11.1.1",
+    "node-xlsx": "^0.21.2"
+  }
+}