Height sort, 한 파일에

This commit is contained in:
2025-07-28 11:20:21 +09:00
parent 9b94b59c49
commit 8bd5d9580c
3 changed files with 706 additions and 0 deletions

View File

@@ -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; }
}
}