10 changed files with 179 additions and 50 deletions
@ -0,0 +1,140 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using OfficeOpenXml; |
||||||
|
using UnityEngine; |
||||||
|
|
||||||
|
namespace Tools.ExcelResolver.Editor |
||||||
|
{ |
||||||
|
public static partial class ExcelResolverUtil |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 读取指定行的数据 |
||||||
|
/// </summary> |
||||||
|
public static List<string> ReadRow(ExcelWorksheet worksheet, int row, int colCount, string rowType) |
||||||
|
{ |
||||||
|
List<string> values = new(colCount); |
||||||
|
for (int col = 1; col <= colCount; col++) |
||||||
|
{ |
||||||
|
string value = worksheet.Cells[row, col].Text?.Trim(); |
||||||
|
if (rowType == "headers" && string.IsNullOrEmpty(value)) |
||||||
|
{ |
||||||
|
Debug.LogWarning( |
||||||
|
$"Empty header found in worksheet '{worksheet.Name}', column {col}. Skipping this column."); |
||||||
|
values.Add(string.Empty); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (rowType == "types" && string.IsNullOrEmpty(value)) |
||||||
|
{ |
||||||
|
value = "string"; |
||||||
|
Debug.LogWarning( |
||||||
|
$"Empty type found for column '{worksheet.Cells[1, col].Text}' in worksheet '{worksheet.Name}'. Defaulting to 'string'."); |
||||||
|
} |
||||||
|
|
||||||
|
values.Add(value); |
||||||
|
} |
||||||
|
return values; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 通用的单元格 -> C# 对象转换 |
||||||
|
/// </summary> |
||||||
|
public static object ConvertCellValue(ExcelRange cell, string type, string header, string className) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
string cellValue = cell.Value?.ToString()?.Trim(); |
||||||
|
|
||||||
|
if (type.StartsWith("list<", StringComparison.OrdinalIgnoreCase) && type.EndsWith(">")) |
||||||
|
{ |
||||||
|
return ConvertToList(cellValue, type, header, className); |
||||||
|
} |
||||||
|
else if (TypeConverters.TryGetValue(type, out var converter)) |
||||||
|
{ |
||||||
|
return converter(cellValue); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Debug.LogError($"Unsupported type '{type}' for field '{header}' in class '{className}'."); |
||||||
|
return GetDefaultValue(type); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
Debug.LogError($"Error converting value for '{header}' in '{className}': {ex.Message}"); |
||||||
|
return GetDefaultValue(type); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 返回类型的默认值 (包含 List<...> 场景) |
||||||
|
/// </summary> |
||||||
|
public static object GetDefaultValue(string type) |
||||||
|
{ |
||||||
|
if (type.StartsWith("list<", StringComparison.OrdinalIgnoreCase) && type.EndsWith(">")) |
||||||
|
{ |
||||||
|
var insideType = type.Substring(5, type.Length - 6).Trim(); |
||||||
|
return insideType.ToLower() switch |
||||||
|
{ |
||||||
|
"int" or "integer" => new List<int>(), |
||||||
|
"float" => new List<float>(), |
||||||
|
"double" => new List<double>(), |
||||||
|
"bool" or "boolean" => new List<bool>(), |
||||||
|
"string" => new List<string>(), |
||||||
|
_ => null |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
return type.ToLower() switch |
||||||
|
{ |
||||||
|
"int" or "integer" => 0, |
||||||
|
"float" => 0f, |
||||||
|
"double" => 0.0, |
||||||
|
"bool" or "boolean" => false, |
||||||
|
"string" => string.Empty, |
||||||
|
_ => null, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 转换逗号分隔的字符串到 List<...> (List<int>, List<string>, ...) |
||||||
|
/// </summary> |
||||||
|
public static object ConvertToList(string cellValue, string type, string header, string className) |
||||||
|
{ |
||||||
|
var insideType = type.Substring(5, type.Length - 6).Trim(); |
||||||
|
var splitted = string.IsNullOrEmpty(cellValue) |
||||||
|
? Array.Empty<string>() |
||||||
|
: cellValue.Split(','); |
||||||
|
|
||||||
|
return insideType.ToLower() switch |
||||||
|
{ |
||||||
|
"int" or "integer" => splitted.Select(s => { |
||||||
|
int.TryParse(s.Trim(), out var parsed); return parsed; |
||||||
|
}).ToList(), |
||||||
|
"float" => splitted.Select(s => { |
||||||
|
float.TryParse(s.Trim(), out var parsed); return parsed; |
||||||
|
}).ToList(), |
||||||
|
"double" => splitted.Select(s => { |
||||||
|
double.TryParse(s.Trim(), out var parsed); return parsed; |
||||||
|
}).ToList(), |
||||||
|
"bool" or "boolean" => splitted.Select(s => { |
||||||
|
return bool.TryParse(s.Trim(), out var parsed) ? parsed : (s.Trim() == "1" || s.Trim().Equals("true", StringComparison.OrdinalIgnoreCase)); |
||||||
|
}).ToList(), |
||||||
|
"string" => splitted.Select(s => s.Trim()).ToList(), |
||||||
|
_ => throw new Exception($"Unsupported list element type '{insideType}' for field '{header}' in class '{className}'.") |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public static readonly Dictionary<string, Func<string, object>> TypeConverters = new(StringComparer.OrdinalIgnoreCase) |
||||||
|
{ |
||||||
|
{ "int", value => int.TryParse(value, out var intValue) ? intValue : 0 }, |
||||||
|
{ "float", value => float.TryParse(value, out var floatValue) ? floatValue : 0f }, |
||||||
|
{ "double", value => double.TryParse(value, out var doubleValue) ? doubleValue : 0.0 }, |
||||||
|
{ "bool", value => bool.TryParse(value, out var boolValue) |
||||||
|
? boolValue |
||||||
|
: (value == "1" || value.Equals("true", StringComparison.OrdinalIgnoreCase)) }, |
||||||
|
{ "string", value => value ?? string.Empty } |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 44f4bfea1a574775841f162901455ee2 |
||||||
|
timeCreated: 1736083579 |
Loading…
Reference in new issue