Unity Excel configuration table export tool

The dll plug-in Excel format that needs to be used
insert image description here
:
the first line is the title,
the second line sets whether it is an index column, the content of the index column will be converted into a list form, the
third line sets the data type, and
the specific content of the data is added later
if the content of the first column is empty , do not read the content of this row, and can be used to process notes
(if the first row title is empty, do not read this column of data, the default is the note line, this requirement has not been added yet)
insert image description here

1. Add Excel to json tool

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;

    }
}

2. Add Excel to C# data tool

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

The template file template_1key.txt used for conversion

/*******************************************
 * 从主 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]
       }
   }
}

3. Read the json file during operation

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

   
}

insert image description here

Resource download address: go to download

Guess you like

Origin blog.csdn.net/u011484013/article/details/128634555