基础List的解析和拼接 添加list数据 我们首先给MonsterBase
中添加list
1 2 3 4 5 6 7 [System.Serializable ] public class MonsterBase { [XmlElement("AllString" ) ] public List<string > AllString { get ; set ; } }
修改MonsterData
中的Construction
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class MonsterData : ExcelBase { public override void Construction () { AllMonster = new List<MonsterBase>(5 ); for (int i = 0 ; i < 5 ; i++) { MonsterBase monster = new MonsterBase { Id = i, Name = i + "sq" , OutLook = "Assets/GameData/Prefabs/Attack" , Level = i, Rarity = i, Height = i + 1 , AllString = new List<string >() { "teststr" ,"teststr2" } }; AllMonster.Add(monster); } } }
选中Scripts——ExcelData——MonsterData.cs,然后右键——类转Xml
在GameData——Data——Xml中就有了新的MonsterData.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="utf-8" ?> <MonsterData xmlns:xsd ="http://www.w3.org/2001/XMLSchema" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" > <AllMonster Id ="0" Name ="0sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="0" Rarity ="0" Height ="1" > <AllString > teststr</AllString > <AllString > teststr2</AllString > </AllMonster > <AllMonster Id ="1" Name ="1sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="1" Rarity ="1" Height ="2" > <AllString > teststr</AllString > <AllString > teststr2</AllString > </AllMonster > <AllMonster Id ="2" Name ="2sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="2" Rarity ="2" Height ="3" > <AllString > teststr</AllString > <AllString > teststr2</AllString > </AllMonster > <AllMonster Id ="3" Name ="3sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="3" Rarity ="3" Height ="4" > <AllString > teststr</AllString > <AllString > teststr2</AllString > </AllMonster > <AllMonster Id ="4" Name ="4sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="4" Rarity ="4" Height ="5" > <AllString > teststr</AllString > <AllString > teststr2</AllString > </AllMonster > </MonsterData >
修改reg.xml文件 在游戏工程目录——Data——Reg中修改MonsterDataReg.xml,我们先把list的type定义为“listStr”,演示一下如何解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="utf-8" ?> <data name ="MonsterData" from ="Monster.xlsx" to ="MonsterData.xml" > <variable name ="AllMonster" type ="list" > <list name ="MonsterBase" sheetname ="怪物配置" mainKey ="Id" > <variable name ="Id" col ="ID" type ="int" > </variable > <variable name ="Name" col ="名字" type ="string" > </variable > <variable name ="OutLook" col ="Prefab路径" type ="string" > </variable > <variable name ="Level" col ="等级" type ="int" > </variable > <variable name ="Rarity" col ="稀有度" type ="int" > </variable > <variable name ="Height" col ="高度" type ="float" > </variable > <variable name ="AllString" col ="测试list" type ="listStr" split =";" > </variable > </list > </variable > </data >
解析list 在解析时,只需要在MapDataToSheet
方法内(也就是将反序列化出来的data按照reg赋值给SheetData的阶段),按照对应的变量类型将list反射出来并按照指定的Split符号将list里面的元素合成在一起。
在DataEditor
里面添加GetSplitBaseList
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 private static string GetSplitBaseList (object data, VarClass varClass ){ string result = string .Empty; if (string .IsNullOrEmpty(varClass.Split)) { Debug.LogErrorFormat("{0} List的分隔符为空,请查看对应的Reg.xml" , varClass.Name); return result; } object dataList = GetMemberValue(data, varClass.Name); int listCount = System.Convert.ToInt32(dataList.GetType().InvokeMember("get_Count" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,dataList,new object [] { })); for (int i = 0 ; i < listCount; i++) { string item = dataList.GetType().InvokeMember("get_Item" ,BindingFlags.Default|BindingFlags.InvokeMethod,null ,dataList,new object [] {i}).ToString(); result = result + item; if (i != listCount - 1 ) { result = result + varClass.Split.Replace("\\n" , "\n" ).Replace("\\r" , "\r" ); } } return result; }
修改DataEditor
里面的MapDataToSheet
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private static void MapDataToSheet (object data, SheetClass rootSheet, Dictionary<string , SheetClass> sheetClassDic, Dictionary<string , SheetData> sheetDataDic ){ for (int i = 0 ; i < listCount; i++) { object item = dataList.GetType().InvokeMember("get_Item" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,dataList,new object [] { i }); RowData rowData = new RowData(); childVars.ForEach(childVar => { if (childVar.Type == "list" ) { } else if (childVar.Type == "listStr" || childVar.Type == "listFloat" || childVar.Type == "listInt" || childVar.Type == "listBool" ) { string listCombine = GetSplitBaseList(item, childVar); rowData.RowDataDic.Add(childVar.Col, listCombine); } else { } }); } }
可以看到我们定义了许多新的type:listStr
、listFloat
、listInt
、listBool
,这些就是用来指定在Excel里合并的list类型
我们在Unity的GameData——Data——Xml——MonsterData.xml上右键——Xml转Excel,这时我们的“测试List”都会在同一个Excel里面拼接起来
自定义类List的解析和拼接 使用这种方法解析自定义类的List,必须保证自定义类的内容足够简单。自定义类不能再次嵌套List了。
添加list数据 我们首先给MonsterBase
中添加list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [System.Serializable ] public class MonsterBase { [XmlElement("AllString" ) ] public List<string > AllString { get ; set ; } [XmlElement("AllBuff" ) ] public List<BuffBase> AllBuff { get ; set ; } } [System.Serializable ] public class BuffBase { [XmlAttribute("Id" ) ] public int Id { get ; set ; } [XmlAttribute("Name" ) ] public string Name { get ; set ; } }
修改Construction
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class MonsterData : ExcelBase { public override void Construction () { AllMonster = new List<MonsterBase>(5 ); for (int i = 0 ; i < 5 ; i++) { MonsterBase monster = new MonsterBase { Id = i, Name = i + "sq" , OutLook = "Assets/GameData/Prefabs/Attack" , Level = i, Rarity = i, Height = i + 1 , AllString = new List<string >() { "teststr" ,"teststr2" } AllBuff = new List<BuffBase> { new BuffBase() { Id = i,Name = i + "Buff" } , new BuffBase() { Id = i + 1 ,Name = i + "Buff2" }, new BuffBase() { Id = i + 2 ,Name = i + "Buff3" } } }; AllMonster.Add(monster); } } }
选中Scripts——ExcelData——MonsterData.cs,然后右键——类转Xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <?xml version="1.0" encoding="utf-8" ?> <MonsterData xmlns:xsd ="http://www.w3.org/2001/XMLSchema" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" > <AllMonster Id ="0" Name ="0sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="0" Rarity ="0" Height ="1" > <AllString > teststr</AllString > <AllString > teststr2</AllString > <AllBuff Id ="0" Name ="0Buff" /> <AllBuff Id ="1" Name ="0Buff2" /> <AllBuff Id ="2" Name ="0Buff3" /> </AllMonster > <AllMonster Id ="1" Name ="1sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="1" Rarity ="1" Height ="2" > <AllString > teststr</AllString > <AllString > teststr2</AllString > <AllBuff Id ="1" Name ="1Buff" /> <AllBuff Id ="2" Name ="1Buff2" /> <AllBuff Id ="3" Name ="1Buff3" /> </AllMonster > <AllMonster Id ="2" Name ="2sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="2" Rarity ="2" Height ="3" > <AllString > teststr</AllString > <AllString > teststr2</AllString > <AllBuff Id ="2" Name ="2Buff" /> <AllBuff Id ="3" Name ="2Buff2" /> <AllBuff Id ="4" Name ="2Buff3" /> </AllMonster > <AllMonster Id ="3" Name ="3sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="3" Rarity ="3" Height ="4" > <AllString > teststr</AllString > <AllString > teststr2</AllString > <AllBuff Id ="3" Name ="3Buff" /> <AllBuff Id ="4" Name ="3Buff2" /> <AllBuff Id ="5" Name ="3Buff3" /> </AllMonster > <AllMonster Id ="4" Name ="4sq" OutLook ="Assets/GameData/Prefabs/Attack" Level ="4" Rarity ="4" Height ="5" > <AllString > teststr</AllString > <AllString > teststr2</AllString > <AllBuff Id ="4" Name ="4Buff" /> <AllBuff Id ="5" Name ="4Buff2" /> <AllBuff Id ="6" Name ="4Buff3" /> </AllMonster > </MonsterData >
修改Reg.xml文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="utf-8" ?> <data name ="MonsterData" from ="Monster.xlsx" to ="MonsterData.xml" > <variable name ="AllMonster" type ="list" > <list name ="MonsterBase" sheetname ="怪物配置" mainKey ="Id" > <variable name ="Id" col ="ID" type ="int" > </variable > <variable name ="Name" col ="名字" type ="string" > </variable > <variable name ="OutLook" col ="Prefab路径" type ="string" > </variable > <variable name ="Level" col ="等级" type ="int" > </variable > <variable name ="Rarity" col ="稀有度" type ="int" > </variable > <variable name ="Height" col ="高度" type ="float" > </variable > <variable name ="AllString" col ="测试list" type ="listStr" split =";" > </variable > <variable name ="AllBuff" type ="list" col ="测试BuffList" split ="\n" > <list name ="BuffBase" sheetname ="Buff配置" split =";" > <variable name ="Id" col ="ID" type ="int" > </variable > <variable name ="Name" col ="名字" type ="string" > </variable > </list > </variable > </list > </variable > </data >
解析List 在DataEditor
里面添加GetSplitCustomList
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private static string GetSplitCustomList (object data, VarClass varClass,SheetClass sheetClass ){ string result = string .Empty; if (string .IsNullOrEmpty(varClass.Split) || string .IsNullOrEmpty(sheetClass.Split)) { Debug.LogErrorFormat("{0} List的分隔符为空,请查看对应的Reg.xml" , varClass.Name); return result; } object dataList = GetMemberValue(data, varClass.Name); int listCount = System.Convert.ToInt32(dataList.GetType().InvokeMember("get_Count" , BindingFlags.Default | BindingFlags.InvokeMethod, null , dataList, new object [] { })); for (int i = 0 ; i < listCount; i++) { object item = dataList.GetType().InvokeMember("get_Item" , BindingFlags.Default | BindingFlags.InvokeMethod, null , dataList, new object [] { i }); for (int j = 0 ; j < sheetClass.VarList.Count; j++) { object varItem = GetMemberValue(item, sheetClass.VarList[j].Name); string varItemStr = varItem.ToString(); result += varItemStr; if (j != sheetClass.VarList.Count - 1 ) { result += sheetClass.Split.Replace("\\n" , "\n" ).Replace("\\r" , "\r" ); } } if (i != listCount - 1 ) { result = result + varClass.Split.Replace("\\n" ,"\n" ).Replace("\\r" ,"\r" ); } } return result; }
使用这种方法解析自定义类的List,必须保证自定义类的内容足够简单。自定义类不能再次嵌套List了。
修改DataEditor
里面的MapDataToSheet
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private static void MapDataToSheet (object data, SheetClass rootSheet, Dictionary<string , SheetClass> sheetClassDic, Dictionary<string , SheetData> sheetDataDic ){ for (int i = 0 ; i < listCount; i++) { object item = dataList.GetType().InvokeMember("get_Item" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,dataList,new object [] { i }); RowData rowData = new RowData(); childVars.ForEach(childVar => { if (childVar.Type == "list" && string .IsNullOrEmpty(childVar.Split) { } else if (childVar.Type == "list" ) { SheetClass tempSheetClass = sheetClassDic[childVar.ListSheetName]; string listCombine = GetSplitCustomList(item, childVar, tempSheetClass); rowData.RowDataDic.Add(childVar.Col, listCombine); } else if (childVar.Type == "listStr" || childVar.Type == "listFloat" || childVar.Type == "listInt" || childVar.Type == "listBool" ) { } else { } }); } }
我们在Unity的GameData——Data——Xml——MonsterData.xml上右键——Xml转Excel
自定义类List新建Sheet 如果自定义类比较杂内容比较多,就需要新开一个sheet,子sheet与主sheet通过Foreign指定的列名来联系。
修改Reg.xml文件 修改Reg.xml文件,我们使用上面的list的reg,在variable里面指定foreign,删除掉split和col
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="utf-8" ?> <data name ="MonsterData" from ="Monster.xlsx" to ="MonsterData.xml" > <variable name ="AllMonster" type ="list" > <list name ="MonsterBase" sheetname ="怪物配置" mainKey ="Id" > <variable name ="Id" col ="ID" type ="int" > </variable > <variable name ="Name" col ="名字" type ="string" > </variable > <variable name ="OutLook" col ="Prefab路径" type ="string" > </variable > <variable name ="Level" col ="等级" type ="int" > </variable > <variable name ="Rarity" col ="稀有度" type ="int" > </variable > <variable name ="Height" col ="高度" type ="float" > </variable > <variable name ="AllString" col ="测试list" type ="listStr" split =";" > </variable > <variable name ="AllBuff" type ="list" foreign ="ID" > <list name ="BuffBase" sheetname ="Buff配置" > <variable name ="Id" col ="TestID" type ="int" > </variable > <variable name ="Name" col ="名字" type ="string" > </variable > </list > </variable > </list > </variable > </data >
解析List 我们想要的是:
创建子sheet时,子sheet第一列添加对应的主sheet的Key(Foreign)
子sheet新的列的内容通过上一级list结点(注意是list结点)的“mainKey”来反射获取。
修改DataEditor
里面的MapDataToSheet
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 private static void XmlToExcel (string xmlRegName ) { rootSheets.ForEach(sheet => { MapDataToSheet(data, sheet,allSheetClassDic,sheetDataDic,"" ); }); } private static void MapDataToSheet (object data, SheetClass rootSheet, Dictionary<string , SheetClass> sheetClassDic, Dictionary<string , SheetData> sheetDataDic,string mainKey ) { List<VarClass> childVars = rootSheet.VarList; VarClass parentVar = rootSheet.ParentVar; object dataList = GetMemberValue(data, parentVar.Name); int listCount =System.Convert.ToInt32(dataList.GetType().InvokeMember("get_Count" , BindingFlags.Default | BindingFlags.InvokeMethod, null , dataList, new object [] { })); SheetData sheetData = new SheetData(); if (!string .IsNullOrEmpty(parentVar.Foreign)) { sheetData.AllColName.Add(parentVar.Foreign); sheetData.AllType.Add(parentVar.Type); } childVars.ForEach(item => { if (!string .IsNullOrEmpty(item.Col)) { sheetData.AllColName.Add(item.Col); sheetData.AllType.Add(item.Type); } }); string tempKey = mainKey; for (int i = 0 ; i < listCount; i++) { object item = dataList.GetType().InvokeMember("get_Item" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,dataList,new object [] { i }); RowData rowData = new RowData(); if (!string .IsNullOrEmpty(parentVar.Foreign) && !string .IsNullOrEmpty(tempKey)) { rowData.RowDataDic.Add(parentVar.Foreign, tempKey); } if (!string .IsNullOrEmpty(rootSheet.MainKey)) { mainKey = GetMemberValue(item, rootSheet.MainKey).ToString(); } childVars.ForEach(childVar => { if (childVar.Type == "list" && string .IsNullOrEmpty(childVar.Split)) { SheetClass tempSheetClass = sheetClassDic[childVar.ListSheetName]; MapDataToSheet(item, tempSheetClass, sheetClassDic, sheetDataDic,mainKey); } else if (childVar.Type == "list" ) { SheetClass tempSheetClass = sheetClassDic[childVar.ListSheetName]; string listCombine = GetSplitCustomList(item, childVar, tempSheetClass); rowData.RowDataDic.Add(childVar.Col, listCombine); } else if (childVar.Type == "listStr" || childVar.Type == "listFloat" || childVar.Type == "listInt" || childVar.Type == "listBool" ) { } else { } }); } }
我们在Unity的GameData——Data——Xml——MonsterData.xml上右键——Xml转Excel