Files
manual_wpf/MainWindow.xaml.cs
2025-07-16 17:40:50 +09:00

454 lines
18 KiB
C#

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<double>(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);
}
}
}