using System; using System.Collections.Generic; using System.Data; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using Aspose.Cells; using Aspose.Cells.Rendering; using Newtonsoft.Json; using Sirenix.OdinInspector.Editor; using Unity.VisualScripting; using UnityEditor; using UnityEngine; namespace ZEditor { public class ExcelEditor : Editor //OdinEditorWindow { private static string folderPath = $"{Application.streamingAssetsPath}/Excel/"; private static string genDataPath = $"{Application.streamingAssetsPath}/ExcelData/"; private static string genCSPath = $"{Application.dataPath}/DemoGame/GameScript/Hotfix/Generate/Excel2CS/"; private static string templatePath = $"{Application.dataPath}/DemoGame/GameRes/ExcelTemplate.txt"; private static string constTemplatePath = $"{Application.dataPath}/DemoGame/GameRes/ExcelConstTemplate.txt"; private static string excelManagerTemplatePath = $"{Application.dataPath}/DemoGame/GameRes/ExcelManagerTemplate.txt"; [MenuItem("Tool/表格数据生成")] static void Gen() { DeleteAndCreateFolder(); DirectoryInfo info = new DirectoryInfo(folderPath); var fileInfos = info.GetFiles(); foreach (var fileInfo in fileInfos) { if (fileInfo.Name.Contains(".meta")) continue; // Debug.Log($"{fileInfo.FullName} , {fileInfo.Name}"); string fileName = fileInfo.Name.Replace(".xlsx", ""); LoadExcelAndCreateCS(fileInfo.FullName, fileName); LoadExcelAndCreateData(fileInfo.FullName, fileName); } LoadExcelAndGenData(fileInfos); GenExcelManager(fileInfos); } static void DeleteAndCreateFolder() { DirectoryInfo info = new DirectoryInfo(genCSPath); var fileInfos = info.GetFiles(); foreach (var fileInfo in fileInfos) { fileInfo.Delete(); } info = new DirectoryInfo(genDataPath); fileInfos = info.GetFiles(); foreach (var fileInfo in fileInfos) { fileInfo.Delete(); } if (!Directory.Exists(genDataPath)) Directory.CreateDirectory(genDataPath); if (!Directory.Exists(genCSPath)) Directory.CreateDirectory(genCSPath); } static void LoadExcelAndGenData(FileInfo[] fileInfos) { StringBuilder sb = new StringBuilder(); foreach (var fileInfo in fileInfos) { if (fileInfo.Name.Contains(".meta")) continue; string fileName = fileInfo.Name.Replace(".xlsx", ""); //查找整个文档 Workbook book = new Workbook(fileInfo.FullName); //获取一个工作表 Worksheet sheet = book.Worksheets[0]; for (var i = 2; i < sheet.Cells.Rows.Count - 2; i++) { var cellsColumn = sheet.Cells[i + 3, 2].Value; if (cellsColumn == null) { continue; } string str = cellsColumn.ToString(); var id = int.Parse(str); sb.AppendLine($"public const int {fileName}_{str} = {id};"); } } string text = File.ReadAllText(constTemplatePath); text = text.Replace("#CONSTCONTENT#", sb.ToString()); text = text.Replace("#CLASSNAME#", "ExcelConstData"); var csPath = $"{genCSPath}/ExcelConstData.cs"; if (!File.Exists(csPath)) { File.Create(csPath).Dispose(); } File.WriteAllText(csPath, text); } static void GenExcelManager(FileInfo[] fileInfos) { StringBuilder sb_Pri = new StringBuilder(); StringBuilder sb_Pub = new StringBuilder(); StringBuilder sb_New = new StringBuilder(); foreach (var fileInfo in fileInfos) { if (fileInfo.Name.Contains(".meta")) continue; string fileName = fileInfo.Name.Replace(".xlsx", ""); var lower = fileName.ToLower(); sb_Pri.AppendLine($"private static {fileName}DataExcel _{lower};"); sb_Pub.AppendLine($"public static {fileName}DataExcel {fileName} => _{lower};"); sb_New.AppendLine($"_{lower} = new {fileName}DataExcel();"); } string text = File.ReadAllText(excelManagerTemplatePath); text = text.Replace("#PRI_EXCELDATA#", sb_Pri.ToString()); text = text.Replace("#PUB_EXCELDATA#", sb_Pub.ToString()); text = text.Replace("#NEWDATA#", sb_New.ToString()); var csPath = $"{genCSPath}/ExcelManager.cs"; if (!File.Exists(csPath)) { File.Create(csPath).Dispose(); } File.WriteAllText(csPath, text); } /// /// 加载excel /// /// static void LoadExcelAndCreateCS(string path, string fileName) { //查找整个文档 Workbook book = new Workbook(path); //获取一个工作表 Worksheet sheet = book.Worksheets[0]; List zhuShi = new List(); List name = new List(); List typeStr = new List(); List type = new List(); for (var i = 0; i < sheet.Cells.Rows.Count; i++) { for (var j = 0; j < sheet.Cells.Columns.Count; j++) { var cellsColumn = sheet.Cells[i + 2, j + 2].Value; if (cellsColumn == null) continue; string str = cellsColumn.ToString(); if (i == 0) zhuShi.Add(str); else if (i == 1) name.Add(str); else if (i == 2) { typeStr.Add(str); type.Add(GetType(str)); } else break; } } var text = File.ReadAllText(templatePath); var newName = fileName + "Data"; text = text.Replace("#CLASSNAME#", newName); StringBuilder sb = new StringBuilder(); for (var i = 0; i < zhuShi.Count; i++) { sb.AppendLine("/// "); sb.AppendLine($"/// {zhuShi[i]}"); sb.AppendLine("/// "); string str = string.Empty; if (type[i] == typeof(string[]) || type[i] == typeof(float[]) || type[i] == typeof(bool[])) { var s = typeStr[i].Replace("[]", ""); str = $"public List<{s}> {name[i]} = new List<{s}>();"; } else { str = $"public {typeStr[i]} {name[i]};"; } sb.AppendLine(str); } text = text.Replace("#CONSTCONTENT#", sb.ToString()); text = text.Replace("#LISTNAME#", $"{fileName}List"); text = text.Replace("#FILENAME#", $"{fileName}"); string filePath = genCSPath + "/" + newName + ".cs"; if (!File.Exists(filePath)) { File.Create(filePath).Dispose(); } File.WriteAllText(filePath, text); } static void LoadExcelAndCreateData(string path, string fileName) { //查找整个文档 Workbook book = new Workbook(path); //获取一个工作表 Worksheet sheet = book.Worksheets[0]; DataTable table = new DataTable(); for (var i = 0; i < sheet.Cells.Rows.Count + 2; i++) { List list = new List(); for (var j = 0; j < sheet.Cells.Columns.Count; j++) { if (i == 4) { string name = sheet.Cells[3, j + 2].Value.ToString(); var typeName = sheet.Cells[4, j + 2].Value.ToString(); Type type = GetType(typeName); table.Columns.Add(name, type); } else if (i > 4) { var typeName = sheet.Cells[4, j + 2].Value.ToString(); Type type = GetType(typeName); var cellsColumn = sheet.Cells[i, j + 2].Value; var cons = cellsColumn.ToString(); if (type == typeof(string)) { list.Add(cons); } else if (type == typeof(int)) { int id = int.Parse(cons); list.Add(id); } else if (type == typeof(bool)) { var b = bool.Parse(cons); list.Add(b); } else if (type == typeof(float)) { var b = float.Parse(cons); list.Add(b); } // array else if (type == typeof(string[])) { var huanList = ZhuanHuanList(cons); list.Add(huanList.ToArray()); } else if (type == typeof(float[])) { var huanList = ZhuanHuanList(cons); var tmp = new List(); foreach (var s in huanList) { var f = float.Parse(s); tmp.Add(f); } list.Add(tmp.ToArray()); } else if (type == typeof(int[])) { var huanList = ZhuanHuanList(cons); var tmp = new List(); foreach (var s in huanList) { var f = int.Parse(s); tmp.Add(f); } list.Add(tmp.ToArray()); } else if (type == typeof(bool[])) { var huanList = ZhuanHuanList(cons); var tmp = new List(); foreach (var s in huanList) { var f = bool.Parse(s); tmp.Add(f); } list.Add(tmp.ToArray()); } // Vector3 暂时不添加,因为不受支持,后续想办法处理一下 // else if (type == typeof(Vector3) || type == typeof(Vector3[])) // { // var huanList = ZhuanHuanList_Vector3(cons); // if (huanList.Count > 1) // { // list.Add(huanList.ToArray()); // } // else if (huanList.Count == 1) // { // list.Add(huanList[0]); // } // } else { list.Add(cellsColumn); } } } if (i > 4) { var objects = list.ToArray(); table.Rows.Add(objects); } } var json = JsonConvert.SerializeObject(table); string newStr = "{" + $"\"{fileName}List\":" + json + "}"; // Debug.Log(newStr); string filePath = genDataPath + "/" + fileName + ".json"; if (!File.Exists(filePath)) { File.Create(filePath).Dispose(); } File.WriteAllText(filePath, newStr); AssetDatabase.Refresh(); } static List ZhuanHuanList(string cons) { if (cons.Contains(";")) { cons = cons.Replace("\n", ""); var strings = cons.Split(";"); var tmp = strings.ToList(); tmp.RemoveAt(tmp.Count - 1); return tmp; } else if (cons.Contains(",")) { cons = cons.Replace("\n", ""); var strings = cons.Split(","); var tmp = strings.ToList(); tmp.RemoveAt(tmp.Count - 1); return tmp; } else { List tmp = new List(); tmp.Add(cons); return tmp; } } static List ZhuanHuanList_Vector3(string cons) { List vecs = new List(); if (cons.Contains(";")) { cons = cons.Replace("\n", ""); var strings = cons.Split(";"); var tmp = strings.ToList(); tmp.RemoveAt(tmp.Count - 1); foreach (var s in tmp) { var vec = GenVec(s); vecs.Add(vec); } return vecs; } else { var vec = GenVec(cons); vecs.Add(vec); return vecs; } Vector3 GenVec(string str) { str = str.Replace("\n", ""); var strings = str.Split(","); List tmp = new List(); foreach (var s in strings) { var f = float.Parse(s); tmp.Add(f); } Vector3 vec = new Vector3(tmp[0], tmp[1], tmp[2]); return vec; } } static Type GetType(string name) { switch (name) { case "int": return typeof(int); break; case "int[]": return typeof(int[]); break; case "bool": return typeof(bool); break; case "bool[]": return typeof(bool[]); break; case "string": return typeof(string); break; case "Vector3": return typeof(Vector3); break; case "string[]": return typeof(string[]); break; case "float": return typeof(float); break; case "float[]": return typeof(float[]); break; case "Vector3[]": return typeof(Vector3[]); break; default: throw new ArgumentException(); break; } } } }