Unity常用工具之自动化读取Excel表(可读取数组)

前言
最近需要读取策划的配置表,查找了相关文章,发现内容都不甚详细,不是缺少了这个功能就是缺少了那个功能,遂决定自己动手写一个
包含的功能有:
1.生成或读取对应的类
2.根据表内数据生成Json数据文件
效果
在这里插入图片描述

准备
1.接入3个第三方库(2023.7.7更新,脚本也加入了网盘)
链接:https://pan.baidu.com/s/1PuvP6zHncRalvtHhqp-VtQ?pwd=2fj9
提取码:2fj9

把三个dll扔到Unity项目的Plugins里就行(还没有这个文件夹就手动创建一个)
在这里插入图片描述

2.一个表格
在这里插入图片描述
包含的内容为:①字段描述②字段名③字段类型④数据,前三个的顺序不重要,根据自己习惯来就行,不过这个不一样的话要稍加修改代码,修改哪下文会提到

正题

思路:
1.首先 考虑清楚流程是什么样的
第一步 我们读取excel表中的数据
第二步 创建或者获取类
第三步 把读取的数据转化成对应的类的列表 然后转成json

2.去实现相关方法

如何获取文件夹下的所有excel文件

想法是 获取所有文件 然后判断文件后缀 如果为excel则加入列表

public static List<FileInfo> GetAllExcel(string dirPath)
    {
        List<FileInfo> fileList = new List<FileInfo>();
        if (!Directory.Exists(dirPath))
        {
            Debug.LogError("文件夹地址错误");
            return null;
        }
        DirectoryInfo direction = new DirectoryInfo(dirPath);//获取文件夹,exportPath是文件夹的路径
        FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].Name.EndsWith(".xlsx"))
            {
                if (!fileList.Contains(files[i]))
                {
                    fileList.Add(files[i]);
                }
            }
        }
        return fileList;
    }

如何读取数据

引入命名空间

using Microsoft.SqlServer.Server;
using Excel;

根据文件地址读取表的内容

public static DataRowCollection ReadExcel(string filePath, ref int columnNum, ref int rowNum)
    {
        FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        DataSet result = excelReader.AsDataSet();
        //Tables[0] 下标0表示excel文件中第一张表的数据
        columnNum = result.Tables[0].Columns.Count;
        rowNum = result.Tables[0].Rows.Count;
        stream.Close();
        return result.Tables[0].Rows;
    }

如何生成类

获取对应表的第二行和第三行的内容,第二行为属性名,第三行为类型,写入文件的方法很简单,就是像打字一样把内容输入进去,就会自动识别 如"public “+” "+“类型名” +“ ” +属性名 +“;” 这样就可以完成一行属性的定义,类名设定为表名

public static void AutoCreateClass(string filePath)
    {
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        string storeEntityPath= $"{m_EntitySavePath}/{fileName}.cs";
        //获得表数据
        int columnNum = 0, rowNum = 0;
        DataRowCollection collect = ReadExcel(filePath, ref columnNum, ref rowNum);
        StringBuilder sb = new StringBuilder();

        sb.AppendLine($"\tpublic class {fileName}");
        sb.AppendLine("\t{");
        for (int i = 0; i < columnNum; i++)
        {
            sb.AppendLine($"\t\tpublic {collect[2][i].ToString()} {collect[1][i].ToString()};");
        }
        sb.AppendLine("\t}");
        try
        {
            if (!Directory.Exists(m_EntitySavePath))
            {
                Directory.CreateDirectory(m_EntitySavePath);
            }
            if (!File.Exists(storeEntityPath))
            {
                File.Create(storeEntityPath).Dispose(); //避免资源占用
            }
            File.WriteAllText(storeEntityPath, sb.ToString());
        }
        catch (System.Exception e)
        {
            Debug.LogError($"Excel转json时创建对应的实体类出错,实体类为:{fileName},e:{e.Message}");
        }
    }

如何将数据转化成json

