using Microsoft.Extensions.Logging; using SQLVision.Core.Interfaces; using SQLVision.Core.Models; using SQLVision.Services.Exporters; using System.Data; namespace SQLVision.Services.Services; public class ExportService : IExportService { private readonly ILogger _logger; private readonly Dictionary _exportHandlers; public ExportService( ILogger logger, IEnumerable exportHandlers) { _logger = logger; _exportHandlers = exportHandlers.ToDictionary(h => h.FormatName, h => h); } public async Task ExportAsync(DataTable data, string filePath, ExportOptions options) { if (data == null) throw new ArgumentNullException(nameof(data)); var extension = Path.GetExtension(filePath).TrimStart('.').ToLower(); var format = options?.Format ?? GetFormatFromExtension(extension); if (_exportHandlers.TryGetValue(format, out var handler)) { try { await handler.ExportAsync(data, filePath, options ?? new ExportOptions()); _logger.LogInformation("Exported {Rows} rows to {FilePath} as {Format}", data.Rows.Count, filePath, format); } catch (Exception ex) { _logger.LogError(ex, "Error exporting to {Format}", format); throw; } } else { throw new NotSupportedException($"Export format '{format}' is not supported"); } } public async Task ExportAsync(DataSet dataSet, string filePath, ExportOptions options) { if (dataSet.Tables.Count == 0) throw new InvalidOperationException("DataSet contains no tables"); if (dataSet.Tables.Count == 1) { await ExportAsync(dataSet.Tables[0], filePath, options); } else { // Для Excel создаем несколько листов var extension = Path.GetExtension(filePath); if (extension.Equals(".xlsx", StringComparison.OrdinalIgnoreCase)) { await ExportToMultiSheetExcel(dataSet, filePath, options); } else { // Для других форматов - экспортируем каждый лист в отдельный файл var basePath = Path.Combine(Path.GetDirectoryName(filePath)!, Path.GetFileNameWithoutExtension(filePath)); for (int i = 0; i < dataSet.Tables.Count; i++) { var table = dataSet.Tables[i]; var tableFilePath = $"{basePath}_{table.TableName}_{i + 1}{extension}"; await ExportAsync(table, tableFilePath, options); } } } } public async Task ExportToMemoryAsync(DataTable data, ExportOptions options) { var format = options?.Format ?? "Excel"; if (_exportHandlers.TryGetValue(format, out var handler)) { return await handler.ExportToMemoryAsync(data, options ?? new ExportOptions()); } throw new NotSupportedException($"Export format '{format}' is not supported"); } private async Task ExportToMultiSheetExcel(DataSet dataSet, string filePath, ExportOptions options) { using var workbook = new ClosedXML.Excel.XLWorkbook(); for (int i = 0; i < dataSet.Tables.Count; i++) { var table = dataSet.Tables[i]; var worksheet = workbook.Worksheets.Add(table.TableName ?? $"Sheet{i + 1}"); // Используем ExcelExporter для записи данных if (_exportHandlers.TryGetValue("Excel", out var excelHandler) && excelHandler is ExcelExporter excelExporter) { var excelOptions = options ?? new ExportOptions(); await excelExporter.ExportAsync(table, filePath, excelOptions); } } await Task.Run(() => workbook.SaveAs(filePath)); } private string GetFormatFromExtension(string extension) => extension switch { "xlsx" => "Excel", "csv" => "CSV", "json" => "JSON", _ => "Excel" }; }