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

   
}

在这里插入图片描述

资源下载地址: 前往下载

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯过客TYGK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值