导表工具修改

This commit is contained in:
2025-10-09 17:56:21 +08:00
parent e60822137f
commit 9ac305feba
45 changed files with 2753 additions and 557 deletions

View File

@@ -1,487 +1,487 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using ExcelDataReader;
using NBC;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
using Debug = UnityEngine.Debug;
namespace NBF
{
public static class ExcelToJsonWindow
{
#region
public static void GenConfig(bool showMessageBox = true)
{
CfgEditorUtil.GenConfigScripts();
GenConfig(Application.dataPath + "/../Config", showMessageBox);
}
public static void GenConfig(string path, bool showMessageBox = false)
{
List<string> list = new List<string>();
GetFiles(path, fileList: ref list);
AllJsonData.Clear();
Stopwatch s = Stopwatch.StartNew();
ReadExcel(list.ToArray());
BuildAsset();
s.Stop();
if (showMessageBox)
{
EditorUtility.DisplayDialog("成功", $"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒", "知道了");
EditorUtility.ClearProgressBar();
}
else
{
Debug.Log($"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
}
AssetDatabase.Refresh();
}
private static void BuildAsset()
{
var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
var jsonObj = JObject.Parse(json);
Dictionary<string, JToken> tokens = new Dictionary<string, JToken>(StringComparer.OrdinalIgnoreCase);
foreach (var item in jsonObj)
{
try
{
var name = item.Key;
var value = item.Value;
if (value != null)
{
tokens[name] = value;
}
}
catch (Exception e)
{
Log.Error($"读表异常请检查name={item.Key} ex={e}");
}
}
var relativePath = ConfigAssets.SavePath;
var asset = EditorUtils.GetOrCreateAsset<ConfigAssets>(relativePath);
var types = Reflection.GetAllNonAbstractDerivedTypes<ConfigBase>();
foreach (var type in types)
{
var tableNameAttribute = type.GetCustomAttribute<TableNameAttribute>();
if (tableNameAttribute == null) continue;
if (!tokens.TryGetValue(tableNameAttribute.Name, out var token))
{
Log.Warning($"{tableNameAttribute.Name} 解析失败tableName不一致");
continue;
}
if (token is not JArray jArray) return;
asset.Parse(jArray.ToArray(), type);
}
EditorUtility.SetDirty(asset);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
#endregion
#region
public static void GenLanguage()
{
var path = Application.dataPath + "/../Config/language";
List<string> list = new List<string>();
GetFiles(path, fileList: ref list);
AllJsonData.Clear();
Stopwatch s = Stopwatch.StartNew();
ReadExcel(list.ToArray());
var savePath = Path.Combine(Application.dataPath, "Resources/config/language.json");
BuildJson(savePath);
s.Stop();
Debug.Log($"导多语言完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
AssetDatabase.Refresh();
}
private static void BuildJson(string savaPath)
{
var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
SaveJson(savaPath, json);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
#endregion
#region
private static void GetFiles(string path, ref List<string> fileList)
{
var files = Directory.GetFiles(path);
if (files.Length > 0)
{
foreach (var file in files)
{
var fileName = Path.GetFileName(file);
if ((fileName.EndsWith(".xls", true, CultureInfo.CurrentCulture) ||
fileName.EndsWith(".xlsx", true, CultureInfo.CurrentCulture)) && !fileName.StartsWith(".") &&
!fileName.StartsWith("~"))
{
fileList.Add(file.Replace('\\', '/'));
}
}
}
}
private static void SaveJson(string jsonPath, string json)
{
try
{
if (File.Exists(jsonPath))
{
File.Delete(jsonPath);
}
File.WriteAllBytes(jsonPath, Encoding.UTF8.GetBytes(json));
}
catch (Exception e)
{
// Console.WriteLine(e);
// throw;
}
}
#endregion
#region Excel读取
private static readonly Dictionary<string, object> AllJsonData = new Dictionary<string, object>();
private static bool _buildIng = false;
private static int _buildTotal = 0;
private static int _buildDoneCount = 0;
private static void ReadExcel(IReadOnlyCollection<string> paths)
{
_buildTotal = paths.Count;
_buildDoneCount = 0;
_buildIng = true;
foreach (var t in paths)
{
ReadSingleExcel(t);
}
_buildIng = false;
}
private static void ReadSingleExcelFunc(string xlsxPath, bool isThrow = false)
{
try
{
using FileStream stream = File.Open(xlsxPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
// 读取第一张工资表
DataTableCollection tc = result.Tables;
if (tc.Count >= 1)
{
foreach (DataTable table in tc)
{
if (!table.TableName.StartsWith("!") && !table.TableName.StartsWith("Sheet"))
{
ReadSingleSheet(table, isThrow);
}
}
}
else
{
Debug.LogError("表名为空,请检查表");
}
}
catch (Exception e)
{
Log.Error(e);
}
}
public static void ReadSingleExcel(string xlsxPath, bool isThrow = false)
{
Stopwatch s = Stopwatch.StartNew();
string xlsxName = Path.GetFileName(xlsxPath);
if (!File.Exists(xlsxPath))
{
Debug.LogError("不存在该Excel");
return;
}
try
{
ReadSingleExcelFunc(xlsxPath, isThrow);
Debug.Log(xlsxName + ".xlsx" + "转换Json成功");
s.Stop();
Debug.Log($"导表{xlsxName},花费时间={s.ElapsedMilliseconds}毫秒");
_buildDoneCount++;
}
catch (Exception e)
{
Debug.LogError(e);
}
}
/// <summary>
/// 读取一个工作表的数据
/// </summary>
/// <param name="dataTable">读取的工作表数据</param>
/// <param name="isThrow">是否抛出异常</param>
private static void ReadSingleSheet(DataTable dataTable, bool isThrow = false)
{
int rows = dataTable.Rows.Count;
int columns = dataTable.Columns.Count;
if (rows < 1 || columns < 1)
{
return;
}
// 工作表的行数据
DataRowCollection collect = dataTable.Rows;
// xlsx对应的数据字段规定是第二行
string[] jsonFields = new string[columns];
string[] jsonFieldsType = new string[columns];
// 要保存成Json的obj
List<object> objsToSave = new List<object>();
for (int i = 0; i < columns; i++)
{
//字段
jsonFields[i] = collect[1][i].ToString();
//字段类型
jsonFieldsType[i] = collect[2][i].ToString();
}
// _lastTableName = dataTable.TableName;
// 从第三行开始
for (int i = 3; i < rows; i++)
{
Dictionary<string, object> jObject = new Dictionary<string, object>();
// _lastX = i;
for (int j = 0; j < columns; j++)
{
var objectValue = collect[i][j].ToString();
// _lastY = j;
var lastValue = $"{collect[1][j]}---{objectValue}";
try
{
if (isThrow)
{
Debug.Log($"{i}/{j}/{objectValue}");
}
Type type = GetTypeByString(jsonFieldsType[j]);
// 获取字段
string field = jsonFields[j];
//过滤掉字段为空的值
if (!string.IsNullOrEmpty(field))
{
object value = null;
if (!string.IsNullOrEmpty(objectValue))
{
//需要先判断下是否为数组
if (type != typeof(Array))
{
//需要判断一下是否为bool值 bool 直接返回int 0 或者 1
if (type == typeof(bool))
{
value = int.Parse(objectValue);
}
else if (type == typeof(Vector2))
{
value = objectValue.ToVector2();
}
else if (type == typeof(Vector3))
{
value = objectValue.ToVector3();
}
else
{
value = Convert.ChangeType(objectValue, type);
}
}
else
{
//这里在做二维数组的处理
//一般到这都是Int数组当然还可以更细致的处理不同类型的数组
string[] strs = objectValue.Split(',');
string arrayType = jsonFieldsType[j];
object[] ints = new object[strs.Length];
for (int k = 0; k < strs.Length; k++)
{
switch (arrayType)
{
case "[int]":
{
int.TryParse(strs[k], out var v);
ints[k] = v;
break;
}
case "[float]":
{
float.TryParse(strs[k], out var v);
ints[k] = v;
break;
}
case "[string]":
ints[k] = strs[k];
break;
default:
ints[k] = strs[k];
break;
}
}
value = ints;
}
}
else
{
// Log.I($"{dataTable.TableName} 字段{field}有空值存在 第{j + 1}列数据 请检查表格!!!");
//如果值为空会出现导表失败 这里需要做一下处理
value = GetDataType(type);
}
jObject[field] = value;
}
}
catch (Exception)
{
Debug.LogError($"解析表错误table={dataTable.TableName} y={i} x={j} value={lastValue}");
}
}
objsToSave.Add(jObject);
}
AllJsonData[dataTable.TableName] = objsToSave;
}
/// <summary>
/// 判断一下数据类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static object GetDataType(Type type)
{
object value = null;
if (type == typeof(int) || type == typeof(float))
{
value = 0;
}
else if (type == typeof(string))
{
value = "";
}
else if (type == typeof(bool))
{
//如果boo值类型为空 默认显示
value = 0;
}
else if (type == typeof(Array))
{
value = new List<object>().ToArray();
}
else
{
value = "";
}
return value;
}
/// <summary>
/// 获取字段类型
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Type GetTypeByString(string type)
{
switch (type.ToLower())
{
case "bool":
return typeof(bool);
case "array":
return typeof(Array);
case "double":
return typeof(double);
case "float":
return typeof(float);
case "int":
return typeof(int);
case "long":
return typeof(long);
case "object":
return typeof(object);
case "string":
return typeof(string);
case "[float]":
return typeof(Array);
case "[int]":
return typeof(Array);
case "[string]":
return typeof(Array);
case "v2":
return typeof(Vector2);
case "v3":
return typeof(Vector3);
default:
return typeof(string);
}
}
#endregion
}
}
// using System;
// using System.Collections.Generic;
// using System.Data;
// using System.Diagnostics;
// using System.Globalization;
// using System.IO;
// using System.Linq;
// using System.Reflection;
// using System.Text;
// using ExcelDataReader;
// using NBC;
// using Newtonsoft.Json;
// using Newtonsoft.Json.Linq;
// using UnityEditor;
// using UnityEngine;
// using Debug = UnityEngine.Debug;
//
// namespace NBF
// {
// public static class ExcelToJsonWindow
// {
// #region 生成配置
//
// public static void GenConfig(bool showMessageBox = true)
// {
// CfgEditorUtil.GenConfigScripts();
// GenConfig(Application.dataPath + "/../Config", showMessageBox);
// }
//
//
// public static void GenConfig(string path, bool showMessageBox = false)
// {
// List<string> list = new List<string>();
//
// GetFiles(path, fileList: ref list);
//
// AllJsonData.Clear();
// Stopwatch s = Stopwatch.StartNew();
//
// ReadExcel(list.ToArray());
//
// BuildAsset();
//
// s.Stop();
// if (showMessageBox)
// {
// EditorUtility.DisplayDialog("成功", $"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒", "知道了");
// EditorUtility.ClearProgressBar();
// }
// else
// {
// Debug.Log($"导表完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
// }
//
// AssetDatabase.Refresh();
// }
//
//
// private static void BuildAsset()
// {
// var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
// {
// ReferenceLoopHandling = ReferenceLoopHandling.Ignore
// });
// var jsonObj = JObject.Parse(json);
//
// Dictionary<string, JToken> tokens = new Dictionary<string, JToken>(StringComparer.OrdinalIgnoreCase);
//
// foreach (var item in jsonObj)
// {
// try
// {
// var name = item.Key;
// var value = item.Value;
// if (value != null)
// {
// tokens[name] = value;
// }
// }
// catch (Exception e)
// {
// Log.Error($"读表异常请检查name={item.Key} ex={e}");
// }
// }
//
// var relativePath = ConfigAssets.SavePath;
//
// var asset = EditorUtils.GetOrCreateAsset<ConfigAssets>(relativePath);
//
// var types = Reflection.GetAllNonAbstractDerivedTypes<ConfigBase>();
// foreach (var type in types)
// {
// var tableNameAttribute = type.GetCustomAttribute<TableNameAttribute>();
// if (tableNameAttribute == null) continue;
// if (!tokens.TryGetValue(tableNameAttribute.Name, out var token))
// {
// Log.Warning($"{tableNameAttribute.Name} 解析失败tableName不一致");
// continue;
// }
//
// if (token is not JArray jArray) return;
// asset.Parse(jArray.ToArray(), type);
// }
//
// EditorUtility.SetDirty(asset);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// }
//
// #endregion
//
// #region 生成多语
//
// public static void GenLanguage()
// {
// var path = Application.dataPath + "/../Config/language";
//
// List<string> list = new List<string>();
//
// GetFiles(path, fileList: ref list);
//
// AllJsonData.Clear();
// Stopwatch s = Stopwatch.StartNew();
//
// ReadExcel(list.ToArray());
//
// var savePath = Path.Combine(Application.dataPath, "Resources/config/language.json");
//
// BuildJson(savePath);
//
// s.Stop();
//
// Debug.Log($"导多语言完成,耗时{(s.ElapsedMilliseconds / 1000f):.00}秒");
//
// AssetDatabase.Refresh();
// }
//
// private static void BuildJson(string savaPath)
// {
// var json = JsonConvert.SerializeObject(AllJsonData, Formatting.Indented, new JsonSerializerSettings
// {
// ReferenceLoopHandling = ReferenceLoopHandling.Ignore
// });
// SaveJson(savaPath, json);
//
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// }
//
// #endregion
//
// #region 文件读
//
// private static void GetFiles(string path, ref List<string> fileList)
// {
// var files = Directory.GetFiles(path);
// if (files.Length > 0)
// {
// foreach (var file in files)
// {
// var fileName = Path.GetFileName(file);
//
// if ((fileName.EndsWith(".xls", true, CultureInfo.CurrentCulture) ||
// fileName.EndsWith(".xlsx", true, CultureInfo.CurrentCulture)) && !fileName.StartsWith(".") &&
// !fileName.StartsWith("~"))
// {
// fileList.Add(file.Replace('\\', '/'));
// }
// }
// }
// }
//
// private static void SaveJson(string jsonPath, string json)
// {
// try
// {
// if (File.Exists(jsonPath))
// {
// File.Delete(jsonPath);
// }
//
// File.WriteAllBytes(jsonPath, Encoding.UTF8.GetBytes(json));
// }
// catch (Exception e)
// {
// // Console.WriteLine(e);
// // throw;
// }
// }
//
// #endregion
//
// #region Excel读取
//
// private static readonly Dictionary<string, object> AllJsonData = new Dictionary<string, object>();
// private static bool _buildIng = false;
// private static int _buildTotal = 0;
//
// private static int _buildDoneCount = 0;
//
// private static void ReadExcel(IReadOnlyCollection<string> paths)
// {
// _buildTotal = paths.Count;
// _buildDoneCount = 0;
// _buildIng = true;
//
// foreach (var t in paths)
// {
// ReadSingleExcel(t);
// }
//
// _buildIng = false;
// }
//
// private static void ReadSingleExcelFunc(string xlsxPath, bool isThrow = false)
// {
// try
// {
// using FileStream stream = File.Open(xlsxPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
// DataSet result = excelReader.AsDataSet();
// // 读取第一张工资表
// DataTableCollection tc = result.Tables;
//
// if (tc.Count >= 1)
// {
// foreach (DataTable table in tc)
// {
// if (!table.TableName.StartsWith("!") && !table.TableName.StartsWith("Sheet"))
// {
// ReadSingleSheet(table, isThrow);
// }
// }
// }
// else
// {
// Debug.LogError("表名为空,请检查表");
// }
// }
// catch (Exception e)
// {
// Log.Error(e);
// }
// }
//
//
// public static void ReadSingleExcel(string xlsxPath, bool isThrow = false)
// {
// Stopwatch s = Stopwatch.StartNew();
// string xlsxName = Path.GetFileName(xlsxPath);
//
// if (!File.Exists(xlsxPath))
// {
// Debug.LogError("不存在该Excel");
// return;
// }
//
// try
// {
// ReadSingleExcelFunc(xlsxPath, isThrow);
//
// Debug.Log(xlsxName + ".xlsx" + "转换Json成功");
//
// s.Stop();
// Debug.Log($"导表{xlsxName},花费时间={s.ElapsedMilliseconds}毫秒");
// _buildDoneCount++;
// }
// catch (Exception e)
// {
// Debug.LogError(e);
// }
// }
//
// /// <summary>
// /// 读取一个工作表的数据
// /// </summary>
// /// <param name="dataTable">读取的工作表数据</param>
// /// <param name="isThrow">是否抛出异常</param>
// private static void ReadSingleSheet(DataTable dataTable, bool isThrow = false)
// {
// int rows = dataTable.Rows.Count;
// int columns = dataTable.Columns.Count;
// if (rows < 1 || columns < 1)
// {
// return;
// }
//
// // 工作表的行数据
// DataRowCollection collect = dataTable.Rows;
// // xlsx对应的数据字段规定是第二行
// string[] jsonFields = new string[columns];
// string[] jsonFieldsType = new string[columns];
// // 要保存成Json的obj
// List<object> objsToSave = new List<object>();
// for (int i = 0; i < columns; i++)
// {
// //字段
// jsonFields[i] = collect[1][i].ToString();
// //字段类型
// jsonFieldsType[i] = collect[2][i].ToString();
// }
//
// // _lastTableName = dataTable.TableName;
// // 从第三行开始
// for (int i = 3; i < rows; i++)
// {
// Dictionary<string, object> jObject = new Dictionary<string, object>();
//
// // _lastX = i;
// for (int j = 0; j < columns; j++)
// {
// var objectValue = collect[i][j].ToString();
// // _lastY = j;
// var lastValue = $"{collect[1][j]}---{objectValue}";
// try
// {
// if (isThrow)
// {
// Debug.Log($"{i}/{j}/{objectValue}");
// }
//
// Type type = GetTypeByString(jsonFieldsType[j]);
// // 获取字段
// string field = jsonFields[j];
// //过滤掉字段为空的值
// if (!string.IsNullOrEmpty(field))
// {
// object value = null;
// if (!string.IsNullOrEmpty(objectValue))
// {
// //需要先判断下是否为数组
// if (type != typeof(Array))
// {
// //需要判断一下是否为bool值 bool 直接返回int 0 或者 1
// if (type == typeof(bool))
// {
// value = int.Parse(objectValue);
// }
// else if (type == typeof(Vector2))
// {
// value = objectValue.ToVector2();
// }
// else if (type == typeof(Vector3))
// {
// value = objectValue.ToVector3();
// }
// else
// {
// value = Convert.ChangeType(objectValue, type);
// }
// }
// else
// {
// //这里在做二维数组的处理
// //一般到这都是Int数组当然还可以更细致的处理不同类型的数组
// string[] strs = objectValue.Split(',');
// string arrayType = jsonFieldsType[j];
//
// object[] ints = new object[strs.Length];
//
// for (int k = 0; k < strs.Length; k++)
// {
// switch (arrayType)
// {
// case "[int]":
// {
// int.TryParse(strs[k], out var v);
// ints[k] = v;
// break;
// }
// case "[float]":
// {
// float.TryParse(strs[k], out var v);
// ints[k] = v;
// break;
// }
// case "[string]":
// ints[k] = strs[k];
// break;
// default:
// ints[k] = strs[k];
// break;
// }
// }
//
// value = ints;
// }
// }
// else
// {
// // Log.I($"{dataTable.TableName} 字段{field}有空值存在 第{j + 1}列数据 请检查表格!!!");
// //如果值为空会出现导表失败 这里需要做一下处理
// value = GetDataType(type);
// }
//
// jObject[field] = value;
// }
// }
// catch (Exception)
// {
// Debug.LogError($"解析表错误table={dataTable.TableName} y={i} x={j} value={lastValue}");
// }
// }
//
// objsToSave.Add(jObject);
// }
//
// AllJsonData[dataTable.TableName] = objsToSave;
// }
//
//
// /// <summary>
// /// 判断一下数据类型
// /// </summary>
// /// <param name="type"></param>
// /// <returns></returns>
// public static object GetDataType(Type type)
// {
// object value = null;
// if (type == typeof(int) || type == typeof(float))
// {
// value = 0;
// }
// else if (type == typeof(string))
// {
// value = "";
// }
// else if (type == typeof(bool))
// {
// //如果boo值类型为空 默认显示
// value = 0;
// }
// else if (type == typeof(Array))
// {
// value = new List<object>().ToArray();
// }
// else
// {
// value = "";
// }
//
// return value;
// }
//
// /// <summary>
// /// 获取字段类型
// /// </summary>
// /// <param name="type"></param>
// /// <returns></returns>
// public static Type GetTypeByString(string type)
// {
// switch (type.ToLower())
// {
// case "bool":
// return typeof(bool);
// case "array":
// return typeof(Array);
// case "double":
// return typeof(double);
// case "float":
// return typeof(float);
// case "int":
// return typeof(int);
// case "long":
// return typeof(long);
// case "object":
// return typeof(object);
// case "string":
// return typeof(string);
// case "[float]":
// return typeof(Array);
// case "[int]":
// return typeof(Array);
// case "[string]":
// return typeof(Array);
// case "v2":
// return typeof(Vector2);
// case "v3":
// return typeof(Vector3);
// default:
// return typeof(string);
// }
// }
//
// #endregion
// }
// }