OldBlueWater/BlueWater/Assets/02.Scripts/Editor/ExcelToJsonConverter.cs

319 lines
12 KiB
C#

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 _02.Scripts.Editor
{
public class ExcelToJsonConverter : EditorWindow
{
private readonly string excelFolderPath = "Assets/Resources/Excel";
private readonly string jsonFolderPath = "Assets/Resources/JSON";
public static Dictionary<string, bool> toggleStates;
private List<DifferencePopup.Difference> differences;
private bool showPopup = false;
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;
}
}
}