一、首先問題來了,爲什麼要把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如下