716 lines
28 KiB
C#
716 lines
28 KiB
C#
using UnityEngine;
|
||
using UnityEditor;
|
||
using System;
|
||
using System.IO;
|
||
using System.Collections.Generic;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Linq;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using OfficeOpenXml;
|
||
using Thrift.Protocol;
|
||
using Thrift.Transport.Client;
|
||
using System.Threading;
|
||
|
||
namespace ThriftPipelineTools
|
||
{
|
||
/// <summary>
|
||
/// 快速生成 Bytes 工具(简化版)
|
||
/// 只生成 AllConfigs.bytes,不生成 C# 和 DR
|
||
/// 适用于表结构未变化,只需要更新数据的场景
|
||
/// </summary>
|
||
public class ThriftBytesGeneratorEditor : EditorWindow
|
||
{
|
||
// ========== 版本信息 ==========
|
||
private const string VERSION = "v1.0.0 (Bytes Only)";
|
||
|
||
// ========== 配置Key(使用EditorPrefs) ==========
|
||
private const string PREF_KEY_DOCS_PATH = "ThriftPipeline_DocsPath";
|
||
|
||
// ========== 路径配置 ==========
|
||
private string docsProjectPath = ""; // Docs 项目路径
|
||
|
||
// ========== UI 状态 ==========
|
||
private Vector2 scrollPosition;
|
||
private Vector2 logScrollPosition;
|
||
private StringBuilder logBuilder = new StringBuilder();
|
||
private bool isExecuting = false;
|
||
|
||
// ========== 进度控制 ==========
|
||
private float progress = 0f;
|
||
private string currentStep = "";
|
||
|
||
[MenuItem("蹊径/Thrift/快速生成 Bytes(简化版)")]
|
||
public static void ShowWindow()
|
||
{
|
||
var window = GetWindow<ThriftBytesGeneratorEditor>("快速生成 Bytes");
|
||
window.minSize = new Vector2(800, 600);
|
||
window.Show();
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
LoadConfig();
|
||
}
|
||
|
||
private void OnGUI()
|
||
{
|
||
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
||
|
||
EditorGUILayout.Space(10);
|
||
EditorGUILayout.LabelField($"快速生成 Bytes 工具 - {VERSION}", EditorStyles.boldLabel);
|
||
|
||
EditorGUILayout.HelpBox(
|
||
"此工具只生成 AllConfigs.bytes 文件,不生成 C# 和 DR\n" +
|
||
"适用于:表结构未变化,只需要更新配置数据的场景\n" +
|
||
"⚡ 执行速度更快,跳过编译和代码生成步骤",
|
||
MessageType.Info
|
||
);
|
||
|
||
EditorGUILayout.Space(10);
|
||
|
||
DrawPathConfiguration();
|
||
|
||
EditorGUILayout.Space(10);
|
||
|
||
DrawExecutionSection();
|
||
|
||
EditorGUILayout.Space(10);
|
||
|
||
DrawLogSection();
|
||
|
||
EditorGUILayout.EndScrollView();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绘制路径配置区域
|
||
/// </summary>
|
||
private void DrawPathConfiguration()
|
||
{
|
||
EditorGUILayout.BeginVertical("box");
|
||
EditorGUILayout.LabelField("路径配置", EditorStyles.boldLabel);
|
||
|
||
EditorGUILayout.HelpBox(
|
||
"只需配置 Docs 项目路径(包含 Excel 配置和 cfg_txt.json)",
|
||
MessageType.None
|
||
);
|
||
|
||
// Docs 项目路径
|
||
EditorGUILayout.BeginHorizontal();
|
||
EditorGUILayout.LabelField("Docs 项目路径:", GUILayout.Width(120));
|
||
docsProjectPath = EditorGUILayout.TextField(docsProjectPath);
|
||
if (GUILayout.Button("选择", GUILayout.Width(60)))
|
||
{
|
||
string selected = EditorUtility.OpenFolderPanel("选择 Docs 项目路径", docsProjectPath, "");
|
||
if (!string.IsNullOrEmpty(selected))
|
||
{
|
||
docsProjectPath = selected;
|
||
SaveConfig();
|
||
}
|
||
}
|
||
EditorGUILayout.EndHorizontal();
|
||
|
||
// 显示派生路径预览
|
||
if (!string.IsNullOrEmpty(docsProjectPath))
|
||
{
|
||
EditorGUILayout.Space(5);
|
||
EditorGUILayout.LabelField("派生路径预览:", EditorStyles.miniLabel);
|
||
|
||
var paths = GetDerivedPaths();
|
||
EditorGUILayout.LabelField($" cfg_txt.json: {paths["cfg_json"]}", EditorStyles.miniLabel);
|
||
EditorGUILayout.LabelField($" Config 目录: {paths["config_dir"]}", EditorStyles.miniLabel);
|
||
EditorGUILayout.LabelField($" 输出到 Unity: {paths["unity_bytes_dir"]}", EditorStyles.miniLabel);
|
||
}
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绘制执行区域
|
||
/// </summary>
|
||
private void DrawExecutionSection()
|
||
{
|
||
EditorGUILayout.BeginVertical("box");
|
||
EditorGUILayout.LabelField("执行控制", EditorStyles.boldLabel);
|
||
|
||
GUI.enabled = !isExecuting && ValidatePaths();
|
||
|
||
if (GUILayout.Button("⚡ 快速生成 AllConfigs.bytes", GUILayout.Height(40)))
|
||
{
|
||
GenerateBytes();
|
||
}
|
||
|
||
GUI.enabled = true;
|
||
|
||
if (isExecuting)
|
||
{
|
||
EditorGUILayout.Space(5);
|
||
EditorGUILayout.LabelField($"当前步骤: {currentStep}");
|
||
EditorGUI.ProgressBar(EditorGUILayout.GetControlRect(GUILayout.Height(20)), progress, "执行中...");
|
||
}
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绘制日志区域
|
||
/// </summary>
|
||
private void DrawLogSection()
|
||
{
|
||
EditorGUILayout.BeginVertical("box");
|
||
EditorGUILayout.LabelField("执行日志", EditorStyles.boldLabel);
|
||
|
||
logScrollPosition = EditorGUILayout.BeginScrollView(
|
||
logScrollPosition,
|
||
GUILayout.Height(300)
|
||
);
|
||
|
||
EditorGUILayout.TextArea(logBuilder.ToString(), GUILayout.ExpandHeight(true));
|
||
|
||
EditorGUILayout.EndScrollView();
|
||
|
||
if (GUILayout.Button("清空日志"))
|
||
{
|
||
logBuilder.Clear();
|
||
}
|
||
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载配置(使用 EditorPrefs,本地保存,不会被git提交)
|
||
/// </summary>
|
||
private void LoadConfig()
|
||
{
|
||
try
|
||
{
|
||
docsProjectPath = EditorPrefs.GetString(PREF_KEY_DOCS_PATH, "");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"加载配置失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存配置(使用 EditorPrefs,本地保存,不会被git提交)
|
||
/// </summary>
|
||
private void SaveConfig()
|
||
{
|
||
try
|
||
{
|
||
EditorPrefs.SetString(PREF_KEY_DOCS_PATH, docsProjectPath);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"保存配置失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有派生路径
|
||
/// </summary>
|
||
private Dictionary<string, string> GetDerivedPaths()
|
||
{
|
||
var paths = new Dictionary<string, string>();
|
||
|
||
// Docs 相关路径
|
||
if (!string.IsNullOrEmpty(docsProjectPath))
|
||
{
|
||
paths["cfg_json"] = Path.Combine(docsProjectPath, "tool", "cfg", "cfg_txt.json");
|
||
paths["config_dir"] = Path.Combine(docsProjectPath, "config");
|
||
}
|
||
|
||
// Unity 项目相关路径(当前项目)
|
||
string assetsPath = Application.dataPath;
|
||
paths["unity_bytes_dir"] = Path.Combine(assetsPath, "Design_SubModule", "ConfigData");
|
||
|
||
return paths;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证路径
|
||
/// </summary>
|
||
private bool ValidatePaths()
|
||
{
|
||
if (string.IsNullOrEmpty(docsProjectPath))
|
||
return false;
|
||
|
||
var paths = GetDerivedPaths();
|
||
|
||
if (!File.Exists(paths["cfg_json"]))
|
||
return false;
|
||
|
||
if (!Directory.Exists(paths["config_dir"]))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 日志输出
|
||
/// </summary>
|
||
private void Log(string message)
|
||
{
|
||
logBuilder.AppendLine(message);
|
||
Repaint();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成 Bytes 文件
|
||
/// </summary>
|
||
private async void GenerateBytes()
|
||
{
|
||
isExecuting = true;
|
||
logBuilder.Clear();
|
||
progress = 0f;
|
||
DateTime startTime = DateTime.Now;
|
||
|
||
Log("================================================================================");
|
||
Log($"开始生成 AllConfigs.bytes ({VERSION})");
|
||
Log("================================================================================");
|
||
Log("");
|
||
|
||
try
|
||
{
|
||
var paths = GetDerivedPaths();
|
||
|
||
currentStep = "读取配置并生成 bytes";
|
||
progress = 0.3f;
|
||
Repaint();
|
||
|
||
if (!await GenerateBytesFile(paths))
|
||
{
|
||
Log("[FAIL] 生成失败");
|
||
EditorUtility.DisplayDialog("失败", "生成 AllConfigs.bytes 失败,请查看日志", "确定");
|
||
return;
|
||
}
|
||
|
||
progress = 1f;
|
||
currentStep = "完成";
|
||
Repaint();
|
||
|
||
DateTime endTime = DateTime.Now;
|
||
TimeSpan duration = endTime - startTime;
|
||
|
||
Log("");
|
||
Log("================================================================================");
|
||
Log($"✅ 生成完成!");
|
||
Log($" 耗时: {duration.TotalSeconds:F2} 秒");
|
||
Log($" 输出: {paths["unity_bytes_dir"]}/AllConfigs.bytes");
|
||
Log("================================================================================");
|
||
|
||
EditorUtility.DisplayDialog("成功", $"AllConfigs.bytes 生成完成!\n耗时: {duration.TotalSeconds:F2} 秒", "确定");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log($"\n[FAIL] 执行失败: {ex.Message}");
|
||
Log(ex.StackTrace);
|
||
EditorUtility.DisplayDialog("错误", $"执行失败:\n{ex.Message}", "确定");
|
||
}
|
||
finally
|
||
{
|
||
isExecuting = false;
|
||
AssetDatabase.Refresh();
|
||
Repaint();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成 Bytes 文件
|
||
/// </summary>
|
||
private async Task<bool> GenerateBytesFile(Dictionary<string, string> paths)
|
||
{
|
||
Log("【生成 AllConfigs.bytes】");
|
||
Log("--------------------------------------------------------------------------------");
|
||
|
||
try
|
||
{
|
||
string cfgJsonPath = paths["cfg_json"];
|
||
string configDir = paths["config_dir"];
|
||
string bytesOutputDir = paths["unity_bytes_dir"];
|
||
|
||
// 创建输出目录
|
||
if (!Directory.Exists(bytesOutputDir))
|
||
Directory.CreateDirectory(bytesOutputDir);
|
||
|
||
// 加载程序集
|
||
Log(" [1/3] 加载程序集");
|
||
System.Reflection.Assembly assembly = null;
|
||
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||
{
|
||
if (asm.GetType("Byway.Thrift.Data.AllConfigs") != null)
|
||
{
|
||
assembly = asm;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (assembly == null)
|
||
{
|
||
Log("[FAIL] 找不到 Byway.Thrift.Data.AllConfigs 程序集");
|
||
Log(" 请确保已经执行过完整流程,生成了 C# 类");
|
||
return false;
|
||
}
|
||
|
||
Log(" [OK] 程序集加载成功");
|
||
|
||
// 读取配置
|
||
Log(" [2/3] 读取配置并填充数据");
|
||
string cfgText = File.ReadAllText(cfgJsonPath);
|
||
var cfg = JsonConvert.DeserializeObject<JObject>(cfgText);
|
||
var fileList = cfg["file_list"] as JArray;
|
||
|
||
// 创建AllConfigs实例
|
||
var allConfigsType = assembly.GetType("Byway.Thrift.Data.AllConfigs");
|
||
object allConfigsInstance = Activator.CreateInstance(allConfigsType);
|
||
|
||
int successCount = 0;
|
||
int processedCount = 0;
|
||
|
||
// 填充每个配置
|
||
foreach (JObject configItem in fileList)
|
||
{
|
||
string inFile = configItem["in_file"]?.ToString();
|
||
string outFile = configItem["out_file"]?.ToString();
|
||
string sheetName = configItem["sheet_name"]?.ToString();
|
||
var columnTypes = configItem["coloum_type"] as JArray;
|
||
|
||
if (string.IsNullOrEmpty(inFile) || string.IsNullOrEmpty(outFile))
|
||
continue;
|
||
|
||
string structName = outFile.Replace(".txt", "");
|
||
string excelPath = Path.Combine(configDir, inFile);
|
||
|
||
if (!File.Exists(excelPath))
|
||
{
|
||
Log($" [{++processedCount}] [SKIP] {structName} - Excel文件不存在");
|
||
continue;
|
||
}
|
||
|
||
Log($" [{++processedCount}] 处理: {structName}");
|
||
|
||
if (FillThriftObject(allConfigsInstance, allConfigsType, structName,
|
||
excelPath, sheetName, columnTypes, assembly))
|
||
{
|
||
successCount++;
|
||
}
|
||
}
|
||
|
||
// 序列化为bytes
|
||
Log($"\n [3/3] 序列化 AllConfigs.bytes (已设置 {successCount} 个配置)");
|
||
|
||
// 检查有多少配置实际被设置
|
||
int setCount = 0;
|
||
var issetField = allConfigsType.GetField("__isset",
|
||
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
||
if (issetField != null)
|
||
{
|
||
var issetObj = issetField.GetValue(allConfigsInstance);
|
||
var issetType = issetObj.GetType();
|
||
foreach (var prop in allConfigsType.GetProperties())
|
||
{
|
||
if (prop.Name != "Isset" && prop.PropertyType.Namespace == "Byway.Thrift.Data")
|
||
{
|
||
var issetProp = issetType.GetProperty(prop.Name);
|
||
if (issetProp != null && (bool)issetProp.GetValue(issetObj))
|
||
setCount++;
|
||
}
|
||
}
|
||
}
|
||
Log($" __isset 标志统计: {setCount} 个配置被标记为已设置");
|
||
|
||
using (var memoryStream = new MemoryStream())
|
||
{
|
||
using (var transport = new TStreamTransport(memoryStream, memoryStream, new Thrift.TConfiguration()))
|
||
{
|
||
using (var protocol = new TBinaryProtocol(transport))
|
||
{
|
||
var writeMethod = allConfigsType.GetMethod("WriteAsync");
|
||
if (writeMethod != null)
|
||
{
|
||
var task = (Task)writeMethod.Invoke(allConfigsInstance,
|
||
new object[] { protocol, CancellationToken.None });
|
||
await task;
|
||
|
||
byte[] bytes = memoryStream.ToArray();
|
||
|
||
string allConfigsBytesPath = Path.Combine(bytesOutputDir, "AllConfigs.bytes");
|
||
File.WriteAllBytes(allConfigsBytesPath, bytes);
|
||
|
||
Log($" [OK] 生成成功 ({bytes.Length} bytes / {bytes.Length / 1024.0:F2} KB)");
|
||
|
||
if (bytes.Length < 1000)
|
||
{
|
||
Log($" [WARNING] 文件太小 ({bytes.Length} bytes),可能大部分配置未序列化!");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Log($"\n生成完成: 成功 {successCount} 个配置");
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log($"[FAIL] 生成失败: {ex.Message}");
|
||
Log(ex.StackTrace);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 填充Thrift对象数据
|
||
/// </summary>
|
||
private bool FillThriftObject(object allConfigsInstance, Type allConfigsType, string structName,
|
||
string excelPath, string sheetName, JArray columnTypes, System.Reflection.Assembly assembly)
|
||
{
|
||
try
|
||
{
|
||
var configType = assembly.GetType($"Byway.Thrift.Data.{structName}");
|
||
var itemType = assembly.GetType($"Byway.Thrift.Data.{structName}Item");
|
||
|
||
if (configType == null || itemType == null)
|
||
{
|
||
Log($" [ERROR] 找不到类型: {structName} 或 {structName}Item");
|
||
return false;
|
||
}
|
||
|
||
object configInstance = Activator.CreateInstance(configType);
|
||
var dictType = typeof(Dictionary<,>).MakeGenericType(typeof(int), itemType);
|
||
var dictInstance = Activator.CreateInstance(dictType);
|
||
|
||
// 读取Excel
|
||
FileInfo fileInfo = new FileInfo(excelPath);
|
||
using (ExcelPackage package = new ExcelPackage(fileInfo))
|
||
{
|
||
ExcelWorksheet worksheet = null;
|
||
if (!string.IsNullOrEmpty(sheetName) && package.Workbook.Worksheets[sheetName] != null)
|
||
worksheet = package.Workbook.Worksheets[sheetName];
|
||
else
|
||
worksheet = package.Workbook.Worksheets[0];
|
||
|
||
if (worksheet == null || worksheet.Dimension == null)
|
||
{
|
||
Log($" [ERROR] 工作表为空");
|
||
return false;
|
||
}
|
||
|
||
int maxRows = worksheet.Dimension.End.Row;
|
||
int maxCols = worksheet.Dimension.End.Column;
|
||
|
||
// 读取表头(第1行)
|
||
List<string> headers = new List<string>();
|
||
List<int> validColumns = new List<int>();
|
||
int maxColumns = columnTypes?.Count ?? maxCols;
|
||
|
||
for (int col = 1; col <= maxCols && headers.Count < maxColumns; col++)
|
||
{
|
||
string header = worksheet.Cells[1, col].Value?.ToString() ?? "";
|
||
if (!string.IsNullOrWhiteSpace(header))
|
||
{
|
||
headers.Add(header);
|
||
validColumns.Add(col);
|
||
}
|
||
}
|
||
|
||
// 读取数据(从第3行开始)
|
||
int filledItemCount = 0;
|
||
for (int row = 3; row <= maxRows; row++)
|
||
{
|
||
bool isEmptyRow = true;
|
||
for (int i = 0; i < validColumns.Count; i++)
|
||
{
|
||
if (worksheet.Cells[row, validColumns[i]].Value != null)
|
||
{
|
||
isEmptyRow = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (isEmptyRow)
|
||
continue;
|
||
|
||
object itemInstance = Activator.CreateInstance(itemType);
|
||
int? idValue = null;
|
||
|
||
for (int i = 0; i < headers.Count; i++)
|
||
{
|
||
string originalHeader = headers[i];
|
||
string fieldName = SanitizeFieldName(originalHeader);
|
||
int colIndex = validColumns[i];
|
||
var cell = worksheet.Cells[row, colIndex];
|
||
object cellValue = cell.Value;
|
||
|
||
var property = itemType.GetProperty(fieldName);
|
||
if (property != null)
|
||
{
|
||
try
|
||
{
|
||
object convertedValue;
|
||
|
||
if (cellValue == null)
|
||
{
|
||
if (property.PropertyType == typeof(string))
|
||
{
|
||
convertedValue = "";
|
||
}
|
||
else if (property.PropertyType.IsValueType)
|
||
{
|
||
convertedValue = Activator.CreateInstance(property.PropertyType);
|
||
}
|
||
else
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
convertedValue = ConvertCellValue(cellValue, property.PropertyType);
|
||
}
|
||
|
||
property.SetValue(itemInstance, convertedValue);
|
||
|
||
if (fieldName.ToLower() == "id" && convertedValue is int)
|
||
idValue = (int)convertedValue;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log($" [WARN] 行{row} 字段{fieldName}转换失败: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
if (idValue.HasValue)
|
||
{
|
||
var addMethod = dictType.GetMethod("Add");
|
||
addMethod.Invoke(dictInstance, new object[] { idValue.Value, itemInstance });
|
||
filledItemCount++;
|
||
}
|
||
}
|
||
|
||
Log($" 读取了 {filledItemCount} 条数据");
|
||
}
|
||
|
||
// 设置字典属性
|
||
string dictPropertyName = char.ToUpper(structName[0]) + structName.Substring(1).ToLower() + "s";
|
||
var dictProperty = configType.GetProperty(dictPropertyName);
|
||
if (dictProperty != null)
|
||
{
|
||
dictProperty.SetValue(configInstance, dictInstance);
|
||
}
|
||
else
|
||
{
|
||
Log($" [ERROR] 未找到字典属性: {dictPropertyName}");
|
||
return false;
|
||
}
|
||
|
||
// 设置到AllConfigs
|
||
var allConfigProperty = allConfigsType.GetProperty(structName);
|
||
if (allConfigProperty != null)
|
||
{
|
||
allConfigProperty.SetValue(allConfigsInstance, configInstance);
|
||
|
||
var verifyValue = allConfigProperty.GetValue(allConfigsInstance);
|
||
if (verifyValue == null)
|
||
{
|
||
Log($" [ERROR] 设置到AllConfigs后为null!");
|
||
return false;
|
||
}
|
||
|
||
Log($" [OK] 成功");
|
||
}
|
||
else
|
||
{
|
||
Log($" [ERROR] AllConfigs中未找到属性: {structName}");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log($" [ERROR] {structName}: {ex.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理并转换字段名为PascalCase
|
||
/// </summary>
|
||
private string SanitizeFieldName(string fieldName)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(fieldName))
|
||
return "Field_unknown";
|
||
|
||
StringBuilder sb = new StringBuilder();
|
||
foreach (char c in fieldName)
|
||
{
|
||
if (char.IsLetterOrDigit(c) || c == '_')
|
||
sb.Append(c);
|
||
else if (c == ' ' || c == '-')
|
||
sb.Append('_');
|
||
}
|
||
|
||
string cleaned = sb.ToString();
|
||
if (string.IsNullOrEmpty(cleaned))
|
||
return "Field_unknown";
|
||
|
||
if (cleaned.Length > 0)
|
||
{
|
||
return char.ToUpper(cleaned[0]) + cleaned.Substring(1);
|
||
}
|
||
|
||
return cleaned;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 转换单元格值
|
||
/// </summary>
|
||
private object ConvertCellValue(object cellValue, Type targetType)
|
||
{
|
||
try
|
||
{
|
||
if (targetType == typeof(int))
|
||
{
|
||
if (cellValue is double d)
|
||
return (int)d;
|
||
return Convert.ToInt32(cellValue);
|
||
}
|
||
else if (targetType == typeof(long))
|
||
{
|
||
if (cellValue is double d)
|
||
return (long)d;
|
||
return Convert.ToInt64(cellValue);
|
||
}
|
||
else if (targetType == typeof(double))
|
||
{
|
||
return Convert.ToDouble(cellValue);
|
||
}
|
||
else if (targetType == typeof(bool))
|
||
{
|
||
return Convert.ToBoolean(cellValue);
|
||
}
|
||
else if (targetType == typeof(string))
|
||
{
|
||
return cellValue.ToString();
|
||
}
|
||
|
||
return cellValue;
|
||
}
|
||
catch
|
||
{
|
||
if (targetType == typeof(int)) return 0;
|
||
if (targetType == typeof(long)) return 0L;
|
||
if (targetType == typeof(double)) return 0.0;
|
||
if (targetType == typeof(bool)) return false;
|
||
if (targetType == typeof(string)) return "";
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
}
|