using SharepointToolbox.Core.Models; using System.IO; using System.Text; namespace SharepointToolbox.Services.Export; /// /// Exports a flat list of StorageNode objects to a UTF-8 BOM CSV. /// Compatible with Microsoft Excel (BOM signals UTF-8 encoding). /// public class StorageCsvExportService { public string BuildCsv(IReadOnlyList nodes) { var sb = new StringBuilder(); // Header sb.AppendLine("Library,Site,Files,Total Size (MB),Version Size (MB),Last Modified"); foreach (var node in nodes) { sb.AppendLine(string.Join(",", Csv(node.Name), Csv(node.SiteTitle), node.TotalFileCount.ToString(), FormatMb(node.TotalSizeBytes), FormatMb(node.VersionSizeBytes), node.LastModified.HasValue ? Csv(node.LastModified.Value.ToString("yyyy-MM-dd")) : string.Empty)); } return sb.ToString(); } public async Task WriteAsync(IReadOnlyList nodes, string filePath, CancellationToken ct) { var csv = BuildCsv(nodes); // UTF-8 with BOM for Excel compatibility await File.WriteAllTextAsync(filePath, csv, new UTF8Encoding(encoderShouldEmitUTF8Identifier: true), ct); } // ── Helpers ─────────────────────────────────────────────────────────────── private static string FormatMb(long bytes) => (bytes / (1024.0 * 1024.0)).ToString("F2"); /// RFC 4180 CSV field quoting. private static string Csv(string value) { if (string.IsNullOrEmpty(value)) return string.Empty; if (value.Contains(',') || value.Contains('"') || value.Contains('\n')) return $"\"{value.Replace("\"", "\"\"")}\""; return value; } }