读取excel文件并将其中数据转换成脚本数据结构--续

前文《读取excel文件并将其中数据转换成脚本数据结构》中说到了将Excel文件中的数据结构自动生成脚本中的类结构。但是上篇中的代码写法在生成出错的情况下不能自动删除错误脚本。需要自己手动删除。

读取excel文件并将其中数据转换成脚本数据结构--续_第1张图片

现在我将代码写法做了点点改动,实现了生成错误脚本之后能自动删除文件。

直接上改后的代码:

using UnityEngine;
using System.Collections;
using Excel;
using System.IO;
using System.Text;
using System.Data;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using UnityEditor;

public class UnityEditorSelection_Test : Editor
{
    [MenuItem("Change/将excel文件内容转换成类结构2")]
    public static void WriteClass2() //这个方法可以将生成的错误文件自动删除
    {
        string path = Application.dataPath + "/MyScripts/";
        string excel = Application.dataPath + "/Excel";

        //原本要保存的文件名为DataClass.cs,但是先生成DataClass2.cs,成功之后将原文件删除,重命名这个文件。
        //这样做是为了避免在写入过程中出现错误,导致原文件都被破坏了
        string targetPath = path + "/DataClass2.cs"; //要写入的文件脚本

        DirectoryInfo di = new DirectoryInfo(excel);
        System.Object data = null;

        FileStream fs = new FileStream(targetPath, FileMode.Create, FileAccess.Write);
        try
        {
            TextWriter tw = new StreamWriter(fs);
            try
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("using UnityEngine;"); //注意格式、大小写、结束符
                sb.AppendLine(); //空一行
                sb.AppendLine("namespace DataClass"); //写入命名空间
                sb.AppendLine("{"); //这是命名空间的前花括号
                tw.Write(sb);
                #region 根据excel表内容写脚本类
                foreach (var f in di.GetFiles("*.xlsx")) //得到所有的excel文件
                {
                    FileStream fs2 = File.Open(f.FullName, FileMode.Open, FileAccess.Read);
                    string className = Path.GetFileNameWithoutExtension(f.FullName); //得到excel表名作为类结构名

                    IExcelDataReader edr = ExcelReaderFactory.CreateOpenXmlReader(fs2);
                    DataSet result = null;

                    try
                    {
                        result = edr.AsDataSet();
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogError("无法获取正确数据! " + e);
                    }

                    if (result.Tables.Count < 1) //判断excel文件中是否存在数据表
                    {
                        Debug.LogWarning("excel文件" + f.Name + "中没有数据表");
                        throw new System.Exception("excel文件" + f.Name + "中没有数据表");
                    }

                    DataTable one = result.Tables[0]; //默认获取第一个数据表

                    if (one.Rows.Count < 1) //判断数据表内是否存在数据
                    {
                        Debug.LogWarning("excel文件" + f.Name + "的第一个数据表中没有数据");
                        throw new System.Exception("excel文件" + f.Name + "的第一个数据表中没有数据");
                    }

                    //存注释
                    List comments = new List();
                    //存字段类型
                    List filedsType = new List();
                    //存字段名
                    List filedsName = new List();

                    string text = string.Empty;
                    for (int i = 0; i < one.Columns.Count; ++i)
                    {
                        //要注意这里获取各个数据的时候,要和excel文件的数据编写顺序一致。excel中第一行是注释,那么这里就要先得到注释
                        //存字段注释
                        comments.Add(one.Rows[0][i].ToString());
                        //存字段类型
                        text = one.Rows[1][i].ToString().Trim(); //以防万一,去掉空格
                        if (string.IsNullOrEmpty(text))
                            continue;

                        switch (text)
                        {
                            case "bool":
                                filedsType.Add("bool");
                                break;
                            case "int":
                                filedsType.Add("int");
                                break;
                            case "float":
                                filedsType.Add("float");
                                break;
                            case "string":
                                filedsType.Add("string");
                                break;
                            case "list":
                                filedsType.Add("List");
                                break;
                            case "vector2":
                                filedsType.Add("Vector2");
                                break;
                            default:
                                Debug.LogWarning("暂不支持类型" + text);
                                break;
                        }
                        //存字段名
                        filedsName.Add(one.Rows[2][i].ToString());
                    }

                    StringBuilder sb2 = new StringBuilder();
                    CultureInfo ci = Thread.CurrentThread.CurrentCulture;
                    TextInfo tf = ci.TextInfo;
                    className = tf.ToTitleCase(className); //转换成首字母大写,其他小写
                                                           //写入声明的类
                    sb2.AppendLine("\tpublic class " + className); //注意换行
                    sb2.AppendLine("\t{"); //类的前花括号

                    for (int i = 0; i < filedsType.Count; ++i)
                    {
                        //字段的注释
                        sb2.AppendLine("\t\t///");
                        sb2.AppendLine("\t\t///" + comments[i]);
                        sb2.AppendLine("\t\t///");
                        //字段具体的声明
                        sb2.AppendLine("\t\tpublic readonly " + filedsType[i] + " " + filedsName[i] + ";");
                    }

                    sb2.AppendLine("\t}"); //类的后花括号
                    sb2.AppendLine(); //空一行 之后写下一个类

                    tw.Write(sb2);
                }
                #endregion
                tw.Write("}");//这是命名空间的后花括号
                data = fs;
            }
            catch (System.Exception e)
            {
                DirectoryInfo di3 = new DirectoryInfo(path);
                FileInfo[] files2 = di3.GetFiles();
                if (files2 != null)
                {
                    for (int i = 0; i < files2.Length; ++i)
                    {
                        if (files2[i].Name.Equals("DataClass2.cs"))
                        {
                            files2[i].Delete();
                            Debug.Log("*****删除原数据结构脚本DataClass2.cs");
                            break;
                        }
                    }
                }
                AssetDatabase.Refresh();
                return; //这里要跳出函数不再执行了
            }
            finally
            {
                tw.Dispose(); //这里一定要释放非托管资源
            }
        }
        catch (System.Exception e)
        {
            DirectoryInfo di3 = new DirectoryInfo(path);
            FileInfo[] files2 = di3.GetFiles();
            if (files2 != null)
            {
                for (int i = 0; i < files2.Length; ++i)
                {
                    if (files2[i].Name.Equals("DataClass2.cs"))
                    {
                        files2[i].Delete();
                        Debug.Log("*****删除原数据结构脚本DataClass2.cs");
                        break;
                    }
                }
            }
            AssetDatabase.Refresh();
            return; //这里要跳出函数不再执行了
        }
        finally
        {
            fs.Dispose(); //这里一定要释放非托管资源
        }

        Debug.Log("新的数据结构脚本生成成功!");

        DirectoryInfo di2 = new DirectoryInfo(path);
        FileInfo[] files = di2.GetFiles();
        if (files != null)
        {
            for (int i = 0; i < files.Length; ++i)
            {
                if (files[i].Name.Equals("DataClass.cs"))
                {
                    files[i].Delete();
                    Debug.Log("删除原数据结构脚本DataClass.cs");
                    break;
                }
            }
            AssetDatabase.Refresh(); //这里要添加,不然会报错
            string str = AssetDatabase.RenameAsset("Assets/MyScripts/DataClass2.cs", "DataClass");
            Debug.Log("改名返回信息 " + str);
            Debug.Log("新数据结构脚本已重命名为DataClass.cs");
        }

        AssetDatabase.Refresh();
    }
}
这里的改动很小,其实就是将前文的using()用法改成了这里的try-finally。在数据读取的时候出现错误就抛出异常,然后加上catch捕获异常,出现异常的时候删除生成的错误脚本即可。

你可能感兴趣的:(C#,Excel,unity)