2024-03-22 09:37:06 +05:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
|
|
|
using AsbCloudApp.Data;
|
|
|
|
using AsbCloudApp.Requests.ParserOptions;
|
|
|
|
using AsbCloudApp.Services.Parsers;
|
|
|
|
using AsbCloudInfrastructure.Services.ExcelServices.Templates;
|
|
|
|
using ClosedXML.Excel;
|
|
|
|
using Mapster;
|
|
|
|
|
|
|
|
namespace AsbCloudInfrastructure.Services.ExcelServices;
|
|
|
|
|
|
|
|
public abstract class ExcelParser<TDto, TOptions, TTemplate> : IParserService<TDto, TOptions>
|
2024-07-04 11:02:45 +05:00
|
|
|
where TDto : class, IValidatableObject, IId
|
|
|
|
where TOptions : IParserOptionsRequest
|
|
|
|
where TTemplate : class, ITemplateParameters, new()
|
2024-03-22 09:37:06 +05:00
|
|
|
{
|
2024-07-04 11:02:45 +05:00
|
|
|
protected TTemplate TemplateParameters => new();
|
|
|
|
|
|
|
|
public virtual ParserResultDto<TDto> Parse(Stream file, TOptions options)
|
|
|
|
{
|
|
|
|
using var workbook = new XLWorkbook(file);
|
|
|
|
var sheet = workbook.GetWorksheet(TemplateParameters.SheetName);
|
|
|
|
var dtos = ParseExcelSheet(sheet);
|
|
|
|
return dtos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual Stream GetTemplateFile() =>
|
|
|
|
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateParameters.FileName)
|
|
|
|
?? throw new ArgumentNullException($"Файл '{TemplateParameters.FileName}' не найден");
|
|
|
|
|
|
|
|
|
|
|
|
protected virtual IDictionary<string, object?> ParseRow(IXLRow xlRow)
|
|
|
|
{
|
|
|
|
var cells = TemplateParameters.Cells.ToDictionary(x => x.Key, x =>
|
|
|
|
{
|
|
|
|
var columnNumber = x.Value.ColumnNumber;
|
|
|
|
var xlCell = xlRow.Cell(columnNumber);
|
|
|
|
var cellValue = x.Value.GetValueFromCell(xlCell);
|
|
|
|
return cellValue;
|
|
|
|
});
|
|
|
|
|
|
|
|
return cells;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual TDto BuildDto(IDictionary<string, object?> row, int rowNumber)
|
|
|
|
{
|
|
|
|
var dto = row.Adapt<TDto>();
|
|
|
|
return dto;
|
|
|
|
}
|
|
|
|
|
|
|
|
private ValidationResultDto<TDto> Validate(TDto dto, int rowNumber)
|
|
|
|
{
|
|
|
|
var validationResults = new List<ValidationResult>();
|
|
|
|
|
|
|
|
var isValid = dto.Validate(validationResults);
|
|
|
|
|
|
|
|
if (isValid)
|
|
|
|
{
|
|
|
|
var validDto = new ValidationResultDto<TDto>
|
|
|
|
{
|
|
|
|
Item = dto
|
|
|
|
};
|
|
|
|
|
|
|
|
return validDto;
|
|
|
|
}
|
|
|
|
|
|
|
|
var columnsDict = TemplateParameters.Cells.ToDictionary(x => x.Key, x => x.Value.ColumnNumber);
|
|
|
|
|
|
|
|
var invalidDto = new ValidationResultDto<TDto>
|
|
|
|
{
|
|
|
|
Item = dto,
|
|
|
|
Warnings = validationResults
|
|
|
|
.SelectMany(v => v.MemberNames
|
|
|
|
.Where(columnsDict.ContainsKey)
|
|
|
|
.Select(m =>
|
|
|
|
{
|
|
|
|
var columnNumber = columnsDict[m];
|
|
|
|
var errorMessage = v.ErrorMessage;
|
|
|
|
var warningMessage = string.Format(XLExtentions.ProblemDetailsTemplate,
|
|
|
|
TemplateParameters.SheetName,
|
|
|
|
rowNumber,
|
|
|
|
columnNumber,
|
|
|
|
errorMessage);
|
|
|
|
var warning = new ValidationResult(warningMessage, new[] { m });
|
|
|
|
return warning;
|
|
|
|
}))
|
|
|
|
};
|
|
|
|
|
|
|
|
return invalidDto;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet)
|
|
|
|
{
|
|
|
|
var count = sheet.RowsUsed().Count() - TemplateParameters.HeaderRowsCount;
|
|
|
|
if (count <= 0)
|
|
|
|
return new ParserResultDto<TDto>();
|
|
|
|
|
|
|
|
var valiationResults = new List<ValidationResultDto<TDto>>(count);
|
|
|
|
var warnings = new List<ValidationResult>();
|
|
|
|
|
|
|
|
for (var i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
var xlRow = sheet.Row(1 + i + TemplateParameters.HeaderRowsCount);
|
|
|
|
var rowNumber = xlRow.RowNumber();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var row = ParseRow(xlRow);
|
|
|
|
var dto = BuildDto(row, rowNumber);
|
|
|
|
var validationResult = Validate(dto, rowNumber);
|
|
|
|
valiationResults.Add(validationResult);
|
|
|
|
}
|
|
|
|
catch (FileFormatException ex)
|
|
|
|
{
|
|
|
|
var warning = new ValidationResult(ex.Message);
|
|
|
|
warnings.Add(warning);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var parserResult = new ParserResultDto<TDto>
|
|
|
|
{
|
|
|
|
Item = valiationResults
|
|
|
|
};
|
|
|
|
|
|
|
|
if (warnings.Any())
|
|
|
|
parserResult.Warnings = warnings;
|
|
|
|
|
|
|
|
return parserResult;
|
|
|
|
}
|
2024-03-22 09:37:06 +05:00
|
|
|
}
|