47 lines
1.7 KiB
C#
47 lines
1.7 KiB
C#
using System.Globalization;
|
|
using System.Text;
|
|
|
|
namespace General_Ledger_Service.Services.CsvDocuments
|
|
{
|
|
// Shared row-building/escaping helper for every report's CSV writer (05_LKAS_Report_PDF_Templates.md
|
|
// Section 10) - parallel to Services/PdfDocuments/ReportPageHeader.cs, one small shared piece
|
|
// reused by seven otherwise-independent writer classes, not a base class (CLAUDE.md Rule 2).
|
|
public class CsvBuilder
|
|
{
|
|
private readonly StringBuilder _sb = new();
|
|
|
|
public CsvBuilder AddRow(params object?[] values)
|
|
{
|
|
_sb.AppendLine(string.Join(",", values.Select(Escape)));
|
|
return this;
|
|
}
|
|
|
|
public byte[] Build()
|
|
{
|
|
// UTF-8 BOM so Excel (the realistic consumer of a downloaded .csv) recognizes the
|
|
// encoding instead of guessing at a locale-default codepage.
|
|
var preamble = Encoding.UTF8.GetPreamble();
|
|
var body = Encoding.UTF8.GetBytes(_sb.ToString());
|
|
var result = new byte[preamble.Length + body.Length];
|
|
preamble.CopyTo(result, 0);
|
|
body.CopyTo(result, preamble.Length);
|
|
return result;
|
|
}
|
|
|
|
private static string Escape(object? value)
|
|
{
|
|
var text = value switch
|
|
{
|
|
null => "",
|
|
decimal d => d.ToString(CultureInfo.InvariantCulture),
|
|
DateOnly d => d.ToString("yyyy-MM-dd"),
|
|
_ => value.ToString() ?? ""
|
|
};
|
|
|
|
return text.Contains(',') || text.Contains('"') || text.Contains('\n')
|
|
? $"\"{text.Replace("\"", "\"\"")}\""
|
|
: text;
|
|
}
|
|
}
|
|
}
|