using System.IO; using System.Windows; using System.Diagnostics; using System.Windows.Threading; using DwgExtractorManual.Models; namespace DwgExtractorManual { public partial class MainWindow : Window { private DispatcherTimer _timer; private ExportExcel? _exportExcel; private SqlDatas? _sqlDatas; public MainWindow() { InitializeComponent(); InitializeDefaultPaths(); InitializeTimer(); LogMessage("🚀 DWG 정보 추출기가 시작되었습니다."); } private void InitializeDefaultPaths() { // 기본 경로 설정 - 실제 환경에 맞게 수정 txtSourceFolder.Text = @"D:\MyProjects\AI_TaskForce\AI_도면_dwg_pdf\대산당진_2공구_02도서성과품_01_설계도면\002_토공\01_본선\01_평면 및 종단면도"; txtResultFolder.Text = @"D:\MyProjects\AI_TaskForce\AI_도면_dwg_pdf\대산당진_2공구_02도서성과품_01_설계도면"; // 경로가 존재하지 않으면 기본값으로 설정 if (!Directory.Exists(txtSourceFolder.Text)) { txtSourceFolder.Text = @"C:\"; } if (!Directory.Exists(txtResultFolder.Text)) { txtResultFolder.Text = @"C:\"; } } private void InitializeTimer() { _timer = new DispatcherTimer(); _timer.Interval = TimeSpan.FromSeconds(1); _timer.Tick += (s, e) => txtTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); _timer.Start(); } // Update the code where FolderBrowserDialog is used to ensure compatibility private void BtnBrowseSource_Click(object sender, RoutedEventArgs e) { using (var dialog = new System.Windows.Forms.FolderBrowserDialog()) { dialog.Description = "변환할 DWG 파일이 있는 폴더를 선택하세요"; dialog.ShowNewFolderButton = false; if (!string.IsNullOrEmpty(txtSourceFolder.Text) && Directory.Exists(txtSourceFolder.Text)) { dialog.SelectedPath = txtSourceFolder.Text; } if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { txtSourceFolder.Text = dialog.SelectedPath; LogMessage($"📂 변환할 폴더 선택: {dialog.SelectedPath}"); // 선택한 폴더의 DWG 파일 개수 확인 CheckDwgFiles(dialog.SelectedPath); } } } private void BtnBrowseResult_Click(object sender, RoutedEventArgs e) { using (var dialog = new System.Windows.Forms.FolderBrowserDialog()) { dialog.Description = "결과 파일을 저장할 폴더를 선택하세요"; dialog.ShowNewFolderButton = true; if (!string.IsNullOrEmpty(txtResultFolder.Text) && Directory.Exists(txtResultFolder.Text)) { dialog.SelectedPath = txtResultFolder.Text; } if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { txtResultFolder.Text = dialog.SelectedPath; LogMessage($"💾 결과 저장 폴더 선택: {dialog.SelectedPath}"); } } } private void CheckDwgFiles(string folderPath) { try { var targetDir = new DirectoryInfo(folderPath); var files = targetDir.GetFiles("*.dwg", SearchOption.AllDirectories); txtFileCount.Text = $"파일: {files.Length}개"; if (files.Length > 0) { LogMessage($"✅ 총 {files.Length}개의 DWG 파일을 발견했습니다."); // 처음 몇 개 파일명 로깅 int showCount = Math.Min(5, files.Length); for (int i = 0; i < showCount; i++) { LogMessage($" 📄 {files[i].Name}"); } if (files.Length > 5) { LogMessage($" ... 외 {files.Length - 5}개 파일"); } } else { LogMessage("⚠️ 선택한 폴더에 DWG 파일이 없습니다."); } } catch (Exception ex) { LogMessage($"❌ 폴더 검사 중 오류: {ex.Message}"); } } private async void BtnExtract_Click(object sender, RoutedEventArgs e) { // 입력 유효성 검사 if (string.IsNullOrEmpty(txtSourceFolder.Text) || !Directory.Exists(txtSourceFolder.Text)) { System.Windows.MessageBox.Show("유효한 변환할 폴더를 선택하세요.", "오류", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (string.IsNullOrEmpty(txtResultFolder.Text) || !Directory.Exists(txtResultFolder.Text)) { System.Windows.MessageBox.Show("유효한 결과 저장 폴더를 선택하세요.", "오류", MessageBoxButton.OK, MessageBoxImage.Warning); return; } // 데이터베이스 모드일 때 연결 테스트 if (rbDatabase.IsChecked == true) { LogMessage("🔍 데이터베이스 연결을 확인합니다..."); try { using (var testSql = new SqlDatas()) { if (!testSql.TestConnection()) { System.Windows.MessageBox.Show( "PostgreSQL 데이터베이스에 연결할 수 없습니다.\n\n" + "연결 설정을 확인하고 데이터베이스 서버가 실행 중인지 확인하세요.", "데이터베이스 연결 오류", MessageBoxButton.OK, MessageBoxImage.Error); LogMessage("❌ 데이터베이스 연결 실패"); return; } LogMessage("✅ 데이터베이스 연결 성공"); } } catch (Exception ex) { System.Windows.MessageBox.Show( $"데이터베이스 연결 테스트 중 오류가 발생했습니다:\n\n{ex.Message}", "오류", MessageBoxButton.OK, MessageBoxImage.Error); LogMessage($"❌ 데이터베이스 연결 오류: {ex.Message}"); return; } } // UI 비활성화 btnExtract.IsEnabled = false; btnBrowseSource.IsEnabled = false; btnBrowseResult.IsEnabled = false; rbExcel.IsEnabled = false; rbDatabase.IsEnabled = false; progressBar.Value = 0; UpdateStatus("🚀 추출 작업을 시작합니다..."); LogMessage(new string('=', 50)); // ✅ 정상 작동 LogMessage("🔥 DWG 정보 추출 작업 시작"); LogMessage(new string('=', 50)); // ✅ 정상 작동 try { await ProcessFiles(); } catch (Exception ex) { LogMessage($"❌ 치명적 오류 발생: {ex.Message}"); UpdateStatus("오류가 발생했습니다."); System.Windows.MessageBox.Show($"작업 중 오류가 발생했습니다:\n\n{ex.Message}", "오류", MessageBoxButton.OK, MessageBoxImage.Error); } finally { // UI 활성화 btnExtract.IsEnabled = true; btnBrowseSource.IsEnabled = true; btnBrowseResult.IsEnabled = true; rbExcel.IsEnabled = true; rbDatabase.IsEnabled = true; progressBar.Value = 100; LogMessage(new string('=', 50)); LogMessage("🏁 작업 완료"); LogMessage(new string('=', 50)); // ✅ 정상 작동 } } private async Task ProcessFiles() { var stopwatch = Stopwatch.StartNew(); var targetDir = new DirectoryInfo(txtSourceFolder.Text); var files = targetDir.GetFiles("*.dwg", SearchOption.AllDirectories); if (files.Length == 0) { UpdateStatus("선택한 폴더에 DWG 파일이 없습니다."); System.Windows.MessageBox.Show("선택한 폴더에 DWG 파일이 없습니다.", "정보", MessageBoxButton.OK, MessageBoxImage.Information); return; } UpdateStatus($"총 {files.Length}개의 DWG 파일을 처리합니다..."); LogMessage($"📊 처리할 파일 수: {files.Length}개"); bool isExcelMode = rbExcel.IsChecked == true; string outputMode = isExcelMode ? "Excel" : "PostgreSQL 데이터베이스"; LogMessage($"📋 출력 모드: {outputMode}"); LogMessage($"📂 소스 폴더: {txtSourceFolder.Text}"); LogMessage($"💾 결과 폴더: {txtResultFolder.Text}"); if (isExcelMode) { await ProcessExcelExport(files, stopwatch); } else { await ProcessDatabaseExport(files, stopwatch); } } private async Task ProcessExcelExport(FileInfo[] files, Stopwatch totalStopwatch) { LogMessage("📊 Excel 내보내기 모드로 시작합니다..."); LogMessage("📝 Excel 애플리케이션을 초기화합니다..."); var successCount = 0; var failureCount = 0; var totalProcessingTime = 0.0; try { // ExportExcel 클래스 초기화 _exportExcel = new ExportExcel(); LogMessage("✅ Excel 애플리케이션 초기화 완료"); for (int i = 0; i < files.Length; i++) { var file = files[i]; var fileStopwatch = Stopwatch.StartNew(); UpdateStatus($"처리 중: {file.Name} ({i + 1}/{files.Length})"); LogMessage($"🔄 [{i + 1}/{files.Length}] 처리 중: {file.Name}"); try { // 실제 DWG 처리 로직 var progress = new Progress(value => { // 파일별 진행률을 전체 진행률에 반영 var overallProgress = ((i * 100.0 + value) / files.Length); progressBar.Value = overallProgress; }); bool success = _exportExcel.ExportDwgToExcel(file.FullName, progress); fileStopwatch.Stop(); if (success) { successCount++; totalProcessingTime += fileStopwatch.ElapsedMilliseconds; LogMessage($"✅ {file.Name} 처리 완료 ({fileStopwatch.ElapsedMilliseconds}ms)"); } else { failureCount++; LogMessage($"❌ {file.Name} 처리 실패 ({fileStopwatch.ElapsedMilliseconds}ms)"); } } catch (Exception ex) { failureCount++; fileStopwatch.Stop(); LogMessage($"💥 {file.Name} 처리 중 예외 발생: {ex.Message}"); } // 진행률 업데이트 progressBar.Value = ((i + 1) * 100.0) / files.Length; // UI 응답성을 위한 짧은 지연 await Task.Delay(10); } // Excel 파일 저장 var excelFileName = Path.Combine(txtResultFolder.Text, $"{DateTime.Now:yyyyMMdd_HHmmss}_DwgToExcel.xlsx"); LogMessage("💾 Excel 파일을 저장합니다..."); _exportExcel.SaveAndCloseExcel(excelFileName); LogMessage($"✅ Excel 파일 저장 완료: {Path.GetFileName(excelFileName)}"); } catch (Exception ex) { LogMessage($"❌ Excel 처리 중 치명적 오류: {ex.Message}"); throw; } finally { _exportExcel?.Dispose(); _exportExcel = null; } totalStopwatch.Stop(); UpdateStatus("Excel 내보내기 완료!"); var excelFile = Path.Combine(txtResultFolder.Text, $"{DateTime.Now:yyyyMMdd_HHmmss}_DwgToExcel.xlsx"); LogMessage($"📈 성공: {successCount}개, 실패: {failureCount}개"); LogMessage($"⏱️ 평균 처리 시간: {(successCount > 0 ? totalProcessingTime / successCount : 0):F1}ms"); LogMessage($"🕐 총 소요 시간: {totalStopwatch.ElapsedMilliseconds}ms"); System.Windows.MessageBox.Show( $"Excel 내보내기가 완료되었습니다!\n\n" + $"✅ 성공: {successCount}개\n" + $"❌ 실패: {failureCount}개\n" + $"⏱️ 총 소요시간: {totalStopwatch.Elapsed:mm\\:ss}\n\n" + $"📄 결과 파일이 저장 폴더에 생성되었습니다.", "완료", MessageBoxButton.OK, MessageBoxImage.Information); } private async Task ProcessDatabaseExport(FileInfo[] files, Stopwatch totalStopwatch) { LogMessage("🗄️ 데이터베이스 내보내기 모드로 시작합니다..."); LogMessage("🔗 데이터베이스 연결을 초기화합니다..."); var successCount = 0; var failureCount = 0; var totalProcessingTime = 0.0; try { // SqlDatas 클래스 초기화 _sqlDatas = new SqlDatas(); LogMessage("✅ 데이터베이스 연결 초기화 완료"); for (int i = 0; i < files.Length; i++) { var file = files[i]; var fileStopwatch = Stopwatch.StartNew(); UpdateStatus($"처리 중: {file.Name} ({i + 1}/{files.Length})"); LogMessage($"🔄 [{i + 1}/{files.Length}] 처리 중: {file.Name}"); try { // 실제 DWG 처리 로직 (DwgToDB는 실패시 true 반환) bool failed = _sqlDatas.DwgToDB(file.FullName); bool success = !failed; fileStopwatch.Stop(); if (success) { successCount++; totalProcessingTime += fileStopwatch.ElapsedMilliseconds; LogMessage($"✅ {file.Name} DB 저장 완료 ({fileStopwatch.ElapsedMilliseconds}ms)"); } else { failureCount++; LogMessage($"❌ {file.Name} DB 저장 실패 ({fileStopwatch.ElapsedMilliseconds}ms)"); } } catch (Exception ex) { failureCount++; fileStopwatch.Stop(); LogMessage($"💥 {file.Name} 처리 중 예외 발생: {ex.Message}"); } // 진행률 업데이트 progressBar.Value = ((i + 1) * 100.0) / files.Length; // UI 응답성을 위한 짧은 지연 await Task.Delay(10); } } catch (Exception ex) { LogMessage($"❌ 데이터베이스 처리 중 치명적 오류: {ex.Message}"); throw; } finally { _sqlDatas?.Dispose(); _sqlDatas = null; } totalStopwatch.Stop(); UpdateStatus("데이터베이스 내보내기 완료!"); LogMessage($"🗄️ PostgreSQL 데이터베이스에 저장 완료"); LogMessage($"📈 성공: {successCount}개, 실패: {failureCount}개"); LogMessage($"⏱️ 평균 처리 시간: {(successCount > 0 ? totalProcessingTime / successCount : 0):F1}ms"); LogMessage($"🕐 총 소요 시간: {totalStopwatch.ElapsedMilliseconds}ms"); System.Windows.MessageBox.Show( $"데이터베이스 내보내기가 완료되었습니다!\n\n" + $"✅ 성공: {successCount}개\n" + $"❌ 실패: {failureCount}개\n" + $"⏱️ 총 소요시간: {totalStopwatch.Elapsed:mm\\:ss}\n\n" + $"🗄️ PostgreSQL 데이터베이스에 저장됨", "완료", MessageBoxButton.OK, MessageBoxImage.Information); } private void UpdateStatus(string message) { txtStatus.Text = message; txtStatusBar.Text = message; } private void LogMessage(string message) { var timestamp = DateTime.Now.ToString("HH:mm:ss"); txtLog.AppendText($"[{timestamp}] {message}\n"); txtLog.ScrollToEnd(); } protected override void OnClosed(EventArgs e) { _timer?.Stop(); _exportExcel?.Dispose(); _sqlDatas?.Dispose(); base.OnClosed(e); } } }