diff --git a/MainWindow.xaml b/MainWindow.xaml index 9708447..7d58398 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -193,6 +193,23 @@ + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index bebf957..212048a 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1733,6 +1733,88 @@ namespace DwgExtractorManual } } + /// + /// DWG μΆ”μΆœ (Height μ •λ ¬) λ²„νŠΌ 클릭 이벀트 + /// + private async void BtnDwgHeightSort_Click(object sender, RoutedEventArgs e) + { + try + { + // 경둜 검증 + string sourceFolder = txtSourceFolder.Text; + string resultFolder = txtResultFolder.Text; + + if (string.IsNullOrWhiteSpace(sourceFolder) || !Directory.Exists(sourceFolder)) + { + ShowMessageBox("μ˜¬λ°”λ₯Έ μ†ŒμŠ€ 폴더λ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”.", "경둜 였λ₯˜", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + if (string.IsNullOrWhiteSpace(resultFolder) || !Directory.Exists(resultFolder)) + { + ShowMessageBox("μ˜¬λ°”λ₯Έ κ²°κ³Ό μ €μž₯ 폴더λ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”.", "경둜 였λ₯˜", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + // 리프 폴더 μ°ΎκΈ° + var leafFolders = FindLeafFolders(sourceFolder); + if (leafFolders.Count == 0) + { + ShowMessageBox("μ²˜λ¦¬ν•  리프 폴더가 μ—†μŠ΅λ‹ˆλ‹€.", "정보", MessageBoxButton.OK, MessageBoxImage.Information); + return; + } + + LogMessage($"πŸ” 발견된 리프 폴더: {leafFolders.Count}개"); + foreach (var folder in leafFolders) + { + LogMessage($" - {folder}"); + } + + // μ‚¬μš©μž 확인 + var result = ShowConfirmationDialog( + $"총 {leafFolders.Count}개의 리프 ν΄λ”μ—μ„œ DWG Height μ •λ ¬ μΆ”μΆœμ„ ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ?\n\n" + + "각 ν΄λ”λ§ˆλ‹€ DWG νŒŒμΌλ³„λ‘œ μ‹œνŠΈκ°€ μƒμ„±λ˜κ³ , ν…μŠ€νŠΈ 높이 순으둜 μ •λ ¬λœ Excel 파일이 μƒμ„±λ©λ‹ˆλ‹€.", + "DWG Height μ •λ ¬ μΆ”μΆœ 확인"); + + if (result != MessageBoxResult.Yes) + { + return; + } + + // UI μƒνƒœ λ³€κ²½ + SetButtonsEnabled(false); + progressBar.Value = 0; + UpdateStatus("πŸ“ DWG Height μ •λ ¬ μΆ”μΆœ μ‹œμž‘..."); + + // μžλ™ 처리 λͺ¨λ“œ ν™œμ„±ν™” + isAutoProcessing = true; + + await ProcessLeafFoldersDwgHeightSort(leafFolders, resultFolder); + + ShowMessageBox( + $"DWG Height μ •λ ¬ μΆ”μΆœμ΄ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€!\n\n" + + $"처리된 폴더: {leafFolders.Count}개\n" + + $"κ²°κ³Ό μ €μž₯ μœ„μΉ˜: {resultFolder}", + "μ™„λ£Œ", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + LogMessage($"❌ DWG Height μ •λ ¬ μΆ”μΆœ 쀑 였λ₯˜: {ex.Message}"); + ShowMessageBox($"DWG Height μ •λ ¬ μΆ”μΆœ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€:\n{ex.Message}", "였λ₯˜", MessageBoxButton.OK, MessageBoxImage.Error); + } + finally + { + SetButtonsEnabled(true); + progressBar.Value = 0; + UpdateStatus("βœ… μ€€λΉ„"); + + // μžλ™ 처리 λͺ¨λ“œ λΉ„ν™œμ„±ν™” + isAutoProcessing = false; + } + } + /// /// ν΄λ”μ—μ„œ 리프 폴더듀(ν•˜μœ„ 폴더가 μ—†λŠ” 폴더)을 μž¬κ·€μ μœΌλ‘œ μ°ΎμŠ΅λ‹ˆλ‹€. /// @@ -1935,6 +2017,114 @@ namespace DwgExtractorManual UpdateStatus("βœ… DWG μ „μš© μΆ”μΆœ μ™„λ£Œ"); } + /// + /// DWG Height μ •λ ¬ 처리λ₯Ό μœ„ν•œ 리프 폴더 처리 + /// + /// μ²˜λ¦¬ν•  리프 폴더 λͺ©λ‘ + /// κ²°κ³Ό μ €μž₯ κΈ°λ³Έ 폴더 + private async Task ProcessLeafFoldersDwgHeightSort(List leafFolders, string resultBaseFolder) + { + int totalFolders = leafFolders.Count; + LogMessage($"πŸ“ DWG Height μ •λ ¬ μΆ”μΆœ μ‹œμž‘: {totalFolders}개 폴더"); + + try + { + // λͺ¨λ“  ν΄λ”μ˜ DWG νŒŒμΌμ„ μˆ˜μ§‘ + var allDwgFiles = new List<(string filePath, string folderName)>(); + + for (int i = 0; i < leafFolders.Count; i++) + { + string leafFolder = leafFolders[i]; + progressBar.Value = (double)(i + 1) / totalFolders * 50; // 첫 50%λŠ” 파일 μˆ˜μ§‘μš© + + LogMessage($"πŸ“ [{i + 1}/{totalFolders}] 폴더 μŠ€μΊ” 쀑: {leafFolder}"); + + var dwgFiles = Directory.GetFiles(leafFolder, "*.dwg", SearchOption.TopDirectoryOnly); + string folderName = Path.GetFileName(leafFolder); + + foreach (var dwgFile in dwgFiles) + { + allDwgFiles.Add((dwgFile, folderName)); + } + + LogMessage($"πŸ“Š [{i + 1}/{totalFolders}] 발견된 DWG 파일: {dwgFiles.Length}개"); + + // UI 응닡성을 μœ„ν•œ 양보 + await Task.Yield(); + } + + LogMessage($"πŸ“Š 총 발견된 DWG 파일: {allDwgFiles.Count}개"); + + if (allDwgFiles.Count > 0) + { + // 단일 Excel νŒŒμΌμ— λͺ¨λ“  DWG 파일 처리 + LogMessage("πŸ“ 단일 Height μ •λ ¬ Excel 파일 생성 쀑..."); + await ProcessAllFilesDwgHeightSort(allDwgFiles, resultBaseFolder); + LogMessage("βœ… Height μ •λ ¬ Excel 파일 생성 μ™„λ£Œ"); + } + else + { + LogMessage("⚠️ μ²˜λ¦¬ν•  DWG 파일이 μ—†μŠ΅λ‹ˆλ‹€."); + } + + progressBar.Value = 100; + } + catch (Exception ex) + { + LogMessage($"❌ DWG Height μ •λ ¬ μΆ”μΆœ 쀑 였λ₯˜: {ex.Message}"); + throw; + } + + LogMessage($"πŸŽ‰ DWG Height μ •λ ¬ μΆ”μΆœ μ™„λ£Œ! 총 {totalFolders}개 폴더 처리됨"); + UpdateStatus("βœ… DWG Height μ •λ ¬ μΆ”μΆœ μ™„λ£Œ"); + } + + /// + /// λͺ¨λ“  DWG νŒŒμΌμ„ 단일 Excel νŒŒμΌμ—μ„œ Height μ •λ ¬ν•˜μ—¬ μ²˜λ¦¬ν•©λ‹ˆλ‹€. + /// + /// λͺ¨λ“  DWG 파일 정보 (파일경둜, 폴더λͺ…) + /// κ²°κ³Ό 폴더 + private async Task ProcessAllFilesDwgHeightSort(List<(string filePath, string folderName)> allDwgFiles, string resultFolder) + { + ExportExcel exportExcel = null; + try + { + LogMessage($"πŸ“Š 총 DWG 파일 수: {allDwgFiles.Count}개"); + LogMessage($"πŸ“‹ 좜λ ₯ λͺ¨λ“œ: Excel (Height μ •λ ¬)"); + LogMessage($"πŸ’Ύ κ²°κ³Ό 폴더: {resultFolder}"); + + LogMessage("πŸ“Š Excel Height μ •λ ¬ 내보내기 λͺ¨λ“œλ‘œ μ‹œμž‘ν•©λ‹ˆλ‹€..."); + LogMessage("πŸ“ Excel μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€..."); + + exportExcel = new ExportExcel(); + + // UI 응닡성을 μœ„ν•œ 양보 + await Task.Yield(); + + // Height μ •λ ¬λœ Excel 파일 생성 + LogMessage("πŸ“ Height μ •λ ¬ Excel 파일 생성 쀑..."); + + // 단일 νƒ€μž„μŠ€νƒ¬ν”„λ‘œ 파일λͺ… 생성 + string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); + string savePath = Path.Combine(resultFolder, $"{timestamp}_AllDWG_HeightSorted.xlsx"); + + exportExcel.ExportAllDwgToExcelHeightSorted(allDwgFiles, savePath); + + LogMessage("βœ… Height μ •λ ¬ Excel 파일 생성 μ™„λ£Œ"); + LogMessage($"πŸ“ μ €μž₯된 파일: {Path.GetFileName(savePath)}"); + } + catch (Exception ex) + { + LogMessage($"❌ DWG Height μ •λ ¬ 처리 쀑 치λͺ…적 였λ₯˜: {ex.Message}"); + throw; + } + finally + { + exportExcel?.Dispose(); + exportExcel = null; + } + } + /// /// μ§€μ •λœ ν΄λ”μ—μ„œ DWG νŒŒμΌλ“€λ§Œ μ²˜λ¦¬ν•©λ‹ˆλ‹€. /// @@ -2044,6 +2234,104 @@ namespace DwgExtractorManual } } + /// + /// μ§€μ •λœ ν΄λ”μ—μ„œ DWG νŒŒμΌλ“€μ„ Height μ •λ ¬ν•˜μ—¬ μ²˜λ¦¬ν•©λ‹ˆλ‹€. + /// + /// μ²˜λ¦¬ν•  폴더 경둜 + private async Task ProcessFilesDwgHeightSort(string sourceFolderPath) + { + ExportExcel exportExcel = null; + try + { + string resultFolder = txtResultFolder.Text; + + if (!Directory.Exists(sourceFolderPath)) + { + LogMessage($"❌ μ†ŒμŠ€ 폴더가 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€: {sourceFolderPath}"); + return; + } + + var dwgFiles = Directory.GetFiles(sourceFolderPath, "*.dwg", SearchOption.TopDirectoryOnly); + + if (dwgFiles.Length == 0) + { + LogMessage($"πŸ“„ μ²˜λ¦¬ν•  DWG 파일이 μ—†μŠ΅λ‹ˆλ‹€: {sourceFolderPath}"); + return; + } + + LogMessage($"πŸ“Š μ²˜λ¦¬ν•  DWG 파일 수: {dwgFiles.Length}개"); + LogMessage($"πŸ“‹ 좜λ ₯ λͺ¨λ“œ: Excel (Height μ •λ ¬)"); + LogMessage($"πŸ“‚ μ†ŒμŠ€ 폴더: {sourceFolderPath}"); + LogMessage($"πŸ’Ύ κ²°κ³Ό 폴더: {resultFolder}"); + + LogMessage("πŸ“Š Excel Height μ •λ ¬ 내보내기 λͺ¨λ“œλ‘œ μ‹œμž‘ν•©λ‹ˆλ‹€..."); + LogMessage("πŸ“ Excel μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€..."); + + exportExcel = new ExportExcel(); + + // UI 응닡성을 μœ„ν•œ 양보 + await Task.Yield(); + + // Height μ •λ ¬λœ Excel 파일 생성 + LogMessage("πŸ“ Height μ •λ ¬ Excel 파일 생성 쀑..."); + exportExcel.ExportDwgToExcelHeightSorted(dwgFiles, resultFolder); + + LogMessage("βœ… Height μ •λ ¬ Excel 파일 생성 μ™„λ£Œ"); + } + catch (Exception ex) + { + LogMessage($"❌ DWG Height μ •λ ¬ 처리 쀑 치λͺ…적 였λ₯˜: {ex.Message}"); + throw; + } + finally + { + exportExcel?.Dispose(); + exportExcel = null; + } + } + + /// + /// DWG Height μ •λ ¬ Excel νŒŒμΌμ„ λͺ©ν‘œ 경둜둜 이름 λ³€κ²½ + /// + /// κ²°κ³Ό 폴더 + /// 리프 폴더 경둜 + private async Task RenameDwgHeightSortExcelFile(string resultFolder, string leafFolderPath) + { + try + { + // μ΅œμ‹  *_HeightSorted.xlsx 파일 μ°ΎκΈ° + var excelFiles = Directory.GetFiles(resultFolder, "*_HeightSorted.xlsx") + .Where(f => !Path.GetFileName(f).StartsWith("~$")) + .OrderByDescending(f => File.GetCreationTime(f)) + .ToList(); + + if (excelFiles.Any()) + { + string latestFile = excelFiles.First(); + + // 리프 폴더 경둜λ₯Ό 기반으둜 파일λͺ… 생성 + string relativePath = Path.GetRelativePath(txtSourceFolder.Text, leafFolderPath); + string safePath = relativePath.Replace('\\', '_').Replace('/', '_').Replace(':', '_'); + string targetFileName = $"{safePath}_HeightSorted.xlsx"; + string targetPath = Path.Combine(resultFolder, targetFileName); + + // λͺ©ν‘œ 파일이 이미 μ‘΄μž¬ν•˜λ©΄ μ‚­μ œ + if (File.Exists(targetPath)) + { + File.Delete(targetPath); + } + + // 파일 이름 λ³€κ²½ + File.Move(latestFile, targetPath); + LogMessage($"πŸ“‹ Height μ •λ ¬ Excel 파일 이름 변경됨: {targetFileName}"); + } + } + catch (Exception ex) + { + LogMessage($"⚠️ Height μ •λ ¬ Excel 파일 이름 λ³€κ²½ μ‹€νŒ¨: {ex.Message}"); + } + } + /// /// μ΅œμ‹  Excel νŒŒμΌμ„ λͺ©ν‘œ 경둜둜 이름 λ³€κ²½ /// diff --git a/Models/ExportExcel.cs b/Models/ExportExcel.cs index bd69ac5..c3a2e33 100644 --- a/Models/ExportExcel.cs +++ b/Models/ExportExcel.cs @@ -329,6 +329,7 @@ namespace DwgExtractorManual.Models titleBlockSheet.Cells[titleBlockCurrentRow, 5] = attRef.TextString; titleBlockSheet.Cells[titleBlockCurrentRow, 6] = database.Filename; titleBlockSheet.Cells[titleBlockCurrentRow, 7] = Path.GetFileName(database.Filename); + titleBlockCurrentRow++; var tag = attRef.Tag; @@ -373,6 +374,7 @@ namespace DwgExtractorManual.Models textEntitiesSheet.Cells[textEntitiesCurrentRow, 3] = dbText.TextString; // Text textEntitiesSheet.Cells[textEntitiesCurrentRow, 4] = database.Filename; // Path textEntitiesSheet.Cells[textEntitiesCurrentRow, 5] = Path.GetFileName(database.Filename); // FileName + textEntitiesCurrentRow++; } // MText μ—”ν‹°ν‹° μΆ”μΆœ (별도 μ‹œνŠΈ) @@ -383,6 +385,7 @@ namespace DwgExtractorManual.Models textEntitiesSheet.Cells[textEntitiesCurrentRow, 3] = mText.Contents; // Text textEntitiesSheet.Cells[textEntitiesCurrentRow, 4] = database.Filename; // Path textEntitiesSheet.Cells[textEntitiesCurrentRow, 5] = Path.GetFileName(database.Filename); // FileName + textEntitiesCurrentRow++; } } @@ -1532,6 +1535,392 @@ namespace DwgExtractorManual.Models } } + /// + /// DWG νŒŒμΌλ“€μ„ μ²˜λ¦¬ν•˜μ—¬ 각 νŒŒμΌλ³„λ‘œ μ‹œνŠΈλ₯Ό μƒμ„±ν•˜κ³  Height 순으둜 μ •λ ¬λœ Excel νŒŒμΌμ„ μƒμ„±ν•©λ‹ˆλ‹€. + /// + /// μ²˜λ¦¬ν•  DWG 파일 경둜 λ°°μ—΄ + /// κ²°κ³Ό 파일 μ €μž₯ 폴더 + 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"); + + // μƒˆλ‘œμš΄ Excel μ›Œν¬λΆ 생성 + if (excelApplication == null) + { + excelApplication = new Excel.Application(); + excelApplication.Visible = false; + } + + var heightSortedWorkbook = excelApplication.Workbooks.Add(); + + Debug.WriteLine($"[DEBUG] DWG 파일 처리 μ‹œμž‘"); + + bool firstSheetProcessed = false; + + foreach (string dwgFile in dwgFiles) + { + if (!File.Exists(dwgFile)) + { + Debug.WriteLine($"[DEBUG] 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ: {dwgFile}"); + continue; + } + + string fileName = Path.GetFileNameWithoutExtension(dwgFile); + Debug.WriteLine($"[DEBUG] 처리 쀑인 파일: {fileName}"); + + try + { + Excel.Worksheet worksheet; + if (!firstSheetProcessed) + { + // 첫 번째 νŒŒμΌμ€ κΈ°λ³Έ μ‹œνŠΈ μ‚¬μš© + worksheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; + firstSheetProcessed = true; + } + else + { + // 이후 νŒŒμΌλ“€μ€ μƒˆ μ‹œνŠΈ 생성 + worksheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets.Add(); + } + worksheet.Name = GetValidSheetName(fileName); + + // 헀더 μ„€μ • + worksheet.Cells[1, 1] = "Height"; + worksheet.Cells[1, 2] = "Type"; + worksheet.Cells[1, 3] = "Layer"; + worksheet.Cells[1, 4] = "Tag"; + worksheet.Cells[1, 5] = "FileName"; + worksheet.Cells[1, 6] = "Text"; + + // 헀더 μŠ€νƒ€μΌ 적용 + var headerRange = worksheet.Range["A1:F1"]; + headerRange.Font.Bold = true; + headerRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue); + + // DWG νŒŒμΌμ—μ„œ ν…μŠ€νŠΈ μ—”ν‹°ν‹° μΆ”μΆœ + var textEntities = ExtractTextEntitiesWithHeight(dwgFile); + + // Height 순으둜 λ‚΄λ¦Όμ°¨μˆœ μ •λ ¬ + var sortedEntities = textEntities.OrderByDescending(entity => entity.Height).ToList(); + + Debug.WriteLine($"[DEBUG] {fileName}: {sortedEntities.Count}개 ν…μŠ€νŠΈ μ—”ν‹°ν‹° μΆ”μΆœλ¨"); + + // 데이터 μž…λ ₯ + int row = 2; + foreach (var entity in sortedEntities) + { + worksheet.Cells[row, 1] = entity.Height; + worksheet.Cells[row, 2] = entity.Type; + worksheet.Cells[row, 3] = entity.Layer; + worksheet.Cells[row, 4] = entity.Tag; + worksheet.Cells[row, 5] = fileName; + worksheet.Cells[row, 6] = entity.Text; + row++; + } + + // 컬럼 μžλ™ 크기 μ‘°μ • + worksheet.Columns.AutoFit(); + + Debug.WriteLine($"[DEBUG] {fileName} μ‹œνŠΈ μ™„λ£Œ: {sortedEntities.Count}개 ν–‰"); + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ {fileName} 처리 쀑 였λ₯˜: {ex.Message}"); + continue; + } + } + + // DWG 파일이 ν•˜λ‚˜λ„ μ—†μ—ˆλ‹€λ©΄ κΈ°λ³Έ μ‹œνŠΈμ— λ©”μ‹œμ§€ μΆ”κ°€ + if (!firstSheetProcessed) + { + var defaultSheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; + defaultSheet.Name = "No_DWG_Files"; + defaultSheet.Cells[1, 1] = "No DWG files found in this folder"; + Debug.WriteLine("[DEBUG] DWG 파일이 μ—†μ–΄ κΈ°λ³Έ λ©”μ‹œμ§€ μ‹œνŠΈ 생성"); + } + + // 파일 μ €μž₯ + string directory = Path.GetDirectoryName(savePath); + if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + heightSortedWorkbook.SaveAs(savePath, + FileFormat: Excel.XlFileFormat.xlOpenXMLWorkbook, + AccessMode: Excel.XlSaveAsAccessMode.xlNoChange); + + Debug.WriteLine($"βœ… Height μ •λ ¬ Excel 파일 μ €μž₯ μ™„λ£Œ: {Path.GetFileName(savePath)}"); + + // μ›Œν¬λΆ 정리 + heightSortedWorkbook.Close(false); + ReleaseComObject(heightSortedWorkbook); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ Height μ •λ ¬ Excel 생성 쀑 였λ₯˜: {ex.Message}"); + Debug.WriteLine($" μŠ€νƒ 트레이슀: {ex.StackTrace}"); + throw; + } + } + + /// + /// DWG νŒŒμΌμ—μ„œ ν…μŠ€νŠΈ 엔티티듀을 μΆ”μΆœν•˜μ—¬ Height 정보와 ν•¨κ»˜ λ°˜ν™˜ν•©λ‹ˆλ‹€. + /// + /// DWG 파일 경둜 + /// ν…μŠ€νŠΈ μ—”ν‹°ν‹° 정보 리슀트 + private List ExtractTextEntitiesWithHeight(string filePath) + { + var textEntities = new List(); + + try + { + using (var database = new Database(false, true)) + { + database.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndWriteNoShare, false, null); + + using (var tran = database.TransactionManager.StartTransaction()) + { + var bt = tran.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable; + using (var btr = tran.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord) + { + foreach (ObjectId entId in btr) + { + using (var ent = tran.GetObject(entId, OpenMode.ForRead) as Entity) + { + string layerName = GetLayerName(ent.LayerId, tran, database); + + // AttributeReference 처리 + if (ent is BlockReference blr) + { + foreach (ObjectId attId in blr.AttributeCollection) + { + using (var attRef = tran.GetObject(attId, OpenMode.ForRead) as AttributeReference) + { + if (attRef != null && !string.IsNullOrWhiteSpace(attRef.TextString)) + { + textEntities.Add(new TextEntityInfo + { + Height = attRef.Height, + Type = "AttRef", + Layer = layerName, + Tag = attRef.Tag, + Text = attRef.TextString + }); + } + } + } + } + // DBText 처리 + else if (ent is DBText dbText) + { + textEntities.Add(new TextEntityInfo + { + Height = dbText.Height, + Type = "DBText", + Layer = layerName, + Tag = "", + Text = dbText.TextString + }); + } + // MText 처리 + else if (ent is MText mText) + { + textEntities.Add(new TextEntityInfo + { + Height = mText.Height, + Type = "MText", + Layer = layerName, + Tag = "", + Text = mText.Contents + }); + } + } + } + } + + tran.Commit(); + } + } + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ ν…μŠ€νŠΈ μ—”ν‹°ν‹° μΆ”μΆœ 쀑 였λ₯˜ ({Path.GetFileName(filePath)}): {ex.Message}"); + } + + return textEntities; + } + + /// + /// λͺ¨λ“  DWG νŒŒμΌλ“€μ„ ν•˜λ‚˜μ˜ Excel 파일둜 μ²˜λ¦¬ν•˜μ—¬ 각 νŒŒμΌλ³„λ‘œ μ‹œνŠΈλ₯Ό μƒμ„±ν•˜κ³  Height 순으둜 μ •λ ¬ν•©λ‹ˆλ‹€. + /// + /// μ²˜λ¦¬ν•  DWG 파일 리슀트 (파일경둜, 폴더λͺ…) + /// κ²°κ³Ό Excel 파일 μ €μž₯ 경둜 + public void ExportAllDwgToExcelHeightSorted(List<(string filePath, string folderName)> allDwgFiles, string savePath) + { + try + { + Debug.WriteLine($"[DEBUG] 단일 Excel 파일둜 Height μ •λ ¬ 생성 μ‹œμž‘: {allDwgFiles.Count}개 파일"); + + // μƒˆλ‘œμš΄ Excel μ›Œν¬λΆ 생성 + if (excelApplication == null) + { + excelApplication = new Excel.Application(); + excelApplication.Visible = false; + } + + var heightSortedWorkbook = excelApplication.Workbooks.Add(); + + Debug.WriteLine($"[DEBUG] DWG 파일 처리 μ‹œμž‘"); + + bool firstSheetProcessed = false; + + foreach (var (filePath, folderName) in allDwgFiles) + { + if (!File.Exists(filePath)) + { + Debug.WriteLine($"[DEBUG] 파일이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ: {filePath}"); + continue; + } + + string fileName = Path.GetFileNameWithoutExtension(filePath); + Debug.WriteLine($"[DEBUG] 처리 쀑인 파일: {fileName} (폴더: {folderName})"); + + try + { + Excel.Worksheet worksheet; + if (!firstSheetProcessed) + { + // 첫 번째 νŒŒμΌμ€ κΈ°λ³Έ μ‹œνŠΈ μ‚¬μš© + worksheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; + firstSheetProcessed = true; + } + else + { + // 이후 νŒŒμΌλ“€μ€ μƒˆ μ‹œνŠΈ 생성 + worksheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets.Add(); + } + worksheet.Name = GetValidSheetName(fileName); + + // 헀더 μ„€μ • + worksheet.Cells[1, 1] = "Height"; + worksheet.Cells[1, 2] = "Type"; + worksheet.Cells[1, 3] = "Layer"; + worksheet.Cells[1, 4] = "Tag"; + worksheet.Cells[1, 5] = "FileName"; + worksheet.Cells[1, 6] = "Text"; + + // 헀더 μŠ€νƒ€μΌ 적용 + var headerRange = worksheet.Range["A1:F1"]; + headerRange.Font.Bold = true; + headerRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue); + + // DWG νŒŒμΌμ—μ„œ ν…μŠ€νŠΈ μ—”ν‹°ν‹° μΆ”μΆœ + var textEntities = ExtractTextEntitiesWithHeight(filePath); + + // Height 순으둜 λ‚΄λ¦Όμ°¨μˆœ μ •λ ¬ + var sortedEntities = textEntities.OrderByDescending(entity => entity.Height).ToList(); + + Debug.WriteLine($"[DEBUG] {fileName}: {sortedEntities.Count}개 ν…μŠ€νŠΈ μ—”ν‹°ν‹° μΆ”μΆœλ¨"); + + // 데이터 μž…λ ₯ + int row = 2; + foreach (var entity in sortedEntities) + { + worksheet.Cells[row, 1] = entity.Height; + worksheet.Cells[row, 2] = entity.Type; + worksheet.Cells[row, 3] = entity.Layer; + worksheet.Cells[row, 4] = entity.Tag; + worksheet.Cells[row, 5] = fileName; + worksheet.Cells[row, 6] = entity.Text; + row++; + } + + // 컬럼 μžλ™ 크기 μ‘°μ • + worksheet.Columns.AutoFit(); + + Debug.WriteLine($"[DEBUG] {fileName} μ‹œνŠΈ μ™„λ£Œ: {sortedEntities.Count}개 ν–‰"); + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ {fileName} 처리 쀑 였λ₯˜: {ex.Message}"); + continue; + } + } + + // DWG 파일이 ν•˜λ‚˜λ„ μ—†μ—ˆλ‹€λ©΄ κΈ°λ³Έ μ‹œνŠΈμ— λ©”μ‹œμ§€ μΆ”κ°€ + if (!firstSheetProcessed) + { + var defaultSheet = (Excel.Worksheet)heightSortedWorkbook.Worksheets[1]; + defaultSheet.Name = "No_DWG_Files"; + defaultSheet.Cells[1, 1] = "No DWG files found in any folder"; + Debug.WriteLine("[DEBUG] DWG 파일이 μ—†μ–΄ κΈ°λ³Έ λ©”μ‹œμ§€ μ‹œνŠΈ 생성"); + } + + // 파일 μ €μž₯ + string directory = Path.GetDirectoryName(savePath); + if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + heightSortedWorkbook.SaveAs(savePath, + FileFormat: Excel.XlFileFormat.xlOpenXMLWorkbook, + AccessMode: Excel.XlSaveAsAccessMode.xlNoChange); + + Debug.WriteLine($"βœ… 단일 Height μ •λ ¬ Excel 파일 μ €μž₯ μ™„λ£Œ: {Path.GetFileName(savePath)}"); + + // μ›Œν¬λΆ 정리 + heightSortedWorkbook.Close(false); + ReleaseComObject(heightSortedWorkbook); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ 단일 Height μ •λ ¬ Excel 생성 쀑 였λ₯˜: {ex.Message}"); + Debug.WriteLine($" μŠ€νƒ 트레이슀: {ex.StackTrace}"); + throw; + } + } + + /// + /// Excel μ‹œνŠΈλͺ…μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλŠ” μœ νš¨ν•œ 이름을 μƒμ„±ν•©λ‹ˆλ‹€. + /// + /// 원본 파일λͺ… + /// μœ νš¨ν•œ μ‹œνŠΈλͺ… + private string GetValidSheetName(string originalName) + { + if (string.IsNullOrEmpty(originalName)) + return "Sheet"; + + // Excel μ‹œνŠΈλͺ…μ—μ„œ ν—ˆμš©λ˜μ§€ μ•ŠλŠ” 문자 제거 + string validName = originalName; + char[] invalidChars = { '\\', '/', '?', '*', '[', ']', ':' }; + + foreach (char c in invalidChars) + { + validName = validName.Replace(c, '_'); + } + + // 31자둜 μ œν•œ (Excel μ‹œνŠΈλͺ… μ΅œλŒ€ 길이) + if (validName.Length > 31) + { + validName = validName.Substring(0, 31); + } + + return validName; + } + public void Dispose() { try @@ -1571,4 +1960,16 @@ namespace DwgExtractorManual.Models } } } + + /// + /// ν…μŠ€νŠΈ μ—”ν‹°ν‹° 정보λ₯Ό λ‹΄λŠ” 클래슀 + /// + public class TextEntityInfo + { + public double Height { get; set; } + public string Type { get; set; } + public string Layer { get; set; } + public string Tag { get; set; } + public string Text { get; set; } + } }