最近写代码测试了在unity中读取Excel配置文件,将配置中的数据结构自动写成脚本中的数据结构。
要写的Excel文件如下:
角色信息表
boss信息表
读取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文件内容转换成类结构")]
public static void WriteClass()
{
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;
using (FileStream fs = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
{
using (TextWriter tw = new StreamWriter(fs))
{
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 + "中没有数据表");
return;
}
DataTable one = result.Tables[0]; //默认获取第一个数据表
if (one.Rows.Count < 1) //判断数据表内是否存在数据
{
Debug.LogWarning("excel文件" + f.Name + "的第一个数据表中没有数据");
return;
}
//存注释
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; } } 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(); } }
代码执行后,会在目录Assets/MyScripts中生成一个新的脚本DataClass.cs。里面的内容就是Assets/Excel目录中所有的Excel文件对应生成的类。
如下,就是我测试时生成的结果。
当Excel表转换脚本出错时(代码中执行到return语句了),还是会生成DataClass2.cs这个脚本,这个时候需要手动将这个文件删除了。生成成功是会自动删除的。
代码中用到的动态库可在这里下载。
可供参考的网页: