using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; using AsbCloudApp.Data; using AsbCloudApp.Requests.ParserOptions; using AsbCloudApp.Services; using ClosedXML.Excel; namespace AsbCloudInfrastructure.Services; public abstract class ParserExcelService : IParserService where TDto : class, IValidatableObject, IId where TOptions : IParserOptionsRequest { protected readonly IServiceProvider serviceProvider; protected ParserExcelService(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } protected abstract string SheetName { get; } protected abstract IDictionary PropertyColumnNumbers { get; } public abstract ParserResultDto Parse(Stream file, TOptions options); public abstract Stream GetTemplateFile(); protected abstract TDto ParseRow(IXLRow xlRow); private ValidationResultDto Validate(TDto dto, int rowNumber) { var validationResults = new List(); var isValid = dto.Validate(validationResults); if (isValid) { var validDto = new ValidationResultDto() { Item = dto }; return validDto; } var invalidDto = new ValidationResultDto { Item = dto, Warnings = validationResults .SelectMany(v => v.MemberNames .Where(PropertyColumnNumbers.ContainsKey) .Select(m => { var columnNumber = PropertyColumnNumbers[m]; var errorMessage = v.ErrorMessage; var warningMessage = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, rowNumber, columnNumber, errorMessage); var warning = new ValidationResult(warningMessage, new[] { m }); return warning; })) }; return invalidDto; } protected virtual ParserResultDto ParseExcelSheet(IXLWorksheet sheet, int columnCount, int headerRowsCount = 0) { if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount) throw new FileFormatException(string.Format(XLMessageTemplates.FewerColumnsTemplate, SheetName)); var count = sheet.RowsUsed().Count() - headerRowsCount; if (count > 1024) throw new FileFormatException(string.Format(XLMessageTemplates.ExceedingMaxRowLimitTemplate, SheetName)); if (count <= 0) return new ParserResultDto(); var valiationResults = new List>(count); var warnings = new List(); for (var i = 0; i < count; i++) { var row = sheet.Row(1 + i + headerRowsCount); try { var dto = ParseRow(row); var validationResult = Validate(dto, row.RowNumber()); valiationResults.Add(validationResult); } catch (FileFormatException ex) { var warning = new ValidationResult(ex.Message); warnings.Add(warning); } } var parserResult = new ParserResultDto { Item = valiationResults }; if (warnings.Any()) parserResult.Warnings = warnings; return parserResult; } }