261 lines
10 KiB
C#
261 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace DwgExtractorManual.Models
|
|
{
|
|
/// <summary>
|
|
/// Note 데이터를 CSV 파일로 출력하는 클래스
|
|
/// Note Box 안의 일반 텍스트와 테이블 텍스트를 분리하여 CSV로 출력
|
|
/// </summary>
|
|
public class CsvDataWriter
|
|
{
|
|
/// <summary>
|
|
/// Note 박스 안의 일반 텍스트들을 CSV 파일로 저장
|
|
/// </summary>
|
|
public void WriteNoteBoxTextToCsv(List<NoteEntityInfo> noteEntities, string filePath)
|
|
{
|
|
if (noteEntities == null || noteEntities.Count == 0)
|
|
return;
|
|
|
|
var csvLines = new List<string>();
|
|
|
|
// CSV 헤더 추가
|
|
csvLines.Add("Type,Layer,Text,X,Y,SortOrder,Path,FileName");
|
|
|
|
// Note와 NoteContent 데이터 추출 (테이블 제외)
|
|
var noteBoxTexts = noteEntities
|
|
.Where(ne => ne.Type == "Note" || ne.Type == "NoteContent")
|
|
.OrderBy(ne => ne.SortOrder)
|
|
.ToList();
|
|
|
|
foreach (var noteEntity in noteBoxTexts)
|
|
{
|
|
var csvLine = $"{EscapeCsvField(noteEntity.Type)}," +
|
|
$"{EscapeCsvField(noteEntity.Layer)}," +
|
|
$"{EscapeCsvField(noteEntity.Text)}," +
|
|
$"{noteEntity.X:F3}," +
|
|
$"{noteEntity.Y:F3}," +
|
|
$"{noteEntity.SortOrder}," +
|
|
$"{EscapeCsvField(noteEntity.Path)}," +
|
|
$"{EscapeCsvField(noteEntity.FileName)}";
|
|
|
|
csvLines.Add(csvLine);
|
|
}
|
|
|
|
// UTF-8 BOM 포함하여 파일 저장 (Excel에서 한글 깨짐 방지)
|
|
var utf8WithBom = new UTF8Encoding(true);
|
|
File.WriteAllLines(filePath, csvLines, utf8WithBom);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Note 박스 안의 테이블 데이터들을 별도 CSV 파일로 저장
|
|
/// </summary>
|
|
public void WriteNoteTablesToCsv(List<NoteEntityInfo> noteEntities, string filePath)
|
|
{
|
|
if (noteEntities == null || noteEntities.Count == 0)
|
|
return;
|
|
|
|
var allCsvLines = new List<string>();
|
|
|
|
// 테이블 데이터가 있는 Note들 추출
|
|
var notesWithTables = noteEntities
|
|
.Where(ne => ne.Type == "Note" && !string.IsNullOrEmpty(ne.TableCsv))
|
|
.OrderByDescending(ne => ne.Y) // Y 좌표로 정렬 (위에서 아래로)
|
|
.ToList();
|
|
|
|
foreach (var noteWithTable in notesWithTables)
|
|
{
|
|
// Note 정보 헤더 추가
|
|
allCsvLines.Add($"=== NOTE: {noteWithTable.Text} (at {noteWithTable.X:F1}, {noteWithTable.Y:F1}) ===");
|
|
allCsvLines.Add(""); // 빈 줄
|
|
|
|
// 테이블 CSV 데이터 추가
|
|
var tableLines = noteWithTable.TableCsv.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
|
allCsvLines.AddRange(tableLines);
|
|
|
|
// Note 간 구분을 위한 빈 줄들
|
|
allCsvLines.Add("");
|
|
allCsvLines.Add("");
|
|
}
|
|
|
|
// UTF-8 BOM 포함하여 파일 저장
|
|
var utf8WithBom = new UTF8Encoding(true);
|
|
File.WriteAllLines(filePath, allCsvLines, utf8WithBom);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Note 박스와 테이블 데이터를 통합하여 하나의 CSV 파일로 저장
|
|
/// </summary>
|
|
public void WriteNoteDataToCombinedCsv(List<NoteEntityInfo> noteEntities, string filePath)
|
|
{
|
|
if (noteEntities == null || noteEntities.Count == 0)
|
|
return;
|
|
|
|
var csvLines = new List<string>();
|
|
|
|
// CSV 헤더 추가
|
|
csvLines.Add("Type,Layer,Text,X,Y,SortOrder,TableData,Path,FileName");
|
|
|
|
// 모든 Note 관련 데이터를 SortOrder로 정렬
|
|
var sortedNoteEntities = noteEntities
|
|
.OrderBy(ne => ne.SortOrder)
|
|
.ToList();
|
|
|
|
foreach (var noteEntity in sortedNoteEntities)
|
|
{
|
|
// 테이블 데이터가 있는 경우 이를 별도 필드로 처리
|
|
var tableData = "";
|
|
if (noteEntity.Type == "Note" && !string.IsNullOrEmpty(noteEntity.TableCsv))
|
|
{
|
|
// 테이블 CSV 데이터를 하나의 필드로 압축 (줄바꿈을 |로 대체)
|
|
tableData = noteEntity.TableCsv.Replace("\n", "|").Replace("\r", "");
|
|
}
|
|
|
|
var csvLine = $"{EscapeCsvField(noteEntity.Type)}," +
|
|
$"{EscapeCsvField(noteEntity.Layer)}," +
|
|
$"{EscapeCsvField(noteEntity.Text)}," +
|
|
$"{noteEntity.X:F3}," +
|
|
$"{noteEntity.Y:F3}," +
|
|
$"{noteEntity.SortOrder}," +
|
|
$"{EscapeCsvField(tableData)}," +
|
|
$"{EscapeCsvField(noteEntity.Path)}," +
|
|
$"{EscapeCsvField(noteEntity.FileName)}";
|
|
|
|
csvLines.Add(csvLine);
|
|
}
|
|
|
|
// UTF-8 BOM 포함하여 파일 저장
|
|
var utf8WithBom = new UTF8Encoding(true);
|
|
File.WriteAllLines(filePath, csvLines, utf8WithBom);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 각 Note별로 개별 CSV 파일 생성 (테이블이 있는 경우)
|
|
/// </summary>
|
|
public void WriteIndividualNoteTablesCsv(List<NoteEntityInfo> noteEntities, string baseDirectory)
|
|
{
|
|
if (noteEntities == null || noteEntities.Count == 0)
|
|
return;
|
|
|
|
// 디렉토리가 없으면 생성
|
|
if (!Directory.Exists(baseDirectory))
|
|
{
|
|
Directory.CreateDirectory(baseDirectory);
|
|
}
|
|
|
|
var notesWithTables = noteEntities
|
|
.Where(ne => ne.Type == "Note" && !string.IsNullOrEmpty(ne.TableCsv))
|
|
.OrderByDescending(ne => ne.Y)
|
|
.ToList();
|
|
|
|
int noteIndex = 1;
|
|
foreach (var noteWithTable in notesWithTables)
|
|
{
|
|
// 파일명 생성 (특수문자 제거)
|
|
var safeNoteText = MakeSafeFileName(noteWithTable.Text);
|
|
var fileName = $"Note_{noteIndex:D2}_{safeNoteText}.csv";
|
|
var fullPath = Path.Combine(baseDirectory, fileName);
|
|
|
|
// 테이블 CSV 데이터를 파일로 저장
|
|
var tableLines = noteWithTable.TableCsv.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
var utf8WithBom = new UTF8Encoding(true);
|
|
File.WriteAllLines(fullPath, tableLines, utf8WithBom);
|
|
|
|
noteIndex++;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// CSV 필드에서 특수문자를 이스케이프 처리
|
|
/// </summary>
|
|
private string EscapeCsvField(string field)
|
|
{
|
|
if (string.IsNullOrEmpty(field))
|
|
return "";
|
|
|
|
// 쉼표, 따옴표, 줄바꿈이 있으면 따옴표로 감싸기
|
|
if (field.Contains(",") || field.Contains("\"") || field.Contains("\n") || field.Contains("\r"))
|
|
{
|
|
return "\"" + field.Replace("\"", "\"\"") + "\"";
|
|
}
|
|
|
|
return field;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파일명에 사용할 수 없는 문자들을 제거하여 안전한 파일명 생성
|
|
/// </summary>
|
|
private string MakeSafeFileName(string fileName)
|
|
{
|
|
if (string.IsNullOrEmpty(fileName))
|
|
return "Unknown";
|
|
|
|
var invalidChars = Path.GetInvalidFileNameChars();
|
|
var safeFileName = fileName;
|
|
|
|
foreach (var invalidChar in invalidChars)
|
|
{
|
|
safeFileName = safeFileName.Replace(invalidChar, '_');
|
|
}
|
|
|
|
// 길이 제한 (Windows 파일명 제한 고려)
|
|
if (safeFileName.Length > 50)
|
|
{
|
|
safeFileName = safeFileName.Substring(0, 50);
|
|
}
|
|
|
|
return safeFileName.Trim();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Note 데이터 통계 정보를 CSV로 저장
|
|
/// </summary>
|
|
public void WriteNoteStatisticsToCsv(List<NoteEntityInfo> noteEntities, string filePath)
|
|
{
|
|
if (noteEntities == null || noteEntities.Count == 0)
|
|
return;
|
|
|
|
var csvLines = new List<string>();
|
|
|
|
// 통계 헤더
|
|
csvLines.Add("Statistic,Count,Details");
|
|
|
|
// 전체 Note 개수
|
|
var totalNotes = noteEntities.Count(ne => ne.Type == "Note");
|
|
csvLines.Add($"Total Notes,{totalNotes},");
|
|
|
|
// 테이블이 있는 Note 개수
|
|
var notesWithTables = noteEntities.Count(ne => ne.Type == "Note" && !string.IsNullOrEmpty(ne.TableCsv));
|
|
csvLines.Add($"Notes with Tables,{notesWithTables},");
|
|
|
|
// 일반 텍스트만 있는 Note 개수
|
|
var notesWithTextOnly = totalNotes - notesWithTables;
|
|
csvLines.Add($"Notes with Text Only,{notesWithTextOnly},");
|
|
|
|
// 전체 Note 콘텐츠 개수
|
|
var totalNoteContents = noteEntities.Count(ne => ne.Type == "NoteContent");
|
|
csvLines.Add($"Total Note Contents,{totalNoteContents},");
|
|
|
|
// 레이어별 분포
|
|
csvLines.Add(",,");
|
|
csvLines.Add("Layer Distribution,,");
|
|
|
|
var layerGroups = noteEntities
|
|
.GroupBy(ne => ne.Layer)
|
|
.OrderByDescending(g => g.Count())
|
|
.ToList();
|
|
|
|
foreach (var layerGroup in layerGroups)
|
|
{
|
|
csvLines.Add($"Layer: {layerGroup.Key},{layerGroup.Count()},");
|
|
}
|
|
|
|
var utf8WithBom = new UTF8Encoding(true);
|
|
File.WriteAllLines(filePath, csvLines, utf8WithBom);
|
|
}
|
|
}
|
|
} |