1. 程式人生 > >unity遊戲開發 Excel表格生成class類

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);
            }
        }
}

原版祕籍拿去,切記 第一章的“欲練此功,必先自宮”,可不必相信,否則後果概與本人無關。