一、首先问题来了,为什么要把Excel转成Asset文件呢
1.Excel的不兼容性。首先PC上打包的程序就比编辑器模式下要多添加几个dll才能读取,移动端对Excel的支持就更差。
2.读取速度慢。这个我亲测过,一份Excel文件,一份该Excel转成的Asset文件。如下图,Excel第一次读取为88毫秒,后面基本维持在40毫秒左右,而Asset文件一直是0毫秒。
为了了解读取Asset文件到底有多快,我使用循环读取来看看,
读取10次和读100次都如下图第一次1毫秒,后面都是0毫秒
读取1000次
这么牛逼吗,10000次试试
一万次才7、8毫秒,又试了一下都一万次Excel,Unity直接卡死了!
后面又试了一下读空Excel,一次大概耗时15毫秒左右,着说名随内容增加,时间也会增加很多。
结论:用Asset文件吧!
二、读取Excel的方法
要先把Excel转成Asset文件,首先还是要读取Excel,介绍两种方式吧。
方法一
1.引入几个读取Excel需要的dll,如图
Excel.dll和ICSharpCode.SharpZipLib.dll的下载链接 https://download.csdn.net/download/yasinxin/11861899
System.Data.dll 在D:\Program Files\Unity2017.2\Editor\Data\Mono\lib\mono\2.0
如过要在PC打包版本读取还需要加加几个
I18N开头的dll 在 D:\Program Files\Unity2017.2\Editor\Data\Mono\lib\mono\unity
备注:Unity2017.2 为你的unity版本,去对应的安装目录中取dll
2.读取方法
public static DataSet ReadExcel(string path)
{
FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
return result;
}
DataSet 为Unity中的一个Excel类,读完就存在里面,然后通过类的属性取想要的数据
Path 为Excel存放路径,如:string path = Application.dataPath + "/Resources/PreparationPatientItem.xlsx";
方法二
csv格式读取
这个方法直接写成编辑模式窗口打开的方式
/// <summary>
/// 文件转存数组内容
/// </summary>
static string[][] array = null;
/// <summary>
/// 打开csv文件
/// </summary>
[MenuItem("Tool/OpenCsv")]
static void OpenFile(string functionName)
{
EditorUtility.DisplayDialog("选择文件夹", "请选择路径!", "OK");
string CompentPath = string.Empty;
//如果按下弹窗的OK按钮
CompentPath = EditorUtility.OpenFilePanel("Overwrite with csv", "", "csv,xls,xlsx");
if (CompentPath.Length != 0)
{
Debug.Log(CompentPath);
if (!CompentPath.EndsWith(".csv") && !CompentPath.EndsWith(".CSV") && !CompentPath.EndsWith(".xls") && !CompentPath.EndsWith(".xlsx"))
{
Debug.LogWarning("请选择Excel文件");
return;
}
string str = File.ReadAllText(CompentPath);
//读取每一行的内容
string[] lineArray = str.Split("\r"[0]);
Debug.Log(lineArray[5]);
//创建二维数组
array = new string[lineArray.Length][];
//把csv中的数据储存在二位数组中
for (int i = 0; i < lineArray.Length; i++)
{
array[i] = lineArray[i].Split(',');
}
PreparationPatientItemFunction();
}
}
这样就把数据存放到了二维数组array里面了。
备注: 方法二只能读取csv格式,因为只有csv格式有UTF-8的编码方式,如图:
试了其他格式打开会成乱码。不过读csv格式比xlsx要快一些,但和读Asset比还不是一个级别的。
但读csv可以不用导入dll就能读取。
三、把数据转成Asset文件
如下图是我数据样式
根据样式创建相应的数据类
public class PreparationPatientItemDatas : ScriptableObject
{
public List<PreparationPatientItemData> PreparationPatientItemDataList = new List<PreparationPatientItemData>();
}
[System.Serializable]
public class PreparationPatientItemData
{
public string id;
public string itemKey;
public string itemContent;
public GMMedicalProjectType internalMedicineType = GMMedicalProjectType.None;
public string questionKey;
public string questionContents;
public string answerKey;
public string answerContents;
}
/// <summary>
/// 医学项目类型 +400
/// </summary>
public enum GMMedicalProjectType
{
None,
Chest,
Abdoment,
Marrow,
Lumber,
Pericardium,
Thyrocricoid,
MarrowChild,
LumberChild,
KneeJoint,
MarrowTibiaChild,
Culdocentesis,
KneeJointChild,
MaleCatheterization,
FemaleCatheterization,
AbdomentChild,
ChestChild,
GastricLavage,
NasogastricGavage
}
然后把从Excel读到的数据填到类中,再生成Asset文件,这里以第二种读取为例
static void PreparationPatientItemFunction()
{
if (array == null || array.Length < 1)
{
Debug.LogWarning("未读csv!!!");
return;
}
string assetName = GetDataByRowAndCol(0, 0);
Debug.Log(assetName);
PreparationPatientItemDatas preparationPatientItemDatas = new PreparationPatientItemDatas();
for (int i = 3; i < array.Length - 1; i++)
{
PreparationPatientItemData preparationPatientItemData = new PreparationPatientItemData();
preparationPatientItemData.id = array[i][0].Replace("\n", "");
Debug.Log(i);
preparationPatientItemData.itemKey = array[i][1];
preparationPatientItemData.itemContent = array[i][2];
preparationPatientItemData.internalMedicineType = (GMMedicalProjectType)(int.Parse(array[i][3]) - 400);
preparationPatientItemData.questionKey = array[i][4];
preparationPatientItemData.questionContents = array[i][5];
preparationPatientItemData.answerKey = array[i][6];
preparationPatientItemData.answerContents = array[i][7];
preparationPatientItemDatas.PreparationPatientItemDataList.Add(preparationPatientItemData);
}
AssetDatabase.CreateAsset(preparationPatientItemDatas, "Assets/Resources/" + assetName + ".asset");
Debug.Log("Save it");
}
static string GetDataByRowAndCol(int nRow, int nCol)
{
if (array.Length <= 0 || nRow >= array.Length)
return "";
if (nCol >= array[0].Length)
return "";
return array[nRow][nCol];
}
最后生成的Asset如下