unity遊戲開發 Excel表格生成class類
加班,閒來無事 吹一波。。。
吹啊吹啊 我的驕傲放縱。。。
五毛錢的來了(良心商家,不漲價)
其實呢,表格生成class類 就是一個編輯器,比如:策劃給你了好多excel表,而你肯定要把表對應一個個的class類。這個時候手動寫那豈不是很難受,有失我高階程式設計師的尊嚴。下面就是我挽回英俊瀟灑的尊嚴的嘶吼(時候)了。
先用一波思路騷情騷情你哦。
首先,要獲取到excel的所在的目錄以及並用io流()讀取到裡面的excel檔案,這個時候最好判斷下目錄中有木有檔案(最好提示個彈框或者debug),倘若是空表,那我豈不是很沒面子。其次獲取到生成class類所放的目錄。
其次,讀取excel表,這可是個比較牛逼的活呀,其實在你沒接觸過的情況下,感覺還是挺神奇的,至少牛逼如我也曾這麼天真的認為過。欸,那個嚷嚷著要程式碼的,注意素質。我貼還不行嗎。。。
FileStream mStream = File.Open(excelFile, FileMode.Open, FileAccess.Read); IExcelDataReader mExcelReader = ExcelReaderFactory.CreateOpenXmlReader(mStream); DataSet mResultSet = mExcelReader.AsDataSet();
牛逼吧,行了 別奉承了。且聽我慢慢吹完。
下面就是要讀取資料表了哈,這個要用到上述程式碼的mResultset。獲取到excel的資料表以及行數和列數,將表頭對應的資料存入字典中。
再其次,獲取excel頭欄位的內容,也就是第一行內容。各位英雄都清楚 生成的class類中數字段,頭欄位內容對應class中欄位名。至於這個也是根據excel行列獲取的。
最後,這節就比較重要了,而且方法很不常見,本店小二也是感覺不太好整啊,其實歸根結底就是一個CodeDom。CodeDom是.net提供的原始碼生成器。各位若想詳細瞭解下其中類 可參考https://blog.csdn.net/firewolffeng/article/details/2214913
鑑於被各位英雄豪傑催程式碼的經驗,本店小二這回也要主動一下下的啦,畢竟男人是要主動的。嘿嘿
好看的程式碼來啦。。。
// fileName:excel檔案
// json:上述“其次”讀出的json
// statements:上述“再其次獨處的頭欄位
private static void Json2Class(string fileName, string json, List<object> statements) { string structName = ""; structName = Path.GetFileName(fileName).ToLower().Replace(".xlsx", ""); //首字母大寫 structName = structName.Substring(0, 1).ToUpper() + structName.Substring(1); //輸出目錄控制 string outputFile = Path.Combine(Application.dataPath,"Code/[email protected]/Table"); if (Directory.Exists(outputFile) == false) { Directory.CreateDirectory(outputFile); } //輸出目錄 outputFile = Path.Combine(outputFile, Path.GetFileName(fileName).Replace(".xlsx", ".cs")); //生成類服務 CodeCompileUnit compunit = new CodeCompileUnit(); CodeNamespace sample = new CodeNamespace("Game.Data"); compunit.Namespaces.Add(sample); //引用名稱空間 sample.Imports.Add(new CodeNamespaceImport("System")); sample.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); //在名稱空間下新增一個類 CodeTypeDeclaration wrapProxyStruct = new CodeTypeDeclaration(structName); wrapProxyStruct.IsClass = false; wrapProxyStruct.IsEnum = false; wrapProxyStruct.IsInterface = false; wrapProxyStruct.IsPartial = false; wrapProxyStruct.IsStruct = true; //把這個類新增到名稱空間 sample.Types.Add(wrapProxyStruct); // var jsonData = JsonMapper.ToObject(json)[0]; int i = 0; foreach (var key in jsonData.Keys) { //欄位 string memberContent = @" public [type] [Name] {get;set;}"; CodeSnippetTypeMember member = new CodeSnippetTypeMember(); if (key.ToLower() == "id" && key != "Id") { Debug.LogErrorFormat("<color=yellow>表格{0}欄位必須為Id[大小寫],請修改後生成</color>", structName); break; } else if (key == "Id") { //增加一個sqlite主鍵 //member.CustomAttributes.Add(new CodeAttributeDeclaration("PrimaryKey")); memberContent = @" [PrimaryKey] public [type] [Name] {get;set;}"; } var value = jsonData[key]; string type = null; if (value.IsArray) { var str = value.ToJson(); if (str.IndexOf("\"") > 0) { type = "List<string>"; } else { type = "List<double>"; } } else if (value.IsInt) type = "int"; else if (value.IsDouble || value.IsLong) type = "double"; else if (value.IsBoolean) type = "bool"; else if (value.IsString) type = "string"; //註釋 member.Comments.Add(new CodeCommentStatement(statements[i].ToString())); member.Text = memberContent.Replace("[type]", type).Replace("[Name]", key); wrapProxyStruct.Members.Add(member); i++; } //生成程式碼 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; options.BlankLinesBetweenMembers = true; using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile)) { provider.GenerateCodeFromCompileUnit(compunit, sw, options); } }
上述功法祕籍,對於未曾接觸過的英雄豪傑來說還是略有難度,不過別怕 ,結合我上述貼出的CodeDom網址一塊修行,效果還是顯著的。望各位珍重身體
行了,口乾舌燥了 也該結束了。
啥,殘卷練得筋脈逆流,走火入魔。就你事多 哪次都是你逼逼。
using System.CodeDom; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.IO; using BDFramework.ResourceMgr; using LitJson; using UnityEditor; using UnityEngine; using System; static public class Excel2Code { public static void GenCode() { var tablePath = Path.Combine(Application.dataPath, "Resource/Table"); var tableDir = Path.GetDirectoryName(tablePath); var xlslFiles = Directory.GetFiles(tableDir, "*.xlsx", SearchOption.AllDirectories); if (xlslFiles.Length == 0) { EditorUtility.DisplayDialog("提示", "未發現xlsx檔案,請注意不是xls", "確定"); return; } foreach (var f in xlslFiles) { var excel = new ExcelUtility(f); var json = excel.GetJson(); var statements = excel.GetLine(0); Json2Class(f, json, statements); Debug.Log("匯出:" + f); } EditorUtility.DisplayDialog("提示", "生成完成!", "確定"); AssetDatabase.Refresh(); } private static void Json2Class(string fileName, string json, List<object> statements) { string structName = ""; structName = Path.GetFileName(fileName).ToLower().Replace(".xlsx", ""); //首字母大寫 structName = structName.Substring(0, 1).ToUpper() + structName.Substring(1); //輸出目錄控制 string outputFile = Path.Combine(Application.dataPath,"Code/[email protected]/Table"); if (Directory.Exists(outputFile) == false) { Directory.CreateDirectory(outputFile); } //輸出目錄 outputFile = Path.Combine(outputFile, Path.GetFileName(fileName).Replace(".xlsx", ".cs")); //生成類服務 CodeCompileUnit compunit = new CodeCompileUnit(); CodeNamespace sample = new CodeNamespace("Game.Data"); compunit.Namespaces.Add(sample); //引用名稱空間 sample.Imports.Add(new CodeNamespaceImport("System")); sample.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); sample.Imports.Add(new CodeNamespaceImport("Game.Data")); sample.Imports.Add(new CodeNamespaceImport("SQLite4Unity3d")); //在名稱空間下新增一個類 CodeTypeDeclaration wrapProxyStruct = new CodeTypeDeclaration(structName); wrapProxyStruct.IsClass = false; wrapProxyStruct.IsEnum = false; wrapProxyStruct.IsInterface = false; wrapProxyStruct.IsPartial = false; wrapProxyStruct.IsStruct = true; //把這個類新增到名稱空間 sample.Types.Add(wrapProxyStruct); // var jsonData = JsonMapper.ToObject(json)[0]; int i = 0; foreach (var key in jsonData.Keys) { //欄位 string memberContent = @" public [type] [Name] {get;set;}"; CodeSnippetTypeMember member = new CodeSnippetTypeMember(); if (key.ToLower() == "id" && key != "Id") { Debug.LogErrorFormat("<color=yellow>表格{0}欄位必須為Id[大小寫],請修改後生成</color>", structName); break; } else if (key == "Id") { //增加一個sqlite主鍵 //member.CustomAttributes.Add(new CodeAttributeDeclaration("PrimaryKey")); memberContent = @" [PrimaryKey] public [type] [Name] {get;set;}"; } var value = jsonData[key]; string type = null; if (value.IsArray) { var str = value.ToJson(); if (str.IndexOf("\"") > 0) { type = "List<string>"; } else { type = "List<double>"; } } else if (value.IsInt) type = "int"; else if (value.IsDouble || value.IsLong) type = "double"; else if (value.IsBoolean) type = "bool"; else if (value.IsString) type = "string"; //註釋 member.Comments.Add(new CodeCommentStatement(statements[i].ToString())); member.Text = memberContent.Replace("[type]", type).Replace("[Name]", key); wrapProxyStruct.Members.Add(member); i++; } //生成程式碼 CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; options.BlankLinesBetweenMembers = true; using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile)) { provider.GenerateCodeFromCompileUnit(compunit, sw, options); } } }
原版祕籍拿去,切記 第一章的“欲練此功,必先自宮”,可不必相信,否則後果概與本人無關。