Height sort, 한 파일에
This commit is contained in:
@@ -193,6 +193,23 @@
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<Button x:Name="btnDwgHeightSort"
|
||||
Content="📏 DWG추출(Height정렬)" Width="150" Height="45"
|
||||
Margin="5,0"
|
||||
Click="BtnDwgHeightSort_Click" FontSize="14" FontWeight="Bold"
|
||||
Background="#FF6B35" Foreground="White"
|
||||
BorderThickness="0">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="#FF6B35"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#E55A2B"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
@@ -1733,6 +1733,88 @@ namespace DwgExtractorManual
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DWG 추출 (Height 정렬) 버튼 클릭 이벤트
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 폴더에서 리프 폴더들(하위 폴더가 없는 폴더)을 재귀적으로 찾습니다.
|
||||
/// </summary>
|
||||
@@ -1935,6 +2017,114 @@ namespace DwgExtractorManual
|
||||
UpdateStatus("✅ DWG 전용 추출 완료");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DWG Height 정렬 처리를 위한 리프 폴더 처리
|
||||
/// </summary>
|
||||
/// <param name="leafFolders">처리할 리프 폴더 목록</param>
|
||||
/// <param name="resultBaseFolder">결과 저장 기본 폴더</param>
|
||||
private async Task ProcessLeafFoldersDwgHeightSort(List<string> 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 정렬 추출 완료");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 DWG 파일을 단일 Excel 파일에서 Height 정렬하여 처리합니다.
|
||||
/// </summary>
|
||||
/// <param name="allDwgFiles">모든 DWG 파일 정보 (파일경로, 폴더명)</param>
|
||||
/// <param name="resultFolder">결과 폴더</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 폴더에서 DWG 파일들만 처리합니다.
|
||||
/// </summary>
|
||||
@@ -2044,6 +2234,104 @@ namespace DwgExtractorManual
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 지정된 폴더에서 DWG 파일들을 Height 정렬하여 처리합니다.
|
||||
/// </summary>
|
||||
/// <param name="sourceFolderPath">처리할 폴더 경로</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DWG Height 정렬 Excel 파일을 목표 경로로 이름 변경
|
||||
/// </summary>
|
||||
/// <param name="resultFolder">결과 폴더</param>
|
||||
/// <param name="leafFolderPath">리프 폴더 경로</param>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 최신 Excel 파일을 목표 경로로 이름 변경
|
||||
/// </summary>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DWG 파일들을 처리하여 각 파일별로 시트를 생성하고 Height 순으로 정렬된 Excel 파일을 생성합니다.
|
||||
/// </summary>
|
||||
/// <param name="dwgFiles">처리할 DWG 파일 경로 배열</param>
|
||||
/// <param name="resultFolder">결과 파일 저장 폴더</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DWG 파일에서 텍스트 엔티티들을 추출하여 Height 정보와 함께 반환합니다.
|
||||
/// </summary>
|
||||
/// <param name="filePath">DWG 파일 경로</param>
|
||||
/// <returns>텍스트 엔티티 정보 리스트</returns>
|
||||
private List<TextEntityInfo> ExtractTextEntitiesWithHeight(string filePath)
|
||||
{
|
||||
var textEntities = new List<TextEntityInfo>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 모든 DWG 파일들을 하나의 Excel 파일로 처리하여 각 파일별로 시트를 생성하고 Height 순으로 정렬합니다.
|
||||
/// </summary>
|
||||
/// <param name="allDwgFiles">처리할 DWG 파일 리스트 (파일경로, 폴더명)</param>
|
||||
/// <param name="savePath">결과 Excel 파일 저장 경로</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Excel 시트명으로 사용할 수 있는 유효한 이름을 생성합니다.
|
||||
/// </summary>
|
||||
/// <param name="originalName">원본 파일명</param>
|
||||
/// <returns>유효한 시트명</returns>
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 텍스트 엔티티 정보를 담는 클래스
|
||||
/// </summary>
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user