438 lines
18 KiB
C#
438 lines
18 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Teigha.Runtime;
|
|
|
|
namespace DwgExtractorManual.Models
|
|
{
|
|
/// <summary>
|
|
/// DWG 파일에서 Excel로 데이터 내보내기 메인 클래스
|
|
/// 리팩토링된 구조로 각 기능별 클래스를 조합하여 사용
|
|
/// </summary>
|
|
internal class ExportExcel : IDisposable
|
|
{
|
|
// 컴포넌트들
|
|
private readonly ExcelManager excelManager;
|
|
public readonly DwgDataExtractor DwgExtractor;
|
|
private readonly JsonDataProcessor jsonProcessor;
|
|
private readonly ExcelDataWriter excelWriter;
|
|
private readonly FieldMapper fieldMapper;
|
|
|
|
// ODA 서비스 관리
|
|
private Services? appServices;
|
|
|
|
// 매핑 데이터 저장용
|
|
private Dictionary<string, Dictionary<string, (string, string, string, string)>> FileToMapkeyToLabelTagValuePdf
|
|
= new Dictionary<string, Dictionary<string, (string, string, string, string)>>();
|
|
|
|
readonly List<string>? MapKeys;
|
|
|
|
/// <summary>
|
|
/// 생성자: 모든 컴포넌트 초기화
|
|
/// </summary>
|
|
public ExportExcel()
|
|
{
|
|
try
|
|
{
|
|
Debug.WriteLine("🔄 FieldMapper 로딩 중: mapping_table_json.json...");
|
|
fieldMapper = FieldMapper.LoadFromFile("fletimageanalysis/mapping_table_json.json");
|
|
Debug.WriteLine("✅ FieldMapper 로딩 성공");
|
|
MapKeys = fieldMapper.GetAllDocAiKeys() ?? new List<string>();
|
|
Debug.WriteLine($"📊 총 DocAI 키 개수: {MapKeys?.Count ?? 0}");
|
|
|
|
// 매핑 테스트 (디버깅용)
|
|
TestFieldMapper();
|
|
|
|
Debug.WriteLine("🔄 ODA 초기화 중...");
|
|
InitializeTeighaServices();
|
|
|
|
// 컴포넌트들 초기화
|
|
excelManager = new ExcelManager();
|
|
DwgExtractor = new DwgDataExtractor(fieldMapper);
|
|
jsonProcessor = new JsonDataProcessor();
|
|
excelWriter = new ExcelDataWriter(excelManager);
|
|
|
|
Debug.WriteLine("🔄 Excel 초기화 중...");
|
|
excelManager.InitializeExcel();
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ ExportExcel 초기화 오류: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 단일 DWG 파일에서 데이터를 추출하여 Excel에 추가
|
|
/// </summary>
|
|
public bool ExportDwgToExcel(string filePath, IProgress<double>? progress = null, CancellationToken cancellationToken = default)
|
|
{
|
|
Debug.WriteLine($"[DEBUG] ExportDwgToExcel 시작: {filePath}");
|
|
|
|
if (excelManager.ExcelApplication == null)
|
|
{
|
|
Debug.WriteLine("❌ Excel이 초기화되지 않았습니다.");
|
|
return false;
|
|
}
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
Debug.WriteLine($"❌ 파일이 존재하지 않습니다: {filePath}");
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
// DWG 데이터 추출
|
|
var extractionResult = DwgExtractor.ExtractFromDwgFile(filePath, progress, cancellationToken);
|
|
|
|
if (extractionResult == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Excel에 데이터 기록
|
|
excelWriter.WriteTitleBlockData(extractionResult.TitleBlockRows);
|
|
excelWriter.WriteTextEntityData(extractionResult.TextEntityRows);
|
|
|
|
// 매핑 데이터 병합
|
|
foreach (var fileEntry in extractionResult.FileToMapkeyToLabelTagValuePdf)
|
|
{
|
|
if (!FileToMapkeyToLabelTagValuePdf.ContainsKey(fileEntry.Key))
|
|
{
|
|
FileToMapkeyToLabelTagValuePdf[fileEntry.Key] = new Dictionary<string, (string, string, string, string)>();
|
|
}
|
|
|
|
foreach (var mapEntry in fileEntry.Value)
|
|
{
|
|
FileToMapkeyToLabelTagValuePdf[fileEntry.Key][mapEntry.Key] = mapEntry.Value;
|
|
}
|
|
}
|
|
|
|
// 매핑 데이터를 Excel에 기록
|
|
excelWriter.WriteMappingDataToExcel(FileToMapkeyToLabelTagValuePdf);
|
|
|
|
return true;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ ExportDwgToExcel 오류: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 기존 Excel 파일을 열어 JSON 파일의 PDF 분석 결과로 업데이트
|
|
/// </summary>
|
|
public bool UpdateExistingExcelWithJson(string excelFilePath, string jsonFilePath)
|
|
{
|
|
try
|
|
{
|
|
Debug.WriteLine($"[DEBUG] 기존 Excel 파일 업데이트 시작: {excelFilePath}");
|
|
|
|
if (!excelManager.OpenExistingFile(excelFilePath))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Debug.WriteLine("✅ 기존 Excel 파일 열기 성공");
|
|
return UpdateMappingSheetFromJson(jsonFilePath);
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ 기존 Excel 파일 업데이트 중 오류: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// JSON 파일에서 PDF 분석 결과를 읽어 Excel 매핑 시트 업데이트
|
|
/// </summary>
|
|
public bool UpdateMappingSheetFromJson(string jsonFilePath)
|
|
{
|
|
if (!File.Exists(jsonFilePath))
|
|
{
|
|
Debug.WriteLine($"❌ JSON 파일이 존재하지 않습니다: {jsonFilePath}");
|
|
return false;
|
|
}
|
|
|
|
// JSON 처리를 통해 매핑 데이터를 업데이트하고, Excel에 반영
|
|
return jsonProcessor.UpdateMappingDataFromJson(FileToMapkeyToLabelTagValuePdf, jsonFilePath) &&
|
|
UpdateExcelFromMappingData();
|
|
}
|
|
|
|
/// <summary>
|
|
/// DWG 파일들을 처리하여 Height 순으로 정렬된 Excel 파일 생성
|
|
/// </summary>
|
|
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");
|
|
|
|
var heightSortedWorkbook = excelManager.CreateNewWorkbook();
|
|
bool firstSheetProcessed = false;
|
|
|
|
foreach (string dwgFile in dwgFiles)
|
|
{
|
|
if (!File.Exists(dwgFile))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string fileName = Path.GetFileNameWithoutExtension(dwgFile);
|
|
|
|
try
|
|
{
|
|
Microsoft.Office.Interop.Excel.Worksheet worksheet = firstSheetProcessed ?
|
|
(Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets.Add() :
|
|
(Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1];
|
|
|
|
worksheet.Name = excelManager.GetValidSheetName(fileName);
|
|
firstSheetProcessed = true;
|
|
|
|
var textEntities = DwgExtractor.ExtractTextEntitiesWithHeight(dwgFile);
|
|
excelWriter.WriteHeightSortedData(textEntities, worksheet, fileName);
|
|
|
|
Debug.WriteLine($"[DEBUG] {fileName} 시트 완료: {textEntities.Count}개 엔티티");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ {fileName} 처리 중 오류: {ex.Message}");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!firstSheetProcessed)
|
|
{
|
|
Microsoft.Office.Interop.Excel.Worksheet defaultSheet = (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1];
|
|
defaultSheet.Name = "No_DWG_Files";
|
|
defaultSheet.Cells[1, 1] = "No DWG files found in this folder";
|
|
}
|
|
|
|
excelManager.SaveWorkbookAs(heightSortedWorkbook, savePath);
|
|
heightSortedWorkbook.Close(false);
|
|
|
|
Debug.WriteLine($"✅ Height 정렬 Excel 파일 저장 완료: {Path.GetFileName(savePath)}");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ Height 정렬 Excel 생성 중 오류: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 모든 DWG 파일들을 하나의 Excel 파일로 처리하여 Height 순으로 정렬
|
|
/// </summary>
|
|
public void ExportAllDwgToExcelHeightSorted(List<(string filePath, string folderName)> allDwgFiles, string savePath)
|
|
{
|
|
try
|
|
{
|
|
Debug.WriteLine($"[DEBUG] 단일 Excel 파일로 Height 정렬 생성 시작: {allDwgFiles.Count}개 파일");
|
|
|
|
// 시각화 데이터 초기화
|
|
MainWindow.ClearVisualizationData();
|
|
Debug.WriteLine("[VISUALIZATION] 시각화 데이터 초기화 완료");
|
|
|
|
var heightSortedWorkbook = excelManager.CreateNewWorkbook();
|
|
bool firstSheetProcessed = false;
|
|
|
|
foreach (var (filePath, folderName) in allDwgFiles)
|
|
{
|
|
if (!File.Exists(filePath))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
|
|
|
try
|
|
{
|
|
Microsoft.Office.Interop.Excel.Worksheet worksheet = firstSheetProcessed ?
|
|
(Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets.Add() :
|
|
(Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1];
|
|
|
|
worksheet.Name = excelManager.GetValidSheetName(fileName);
|
|
firstSheetProcessed = true;
|
|
|
|
var textEntities = DwgExtractor.ExtractTextEntitiesWithHeight(filePath);
|
|
excelWriter.WriteHeightSortedData(textEntities, worksheet, fileName);
|
|
|
|
// Note 엔티티 추출 및 기록
|
|
var noteEntities = DwgExtractor.ExtractNotesFromDrawing(filePath);
|
|
if (noteEntities.NoteEntities.Count > 0)
|
|
{
|
|
excelWriter.WriteNoteEntities(noteEntities.NoteEntities, worksheet, fileName);
|
|
Debug.WriteLine($"[DEBUG] {fileName}: {noteEntities.NoteEntities.Count}개 Note 엔티티 추가됨");
|
|
}
|
|
|
|
Debug.WriteLine($"[DEBUG] {fileName} 시트 완료: {textEntities.Count}개 엔티티");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ {fileName} 처리 중 오류: {ex.Message}");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!firstSheetProcessed)
|
|
{
|
|
Microsoft.Office.Interop.Excel.Worksheet defaultSheet = (Microsoft.Office.Interop.Excel.Worksheet)heightSortedWorkbook.Worksheets[1];
|
|
defaultSheet.Name = "No_DWG_Files";
|
|
defaultSheet.Cells[1, 1] = "No DWG files found in any folder";
|
|
}
|
|
|
|
excelManager.SaveWorkbookAs(heightSortedWorkbook, savePath);
|
|
heightSortedWorkbook.Close(false);
|
|
|
|
Debug.WriteLine($"✅ 단일 Height 정렬 Excel 파일 저장 완료: {Path.GetFileName(savePath)}");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ 단일 Height 정렬 Excel 생성 중 오류: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
// Helper methods and legacy support methods
|
|
public bool SaveExcel() => excelManager.SaveWorkbook();
|
|
|
|
public void SaveMappingWorkbookOnly(string savePath) => excelManager.SaveWorkbookAs(excelManager.MappingWorkbook, savePath);
|
|
|
|
public void SaveDwgOnlyMappingWorkbook(string resultFolderPath) => excelWriter.SaveDwgOnlyMappingWorkbook(FileToMapkeyToLabelTagValuePdf, resultFolderPath);
|
|
|
|
public void SaveAndCloseExcel(string savePath)
|
|
{
|
|
try
|
|
{
|
|
excelManager.SaveWorkbookAs(excelManager.TitleBlockWorkbook, savePath);
|
|
|
|
if (excelManager.MappingWorkbook != null)
|
|
{
|
|
string directory = Path.GetDirectoryName(savePath) ?? "";
|
|
string mappingPath = Path.Combine(directory, Path.GetFileNameWithoutExtension(savePath) + "_Mapping.xlsx");
|
|
excelManager.SaveWorkbookAs(excelManager.MappingWorkbook, mappingPath);
|
|
}
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"Excel 파일 저장 중 오류 발생: {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
excelManager.CloseWorkbooks();
|
|
}
|
|
}
|
|
|
|
public void CloseExcelObjectsWithoutSaving() => excelManager.CloseWorkbooks();
|
|
|
|
public void SaveMappingDictionary(string filePath) => jsonProcessor.SaveMappingDictionary(FileToMapkeyToLabelTagValuePdf, filePath);
|
|
|
|
public void LoadMappingDictionary(string filePath)
|
|
{
|
|
FileToMapkeyToLabelTagValuePdf = jsonProcessor.LoadMappingDictionary(filePath);
|
|
}
|
|
|
|
public void WriteCompleteMapping() => excelWriter.WriteMappingDataToExcel(FileToMapkeyToLabelTagValuePdf);
|
|
|
|
public void UpdateWithPdfData(string jsonFilePath) => jsonProcessor.UpdateMappingDataFromJson(FileToMapkeyToLabelTagValuePdf, jsonFilePath);
|
|
|
|
public void ClearAccumulatedData() => FileToMapkeyToLabelTagValuePdf.Clear();
|
|
|
|
// Private helper methods
|
|
private void TestFieldMapper()
|
|
{
|
|
Debug.WriteLine("[DEBUG] Testing field mapper...");
|
|
var testFields = new[] { "TD_DNAME_MAIN", "TD_DWGNO", "TD_DWGCODE", "TB_MTITIL" };
|
|
|
|
foreach (var field in testFields)
|
|
{
|
|
var aiLabel = fieldMapper.ExpresswayToAilabel(field);
|
|
var docAiKey = fieldMapper.AilabelToDocAiKey(aiLabel);
|
|
Debug.WriteLine($"[DEBUG] Field: {field} -> AILabel: {aiLabel} -> DocAiKey: {docAiKey}");
|
|
}
|
|
}
|
|
|
|
private void InitializeTeighaServices()
|
|
{
|
|
try
|
|
{
|
|
Debug.WriteLine("[DEBUG] TeighaServicesManager를 통한 Services 획득 중...");
|
|
appServices = TeighaServicesManager.Instance.AcquireServices();
|
|
Debug.WriteLine($"[DEBUG] Services 획득 성공. Reference Count: {TeighaServicesManager.Instance.ReferenceCount}");
|
|
}
|
|
catch (Teigha.Runtime.Exception ex)
|
|
{
|
|
Debug.WriteLine($"[DEBUG] Teigha Services 초기화 실패: {ex.Message}");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private bool UpdateExcelFromMappingData()
|
|
{
|
|
try
|
|
{
|
|
foreach (var fileEntry in FileToMapkeyToLabelTagValuePdf)
|
|
{
|
|
foreach (var mapEntry in fileEntry.Value)
|
|
{
|
|
var (aiLabel, dwgTag, dwgValue, pdfValue) = mapEntry.Value;
|
|
if (!string.IsNullOrEmpty(pdfValue))
|
|
{
|
|
excelWriter.UpdateExcelRow(fileEntry.Key, aiLabel, pdfValue);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"❌ Excel 업데이트 중 오류: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try
|
|
{
|
|
Debug.WriteLine("[DEBUG] ExportExcel Dispose 시작");
|
|
|
|
excelManager?.Dispose();
|
|
|
|
if (appServices != null)
|
|
{
|
|
Debug.WriteLine("[DEBUG] Teigha Services 해제 중...");
|
|
try
|
|
{
|
|
TeighaServicesManager.Instance.ReleaseServices();
|
|
Debug.WriteLine($"[DEBUG] Teigha Services 해제 완료. Remaining ref count: {TeighaServicesManager.Instance.ReferenceCount}");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"[DEBUG] Teigha Services 해제 중 오류 (무시됨): {ex.Message}");
|
|
}
|
|
finally
|
|
{
|
|
appServices = null;
|
|
}
|
|
}
|
|
|
|
Debug.WriteLine("[DEBUG] ExportExcel Dispose 완료");
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.WriteLine($"[DEBUG] ExportExcel Dispose 중 전역 오류: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
}
|