前文《读取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(); } }