diff --git a/DwgExtractorManual.csproj b/DwgExtractorManual.csproj index b4fa5d0..c694940 100644 --- a/DwgExtractorManual.csproj +++ b/DwgExtractorManual.csproj @@ -54,30 +54,21 @@ - - + + - + - + - + - + - + @@ -87,18 +78,10 @@ - + - + diff --git a/MainWindow.xaml b/MainWindow.xaml index 5e1ebba..9708447 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -1,7 +1,7 @@  @@ -12,6 +12,7 @@ + @@ -89,6 +90,7 @@ + @@ -171,11 +173,32 @@ + + + + + - - + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index 2fc80dc..405f86a 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1651,6 +1651,88 @@ namespace DwgExtractorManual } } + /// + /// DWG 전용 폴더별 추출 버튼 클릭 이벤트 + /// + private async void BtnDwgOnly_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만 추출하시겠습니까?\n\n" + + "각 폴더마다 DWG 추출 작업이 실행되고, 폴더별로 Excel 파일이 생성됩니다.", + "DWG 전용 추출 확인"); + + if (result != MessageBoxResult.Yes) + { + return; + } + + // UI 상태 변경 + SetButtonsEnabled(false); + progressBar.Value = 0; + UpdateStatus("🔧 DWG 전용 폴더별 추출 시작..."); + + // 자동 처리 모드 활성화 + isAutoProcessing = true; + + await ProcessLeafFoldersDwgOnly(leafFolders, resultFolder); + + ShowMessageBox( + $"DWG 전용 추출이 완료되었습니다!\n\n" + + $"처리된 폴더: {leafFolders.Count}개\n" + + $"결과 저장 위치: {resultFolder}", + "완료", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + LogMessage($"❌ DWG 전용 추출 중 오류: {ex.Message}"); + ShowMessageBox($"DWG 전용 추출 중 오류가 발생했습니다:\n{ex.Message}", "오류", MessageBoxButton.OK, MessageBoxImage.Error); + } + finally + { + SetButtonsEnabled(true); + progressBar.Value = 0; + UpdateStatus("✅ 준비"); + + // 자동 처리 모드 비활성화 + isAutoProcessing = false; + } + } + /// /// 폴더에서 리프 폴더들(하위 폴더가 없는 폴더)을 재귀적으로 찾습니다. /// @@ -1803,6 +1885,163 @@ namespace DwgExtractorManual UpdateStatus("✅ 자동 처리 완료"); } + /// + /// 리프 폴더들에 대해 DWG 전용 추출을 수행합니다. + /// + /// 처리할 리프 폴더 목록 + /// 결과 파일 저장 기본 폴더 + private async Task ProcessLeafFoldersDwgOnly(List leafFolders, string resultBaseFolder) + { + int totalFolders = leafFolders.Count; + int currentFolderIndex = 0; + + LogMessage($"🔧 DWG 전용 폴더별 추출 시작: {totalFolders}개 폴더"); + + foreach (string leafFolder in leafFolders) + { + currentFolderIndex++; + progressBar.Value = (double)currentFolderIndex / totalFolders * 100; + + try + { + LogMessage($"📁 [{currentFolderIndex}/{totalFolders}] DWG 추출 시작: {leafFolder}"); + + // 1. DWG 추출만 수행 + await ProcessFilesDwgOnly(leafFolder); + LogMessage($"✅ [{currentFolderIndex}/{totalFolders}] DWG 추출 완료"); + + // 2초 대기 + await Task.Delay(2000); + + // 2. DWG 전용 Excel 파일 생성 및 이름 변경 + await RenameDwgOnlyExcelFile(resultBaseFolder, leafFolder); + LogMessage($"📋 [{currentFolderIndex}/{totalFolders}] Excel 파일 생성 완료"); + + // 1초 대기 + await Task.Delay(1000); + } + catch (Exception ex) + { + LogMessage($"❌ [{currentFolderIndex}/{totalFolders}] 폴더 처리 실패 ({leafFolder}): {ex.Message}"); + LogMessage($"⏭️ [{currentFolderIndex}/{totalFolders}] 다음 폴더로 계속 진행"); + + // 오류 발생 시 잠시 대기 후 다음 폴더 처리 + await Task.Delay(2000); + continue; + } + } + + LogMessage($"🎉 DWG 전용 추출 완료! 총 {totalFolders}개 폴더 처리됨"); + UpdateStatus("✅ DWG 전용 추출 완료"); + } + + /// + /// 지정된 폴더에서 DWG 파일들만 처리합니다. + /// + /// 처리할 폴더 경로 + private async Task ProcessFilesDwgOnly(string sourceFolderPath) + { + 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"); + LogMessage($"📂 소스 폴더: {sourceFolderPath}"); + LogMessage($"💾 결과 폴더: {resultFolder}"); + + LogMessage("📊 Excel 내보내기 모드로 시작합니다..."); + LogMessage("📝 Excel 애플리케이션을 초기화합니다..."); + + _exportExcel = new ExportExcel(); + + // UI 응답성을 위한 양보 + await Task.Yield(); + + // 각 DWG 파일 처리 + foreach (string dwgFile in dwgFiles) + { + LogMessage($"📄 DWG 파일 처리 중: {Path.GetFileName(dwgFile)}"); + _exportExcel.ExportDwgToExcel(dwgFile); + + // UI 응답성을 위한 양보 + await Task.Yield(); + } + + // DWG 전용 워크북 저장 + LogMessage("💾 DWG 전용 Excel 파일 저장 중..."); + _exportExcel.SaveDwgOnlyMappingWorkbook(resultFolder); + + LogMessage("✅ DWG 전용 Excel 파일 저장 완료"); + } + catch (Exception ex) + { + LogMessage($"❌ DWG 처리 중 치명적 오류: {ex.Message}"); + throw; + } + finally + { + _exportExcel?.Dispose(); + _exportExcel = null; + } + } + + /// + /// DWG 전용 Excel 파일을 목표 경로로 이름 변경 + /// + /// 결과 폴더 + /// 리프 폴더 경로 + private async Task RenameDwgOnlyExcelFile(string resultFolder, string leafFolderPath) + { + try + { + // 최신 *_DwgOnly_Mapping.xlsx 파일 찾기 + var excelFiles = Directory.GetFiles(resultFolder, "*_DwgOnly_Mapping.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}_DwgMapping.xlsx"; + string targetPath = Path.Combine(resultFolder, targetFileName); + + // 목표 파일이 이미 존재하면 삭제 + if (File.Exists(targetPath)) + { + File.Delete(targetPath); + } + + // 파일 이름 변경 + File.Move(latestFile, targetPath); + LogMessage($"📋 DWG Excel 파일 이름 변경됨: {targetFileName}"); + } + } + catch (Exception ex) + { + LogMessage($"⚠️ DWG Excel 파일 이름 변경 실패: {ex.Message}"); + } + } + /// /// 최신 Excel 파일을 목표 경로로 이름 변경 /// @@ -1849,6 +2088,7 @@ namespace DwgExtractorManual btnPdfExtract.IsEnabled = enabled; btnMerge.IsEnabled = enabled; btnAuto.IsEnabled = enabled; + btnDwgOnly.IsEnabled = enabled; } protected override void OnClosed(EventArgs e) diff --git a/Models/ExportExcel.cs b/Models/ExportExcel.cs index 8c0c8ce..c4ba073 100644 --- a/Models/ExportExcel.cs +++ b/Models/ExportExcel.cs @@ -841,6 +841,94 @@ namespace DwgExtractorManual.Models } } + /// + /// DWG 전용 매핑 워크북을 생성하고 저장합니다 (PDF 컬럼 제외). + /// + /// 결과 파일 저장 폴더 경로 + public void SaveDwgOnlyMappingWorkbook(string resultFolderPath) + { + try + { + string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); + string savePath = Path.Combine(resultFolderPath, $"{timestamp}_DwgOnly_Mapping.xlsx"); + + Debug.WriteLine($"[DEBUG] DWG 전용 매핑 워크북 생성 시작: {savePath}"); + + // Excel 애플리케이션 초기화 확인 + if (excelApplication == null) + { + excelApplication = new Excel.Application(); + excelApplication.Visible = false; + Debug.WriteLine("[DEBUG] 새 Excel 애플리케이션 생성됨 (DWG 전용)"); + } + + // DWG 전용 워크북 생성 + var dwgOnlyWorkbook = excelApplication.Workbooks.Add(); + var dwgOnlyWorksheet = (Excel.Worksheet)dwgOnlyWorkbook.Worksheets[1]; + dwgOnlyWorksheet.Name = "DWG Mapping Data"; + + // 헤더 생성 (PDF Value 컬럼 제외) + dwgOnlyWorksheet.Cells[1, 1] = "파일명"; + dwgOnlyWorksheet.Cells[1, 2] = "Map Key"; + dwgOnlyWorksheet.Cells[1, 3] = "AI Label"; + dwgOnlyWorksheet.Cells[1, 4] = "DWG Tag"; + dwgOnlyWorksheet.Cells[1, 5] = "DWG Value"; + + // 헤더 스타일 적용 + var headerRange = dwgOnlyWorksheet.Range["A1:E1"]; + headerRange.Font.Bold = true; + headerRange.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightGray); + headerRange.Borders.LineStyle = Excel.XlLineStyle.xlContinuous; + + // 데이터 입력 + int row = 2; + foreach (var fileEntry in FileToMapkeyToLabelTagValuePdf) + { + string fileName = fileEntry.Key; + foreach (var mapEntry in fileEntry.Value) + { + string mapKey = mapEntry.Key; + var (aiLabel, dwgTag, dwgValue, pdfValue) = mapEntry.Value; + + dwgOnlyWorksheet.Cells[row, 1] = fileName; + dwgOnlyWorksheet.Cells[row, 2] = mapKey; + dwgOnlyWorksheet.Cells[row, 3] = aiLabel; + dwgOnlyWorksheet.Cells[row, 4] = dwgTag; + dwgOnlyWorksheet.Cells[row, 5] = dwgValue; + + row++; + } + } + + // 컬럼 자동 크기 조정 + dwgOnlyWorksheet.Columns.AutoFit(); + + // 파일 저장 + string directory = Path.GetDirectoryName(savePath); + if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + dwgOnlyWorkbook.SaveAs(savePath, + FileFormat: Excel.XlFileFormat.xlOpenXMLWorkbook, + AccessMode: Excel.XlSaveAsAccessMode.xlNoChange); + + Debug.WriteLine($"✅ DWG 전용 매핑 워크북 저장 완료: {Path.GetFileName(savePath)}"); + + // 워크북 정리 + dwgOnlyWorkbook.Close(false); + System.Runtime.InteropServices.Marshal.ReleaseComObject(dwgOnlyWorksheet); + System.Runtime.InteropServices.Marshal.ReleaseComObject(dwgOnlyWorkbook); + } + catch (System.Exception ex) + { + Debug.WriteLine($"❌ DWG 전용 매핑 워크북 저장 중 오류: {ex.Message}"); + Debug.WriteLine($" 스택 트레이스: {ex.StackTrace}"); + throw; + } + } + /// /// 현재 Excel 워크북을 지정된 경로에 저장하고 Excel 애플리케이션을 종료합니다. ///