先读表,然后根据表名在程序集中找类(这里默认生成在Assembly-CSharp里面),没有类就创建类,有类就获取,创建一个对象,然后从第四行开始(因为我这边第四行开始是数据)遍历列,很类中的每个字段一一对应赋值,再将这个对象放入列表,如果想要获取数组,需要规定一个分隔符来分隔数据,这里分隔符设定为|

 public void ToJson(string filePath)
    {
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        string storeJsonPath = $"{m_JsonSavePath}/{fileName}.json";
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            //获得表数据
            int columnNum = 0, rowNum = 0;
            DataRowCollection collect = ReadExcel(filePath, ref columnNum, ref rowNum);
            List<System.Object> objList = new List<object>();
            objList.Clear();
            //获取当前实体类
            Assembly ab = Assembly.Load("Assembly-CSharp");
            Type type = ab.GetType(fileName);
            if (type == null)
            {
                Debug.LogError("你还没有创建对应的实体类!");
                return;
            }
            if (!Directory.Exists(m_JsonSavePath))
                Directory.CreateDirectory(m_JsonSavePath);

            //逐行添加数据 从第四行开始是数据
            for (int i = 3; i < rowNum; i++)
            {
                //创建一个实体类
                object obj = ab.CreateInstance(type.ToString());
                for (int z = 0; z < columnNum; z++)
                {
                    //获取表格中对应字段名的信息
                    FieldInfo info = type.GetField(collect[1][z].ToString());
                    //是数组
                    if (info.FieldType.IsArray)
                    {
                        string currentContext = collect[i][z].ToString();
                        string[] strs = currentContext.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                        //数组内元素的类型
                        Type elementType = info.FieldType.GetElementType();
   
                        //创建数组
                        object array = Activator.CreateInstance(info.FieldType, new object[] { strs.Length });

                        MethodInfo setValue = info.FieldType.GetMethod("SetValue", new Type[2] { typeof(object), typeof(int) });
                        //给数组赋值
                        for (int m = 0; m < strs.Length; m++)
                        {
                            object v = Convert.ChangeType(strs[m], elementType);
                            setValue.Invoke(array, new object[] { v, m });
                        }
                        type.GetField(collect[1][z].ToString()).SetValue(obj, array);

                    }
                    //不是数组
                    else
                    {
                        //将表格中的数据转换为对应的数据类型
                        object value = Convert.ChangeType(collect[i][z].ToString(), info.FieldType);
                        //给对应的字段赋值
                        type.GetField(collect[1][z].ToString()).SetValue(obj, value);
                    }
                   
                    
                }
                objList.Add(obj);
            }
            //写入json文件
            
            if (!File.Exists(storeJsonPath))
            {
                File.Create(storeJsonPath).Dispose();
            }
            File.WriteAllText(storeJsonPath, JsonConvert.SerializeObject(objList));
            Debug.Log($"生成{fileName}Json文件成功");
        }
    }

最后就是一些编辑器扩展方面的

 private static string m_JsonSavePath = "Json";
    private static string m_EntitySavePath = "Entity";
    private static string m_DirPath = "Excel";
    private Vector2 scrollPos;
    public static readonly char[] separators = { '|', ',' };

    [MenuItem("EasyTools/CreateCS")]
    static void OpenWindow()
    {
        ExcelHelper window = (ExcelHelper)EditorWindow.GetWindow(typeof(ExcelHelper));
        window.Show();
    }
    private void OnEnable()
    {
        m_JsonSavePath= EditorPrefs.GetString("JsonSavePath");
        m_EntitySavePath = EditorPrefs.GetString("EntitySavePath");
        m_DirPath = EditorPrefs.GetString("DirPath");
      
    }
    private void OnGUI()
    {
        EditorGUI.BeginChangeCheck();
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("表存放目录: ");
        GUILayout.TextField(m_DirPath);
        if (GUILayout.Button("选择表存放目录"))
        {
            OpenFileSelectWindow_Dir();
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("实体存放目录: ");
        GUILayout.TextField(m_EntitySavePath);
        if (GUILayout.Button("选择实体所在目录"))
        {
            OpenFileSelectWindow_Entity();
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Json存放目录: ");
        GUILayout.TextField(m_JsonSavePath);
        if (GUILayout.Button("选择Json存放目录"))
        {
            OpenFileSelectWindow_Json();
        }
        EditorGUILayout.EndHorizontal();


        if (GUILayout.Button("生成实体类"))
        {
            CreateEntities();
        }
        if (GUILayout.Button("生成Json"))
        {
            ExcelToJson();
        }
        EditorGUILayout.EndScrollView();
        if (EditorGUI.EndChangeCheck())
            EditorPrefs.SetString("JsonSavePath",m_JsonSavePath);
            EditorPrefs.SetString("EntitySavePath", m_EntitySavePath);
            EditorPrefs.SetString("DirPath", m_DirPath);
    }
    private void OpenFileSelectWindow_Dir()
    {
        m_DirPath = EditorUtility.OpenFolderPanel("自定义标题", Application.dataPath, "默认文件名");
    }
    private void OpenFileSelectWindow_Json()
    {
        m_JsonSavePath = EditorUtility.OpenFolderPanel("自定义标题", Application.dataPath, "默认文件名");
    }
    private void OpenFileSelectWindow_Entity()
    {
        m_EntitySavePath = EditorUtility.OpenFolderPanel("自定义标题", Application.dataPath, "默认文件名");
    }
  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值