forked from ddrilling/AsbCloudServer
Доработки парсера excel, рефакторинг парсинга РТК и траекторий
This commit is contained in:
parent
4fb94a443f
commit
14f4ffb6b9
@ -45,6 +45,7 @@ using AsbCloudDb.Model.WellSections;
|
|||||||
using AsbCloudInfrastructure.Services.ProcessMaps;
|
using AsbCloudInfrastructure.Services.ProcessMaps;
|
||||||
using AsbCloudApp.Data.ProcessMapPlan;
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure
|
namespace AsbCloudInfrastructure
|
||||||
{
|
{
|
||||||
|
17
AsbCloudInfrastructure/Services/Parser/Data/Cell.cs
Normal file
17
AsbCloudInfrastructure/Services/Parser/Data/Cell.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
|
|
||||||
|
public class Cell
|
||||||
|
{
|
||||||
|
public Cell(int columnNumber,
|
||||||
|
XLDataType type)
|
||||||
|
{
|
||||||
|
ColumnNumber = columnNumber;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ColumnNumber { get; }
|
||||||
|
|
||||||
|
public XLDataType Type { get; }
|
||||||
|
}
|
17
AsbCloudInfrastructure/Services/Parser/Data/Row.cs
Normal file
17
AsbCloudInfrastructure/Services/Parser/Data/Row.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
|
|
||||||
|
public class Row
|
||||||
|
{
|
||||||
|
public Row(int number,
|
||||||
|
IDictionary<string, (Cell, object?)> cells)
|
||||||
|
{
|
||||||
|
Number = number;
|
||||||
|
Cells = cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Number { get; }
|
||||||
|
|
||||||
|
public IDictionary<string, (Cell CellInfo, object? CellValue)> Cells { get; }
|
||||||
|
}
|
@ -3,12 +3,15 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
|
using Mapster;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services;
|
namespace AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto, TOptions>
|
public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto, TOptions>
|
||||||
where TDto : class, IValidatableObject, IId
|
where TDto : class, IValidatableObject, IId
|
||||||
@ -23,13 +26,47 @@ public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto,
|
|||||||
|
|
||||||
protected abstract string SheetName { get; }
|
protected abstract string SheetName { get; }
|
||||||
|
|
||||||
protected abstract IDictionary<string, int> PropertyColumnNumbers { get; }
|
protected virtual int HeaderRowsCount => 0;
|
||||||
|
|
||||||
public abstract ParserResultDto<TDto> Parse(Stream file, TOptions options);
|
protected abstract string TemplateFileName { get; }
|
||||||
|
|
||||||
public abstract Stream GetTemplateFile();
|
protected abstract IDictionary<string, Cell> Cells { get; }
|
||||||
|
|
||||||
protected abstract TDto ParseRow(IXLRow xlRow);
|
public virtual ParserResultDto<TDto> Parse(Stream file, TOptions options)
|
||||||
|
{
|
||||||
|
using var workbook = new XLWorkbook(file);
|
||||||
|
var sheet = workbook.GetWorksheet(SheetName);
|
||||||
|
var dtos = ParseExcelSheet(sheet);
|
||||||
|
return dtos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Stream GetTemplateFile() =>
|
||||||
|
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
|
||||||
|
?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
|
||||||
|
|
||||||
|
|
||||||
|
protected virtual Row ParseRow(IXLRow xlRow)
|
||||||
|
{
|
||||||
|
var cells = Cells.ToDictionary(x => x.Key, x =>
|
||||||
|
{
|
||||||
|
var columnNumber = x.Value.ColumnNumber;
|
||||||
|
var type = x.Value.Type;
|
||||||
|
var cellValue = xlRow.Cell(columnNumber).GetCellValue(type);
|
||||||
|
|
||||||
|
return (x.Value, cellValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
var row = new Row(xlRow.RowNumber(), cells);
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual TDto BuildDto(Row row)
|
||||||
|
{
|
||||||
|
var propertiesDict = row.Cells.ToDictionary(x => x.Key, x => x.Value.CellValue);
|
||||||
|
|
||||||
|
return propertiesDict.Adapt<TDto>();
|
||||||
|
}
|
||||||
|
|
||||||
private ValidationResultDto<TDto> Validate(TDto dto, int rowNumber)
|
private ValidationResultDto<TDto> Validate(TDto dto, int rowNumber)
|
||||||
{
|
{
|
||||||
@ -39,7 +76,7 @@ public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto,
|
|||||||
|
|
||||||
if (isValid)
|
if (isValid)
|
||||||
{
|
{
|
||||||
var validDto = new ValidationResultDto<TDto>()
|
var validDto = new ValidationResultDto<TDto>
|
||||||
{
|
{
|
||||||
Item = dto
|
Item = dto
|
||||||
};
|
};
|
||||||
@ -47,17 +84,20 @@ public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto,
|
|||||||
return validDto;
|
return validDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var columnsDict = Cells.ToDictionary(x => x.Key, x => x.Value.ColumnNumber);
|
||||||
|
|
||||||
var invalidDto = new ValidationResultDto<TDto>
|
var invalidDto = new ValidationResultDto<TDto>
|
||||||
{
|
{
|
||||||
Item = dto,
|
Item = dto,
|
||||||
Warnings = validationResults
|
Warnings = validationResults
|
||||||
.SelectMany(v => v.MemberNames
|
.SelectMany(v => v.MemberNames
|
||||||
.Where(PropertyColumnNumbers.ContainsKey)
|
.Where(columnsDict.ContainsKey)
|
||||||
.Select(m =>
|
.Select(m =>
|
||||||
{
|
{
|
||||||
var columnNumber = PropertyColumnNumbers[m];
|
var columnNumber = columnsDict[m];
|
||||||
var errorMessage = v.ErrorMessage;
|
var errorMessage = v.ErrorMessage;
|
||||||
var warningMessage = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, rowNumber, columnNumber, errorMessage);
|
var warningMessage = string.Format(XLExtentions.ProblemDetailsTemplate, SheetName, rowNumber, columnNumber,
|
||||||
|
errorMessage);
|
||||||
var warning = new ValidationResult(warningMessage, new[] { m });
|
var warning = new ValidationResult(warningMessage, new[] { m });
|
||||||
return warning;
|
return warning;
|
||||||
}))
|
}))
|
||||||
@ -66,18 +106,9 @@ public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto,
|
|||||||
return invalidDto;
|
return invalidDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet,
|
protected virtual ParserResultDto<TDto> ParseExcelSheet(IXLWorksheet sheet)
|
||||||
int columnCount,
|
|
||||||
int headerRowsCount = 0)
|
|
||||||
{
|
{
|
||||||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < columnCount)
|
var count = sheet.RowsUsed().Count() - HeaderRowsCount;
|
||||||
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)
|
if (count <= 0)
|
||||||
return new ParserResultDto<TDto>();
|
return new ParserResultDto<TDto>();
|
||||||
|
|
||||||
@ -86,12 +117,13 @@ public abstract class ParserExcelService<TDto, TOptions> : IParserService<TDto,
|
|||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var row = sheet.Row(1 + i + headerRowsCount);
|
var xlRow = sheet.Row(1 + i + HeaderRowsCount);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dto = ParseRow(row);
|
var row = ParseRow(xlRow);
|
||||||
var validationResult = Validate(dto, row.RowNumber());
|
var dto = BuildDto(row);
|
||||||
|
var validationResult = Validate(dto, xlRow.RowNumber());
|
||||||
valiationResults.Add(validationResult);
|
valiationResults.Add(validationResult);
|
||||||
}
|
}
|
||||||
catch (FileFormatException ex)
|
catch (FileFormatException ex)
|
@ -7,7 +7,7 @@ using AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
|||||||
using AsbCloudInfrastructure.Services.Trajectory.Parser;
|
using AsbCloudInfrastructure.Services.Trajectory.Parser;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services;
|
namespace AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
public class ParserServiceFactory : IDisposable
|
public class ParserServiceFactory : IDisposable
|
||||||
{
|
{
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.ProcessMapPlan;
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
@ -12,29 +13,6 @@ namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
|||||||
|
|
||||||
public class ProcessMapPlanDrillingParser : ProcessMapPlanParser<ProcessMapPlanDrillingDto>
|
public class ProcessMapPlanDrillingParser : ProcessMapPlanParser<ProcessMapPlanDrillingDto>
|
||||||
{
|
{
|
||||||
#region Columns
|
|
||||||
|
|
||||||
private const int columnSection = 1;
|
|
||||||
private const int columnMode = 2;
|
|
||||||
private const int columnDepthStart = 3;
|
|
||||||
private const int columnDepthEnd = 4;
|
|
||||||
private const int columnPressurePlan = 5;
|
|
||||||
private const int columnPressureLimitMax = 6;
|
|
||||||
private const int columnAxialLoadPlan = 7;
|
|
||||||
private const int columnAxialLoadLimitMax = 8;
|
|
||||||
private const int columnTopDriveTorquePlan = 9;
|
|
||||||
private const int columnTopDriveTorqueLimitMax = 10;
|
|
||||||
private const int columnTopDriveSpeedPlan = 11;
|
|
||||||
private const int columnTopDriveSpeedLimitMax = 12;
|
|
||||||
private const int columnFlowPlan = 13;
|
|
||||||
private const int columnFlowLimitMax = 14;
|
|
||||||
private const int columnRopPlan = 15;
|
|
||||||
private const int columnUsageSaub = 16;
|
|
||||||
private const int columnUsageSpin = 17;
|
|
||||||
private const int columnComment = 18;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private readonly IEnumerable<WellSectionTypeDto> sections;
|
private readonly IEnumerable<WellSectionTypeDto> sections;
|
||||||
|
|
||||||
public ProcessMapPlanDrillingParser(IServiceProvider serviceProvider)
|
public ProcessMapPlanDrillingParser(IServiceProvider serviceProvider)
|
||||||
@ -46,76 +24,58 @@ public class ProcessMapPlanDrillingParser : ProcessMapPlanParser<ProcessMapPlanD
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override string SheetName => "План";
|
protected override string SheetName => "План";
|
||||||
|
|
||||||
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
|
||||||
{
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.DepthStart), columnDepthStart },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.DepthEnd), columnDepthEnd },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.DeltaPressurePlan), columnPressurePlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.DeltaPressureLimitMax), columnPressureLimitMax },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.AxialLoadPlan), columnAxialLoadPlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.AxialLoadLimitMax), columnAxialLoadLimitMax },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.TopDriveTorquePlan), columnTopDriveTorquePlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.TopDriveTorqueLimitMax), columnTopDriveTorqueLimitMax },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.TopDriveSpeedPlan), columnTopDriveSpeedPlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.TopDriveSpeedLimitMax), columnTopDriveSpeedLimitMax },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.FlowPlan), columnFlowPlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.FlowLimitMax), columnFlowLimitMax },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.RopPlan), columnRopPlan },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.UsageSaub), columnUsageSaub },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.UsageSpin), columnUsageSpin },
|
|
||||||
{ nameof(ProcessMapPlanDrillingDto.Comment), columnComment }
|
|
||||||
};
|
|
||||||
|
|
||||||
protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx";
|
protected override string TemplateFileName => "ProcessMapPlanDrillingTemplate.xlsx";
|
||||||
|
|
||||||
protected override ProcessMapPlanDrillingDto ParseRow(IXLRow row)
|
private const int ColumnSection = 1;
|
||||||
|
private const int ColumnMode = 2;
|
||||||
|
|
||||||
|
protected override IDictionary<string, Cell> Cells => new Dictionary<string, Cell>
|
||||||
{
|
{
|
||||||
var sectionCaption = row.Cell(columnSection).GetCellValue<string>()?.Trim().ToLower();
|
{ nameof(ProcessMapPlanDrillingDto.Section), new Cell(ColumnSection, XLDataType.Text) },
|
||||||
var modeName = row.Cell(columnMode).GetCellValue<string>()?.Trim().ToLower();
|
{ nameof(ProcessMapPlanDrillingDto.Mode), new Cell(ColumnMode, XLDataType.Text) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.DepthStart), new Cell(3, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.DepthEnd), new Cell(4, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.DeltaPressurePlan), new Cell(5, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.DeltaPressureLimitMax), new Cell(6, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.AxialLoadPlan), new Cell(7, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.AxialLoadLimitMax), new Cell(8, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.TopDriveTorquePlan), new Cell(9, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.TopDriveTorqueLimitMax), new Cell(10, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.TopDriveSpeedPlan), new Cell(11, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.TopDriveSpeedLimitMax), new Cell(12, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.FlowPlan), new Cell(13, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.FlowLimitMax), new Cell(14, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.RopPlan), new Cell(15, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.UsageSaub), new Cell(16, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.UsageSpin), new Cell(17, XLDataType.Number) },
|
||||||
|
{ nameof(ProcessMapPlanDrillingDto.Comment), new Cell(18, XLDataType.Text) }
|
||||||
|
};
|
||||||
|
|
||||||
|
protected override ProcessMapPlanDrillingDto BuildDto(Row row)
|
||||||
|
{
|
||||||
|
var dto = base.BuildDto(row);
|
||||||
|
|
||||||
var section = sections.FirstOrDefault(s =>
|
var section = sections.FirstOrDefault(s =>
|
||||||
string.Equals(s.Caption.Trim(), sectionCaption?.Trim(), StringComparison.CurrentCultureIgnoreCase));
|
string.Equals(s.Caption.Trim(), dto.Section?.Trim(), StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
if (section is null)
|
if (section is null)
|
||||||
{
|
{
|
||||||
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, row.RowNumber(), columnSection,
|
var message = string.Format(XLExtentions.ProblemDetailsTemplate, SheetName, row.Number, ColumnSection,
|
||||||
"Указана некорректная секция");
|
"Указана некорректная секция");
|
||||||
throw new FileFormatException(message);
|
throw new FileFormatException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
var idMode = GetIdMode(modeName);
|
var idMode = GetIdMode(dto.Mode);
|
||||||
|
|
||||||
if (idMode is null)
|
if (idMode is null)
|
||||||
{
|
{
|
||||||
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, SheetName, row.RowNumber(), columnSection,
|
var message = string.Format(XLExtentions.ProblemDetailsTemplate, SheetName, row.Number, ColumnSection,
|
||||||
"Указан некорректный режим бурения");
|
"Указан некорректный режим бурения");
|
||||||
throw new FileFormatException(message);
|
throw new FileFormatException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dto = new ProcessMapPlanDrillingDto
|
dto.IdWellSectionType = section.Id;
|
||||||
{
|
dto.IdMode = idMode.Value;
|
||||||
IdWellSectionType = section.Id,
|
|
||||||
Section = section.Caption,
|
|
||||||
IdMode = idMode.Value,
|
|
||||||
Mode = modeName,
|
|
||||||
DepthStart = row.Cell(columnDepthStart).GetCellValue<double>(),
|
|
||||||
DepthEnd = row.Cell(columnDepthEnd).GetCellValue<double>(),
|
|
||||||
AxialLoadPlan = row.Cell(columnAxialLoadPlan).GetCellValue<double>(),
|
|
||||||
AxialLoadLimitMax = row.Cell(columnAxialLoadLimitMax).GetCellValue<double>(),
|
|
||||||
DeltaPressurePlan = row.Cell(columnPressurePlan).GetCellValue<double>(),
|
|
||||||
DeltaPressureLimitMax = row.Cell(columnPressureLimitMax).GetCellValue<double>(),
|
|
||||||
TopDriveTorquePlan = row.Cell(columnTopDriveTorquePlan).GetCellValue<double>(),
|
|
||||||
TopDriveTorqueLimitMax = row.Cell(columnTopDriveTorqueLimitMax).GetCellValue<double>(),
|
|
||||||
TopDriveSpeedPlan = row.Cell(columnTopDriveSpeedPlan).GetCellValue<double>(),
|
|
||||||
TopDriveSpeedLimitMax = row.Cell(columnTopDriveSpeedLimitMax).GetCellValue<double>(),
|
|
||||||
FlowPlan = row.Cell(columnFlowPlan).GetCellValue<double>(),
|
|
||||||
FlowLimitMax = row.Cell(columnFlowLimitMax).GetCellValue<double>(),
|
|
||||||
RopPlan = row.Cell(columnRopPlan).GetCellValue<double>(),
|
|
||||||
UsageSaub = row.Cell(columnUsageSaub).GetCellValue<double>(),
|
|
||||||
UsageSpin = row.Cell(columnUsageSpin).GetCellValue<double>(),
|
|
||||||
Comment = row.Cell(columnComment).GetCellValue<string>() ?? string.Empty
|
|
||||||
};
|
|
||||||
|
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Data.ProcessMapPlan;
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
using ClosedXML.Excel;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
namespace AsbCloudInfrastructure.Services.ProcessMapPlan.Parser;
|
||||||
|
|
||||||
@ -16,24 +15,7 @@ public abstract class ProcessMapPlanParser<TDto> : ParserExcelService<TDto, IPar
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int HeaderRowsCount = 2;
|
protected override int HeaderRowsCount => 2;
|
||||||
private const int ColumnCount = 18;
|
|
||||||
|
|
||||||
protected abstract string TemplateFileName { get; }
|
|
||||||
|
|
||||||
public override ParserResultDto<TDto> Parse(Stream file, IParserOptionsRequest options)
|
|
||||||
{
|
|
||||||
using var workbook = new XLWorkbook(file);
|
|
||||||
|
|
||||||
var sheet = workbook.GetWorksheet(SheetName);
|
|
||||||
|
|
||||||
var processMaps = ParseExcelSheet(sheet, ColumnCount, HeaderRowsCount);
|
|
||||||
return processMaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Stream GetTemplateFile() =>
|
|
||||||
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
|
|
||||||
?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
|
|
||||||
|
|
||||||
protected static int? GetIdMode(string? modeName) =>
|
protected static int? GetIdMode(string? modeName) =>
|
||||||
modeName?.Trim().ToLower() switch
|
modeName?.Trim().ToLower() switch
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
||||||
|
|
||||||
public class TrajectoryFactManualParser : TrajectoryParser<TrajectoryGeoFactDto>
|
public class TrajectoryFactManualParser : ParserExcelService<TrajectoryGeoFactDto, IParserOptionsRequest>
|
||||||
{
|
{
|
||||||
#region Columns
|
|
||||||
|
|
||||||
private const int columnWellboreDepth = 1;
|
|
||||||
private const int columnZenithAngle = 2;
|
|
||||||
private const int columnAzimuthGeo = 3;
|
|
||||||
private const int columnAzimuthMagnetic = 4;
|
|
||||||
private const int columnVerticalDepth = 5;
|
|
||||||
private const int columnComment = 6;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public TrajectoryFactManualParser(IServiceProvider serviceProvider)
|
public TrajectoryFactManualParser(IServiceProvider serviceProvider)
|
||||||
: base(serviceProvider)
|
: base(serviceProvider)
|
||||||
{
|
{
|
||||||
@ -25,30 +17,17 @@ public class TrajectoryFactManualParser : TrajectoryParser<TrajectoryGeoFactDto>
|
|||||||
|
|
||||||
protected override string SheetName => "Фактическая траектория";
|
protected override string SheetName => "Фактическая траектория";
|
||||||
|
|
||||||
|
protected override int HeaderRowsCount => 2;
|
||||||
|
|
||||||
protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx";
|
protected override string TemplateFileName => "TrajectoryFactManualTemplate.xlsx";
|
||||||
|
|
||||||
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
protected override IDictionary<string, Cell> Cells => new Dictionary<string, Cell>()
|
||||||
{
|
{
|
||||||
{ nameof(TrajectoryGeoFactDto.WellboreDepth), columnWellboreDepth },
|
{ nameof(TrajectoryGeoFactDto.WellboreDepth), new Cell(1, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoFactDto.ZenithAngle), columnZenithAngle },
|
{ nameof(TrajectoryGeoFactDto.ZenithAngle), new Cell(2, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoFactDto.AzimuthGeo), columnAzimuthGeo },
|
{ nameof(TrajectoryGeoFactDto.AzimuthGeo), new Cell(3, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoFactDto.AzimuthMagnetic), columnAzimuthMagnetic },
|
{ nameof(TrajectoryGeoFactDto.AzimuthMagnetic), new Cell(4, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoFactDto.VerticalDepth), columnVerticalDepth },
|
{ nameof(TrajectoryGeoFactDto.VerticalDepth), new Cell(5, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoFactDto.Comment), columnComment }
|
{ nameof(TrajectoryGeoFactDto.Comment), new Cell(6, XLDataType.Text) }
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override TrajectoryGeoFactDto ParseRow(IXLRow row)
|
|
||||||
{
|
|
||||||
var dto = new TrajectoryGeoFactDto
|
|
||||||
{
|
|
||||||
WellboreDepth = row.Cell(columnWellboreDepth).GetCellValue<double>(),
|
|
||||||
ZenithAngle = row.Cell(columnZenithAngle).GetCellValue<double>(),
|
|
||||||
AzimuthGeo = row.Cell(columnAzimuthGeo).GetCellValue<double>(),
|
|
||||||
AzimuthMagnetic = row.Cell(columnAzimuthMagnetic).GetCellValue<double>(),
|
|
||||||
VerticalDepth = row.Cell(columnVerticalDepth).GetCellValue<double>(),
|
|
||||||
Comment = row.Cell(columnComment).GetCellValue<string?>()
|
|
||||||
};
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,37 +0,0 @@
|
|||||||
using System;
|
|
||||||
using AsbCloudApp.Data.Trajectory;
|
|
||||||
using ClosedXML.Excel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
|
||||||
|
|
||||||
public abstract class TrajectoryParser<T> : ParserExcelService<T, IParserOptionsRequest>
|
|
||||||
where T : TrajectoryGeoDto
|
|
||||||
{
|
|
||||||
private const int HeaderRowsCount = 2;
|
|
||||||
private const int ColumnCount = 6;
|
|
||||||
|
|
||||||
protected TrajectoryParser(IServiceProvider serviceProvider)
|
|
||||||
: base(serviceProvider)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract string TemplateFileName { get; }
|
|
||||||
|
|
||||||
public override Stream GetTemplateFile() =>
|
|
||||||
Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateFileName)
|
|
||||||
?? throw new ArgumentNullException($"Файл '{TemplateFileName}' не найден");
|
|
||||||
|
|
||||||
public override ParserResultDto<T> Parse(Stream file, IParserOptionsRequest options)
|
|
||||||
{
|
|
||||||
using var workbook = new XLWorkbook(file);
|
|
||||||
|
|
||||||
var sheet = workbook.GetWorksheet(SheetName);
|
|
||||||
|
|
||||||
var trajectoryRows = ParseExcelSheet(sheet, ColumnCount, HeaderRowsCount);
|
|
||||||
return trajectoryRows;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using AsbCloudApp.Data;
|
|
||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
using AsbCloudInfrastructure.Services.Parser.Data;
|
||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
|
|
||||||
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
namespace AsbCloudInfrastructure.Services.Trajectory.Parser;
|
||||||
|
|
||||||
public class TrajectoryPlanParser : TrajectoryParser<TrajectoryGeoPlanDto>
|
public class TrajectoryPlanParser : ParserExcelService<TrajectoryGeoPlanDto, IParserOptionsRequest>
|
||||||
{
|
{
|
||||||
#region Columns
|
|
||||||
|
|
||||||
private const int columnWellboreDepth = 1;
|
|
||||||
private const int columnZenithAngle = 2;
|
|
||||||
private const int columnAzimuthGeo = 3;
|
|
||||||
private const int columnAzimuthMagnetic = 4;
|
|
||||||
private const int columnVerticalDepth = 5;
|
|
||||||
private const int columnRadius = 6;
|
|
||||||
private const int columnComment = 7;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public TrajectoryPlanParser(IServiceProvider serviceProvider)
|
public TrajectoryPlanParser(IServiceProvider serviceProvider)
|
||||||
: base(serviceProvider)
|
: base(serviceProvider)
|
||||||
{
|
{
|
||||||
@ -27,32 +17,18 @@ public class TrajectoryPlanParser : TrajectoryParser<TrajectoryGeoPlanDto>
|
|||||||
|
|
||||||
protected override string SheetName => "Плановая траектория";
|
protected override string SheetName => "Плановая траектория";
|
||||||
|
|
||||||
|
protected override int HeaderRowsCount => 2;
|
||||||
|
|
||||||
protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx";
|
protected override string TemplateFileName => "TrajectoryPlanTemplate.xlsx";
|
||||||
|
|
||||||
protected override IDictionary<string, int> PropertyColumnNumbers => new Dictionary<string, int>
|
protected override IDictionary<string, Cell> Cells => new Dictionary<string, Cell>
|
||||||
{
|
{
|
||||||
{ nameof(TrajectoryGeoPlanDto.WellboreDepth), columnWellboreDepth },
|
{ nameof(TrajectoryGeoPlanDto.WellboreDepth), new Cell(1, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.ZenithAngle), columnZenithAngle },
|
{ nameof(TrajectoryGeoPlanDto.ZenithAngle), new Cell(2, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.AzimuthGeo), columnAzimuthGeo },
|
{ nameof(TrajectoryGeoPlanDto.AzimuthGeo), new Cell(3, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.AzimuthMagnetic), columnAzimuthMagnetic },
|
{ nameof(TrajectoryGeoPlanDto.AzimuthMagnetic), new Cell(4, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.VerticalDepth), columnVerticalDepth },
|
{ nameof(TrajectoryGeoPlanDto.VerticalDepth), new Cell(5, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.Radius), columnRadius },
|
{ nameof(TrajectoryGeoPlanDto.Radius), new Cell(6, XLDataType.Number) },
|
||||||
{ nameof(TrajectoryGeoPlanDto.Comment), columnComment }
|
{ nameof(TrajectoryGeoPlanDto.Comment), new Cell(7, XLDataType.Text) }
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override TrajectoryGeoPlanDto ParseRow(IXLRow row)
|
|
||||||
{
|
|
||||||
var dto = new TrajectoryGeoPlanDto
|
|
||||||
{
|
|
||||||
WellboreDepth = row.Cell(columnWellboreDepth).GetCellValue<double>(),
|
|
||||||
ZenithAngle = row.Cell(columnZenithAngle).GetCellValue<double>(),
|
|
||||||
AzimuthGeo = row.Cell(columnAzimuthGeo).GetCellValue<double>(),
|
|
||||||
AzimuthMagnetic = row.Cell(columnAzimuthMagnetic).GetCellValue<double>(),
|
|
||||||
VerticalDepth = row.Cell(columnVerticalDepth).GetCellValue<double>(),
|
|
||||||
Radius = row.Cell(columnRadius).GetCellValue<double>(),
|
|
||||||
Comment = row.Cell(columnComment).GetCellValue<string?>()
|
|
||||||
};
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,9 +7,15 @@ namespace AsbCloudInfrastructure;
|
|||||||
|
|
||||||
public static class XLExtentions
|
public static class XLExtentions
|
||||||
{
|
{
|
||||||
|
public const string ProblemDetailsTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. {3}";
|
||||||
|
|
||||||
|
public const string NotFoundSheetTemplate = "Книга excel не содержит листа {0}";
|
||||||
|
|
||||||
|
public const string InvalidValueTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. Содержит некорректное значение";
|
||||||
|
|
||||||
public static IXLWorksheet GetWorksheet(this IXLWorkbook workbook, string sheetName) =>
|
public static IXLWorksheet GetWorksheet(this IXLWorkbook workbook, string sheetName) =>
|
||||||
workbook.Worksheets.FirstOrDefault(ws => string.Equals(ws.Name.Trim(), sheetName.Trim(), StringComparison.CurrentCultureIgnoreCase))
|
workbook.Worksheets.FirstOrDefault(ws => string.Equals(ws.Name.Trim(), sheetName.Trim(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
?? throw new FileFormatException(string.Format(XLMessageTemplates.NotFoundSheetTemplate, sheetName));
|
?? throw new FileFormatException(string.Format(NotFoundSheetTemplate, sheetName));
|
||||||
|
|
||||||
public static IXLCell SetCellValue<T>(this IXLCell cell, T value)
|
public static IXLCell SetCellValue<T>(this IXLCell cell, T value)
|
||||||
{
|
{
|
||||||
@ -28,6 +34,29 @@ public static class XLExtentions
|
|||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static object? GetCellValue(this IXLCell cell, XLDataType type)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
XLDataType.Blank => null,
|
||||||
|
XLDataType.Boolean => cell.Value.GetBoolean(),
|
||||||
|
XLDataType.Number => cell.Value.GetNumber(),
|
||||||
|
XLDataType.Text => cell.Value.GetText(),
|
||||||
|
XLDataType.Error => cell.Value.GetError(),
|
||||||
|
XLDataType.DateTime => cell.Value.GetDateTime(),
|
||||||
|
XLDataType.TimeSpan => cell.Value.GetTimeSpan(),
|
||||||
|
_ => throw new InvalidCastException()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
var message = string.Format(InvalidValueTemplate, cell.Worksheet.Name, cell.Address.RowNumber, cell.Address.ColumnNumber);
|
||||||
|
throw new FileFormatException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static T? GetCellValue<T>(this IXLCell cell)
|
public static T? GetCellValue<T>(this IXLCell cell)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -39,8 +68,7 @@ public static class XLExtentions
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
var message = string.Format(XLMessageTemplates.ProblemDetailsTemplate, cell.Worksheet.Name, cell.Address.RowNumber,
|
var message = string.Format(InvalidValueTemplate, cell.Worksheet.Name, cell.Address.RowNumber, cell.Address.ColumnNumber);
|
||||||
cell.Address.ColumnNumber, "Содержит некорректное значение");
|
|
||||||
throw new FileFormatException(message);
|
throw new FileFormatException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
namespace AsbCloudInfrastructure;
|
|
||||||
|
|
||||||
public static class XLMessageTemplates
|
|
||||||
{
|
|
||||||
public const string ProblemDetailsTemplate = "Лист: {0}, Строка: {1}, Столбец: {2}. {3}";
|
|
||||||
|
|
||||||
public const string NotFoundSheetTemplate = "Книга excel не содержит листа {0}";
|
|
||||||
|
|
||||||
public const string ExceedingMaxRowLimitTemplate = "Лист {0} содержит слишком большое количество строк";
|
|
||||||
|
|
||||||
public const string FewerColumnsTemplate = "Лист {0} содержит меньшее количество столбцов";
|
|
||||||
}
|
|
@ -29,7 +29,7 @@ public class ProcessMapPlanDrillingControllerTest: BaseIntegrationTest
|
|||||||
DepthEnd = 1.5,
|
DepthEnd = 1.5,
|
||||||
|
|
||||||
IdMode = 1,
|
IdMode = 1,
|
||||||
Mode = "ротор",
|
Mode = "Ротор",
|
||||||
AxialLoadPlan = 2.718281,
|
AxialLoadPlan = 2.718281,
|
||||||
AxialLoadLimitMax = 3.1415926,
|
AxialLoadLimitMax = 3.1415926,
|
||||||
DeltaPressurePlan = 4,
|
DeltaPressurePlan = 4,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
@ -14,7 +14,7 @@ using AsbCloudApp.Services;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
using AsbCloudWebApi.Controllers.Interfaces;
|
using AsbCloudWebApi.Controllers.Interfaces;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
namespace AsbCloudWebApi.Controllers.ProcessMapPlan;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudApp.Data;
|
using AsbCloudApp.Data;
|
||||||
using AsbCloudApp.Requests.ParserOptions;
|
using AsbCloudApp.Requests.ParserOptions;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
using AsbCloudWebApi.Controllers.Interfaces;
|
using AsbCloudWebApi.Controllers.Interfaces;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.Trajectory
|
namespace AsbCloudWebApi.Controllers.Trajectory
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
using AsbCloudApp.Data.Trajectory;
|
using AsbCloudApp.Data.Trajectory;
|
||||||
using AsbCloudApp.Repositories;
|
using AsbCloudApp.Repositories;
|
||||||
using AsbCloudApp.Services;
|
using AsbCloudApp.Services;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
using AsbCloudInfrastructure.Services.Trajectory.Export;
|
using AsbCloudInfrastructure.Services.Trajectory.Export;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsbCloudInfrastructure.Services;
|
using AsbCloudInfrastructure.Services.Parser;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Controllers.Trajectory
|
namespace AsbCloudWebApi.Controllers.Trajectory
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user