CapersProject/Assets/02.Scripts/Editor/ExcelToJsonConverter.cs

319 lines
12 KiB
C#
Raw Normal View History

2024-06-03 18:26:03 +00:00
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using ExcelDataReader;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
namespace BlueWater.Editors
{
public class ExcelToJsonConverter : EditorWindow
{
private const string ExcelFolderPath = "Assets/Resources/Excel";
private const string JsonFolderPath = "Assets/Resources/Json";
public static Dictionary<string, bool> ToggleStates;
private List<DifferencePopup.Difference> _differences;
private bool _showPopup;
private string _selectedExcelFile;
public static ExcelToJsonConverter Instance { get; private set; }
private Vector2 _scrollPosition;
[MenuItem("Tools/EXCEL TO JSON - BlueWater")]
public static void ShowWindow()
{
Instance = GetWindow<ExcelToJsonConverter>("EXCEL TO JSON");
}
private void OnEnable()
{
ToggleStates = new Dictionary<string, bool>();
var excelFiles = Directory.GetFiles(ExcelFolderPath, "*.xlsx");
foreach (var excelFile in excelFiles)
{
ToggleStates[Path.GetFileNameWithoutExtension(excelFile)] = false;
}
}
public void ProcessSelectedFiles()
{
List<DifferencePopup.Difference> currentDifferences = new List<DifferencePopup.Difference>();
bool differencesFound = false;
foreach (var excelFile in ToggleStates.Keys)
{
if (ToggleStates[excelFile])
{
string excelPath = Path.Combine(ExcelFolderPath, excelFile + ".xlsx");
string jsonPath = Path.Combine(JsonFolderPath, excelFile + ".json");
JArray newJsonArray = ConvertExcelToJsonArray(excelPath);
if (File.Exists(jsonPath))
{
JArray existingJsonArray = JArray.Parse(File.ReadAllText(jsonPath));
currentDifferences = CompareJsonObjects(newJsonArray, existingJsonArray);
if (currentDifferences.Count > 0)
{
_selectedExcelFile = excelFile;
_differences = currentDifferences;
_showPopup = true;
differencesFound = true;
break;
}
}
else
{
File.WriteAllText(jsonPath, newJsonArray.ToString());
}
}
}
if (!differencesFound && !_showPopup)
{
EditorUtility.DisplayDialog("달라진점이 없음",
"비교 대상인 새로운 엑셀 파일과 기존의 제이슨 파일에서 다른 점을 발견하지 못했습니다.", "확인");
}
}
private void OnGUI()
{
EditorGUILayout.LabelField("EXCEL TO JSON - Select & Compare", EditorStyles.boldLabel);
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
List<string> keys = new List<string>(ToggleStates.Keys);
foreach (var excelFile in keys)
{
bool currentValue = ToggleStates[excelFile];
bool newValue = EditorGUILayout.ToggleLeft(excelFile, currentValue);
if (currentValue != newValue)
{
ToggleStates[excelFile] = newValue;
}
}
EditorGUILayout.EndScrollView();
if (GUILayout.Button("수정사항 체크"))
{
CheckModifiedToggles();
}
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("전체 해제"))
{
foreach (var excelFile in keys)
{
ToggleStates[excelFile] = false;
}
}
if (GUILayout.Button("전체 선택"))
{
foreach (var excelFile in keys)
{
ToggleStates[excelFile] = true;
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(10);
if (GUILayout.Button("선택된 파일들 비교 및 병합"))
{
ProcessSelectedFiles();
}
if (_showPopup)
{
DifferencePopup window = DifferencePopup.ShowWindow(_differences, _selectedExcelFile, JsonFolderPath);
window.OnClose += () => _showPopup = false;
}
}
public void CheckModifiedToggles()
{
List<string> keysToCheck = new List<string>(ToggleStates.Keys);
foreach (var excelFile in keysToCheck)
{
string excelPath = Path.Combine(ExcelFolderPath, excelFile + ".xlsx");
string jsonPath = Path.Combine(JsonFolderPath, excelFile + ".json");
if (File.Exists(jsonPath))
{
JArray newJsonArray = ConvertExcelToJsonArray(excelPath);
JArray existingJsonArray = JArray.Parse(File.ReadAllText(jsonPath));
List<DifferencePopup.Difference> currentDifferences =
CompareJsonObjects(newJsonArray, existingJsonArray);
if (currentDifferences.Count > 0)
{
ToggleStates[excelFile] = true;
}
else
{
ToggleStates[excelFile] = false;
}
}
}
}
public static JArray ConvertExcelToJsonArray(string excelPath)
{
FileStream stream = File.Open(excelPath, FileMode.Open, FileAccess.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet(new ExcelDataSetConfiguration()
{
ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
{
UseHeaderRow = true
}
});
stream.Close();
DataTable table = result.Tables[0];
JArray jsonArray = new JArray();
foreach (DataRow row in table.Rows)
{
JObject obj = new JObject();
foreach (DataColumn column in table.Columns)
{
string cellValue = row[column].ToString();
if (float.TryParse(cellValue, out float floatResult))
{
if (floatResult % 1 == 0)
{
obj[column.ColumnName] = Convert.ToInt32(floatResult);
}
else
{
obj[column.ColumnName] = floatResult;
}
}
else if (IsString(cellValue))
{
obj[column.ColumnName] = cellValue;
}
else
{
obj[column.ColumnName] = cellValue;
}
}
jsonArray.Add(obj);
}
return jsonArray;
}
private static bool IsString(string value)
{
return value.Any(c => !char.IsDigit(c));
}
private List<DifferencePopup.Difference> CompareJsonObjects(JArray newObj, JArray existingObj)
{
List<DifferencePopup.Difference> differences = new List<DifferencePopup.Difference>();
int minLength = Mathf.Min(newObj.Count, existingObj.Count);
int maxLength = Mathf.Max(newObj.Count, existingObj.Count);
for (int i = 0; i < maxLength; i++)
{
if (i < minLength)
{
JObject newItem = newObj[i] as JObject;
JObject existingItem = existingObj[i] as JObject;
if (newItem != null && existingItem != null)
{
HashSet<string> allPropertyNames = new HashSet<string>(newItem.Properties().Select(p => p.Name));
allPropertyNames.UnionWith(existingItem.Properties().Select(p => p.Name));
foreach (string propertyName in allPropertyNames)
{
JToken newToken;
JToken existingToken;
if (newItem.TryGetValue(propertyName, out newToken) &&
existingItem.TryGetValue(propertyName, out existingToken))
{
string newValueWithoutSpaces = newToken.ToString().Replace(" ", "");
string existingValueWithoutSpaces = existingToken.ToString().Replace(" ", "");
if (!newValueWithoutSpaces.Equals(existingValueWithoutSpaces))
{
differences.Add(new DifferencePopup.Difference(propertyName, newToken.ToString(),
existingToken.ToString(), i));
}
}
else if (!newItem.TryGetValue(propertyName, out newToken) &&
existingItem.TryGetValue(propertyName, out existingToken))
{
differences.Add(new DifferencePopup.Difference(propertyName, "N/A",
existingToken.ToString(), i));
}
else if (newItem.TryGetValue(propertyName, out newToken) &&
!existingItem.TryGetValue(propertyName, out existingToken))
{
differences.Add(new DifferencePopup.Difference(propertyName, newToken.ToString(), "N/A",
i));
}
}
}
else
{
Debug.LogError($"해당 인덱스에서 JSON 객체를 비교하지 못했습니다 {i}");
}
}
else
{
// 추가된 행에 대한 차이를 처리합니다.
JObject newItem = i < newObj.Count ? newObj[i] as JObject : null;
JObject existingItem = i < existingObj.Count ? existingObj[i] as JObject : null;
JObject availableItem = newItem ?? existingItem;
string newValue, existingValue;
foreach (var property in availableItem.Properties())
{
if (newItem != null && newItem.TryGetValue(property.Name, out JToken newToken))
{
newValue = newToken.ToString();
}
else
{
newValue = "N/A";
}
if (existingItem != null && existingItem.TryGetValue(property.Name, out JToken existingToken))
{
existingValue = existingToken.ToString();
}
else
{
existingValue = "N/A";
}
differences.Add(new DifferencePopup.Difference(property.Name, newValue, existingValue, i));
}
}
}
return differences;
}
}
}