unity Excel配置表导出工具

Posted 天涯过客TYGK

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity Excel配置表导出工具相关的知识,希望对你有一定的参考价值。

需要用到的dll插件

Excel格式:
第一行为标题
第二行设置是否是索引列,索引列的内容会被转成列表形式
第三行设置数据类型
后面添加数据具体内容
如果第一列内容为空,不读取本行内容,可以用来处理备注
(如果第一行标题为空,不读取这一列数据,默认为备注行,这个需求暂未添加)

一 、添加Excel 转json工具

using Excel;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEngine;
using UnityEditor;


public class MasterToJson 

    /// <summary>
    /// 配置文件存放在项目根目录
    /// </summary>
    static string fileDirPath = @"ConfigExcel";
    private static string outPath = "OutPutJson";
    private static string KeyText = "k";

    [MenuItem("Tool/Master To Json Text")]
    static void ChangeToJson()
    
        string excelFolderPath = Path.Combine(Application.dataPath, fileDirPath);
        DirectoryInfo dir = new DirectoryInfo(excelFolderPath);
        FileInfo[] fileInfos =  dir.GetFiles("*", SearchOption.AllDirectories);
        for (int i = 0; i < fileInfos.Length; i++)
        
            ExportFile(fileInfos[i].FullName);
        
    

    /// <summary>
    /// 导出单个excel内容
    /// </summary>
    /// <param name="filePath"></param>
    static void ExportFile(string filePath)
    
        if (filePath.EndsWith("meta") || filePath.Contains("$")) return;
        //取Excel名字的第一部分作为保存文件名称
        Debug.Log(filePath);
        string excelName = Path.GetFileNameWithoutExtension(filePath);

        using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
        
            IExcelDataReader excelDataReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
            DataSet result = excelDataReader.AsDataSet();


            DataTableCollection tables = result.Tables;

            foreach (DataTable sheetTable in tables)
            
                //Debug.Log("table sheet Name is " + sheetTable.TableName);
                //获取需要转换的sheet标签页,sheet页名称不包含#并且不以下划线开头,#是备注类用的表,下划线是服务器用的表
                if (sheetTable.TableName.IndexOf('#') == -1 && (sheetTable.TableName.IndexOf('_') > 0 || sheetTable.TableName.IndexOf('_') == -1))
                
                    ConvertSheetToJson(sheetTable, excelName);
                
            
            excelDataReader.Dispose();
        ;
    
    
    /// <summary>
    /// 把单个sheet文件转json
    /// </summary>
    /// <param name="data"></param>
    /// <param name="excelName"></param>
    static void ConvertSheetToJson(DataTable sheetTable, string excelName)
    
        int columIndex = 0;
        int keyCount = 0;

        int columnsCount = sheetTable.Columns.Count;
        int rowCount = sheetTable.Rows.Count;
        if (columnsCount <= 3 || rowCount <= 1) 
            Debug.Log("skip empty table:" + sheetTable.TableName);
            return;
        
        //List<string> titleList = new List<string>();
        List<ColumData> paramsList = new List<ColumData>();
        for (int i = 0; i < columnsCount; i++)
        
            ColumData cData = new ColumData();
            string content = sheetTable.Rows[2][i].ToString();
            if (IsString(content)) cData.type = ParamsType.String;
            else if(IsInt(content)) cData.type = ParamsType.Int;
            else cData.type =  ParamsType.None;
            paramsList.Add(cData);
        
        JSONObject tableJson = new JSONObject();
        JSONObject contentJson = new JSONObject();
        tableJson.AddField(sheetTable.TableName, contentJson);
        bool isFinish = false;

        for (int i = 0; i < rowCount; i++)
        
            JSONObject job = new JSONObject();
            for (int j = 0; j < columnsCount; j++)
            
                if (i == 0)//标题
                
                    paramsList[j].name = sheetTable.Rows[i][j].ToString();
                else if (paramsList[j].type != ParamsType.None)
                
                    if (i == 1)//索引类型 keyText 表示该列是索引
                    
                        if (sheetTable.Rows[i][j].ToString().Equals(KeyText))
                        
                            keyCount++;
                            paramsList[j].isKey = true;
                        
                    
                    else if (i == 2) continue;
                    else
                    
                        if (j == 0 && string.IsNullOrEmpty(sheetTable.Rows[i][j].ToString())) //第一列内容为空,判定该表内容读取结束
                        
                            continue;
                        
                        if (!paramsList[j].isKey)
                        
                            GetColumJson(sheetTable.Rows, 0, i, paramsList, job);
                            string res = job.ToString();
                            Debug.Log(res);
                            break;
                        
                    
                
                
                
            

            
            if (job && !job.IsNull)
            
                contentJson.Add(job);
            
        
        SaveFile(tableJson.ToString(), excelName, sheetTable.TableName);
    

    /// <summary>
    /// 把表格单行数据转换为json对象
    /// </summary>
    /// <param name="item"></param>
    /// <param name="columnIndex"></param>
    /// <param name="rowIndex"></param>
    /// <param name="paramsList"></param>
    /// <param name="job"></param>
    private static void GetColumJson(DataRowCollection item, int columnIndex, int rowIndex, List<ColumData> paramsList, JSONObject job)
    
        if (columnIndex >= paramsList.Count) return;
        if (paramsList[columnIndex].type == ParamsType.None)
        
            columnIndex++;
            GetColumJson(item, columnIndex, rowIndex, paramsList, job);
        
        else if (paramsList[columnIndex].isKey && columnIndex > 0)
        
            string arrKey = "index_list";
            JSONObject jsonArr = new JSONObject();
            JSONObject itemJson = new JSONObject();
            jsonArr.Add(itemJson);
            job.AddField(arrKey, jsonArr);
            itemJson.AddField(paramsList[columnIndex].name, item[rowIndex][columnIndex].ToString());

            columnIndex++;
            GetColumJson(item, columnIndex, rowIndex, paramsList, itemJson);
        
        else 
            job.AddField(paramsList[columnIndex].name, item[rowIndex][columnIndex].ToString());
            columnIndex++;
            GetColumJson(item, columnIndex, rowIndex, paramsList, job);
        
    

    private static bool IsInt(string typeName)
    
        if (typeName.ToLower().Contains("int") || typeName.ToLower().Contains("timestamp"))
        
            return true;
        
        return false;
    

    private static bool IsString(string typeName)
    
        if (typeName.ToLower().Contains("string") || typeName.ToLower().Contains("time") || typeName.ToLower().Contains("text"))
        
            return true;
        
        return false;
    

    private static void SaveFile(string content, string excelName, string sheetName)
    
        string groupName = excelName.Split('_')[0];
        string saveFolderPath = Path.Combine(outPath, groupName);
        saveFolderPath = Path.Combine(Application.dataPath, saveFolderPath);
        if (!Directory.Exists(saveFolderPath))
            Directory.CreateDirectory(saveFolderPath);
        File.WriteAllText(Path.Combine(saveFolderPath, sheetName + ".json"), content);
    

    protected enum ParamsType
    
        None,
        Int,
        String,
    

    protected class ColumData
    
        public string name;
        public ParamsType type;
        public bool isKey;

    


