前文《读取excel文件并将其中数据转换成脚本数据结构》中说到了将Excel文件中的数据结构自动生成脚本中的类结构。但是上篇中的代码写法在生成出错的情况下不能自动删除错误脚本。需要自己手动删除。
现在我将代码写法做了点点改动,实现了生成错误脚本之后能自动删除文件。
直接上改后的代码:
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();
}
}