Files
SQLVision/SQLVision.Services/Services/ExportService.cs
2026-01-05 00:37:54 +03:00

122 lines
4.3 KiB
C#

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<ExportService> _logger;
private readonly Dictionary<string, IExportHandler> _exportHandlers;
public ExportService(
ILogger<ExportService> logger,
IEnumerable<IExportHandler> 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<byte[]> 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"
};
}