二、添加Excel 转C#数据类工具

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using Excel;
using System.Data;

public class MasterToCs

    static List<string> masterNameList = new List<string>()
    
        "unit_config.xlsx",
    ;

    [MenuItem("Tool/Master To Client Template")]
    public static void MasterExport()
    
        foreach (var item in masterNameList)
        
            MasterUtil.Export(item);
        

    

    class MasterUtil
    
        private const string TemplatePath = "/Editor/MasterToCS/Template/";
        private const string TemplateOneKeyFile = "template_1key.txt";
        private const string TemplateTwoKeyFile = "template_2key.txt";
        private const string TemplateThreeKeyFile = "template_3key.txt";
        private const string TemplateFourKeyFile = "template_4key.txt";
        private const string TemplateParamFile = "template_param.txt";
        
        // 直接更新所有的表文件,使用这个路径
        private const string OutputPath = "output";
        private const string TemplateFile = "";
        private const string KeyText = "k";

        private const string MasterUpperNameReplaceStr = "[MasterName]";
        private const string MasterLowerNameReplaceStr = "[mastername]";
        private const string ParamListStr = "[paramList]";

        private const string MasterFilePath = @"ConfigExcel/";

        public static string masterGroupName = "";
        public static string outputFilePath = "";

        static string appPath = Application.dataPath;

        public static void Export(string masterFileName)
        
            masterGroupName = "";

            string[] tmpGroupName = masterFileName.Split('.')[0].Split('_');
            for (int i = 0; i < tmpGroupName.Count() - 1; i++)
            
                masterGroupName += GetUpperName(tmpGroupName[i]);
            
            outputFilePath = OutputPath + "/" + masterGroupName;
            outputFilePath = Path.Combine(Application.dataPath, outputFilePath);

            //Debug.Log("输出文件名 : " + masterGroupName);

            Debug.Log("输出路径 : " + outputFilePath);

            if (!Directory.Exists(outputFilePath))
            
                Debug.Log("创建路径" + outputFilePath);
                Directory.CreateDirectory(outputFilePath);
            


            #region excel
            

            string masterFilePath =  MasterFilePath + masterFileName;
            masterFilePath = Path.Combine(Application.dataPath, masterFilePath);
            if (!File.Exists(masterFilePath))
            
                Debug.LogError("not exist path.." + masterFilePath);
                return;
            
            using (FileStream stream = File.Open(masterFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            
                IExcelDataReader excelDataReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
                DataSet result = excelDataReader.AsDataSet();


                DataTableCollection tables = result.Tables;

                foreach (DataTable item in tables)
                
                    Debug.Log("tableName is "+item.TableName);

                    ConvertSheetToCs(item);
                
                excelDataReader.Dispose();
            ;


            Debug.Log("export template finish!");
            #endregion
        


        /// <summary>
        /// 转换单个sheet表,生成对应的数据类
        /// </summary>
        /// <param name="sheet"></param>
        static void ConvertSheetToCs(DataTable sheet)
        
            //列数
            int colNum = 0;
            //主键个数
            int keyCnt = 0;

            List<ColumData> columList = new List<ColumData>();

            while (true)
            
                if (colNum >= sheet.Columns.Count) break;
                string columName = sheet.Rows[0][colNum].ToString();
                string columType = sheet.Rows[2][colNum].ToString();
                if (columName == "")
                
                    break;
                
                if (columType != "")
                
                    Debug.LogError(sheet.Rows[1][colNum].ToString().ToLower() + "-->" + colNum);
                    bool isKey = sheet.Rows[1][colNum].ToString().ToLower().Equals( KeyText ) ? true : false;
                    if (isKey)
                    
                        keyCnt++;
                    
                    //Debug.Log(columName + " (" + columType + "), isKey : " + isKey);

                    ColumData data = new ColumData(columName, columType, isKey);
                    columList.Add(data);
                

                colNum++;
            

            Debug.Log("keyCnt : " + keyCnt);
            if (keyCnt == 1)
            
                ConvertOneKeyMaster(sheet, columList);
            
            if (keyCnt < 5 && keyCnt > 1)
            
                ConvertTwoMoreKeyMaster(sheet, columList, keyCnt);
            
            if (keyCnt >= 5)
            
                Debug.LogError("========= 暂不支持5个以上主键,请添加template文件。");
            
        

        /// <summary>
        /// 包含单个主键的配置表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="columList"></param>
        private static void ConvertOneKeyMaster(DataTable sheet, List<ColumData> columList)
        
            string masterNameInLower = sheet.TableName;
            string masterNameInUpper = GetUpperName(masterNameInLower);
            Debug.Log("master class 名 : " + masterNameInLower + " / " + masterNameInUpper);
            string appPath = Application.dataPath;
            string template_file_path = appPath + TemplatePath + TemplateOneKeyFile;
            Debug.Log("template file path : " + template_file_path);
            if (!System.IO.File.Exists(template_file_path))
            
                Debug.LogWarning("not find template!");
                return;
            
             
            string template_file_data = string.Empty;     
            using (System.IO.StreamReader sr = new System.IO.StreamReader(template_file_path))
            
                template_file_data = sr.ReadToEnd();  
            

            template_file_data = template_file_data.Replace(MasterUpperNameReplaceStr, masterNameInUpper);
            template_file_data = template_file_data.Replace(MasterLowerNameReplaceStr, masterNameInLower);

             
            string template_param_file_path = appPath + TemplatePath + TemplateParamFile;
            string param_template = "";    
            string param_str = "";     
            using (System.IO.StreamReader sr = new System.IO.StreamReader(template_param_file_path))
            
                param_template = sr.ReadToEnd();  
            

            var keyList = columList.Where(t => t.isKey == true);

            var paramList = columList.Where(t => t.isKey != true);

            foreach (var k in keyList)
            
                Debug.Log("Key is : " + k.name);
                //string key_param = param_template.Replace("[param]", masterNameInUpper);
                template_file_data = template_file_data.Replace("[key]", k.name);
                template_file_data = template_file_data.Replace("[Key]", GetUpperName(k.name));

                if (IsInt(k.type))
                
                    template_file_data = template_file_data.Replace("[key_type]", "int");
                
                else if (IsString(k.type))
                
                    template_file_data = template_file_data.Replace("[key_type]", "string");
                
            

            foreach (var param in paramList)
            
                string paramNamaInUpper = GetUpperName(param.name);
                string tmpStr = param_template.Replace("[param]", param.name);

                if (IsInt(param.type))
                
                    tmpStr = tmpStr.Replace("[param_type]", "int");
                
                else if (IsString(param.type))
                
                    tmpStr = tmpStr.Replace("[param_type]", "string");
                

                param_str += tmpStr.Replace("[Param]", paramNamaInUpper);
            

            template_file_data = template_file_data.Replace(ParamListStr, param_str);
            string fileName = string.Format(@"0\\1.cs", outputFilePath, masterNameInUpper);
            Debug.Log("output : " + fileName);
            File.WriteAllText(fileName, template_file_data);
        

        /// <summary>
        /// 包含多个主键的配置表
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="columList"></param>
        private static void ConvertTwoMoreKeyMaster(DataTable sheet, List<ColumData> columList, int keyNum)
        
            string masterNameInLower = sheet.TableName;
            string masterNameInUpper = GetUpperName(masterNameInLower);
            Debug.Log("master class 名 : " + masterNameInLower + " / " + masterNameInUpper);
            string appPath = Application.dataPath;
            string template_file_path = appPath + TemplatePath + TemplateTwoKeyFile;
            if (keyNum == 3)
            
                template_file_path = appPath + TemplatePath + TemplateThreeKeyFile;
            
            if (keyNum == 4)
            
                template_file_path = appPath + TemplatePath + TemplateFourKeyFile;
            
            Debug.Log("template file path : " + template_file_path);
            if (!System.IO.File.Exists(template_file_path))
            
                Debug.LogWarning("not find template!");
                return;
            
            
            string template_file_data = string.Empty;     
            using (System.IO.StreamReader sr = new System.IO.StreamReader(template_file_path))
            
                template_file_data = sr.ReadToEnd();  
            

            template_file_data = template_file_data.Replace(MasterUpperNameReplaceStr, masterNameInUpper);
            template_file_data = template_file_data.Replace(MasterLowerNameReplaceStr, masterNameInLower);

             
            string template_param_file_path = appPath + TemplatePath + TemplateParamFile;
            string param_template = "";     
            string param_str = "";     
            using (System.IO.StreamReader sr = new System.IO.StreamReader(template_param_file_path))
            
                param_template = sr.ReadToEnd(); 
            

            var keyList = columList.Where(t => t.isKey == true);

            var paramList = columList.Where(t => t.isKey != true);

            int keyCnt = 1;
            foreach (var k in keyList)
            
                Debug.Log("Key" + keyCnt + " is : " + k.name);
                template_file_data = template_file_data.Replace("[key" + keyCnt + "]", k.name);
                template_file_data = template_file_data.Replace("[Key" + keyCnt + "]", GetUpperName(k.name));

                if (IsInt(k.type))
                
                    template_file_data = template_file_data.Replace("[key_type" + keyCnt + "]", "int");
                
                else if (IsString(k.type))
                
                    template_file_data = template_file_data.Replace("[key_type" + keyCnt + "]", "string");
                
                keyCnt++;
            

            foreach (var param in paramList)
            
                string paramNamaInUpper = GetUpperName(param.name);
                string tmpStr = param_template.Replace("[param]", param.name);

                if (IsInt(param.type))
                
                    tmpStr = tmpStr.Replace("[param_type]", "int");
                
                else if (IsString(param.type))
                
                    tmpStr = tmpStr.Replace("[param_type]", "string");
                

                param_str += tmpStr.Replace("[Param]", paramNamaInUpper);
            

            template_file_data = template_file_data.Replace(ParamListStr, param_str);
            string fileName = string.Format(@"0\\1.cs", outputFilePath, masterNameInUpper);
            Debug.Log("output : " + fileName);
            File.WriteAllText(fileName, template_file_data);
        


        private static string GetUpperName(string name)
        
            string[] tmpNameArray = name.Split('_');
            string nameInUpper = "";

            System.Globalization.TextInfo ti = System.Globalization.CultureInfo.CurrentCulture.TextInfo;

            foreach (var t in tmpNameArray)
            
                nameInUpper += ti.ToTitleCase(t);
            

            return nameInUpper;
        

        private static bool IsInt(string typeName)
        
            if (typeName.ToLower().Contains("int") || typeName.ToLower().Contains("timestamp"))
            
                return true;
            
            return false;
        

        private static bool IsString(string typeName)
        
            if (typeName.ToLower().Contains("string") || typeName.ToLower().Contains("time") || typeName.ToLower().Contains("text"))
            
                return true;
            
            return false;
        
    

    public class ColumData
    
        public string name;
        public string type;
        public bool isKey;

        public ColumData(string _name, string _type, bool _isKey)
        
            name = _name;
            type = _type;
            isKey = _isKey;
        
    


转换时候用到的模板文件 template_1key.txt

/*******************************************
 * 从主 Excel 自动生成的文件 *
 * 不要手动修改该文件! *
 *******************************************/

using System.Collections.ObjectModel;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;

namespace Master

    public class [MasterName]Data : ISerializationCallbackReceiver
    
        /// <summary>
        /// 序列化列表
        /// </summary>
        [SerializeField]
        private List<[MasterName]DataFormat> [mastername];
        /// <summary>
        /// 私有Dictionary
        /// </summary>
        private ReadOnlyDictionary<[key_type], [MasterName]DataFormat> _[mastername];
        /// <summary>
        /// 属性Dictionary
        /// key:[key]
        /// </summary>
        public ReadOnlyDictionary<[key_type], [MasterName]DataFormat> [MasterName]Dic  get  return _[mastername];  

        public void OnAfterDeserialize()
        
            if (_[mastername] != null)
            
                _[mastername] = null;
            
            _[mastername] = new ReadOnlyDictionary<[key_type], [MasterName]DataFormat>([mastername].ToDictionary(key => key.[Key], value => value));
        

        public void OnBeforeSerialize()
        
        

        [Serializable]
        public class [MasterName]DataFormat
        
            [SerializeField]
            private [key_type] [key];
            public [key_type] [Key]  get  return [key];  
[paramList]
        
    

template_2key.txt


/*******************************************
* 从主 Excel 自动生成的文件 *
* 不要手动修改该文件! *
*******************************************/

using System.Collections.ObjectModel;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;

namespace Master

   public class [MasterName]Data : ISerializationCallbackReceiver
   
       / <summary>
       /// 序列化列表
       /// </summary>
       [SerializeField]
       private List<[MasterName]DataFormat> [mastername];
       /// <summary>
       /// 私有Dictionary
       /// </summary>
       private ReadOnlyDictionary<[key_type1], [MasterName]DataFormat> _[mastername];
       /// <summary>
       /// 属性Dictionary
       /// key:unit id
       /// </summary>
       public ReadOnlyDictionary<[key_type1], [MasterName]DataFormat> [MasterName]Dic  get  return _[mastername];  

       public void OnAfterDeserialize()
       
           if (_[mastername] != null)
           
               _[mastername] = null;
           
           _[mastername] = new ReadOnlyDictionary<[key_type1], [MasterName]DataFormat>([mastername].ToDictionary(key => key.[Key1], value => value));
       

       public void OnBeforeSerialize()
       
       

       [Serializable]
       public class [MasterName]DataFormat : ISerializationCallbackReceiver
       
           [SerializeField]
           private [key_type1] [key1];
           public [key_type1] [Key1]  get  return [key1];  

           / <summary>
           /// 序列化列表
           /// </summary>
           [SerializeField]
           private List<[MasterName]IndexFormat> index_list;
           /// <summary>
           /// 私有Dictionary
           /// </summary>
           private ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat> _index_list;
           /// <summary>
           /// 属性Dictionary
           /// key:unit id
           /// </summary>
           public ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat> Index  get  return _index_list;  

           public void OnAfterDeserialize()
           
               if (_index_list != null)
               
                   _index_list = null;
               
               _index_list = new ReadOnlyDictionary<[key_type2], [MasterName]IndexFormat>(index_list.ToDictionary(key => key.[Key2], value => value));
           

           public void OnBeforeSerialize()
           
           
       

       [Serializable]
       public class [MasterName]IndexFormat
       
           [SerializeField]
           private [key_type2] [key2];
           public [key_type2] [Key2]  get  return [key2];  
[paramList]
       
   

三、运行过程中读取json文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConfigManger : MonoBehaviour

    public TextAsset fonfigJson;
    
    void Start()
    
        string content = fonfigJson.text;
        Master.UnitData unitData = JsonUtility.FromJson<Master.UnitData>(content);
        Debug.Log(unitData.UnitDic.Count);
        foreach (var item in unitData.UnitDic)
        
            Debug.Log(item.Value.Name);
        
    

   


资源下载地址: 前往下载

以上是关于unity Excel配置表导出工具的主要内容,如果未能解决你的问题,请参考以下文章

Unity中解析Excel表格工具

Unity中解析Excel表格工具

Unity中根据Excel配表产生C#配置类

如何导出一个excel

配置简单功能强大的excel工具类搞定excel导入导出工具类

java导出复杂Excel报表求帮助