Добавьте файлы проекта.
This commit is contained in:
86
SQLVision.Services/Exporters/CsvExporter.cs
Normal file
86
SQLVision.Services/Exporters/CsvExporter.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using CsvHelper;
|
||||
using CsvHelper.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SQLVision.Core.Models;
|
||||
using System.Data;
|
||||
|
||||
namespace SQLVision.Services.Exporters;
|
||||
|
||||
public class CsvExporter : IExportHandler
|
||||
{
|
||||
private readonly ILogger<CsvExporter> _logger;
|
||||
|
||||
public string FormatName => "CSV";
|
||||
|
||||
public CsvExporter(ILogger<CsvExporter> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task ExportAsync(DataTable data, string filePath, ExportOptions options)
|
||||
{
|
||||
var config = new CsvConfiguration(System.Globalization.CultureInfo.CurrentCulture)
|
||||
{
|
||||
Delimiter = options.CustomOptions.TryGetValue("Delimiter", out var delimiter)
|
||||
? delimiter.ToString() ?? ","
|
||||
: ","
|
||||
};
|
||||
|
||||
using var writer = new StreamWriter(filePath);
|
||||
using var csv = new CsvWriter(writer, config);
|
||||
|
||||
// Запись заголовков
|
||||
if (options.IncludeHeaders)
|
||||
{
|
||||
foreach (DataColumn column in data.Columns)
|
||||
{
|
||||
csv.WriteField(column.ColumnName);
|
||||
}
|
||||
csv.NextRecord();
|
||||
}
|
||||
|
||||
// Запись данных
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
for (int i = 0; i < data.Columns.Count; i++)
|
||||
{
|
||||
csv.WriteField(row[i]);
|
||||
}
|
||||
csv.NextRecord();
|
||||
}
|
||||
|
||||
await csv.FlushAsync();
|
||||
_logger.LogInformation("Exported {Rows} rows to CSV: {FilePath}", data.Rows.Count, filePath);
|
||||
}
|
||||
|
||||
public async Task<byte[]> ExportToMemoryAsync(DataTable data, ExportOptions options)
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using var writer = new StreamWriter(stream);
|
||||
using var csv = new CsvWriter(writer, System.Globalization.CultureInfo.CurrentCulture);
|
||||
|
||||
// Запись заголовков
|
||||
if (options.IncludeHeaders)
|
||||
{
|
||||
foreach (DataColumn column in data.Columns)
|
||||
{
|
||||
csv.WriteField(column.ColumnName);
|
||||
}
|
||||
csv.NextRecord();
|
||||
}
|
||||
|
||||
// Запись данных
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
for (int i = 0; i < data.Columns.Count; i++)
|
||||
{
|
||||
csv.WriteField(row[i]);
|
||||
}
|
||||
csv.NextRecord();
|
||||
}
|
||||
|
||||
await csv.FlushAsync();
|
||||
await writer.FlushAsync();
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
139
SQLVision.Services/Exporters/ExcelExporter.cs
Normal file
139
SQLVision.Services/Exporters/ExcelExporter.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using ClosedXML.Excel;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SQLVision.Core.Models;
|
||||
using System.Data;
|
||||
|
||||
namespace SQLVision.Services.Exporters;
|
||||
|
||||
public class ExcelExporter : IExportHandler
|
||||
{
|
||||
private readonly ILogger<ExcelExporter> _logger;
|
||||
|
||||
public string FormatName => "Excel";
|
||||
|
||||
public ExcelExporter(ILogger<ExcelExporter> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task ExportAsync(DataTable data, string filePath, ExportOptions options)
|
||||
{
|
||||
using var workbook = new XLWorkbook();
|
||||
var worksheet = workbook.Worksheets.Add("Data");
|
||||
|
||||
WriteDataToWorksheet(worksheet, data, options);
|
||||
|
||||
if (options.IncludeCharts && data.Rows.Count > 0)
|
||||
{
|
||||
AddCharts(worksheet, data, options);
|
||||
}
|
||||
|
||||
await Task.Run(() => workbook.SaveAs(filePath));
|
||||
_logger.LogInformation("Exported {Rows} rows to Excel: {FilePath}", data.Rows.Count, filePath);
|
||||
}
|
||||
|
||||
public async Task<byte[]> ExportToMemoryAsync(DataTable data, ExportOptions options)
|
||||
{
|
||||
using var workbook = new XLWorkbook();
|
||||
var worksheet = workbook.Worksheets.Add("Data");
|
||||
|
||||
WriteDataToWorksheet(worksheet, data, options);
|
||||
|
||||
using var stream = new MemoryStream();
|
||||
await Task.Run(() => workbook.SaveAs(stream));
|
||||
return stream.ToArray();
|
||||
}
|
||||
|
||||
private void WriteDataToWorksheet(IXLWorksheet worksheet, DataTable data, ExportOptions options)
|
||||
{
|
||||
if (options.IncludeHeaders)
|
||||
{
|
||||
for (int col = 0; col < data.Columns.Count; col++)
|
||||
{
|
||||
worksheet.Cell(1, col + 1).Value = data.Columns[col].ColumnName;
|
||||
worksheet.Cell(1, col + 1).Style.Font.Bold = true;
|
||||
}
|
||||
}
|
||||
|
||||
int startRow = options.IncludeHeaders ? 2 : 1;
|
||||
|
||||
for (int row = 0; row < data.Rows.Count; row++)
|
||||
{
|
||||
for (int col = 0; col < data.Columns.Count; col++)
|
||||
{
|
||||
var value = data.Rows[row][col];
|
||||
worksheet.Cell(startRow + row, col + 1).Value = ConvertValue(value);
|
||||
|
||||
ApplyFormatting(worksheet.Cell(startRow + row, col + 1), value);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.AutoFilter)
|
||||
{
|
||||
var endRow = startRow + data.Rows.Count - 1;
|
||||
worksheet.Range(1, 1, endRow, data.Columns.Count).SetAutoFilter();
|
||||
}
|
||||
|
||||
worksheet.Columns().AdjustToContents();
|
||||
}
|
||||
|
||||
private XLCellValue ConvertValue(object value)
|
||||
{
|
||||
if (value == null || value == DBNull.Value) return Blank.Value;
|
||||
|
||||
if (value is DateTime dateTime)
|
||||
return dateTime;
|
||||
|
||||
if (value is decimal || value is double || value is float)
|
||||
return Convert.ToDouble(value);
|
||||
|
||||
if (value is bool b)
|
||||
return b;
|
||||
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
private void ApplyFormatting(IXLCell cell, object value)
|
||||
{
|
||||
if (value is DateTime)
|
||||
{
|
||||
cell.Style.DateFormat.Format = "dd.MM.yyyy HH:mm:ss";
|
||||
}
|
||||
else if (value is decimal || value is double || value is float)
|
||||
{
|
||||
cell.Style.NumberFormat.Format = "#,##0.00";
|
||||
}
|
||||
}
|
||||
|
||||
private void AddCharts(IXLWorksheet worksheet, DataTable data, ExportOptions options)
|
||||
{
|
||||
if (data.Columns.Count < 2) return;
|
||||
|
||||
//TODO: chart
|
||||
/*var chartType = GetChartType(options.ChartType);
|
||||
var chart = worksheet.CreateChart(0, data.Columns.Count + 2, 20, data.Columns.Count + 10);
|
||||
chart.ChartType = chartType;
|
||||
|
||||
// Добавление серий на основе данных
|
||||
for (int col = 1; col < Math.Min(5, data.Columns.Count); col++)
|
||||
{
|
||||
var series = chart.AddSeries(
|
||||
worksheet.Range(2, col + 1, data.Rows.Count + 1, col + 1),
|
||||
worksheet.Range(2, 1, data.Rows.Count + 1, 1));
|
||||
|
||||
series.ChartType = chartType;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private XLChartType GetChartType(string? chartType) => chartType?.ToLower() switch
|
||||
{
|
||||
"line" => XLChartType.Line,
|
||||
"column" => XLChartType.ColumnClustered,
|
||||
"bar" => XLChartType.BarClustered,
|
||||
"pie" => XLChartType.Pie,
|
||||
"area" => XLChartType.Area,
|
||||
_ => XLChartType.Line
|
||||
};
|
||||
}
|
||||
|
||||
59
SQLVision.Services/Exporters/JsonExporter.cs
Normal file
59
SQLVision.Services/Exporters/JsonExporter.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SQLVision.Core.Models;
|
||||
using System.Data;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SQLVision.Services.Exporters;
|
||||
|
||||
public class JsonExporter : IExportHandler
|
||||
{
|
||||
private readonly ILogger<JsonExporter> _logger;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public string FormatName => "JSON";
|
||||
|
||||
public JsonExporter(ILogger<JsonExporter> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
}
|
||||
|
||||
public async Task ExportAsync(DataTable data, string filePath, ExportOptions options)
|
||||
{
|
||||
var records = ConvertDataTableToList(data);
|
||||
var json = JsonSerializer.Serialize(records, _jsonOptions);
|
||||
await File.WriteAllTextAsync(filePath, json);
|
||||
|
||||
_logger.LogInformation("Exported {Rows} rows to JSON: {FilePath}", data.Rows.Count, filePath);
|
||||
}
|
||||
|
||||
public async Task<byte[]> ExportToMemoryAsync(DataTable data, ExportOptions options)
|
||||
{
|
||||
var records = ConvertDataTableToList(data);
|
||||
var json = JsonSerializer.Serialize(records, _jsonOptions);
|
||||
return System.Text.Encoding.UTF8.GetBytes(json);
|
||||
}
|
||||
|
||||
private List<Dictionary<string, object>> ConvertDataTableToList(DataTable data)
|
||||
{
|
||||
var list = new List<Dictionary<string, object>>();
|
||||
|
||||
foreach (DataRow row in data.Rows)
|
||||
{
|
||||
var dict = new Dictionary<string, object>();
|
||||
|
||||
foreach (DataColumn column in data.Columns)
|
||||
{
|
||||
dict[column.ColumnName] = row[column] ?? DBNull.Value;
|
||||
}
|
||||
|
||||
list.Add(dict);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user