using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Teigha.Runtime; namespace DwgExtractorManual.Models { /// /// DWG 파일에서 Excel로 데이터 내보내기 메인 클래스 /// 리팩토링된 구조로 각 기능별 클래스를 조합하여 사용 /// internal class ExportExcel : IDisposable { // 컴포넌트들 private readonly ExcelManager excelManager; private readonly DwgDataExtractor dwgExtractor; private readonly JsonDataProcessor jsonProcessor; private readonly ExcelDataWriter excelWriter; private readonly FieldMapper fieldMapper; // ODA 서비스 관리 private Services? appServices; // 매핑 데이터 저장용 private Dictionary> FileToMapkeyToLabelTagValuePdf = new Dictionary>(); readonly List MapKeys; /// /// 생성자: 모든 컴포넌트 초기화 /// public ExportExcel() { try { Debug.WriteLine("🔄 FieldMapper 로딩 중: mapping_table_json.json..."); fieldMapper = FieldMapper.LoadFromFile("fletimageanalysis/mapping_table_json.json"); Debug.WriteLine("✅ FieldMapper 로딩 성공"); MapKeys = fieldMapper.GetAllDocAiKeys(); Debug.WriteLine($"📊 총 DocAI 키 개수: {MapKeys?.Count ?? 0}"); // 매핑 테스트 (디버깅용) TestFieldMapper(); Debug.WriteLine("🔄 ODA 초기화 중..."); InitializeTeighaServices(); // 컴포넌트들 초기화 excelManager = new ExcelManager(); dwgExtractor = new DwgDataExtractor(fieldMapper); jsonProcessor = new JsonDataProcessor(); excelWriter = new ExcelDataWriter(excelManager); Debug.WriteLine("🔄 Excel 초기화 중..."); excelManager.InitializeExcel(); } catch (System.Exception ex) { Debug.WriteLine($"❌ ExportExcel 초기화 오류: {ex.Message}"); throw; } } /// /// 단일 DWG 파일에서 데이터를 추출하여 Excel에 추가 /// public bool ExportDwgToExcel(string filePath, IProgress? progress = null, CancellationToken cancellationToken = default) { Debug.WriteLine($"[DEBUG] ExportDwgToExcel 시작: {filePath}"); if (excelManager.ExcelApplication == null) { Debug.WriteLine("❌ Excel이 초기화되지 않았습니다."); return false; } if (!File.Exists(filePath)) { Debug.WriteLine($"❌ 파일이 존재하지 않습니다: {filePath}"); return false; } try { // DWG 데이터 추출 var extractionResult = dwgExtractor.ExtractFromDwgFile(filePath, progress, cancellationToken); if (extractionResult == null) { return false; } // Excel에 데이터 기록 excelWriter.WriteTitleBlockData(extractionResult.TitleBlockRows); excelWriter.WriteTextEntityData(extractionResult.TextEntityRows); // 매핑 데이터 병합 foreach (var fileEntry in extractionResult.FileToMapkeyToLabelTagValuePdf) { if (!FileToMapkeyToLabelTagValuePdf.ContainsKey(fileEntry.Key)) { FileToMapkeyToLabelTagValuePdf[fileEntry.Key] = new Dictionary(); } foreach (var mapEntry in fileEntry.Value) { FileToMapkeyToLabelTagValuePdf[fileEntry.Key][mapEntry.Key] = mapEntry.Value; } } // 매핑 데이터를 Excel에 기록 excelWriter.WriteMappingDataToExcel(FileToMapkeyToLabelTagValuePdf); return true; } catch (System.Exception ex) { Debug.WriteLine($"❌ ExportDwgToExcel 오류: {ex.Message}"); return false; } } /// /// 기존 Excel 파일을 열어 JSON 파일의 PDF 분석 결과로 업데이트 /// public bool UpdateExistingExcelWithJson(string excelFilePath, string jsonFilePath) { try { Debug.WriteLine($"[DEBUG] 기존 Excel 파일 업데이트 시작: {excelFilePath}"); if (!excelManager.OpenExistingFile(excelFilePath)) { return false; } Debug.WriteLine("✅ 기존 Excel 파일 열기 성공"); return UpdateMappingSheetFromJson(jsonFilePath); } catch (System.Exception ex) { Debug.WriteLine($"❌ 기존 Excel 파일 업데이트 중 오류: {ex.Message}"); return false; } } /// /// JSON 파일에서 PDF 분석 결과를 읽어 Excel 매핑 시트 업데이트 /// public bool UpdateMappingSheetFromJson(string jsonFilePath) { if (!File.Exists(jsonFilePath)) { Debug.WriteLine($"❌ JSON 파일이 존재하지 않습니다: {jsonFilePath}"); return false; } // JSON 처리를 통해 매핑 데이터를 업데이트하고, Excel에 반영 return jsonProcessor.UpdateMappingDataFromJson(FileToMapkeyToLabelTagValuePdf, jsonFilePath) && UpdateExcelFromMappingData(); } /// /// DWG 파일들을 처리하여 Height 순으로 정렬된 Excel 파일 생성 /// public void ExportDwgToExcelHeightSorted(string[] dwgFiles, string resultFolder) { try { Debug.WriteLine($"[DEBUG] Height 정렬 Excel 생성 시작: {dwgFiles.Length}개 파일"); string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); string savePath = Path.Combine(resultFolder, $"{timestamp}_HeightSorted.xlsx"); var heightSortedWorkbook = excelManager.CreateNewWorkbook(); bool firstSheetProcessed = false; foreach (string dwgFile in dwgFiles) { if (!File.Exists(dwgFile)) { continue; } string fileName = Path.GetFileNameWithoutExtension(dwgFile); try { var worksheet = firstSheetProcessed ? heightSortedWorkbook.Worksheets.Add() : (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; worksheet.Name = excelManager.GetValidSheetName(fileName); firstSheetProcessed = true; var textEntities = dwgExtractor.ExtractTextEntitiesWithHeight(dwgFile); excelWriter.WriteHeightSortedData(textEntities, worksheet, fileName); Debug.WriteLine($"[DEBUG] {fileName} 시트 완료: {textEntities.Count}개 엔티티"); } catch (System.Exception ex) { Debug.WriteLine($"❌ {fileName} 처리 중 오류: {ex.Message}"); continue; } } if (!firstSheetProcessed) { var defaultSheet = (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; defaultSheet.Name = "No_DWG_Files"; defaultSheet.Cells[1, 1] = "No DWG files found in this folder"; } excelManager.SaveWorkbookAs(heightSortedWorkbook, savePath); heightSortedWorkbook.Close(false); Debug.WriteLine($"✅ Height 정렬 Excel 파일 저장 완료: {Path.GetFileName(savePath)}"); } catch (System.Exception ex) { Debug.WriteLine($"❌ Height 정렬 Excel 생성 중 오류: {ex.Message}"); throw; } } /// /// 모든 DWG 파일들을 하나의 Excel 파일로 처리하여 Height 순으로 정렬 /// public void ExportAllDwgToExcelHeightSorted(List<(string filePath, string folderName)> allDwgFiles, string savePath) { try { Debug.WriteLine($"[DEBUG] 단일 Excel 파일로 Height 정렬 생성 시작: {allDwgFiles.Count}개 파일"); var heightSortedWorkbook = excelManager.CreateNewWorkbook(); bool firstSheetProcessed = false; foreach (var (filePath, folderName) in allDwgFiles) { if (!File.Exists(filePath)) { continue; } string fileName = Path.GetFileNameWithoutExtension(filePath); try { var worksheet = firstSheetProcessed ? heightSortedWorkbook.Worksheets.Add() : (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; worksheet.Name = excelManager.GetValidSheetName(fileName); firstSheetProcessed = true; var textEntities = dwgExtractor.ExtractTextEntitiesWithHeight(filePath); excelWriter.WriteHeightSortedData(textEntities, worksheet, fileName); Debug.WriteLine($"[DEBUG] {fileName} 시트 완료: {textEntities.Count}개 엔티티"); } catch (System.Exception ex) { Debug.WriteLine($"❌ {fileName} 처리 중 오류: {ex.Message}"); continue; } } if (!firstSheetProcessed) { var defaultSheet = (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; defaultSheet.Name = "No_DWG_Files"; defaultSheet.Cells[1, 1] = "No DWG files found in any folder"; } excelManager.SaveWorkbookAs(heightSortedWorkbook, savePath); heightSortedWorkbook.Close(false); Debug.WriteLine($"✅ 단일 Height 정렬 Excel 파일 저장 완료: {Path.GetFileName(savePath)}"); } catch (System.Exception ex) { Debug.WriteLine($"❌ 단일 Height 정렬 Excel 생성 중 오류: {ex.Message}"); throw; } } // Helper methods and legacy support methods public bool SaveExcel() => excelManager.SaveWorkbook(); public void SaveMappingWorkbookOnly(string savePath) => excelManager.SaveWorkbookAs(excelManager.MappingWorkbook, savePath); public void SaveDwgOnlyMappingWorkbook(string resultFolderPath) => excelWriter.SaveDwgOnlyMappingWorkbook(FileToMapkeyToLabelTagValuePdf, resultFolderPath); public void SaveAndCloseExcel(string savePath) { try { excelManager.SaveWorkbookAs(excelManager.TitleBlockWorkbook, savePath); if (excelManager.MappingWorkbook != null) { string directory = Path.GetDirectoryName(savePath) ?? ""; string mappingPath = Path.Combine(directory, Path.GetFileNameWithoutExtension(savePath) + "_Mapping.xlsx"); excelManager.SaveWorkbookAs(excelManager.MappingWorkbook, mappingPath); } } catch (System.Exception ex) { Debug.WriteLine($"Excel 파일 저장 중 오류 발생: {ex.Message}"); } finally { excelManager.CloseWorkbooks(); } } public void CloseExcelObjectsWithoutSaving() => excelManager.CloseWorkbooks(); public void SaveMappingDictionary(string filePath) => jsonProcessor.SaveMappingDictionary(FileToMapkeyToLabelTagValuePdf, filePath); public void LoadMappingDictionary(string filePath) { FileToMapkeyToLabelTagValuePdf = jsonProcessor.LoadMappingDictionary(filePath); } public void WriteCompleteMapping() => excelWriter.WriteMappingDataToExcel(FileToMapkeyToLabelTagValuePdf); public void UpdateWithPdfData(string jsonFilePath) => jsonProcessor.UpdateMappingDataFromJson(FileToMapkeyToLabelTagValuePdf, jsonFilePath); public void ClearAccumulatedData() => FileToMapkeyToLabelTagValuePdf.Clear(); // Private helper methods private void TestFieldMapper() { Debug.WriteLine("[DEBUG] Testing field mapper..."); var testFields = new[] { "TD_DNAME_MAIN", "TD_DWGNO", "TD_DWGCODE", "TB_MTITIL" }; foreach (var field in testFields) { var aiLabel = fieldMapper.ExpresswayToAilabel(field); var docAiKey = fieldMapper.AilabelToDocAiKey(aiLabel); Debug.WriteLine($"[DEBUG] Field: {field} -> AILabel: {aiLabel} -> DocAiKey: {docAiKey}"); } } private void InitializeTeighaServices() { try { Debug.WriteLine("[DEBUG] TeighaServicesManager를 통한 Services 획득 중..."); appServices = TeighaServicesManager.Instance.AcquireServices(); Debug.WriteLine($"[DEBUG] Services 획득 성공. Reference Count: {TeighaServicesManager.Instance.ReferenceCount}"); } catch (Teigha.Runtime.Exception ex) { Debug.WriteLine($"[DEBUG] Teigha Services 초기화 실패: {ex.Message}"); throw; } } private bool UpdateExcelFromMappingData() { try { foreach (var fileEntry in FileToMapkeyToLabelTagValuePdf) { foreach (var mapEntry in fileEntry.Value) { var (aiLabel, dwgTag, dwgValue, pdfValue) = mapEntry.Value; if (!string.IsNullOrEmpty(pdfValue)) { excelWriter.UpdateExcelRow(fileEntry.Key, aiLabel, pdfValue); } } } return true; } catch (System.Exception ex) { Debug.WriteLine($"❌ Excel 업데이트 중 오류: {ex.Message}"); return false; } } public void Dispose() { try { Debug.WriteLine("[DEBUG] ExportExcel Dispose 시작"); excelManager?.Dispose(); if (appServices != null) { Debug.WriteLine("[DEBUG] Teigha Services 해제 중..."); try { TeighaServicesManager.Instance.ReleaseServices(); Debug.WriteLine($"[DEBUG] Teigha Services 해제 완료. Remaining ref count: {TeighaServicesManager.Instance.ReferenceCount}"); } catch (System.Exception ex) { Debug.WriteLine($"[DEBUG] Teigha Services 해제 중 오류 (무시됨): {ex.Message}"); } finally { appServices = null; } } Debug.WriteLine("[DEBUG] ExportExcel Dispose 완료"); } catch (System.Exception ex) { Debug.WriteLine($"[DEBUG] ExportExcel Dispose 중 전역 오류: {ex.Message}"); } } } }