#if UNITY_EDITOR using System; using System.Collections.Generic; using System.Globalization; using System.IO; using Gameplay.Story.Cmp.Data; using Gameplay.Story.I18N; using UnityEngine; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; namespace Gameplay.Story.Cmp.Utils { public static class ExcelReader { public static List ReadI18NData(string excelPath) { var result = new List(); if (string.IsNullOrEmpty(excelPath)) { return result; } var workbook = _GetSheet(excelPath); if (workbook == null) return result; // 读取sheetcount var sheetCount = workbook.NumberOfSheets; for (int i = 0; i < sheetCount; i++) { var readSheet = workbook.GetSheetAt(i); var sheetName = readSheet.SheetName; var i18NData = _Readi18NData(readSheet); i18NData.languageName = sheetName; result.Add(i18NData); } workbook.Close(); return result; } private static StoryI18NItemDataWrapper _Readi18NData(ISheet sheet) { // 第一行不读 var currentRowIndex = 1; var row = sheet.GetRow(currentRowIndex); var result = new StoryI18NItemDataWrapper(); var data = new List(); while (row != null) { var cellIndex = 0; var cellHashCode = row.GetCell(cellIndex++); var cellValue = row.GetCell(cellIndex++); var hashCode = _TryReadMsg(cellHashCode); var value = _TryReadMsg(cellValue); var item = new StoryI18NItemData { hashCode = hashCode, value = value }; data.Add(item); currentRowIndex++; row = sheet.GetRow(currentRowIndex); } result.data = data.ToArray(); return result; } public static StoryExcelData TryReadExcelData(string excelPath) { if (string.IsNullOrEmpty(excelPath)) { return null; } var storyExcelData = new StoryExcelData(); _TryReadExcelData(excelPath, storyExcelData); return storyExcelData; } private static void _TryReadExcelData(string excelPath, StoryExcelData storyExcelData) { var workbook = _GetSheet(excelPath); if (workbook == null) return; var readSheet = workbook.GetSheetAt(0); var currentRowIndex = 2; var row = readSheet.GetRow(currentRowIndex); var name2Id = new Dictionary(); while (row != null) { // 读取一行的所有信息 // 0 无用 // 1 blockid // 2 characterName // 3 playerId // 4 isTalk 0 1 // 5 modelId // 6 对话信息 // 7 动作信息 // 8 表情信息 // 9 blocktime var cellIndex = 1; var cellBlockId = row.GetCell(cellIndex++); var cellCharacterName = row.GetCell(cellIndex++); var cellPlayerId = row.GetCell(cellIndex++); var cellIsTalk = row.GetCell(cellIndex++); var cellModelId = row.GetCell(cellIndex++); var cellDialog = row.GetCell(cellIndex++); var cellMotionName = row.GetCell(cellIndex++); var cellFaceName = row.GetCell(cellIndex++); var cellBlockTime = row.GetCell(cellIndex++); var msgBlockId = _TryReadMsg(cellBlockId); var msgCharacterName = _TryReadMsg(cellCharacterName); var msgPlayerId = _TryReadMsg(cellPlayerId); var msgIsTalk = _TryReadMsg(cellIsTalk); var msgModelId = _TryReadMsg(cellModelId); var msgDialog = _TryReadMsg(cellDialog); var msgMotionName = _TryReadMsg(cellMotionName); var msgFaceName = _TryReadMsg(cellFaceName); var msgBlockTime = _TryReadMsg(cellBlockTime); var blockId = _TryGetId(msgBlockId, -1); if (blockId == -1) { currentRowIndex++; row = readSheet.GetRow(currentRowIndex); continue; } var getBlockData = storyExcelData.TryGetExcelBlockData(blockId); if (getBlockData == null) { getBlockData = new StoryExcelBlockData(blockId); storyExcelData.AddBlockData(getBlockData); } // 如果有对话内容,则进行覆盖 if (!string.IsNullOrEmpty(msgDialog)) { getBlockData.TrySetMsg(msgDialog); } var isTalk = _TryGetId(msgIsTalk, 0) == 1; var modelId = _TryGetId(msgModelId); var playerId = _TryGetId(msgPlayerId); if (name2Id.TryGetValue(msgCharacterName, out var cachePlayerId)) { playerId = cachePlayerId; } else { name2Id.Add(msgCharacterName, playerId); } var newPlayerData = new StoryExcelPlayerData { playerName = msgCharacterName, playerId = playerId, configId = modelId, isTalk = isTalk }; if (!string.IsNullOrEmpty(msgMotionName)) { newPlayerData.motionName = msgMotionName; } if (!string.IsNullOrEmpty(msgFaceName)) { var splitFaceNames = msgFaceName.Split('|'); foreach (string splitFaceName in splitFaceNames) { newPlayerData.faceNames.Add(splitFaceName); } } getBlockData.TryAddPlayerData(newPlayerData); if (string.IsNullOrEmpty(msgBlockTime)) { getBlockData.blockTime = 0f; } else { getBlockData.blockTime = _TryGetFloat(msgBlockTime); } currentRowIndex++; row = readSheet.GetRow(currentRowIndex); } } private static float _TryGetFloat(string msg, float defaultValue = 0) { if (float.TryParse(msg, out var result)) { return result; } return defaultValue; } private static int _TryGetId(string msg, int defaultValue = 0) { if (int.TryParse(msg, out var result)) { return result; } return defaultValue; } private static string _TryReadMsg(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 IWorkbook _GetSheet(string excelPath) { Debug.Log("处理文件:" + excelPath); FileStream fs = null; try { fs = new FileStream(excelPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); } catch (Exception e) { Debug.LogException(e); } if (fs == null) { Debug.LogError("无法打开文件{0},跳过处理:" + excelPath); return null; } var isXlsx = excelPath.EndsWith(".xlsx", System.StringComparison.CurrentCultureIgnoreCase); IWorkbook workbook = null; if (isXlsx) { workbook = new XSSFWorkbook(fs); } else { workbook = new HSSFWorkbook(fs); } return workbook; } } } #endif