using System; using UnityEditor; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using TGS; using UnityEngine; namespace AutoConfig { public static class ExcelRead { private static List _stringCfgMixKeyList; //stringCfg里面所有的MixKey public static List StringCfgMixValueList = new(); public static List StringCfgMixKeyList => _stringCfgMixKeyList; private static Dictionary _cacheWorkbooks = new(); private static List _listFileStreams = new(); public enum RowInfo { Variable, Type, Config } #region 生成StringConfig对应的Key/Value /// /// 加载StringConfig表中的MixKey,放入列表 /// public static void LoadStrCfgMixKeyList() { if (_stringCfgMixKeyList == null) { _stringCfgMixKeyList = new List(); } else { _stringCfgMixKeyList.Clear(); } //ExcelWrite.CfgMixKeyDataList.Clear(); var stringCfgPath = GenMixKeyTool.CfgPath + GenMixKeyTool.StringConfigPath; var workBook = GetWorkBook(stringCfgPath); if (workBook == null) { DebugUtil.LogError($"找不到配置表文件,路径: {stringCfgPath}"); return; } var sheetNum = workBook.NumberOfSheets; for (int i = 0; i < sheetNum; i++) { int sheetIdx = i; int rowIdx = -1; int lineIdx = -1; var sheet = workBook.GetSheetAt(i); var row = sheet.GetRow(0); var curRowIdx = 0; var mixKeyLineIdx = new List(); while (row != null) { var cell = row.GetCell(0); var cellContent = TryReadCell(cell); var lineNum = row.PhysicalNumberOfCells; rowIdx = curRowIdx; if (cellContent == "##var") { int cIdx = 1; for (; cIdx < lineNum; cIdx++) { var curCell = row.GetCell(cIdx); var curContent = TryReadCell(curCell); if (curContent.Contains("Param")) { mixKeyLineIdx.Add(cIdx); } } } else { if (cellContent != "##type" && cellContent != "##group" && cellContent != "##") { for (int idx = 0; idx < mixKeyLineIdx.Count; idx++) { lineIdx = mixKeyLineIdx[idx]; var curCell = row.GetCell(mixKeyLineIdx[idx]); var curContent = TryReadCell(curCell); if (curContent.Length > 0) { if (!_stringCfgMixKeyList.Contains(curContent)) { _stringCfgMixKeyList.Add(curContent); // ExcelWrite.CfgMixKeyDataList.Add(curContent, new CfgMixKeyData() // { // key = curContent, // rowIndex = rowIdx, // lineIndex = lineIdx, // sheetIndex = sheetIdx // }); } } } } } row = sheet.GetRow(++curRowIdx); } } } public static List GetValueIndexList(string configName, List keys) { var cfgPath = GenMixKeyTool.CfgPath + configName + ".xlsx"; var workBook = GetWorkBook(cfgPath); if (workBook == null) { DebugUtil.LogError($"找不到配置表文件,路径: {cfgPath}"); return null; } var keyCount = keys.Count; var needKeyList = GetMultipleKey(configName); if (needKeyList == null) { DebugUtil.LogError($"配置的Key值不对劲, 数量错误, 配置的表: {configName}, Key:{keys[0]}"); return default; } if(needKeyList.Count != keyCount) { DebugUtil.LogError($"配置的Key值不对劲, 数量错误, 配置的表: {configName}, Key:{keys[0]}"); return default; } var sheetCount = workBook.NumberOfSheets; var keyIdxList = new List(needKeyList.Count); for (int i = 0; i < keyCount; i++) { keyIdxList.Add(-1); } for (int i = 0; i < sheetCount; i++) { var sheet = workBook.GetSheetAt(i); var row = sheet.GetRow(0); var rowIndex = 0; while (row != null) { var cell = row.GetCell(0); var content = TryReadCell(cell); if (content == "##var") { int keyIdx = 1; for (; keyIdx < row.PhysicalNumberOfCells; keyIdx++) { cell = row.GetCell(keyIdx); content = TryReadCell(cell); for (int n = 0; n < needKeyList.Count; n++) { if (needKeyList[n] == content) { keyIdxList[n] = keyIdx; } } } if (keyIdxList.Contains(-1)) { DebugUtil.LogError("获取索引值列表时有误,有数据为-1!!! "); } return keyIdxList; } row = sheet.GetRow(++rowIndex); } } return keyIdxList; } /// /// 根据索引获取到具体的配置值 /// /// /// /// /// /// public static string GetStringValByIndex(string configName, string param, List keyIdxList, List indexList, int listIdx = 0) { var cfgPath = GenMixKeyTool.CfgPath + configName + ".xlsx"; var workBook = GetWorkBook(cfgPath); if (workBook == null) { DebugUtil.LogError($"找不到配置表文件,路径: {cfgPath}"); return null; } var idxCount = indexList.Count; if (idxCount != keyIdxList.Count) { DebugUtil.LogError($"获取配置表对应ID内容时失败,原因: keyList和indexList数量无法对应。"); return null; } char departChar = '|'; bool isList = false; var sheetCount = workBook.NumberOfSheets; int valueParamIdx = 0; //寻找对应参数那一列 for (int i = 0; i < sheetCount; i++) { var sheet = workBook.GetSheetAt(i); var row = sheet.GetRow(0); var rowIndex = 0; while (row != null) { var cell0 = row.GetCell(0); var content0 = TryReadCell(cell0); if (content0 == "##var") { for (int idx = 1; idx < row.PhysicalNumberOfCells; idx++) { var cell = row.GetCell(idx); var content = TryReadCell(cell); if (content == param) { valueParamIdx = idx; break; } } break; } row = sheet.GetRow(++rowIndex); } //识别是否为List rowIndex = 0; row = sheet.GetRow(0); while (row != null) { var cell0 = row.GetCell(0); var content0 = TryReadCell(cell0); if (content0 == "##type") { var idx = valueParamIdx; var cell = row.GetCell(idx); var content = TryReadCell(cell); if (content.Contains("list")) { isList = true; var length = "(list#sep=".Length; departChar = content[length]; } break; } row = sheet.GetRow(++rowIndex); } //获取格子内容 rowIndex = 0; row = sheet.GetRow(0); while (row != null) { var cell0 = row.GetCell(keyIdxList[0]); var content0 = TryReadCell(cell0); if (content0 == indexList[0]) { int idx = 1; bool isCurRow = true; for (; idx < indexList.Count; idx++) { var cell = row.GetCell(keyIdxList[idx]); if (cell == null) { DebugUtil.LogError($"获取配置表对应ID内容时失败,原因: 传入的Key索引元素在配置表中不存在!!!"); return null; } var content = TryReadCell(cell); if (content != indexList[idx]) { isCurRow = false; break; } } if (isCurRow) { var val = TryReadCell(row.GetCell(valueParamIdx)); if (isList) { string[] strList = val.Split(departChar); if (listIdx >= strList.Length) { DebugUtil.LogError($"配置的list索引超出了list长度! configName: {configName}", $"rowIdx:{rowIndex}, valueIdx:{valueParamIdx}"); return ""; } return strList[listIdx]; } return val; } } row = sheet.GetRow(++rowIndex); } } return null; } #endregion /// /// 获取工作簿 /// /// /// public static IWorkbook GetWorkBook(string excelPath) { FileStream fs = null; if (_cacheWorkbooks.TryGetValue(excelPath, out var workbook)) { return workbook; } try { fs = new FileStream(excelPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); _listFileStreams.Add(fs); } catch (Exception e) { Debug.LogException(e); } if (fs == null) { Debug.LogError("无法打开文件{0},跳过处理:" + excelPath); return null; } var isXlsx = excelPath.EndsWith(".xlsx", System.StringComparison.CurrentCultureIgnoreCase); if (isXlsx) { IWorkbook workBook = new XSSFWorkbook(fs); _cacheWorkbooks.TryAdd(excelPath, workBook); return workBook; } return null; } public static void InitAll() { _cacheWorkbooks.Clear(); _listFileStreams.Clear(); } public static void ReleaseAll() { for (int i = _listFileStreams.Count - 1; i >= 0; i--) { _listFileStreams[i].Close(); } _cacheWorkbooks.Clear(); _listFileStreams.Clear(); } /// /// 读格子,转换成string /// /// /// public static string TryReadCell(ICell cell) { if (cell == null) { return ""; } if (cell.CellType == CellType.String) { return cell.StringCellValue; } if (cell.CellType == CellType.Numeric) { return cell.NumericCellValue.ToString(CultureInfo.InvariantCulture); } if (cell.CellType == CellType.Boolean) { return cell.BooleanCellValue.ToString(); } if (cell.CellType == CellType.Blank) { return ""; } Debug.LogError("暂不支持的单元格类型:" + cell.CellType + ""); return ""; } private static List GetMultipleKey(string cfgName) { var cfgFullName = cfgName + ".xlsx"; var tableCfg = GenMixKeyTool.CfgPath + "__tables__" + ".xlsx"; var workBook = GetWorkBook(tableCfg); if (workBook == null) { DebugUtil.LogError("__tables__ 不存在,请检查传入路径"); return null; } var sheetNum = workBook.NumberOfSheets; int cfgIdx = -1; //配置表列索引 int keyNumIdx = -1; //key数量列索引 //先取对应的表名和key值列索引 for (int i = 0; i < sheetNum; i++) { var sheet = workBook.GetSheetAt(i); var rowIndex = 0; var row = sheet.GetRow(rowIndex); if (i == 0) { while (row != null) { var cell = row.GetCell(0); var content = TryReadCell(cell); if (content == "##var") { for (int idx = 1; idx < row.PhysicalNumberOfCells; idx++) { var curCell = row.GetCell(idx); var curContent = TryReadCell(curCell); if (curContent == "input") { cfgIdx = idx; } if (curContent == "index") { keyNumIdx = idx; } } break; } row = sheet.GetRow(++rowIndex); } } //取到后找到对应的配置表那一行,取key值判断 rowIndex = 0; row = sheet.GetRow(rowIndex); while (row != null) { var inputContent = TryReadCell(row.GetCell(cfgIdx)); if (inputContent.Contains(cfgFullName)) { var keyContent = TryReadCell(row.GetCell(keyNumIdx)); if (keyContent.Contains("+")) { string[] list = keyContent.Split('+'); return list.ToList(); } if(keyContent.Contains(",")) { string[] list = keyContent.Split(','); return new List { list[0] }; } var firstKey = GetFirstKey(cfgName); return new List {firstKey}; } row = sheet.GetRow(++rowIndex); } } return null; } private static string GetFirstKey(string configName) { var cfgPath = GenMixKeyTool.CfgPath + configName + ".xlsx"; var workBook = GetWorkBook(cfgPath); if (workBook == null) { DebugUtil.LogError($"找不到配置表文件,路径: {cfgPath}"); return null; } var sheet = workBook.GetSheetAt(0); var rowIndex = 0; var row = sheet.GetRow(rowIndex); while (row != null) { var cell0 = row.GetCell(0); var str0 = TryReadCell(cell0); if (str0 == "##var") { return TryReadCell(row.GetCell(1)); } row = sheet.GetRow(++rowIndex); } return null; } } }