forked from ddrilling/AsbCloudServer
Степанов Дмитрий
ff02a29115
1. Добавил парсинг Газпромовских файлов 2. Сделал рефакторинг существующего импорта
106 lines
3.6 KiB
C#
106 lines
3.6 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using AsbCloudApp.Data.WellOperationImport;
|
||
using AsbCloudApp.Exceptions;
|
||
using AsbCloudApp.Services.WellOperationImport;
|
||
using AsbCloudDb.Model;
|
||
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||
using ClosedXML.Excel;
|
||
|
||
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
|
||
|
||
public class WellOperationDefaultExcelParser : IWellOperationExcelParser
|
||
{
|
||
public int IdTemplate => Templates.IdDefaultTemplate;
|
||
public IEnumerable<int> IdTypes => new[] { WellOperation.IdOperationTypePlan, WellOperation.IdOperationTypeFact };
|
||
|
||
public IEnumerable<RowDto> Parse(Stream stream, WellOperationParserOptionsDto options)
|
||
{
|
||
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
|
||
|
||
return ParseWorkbook(workbook, options);
|
||
}
|
||
|
||
private static IEnumerable<RowDto> ParseWorkbook(IXLWorkbook workbook, WellOperationParserOptionsDto options)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(options.SheetName))
|
||
throw new ArgumentInvalidException("Не указано название листа", nameof(options.SheetName));
|
||
|
||
var sheet = workbook.Worksheets.FirstOrDefault(ws =>
|
||
string.Equals(ws.Name, options.SheetName, StringComparison.CurrentCultureIgnoreCase))
|
||
?? throw new FileFormatException($"Книга excel не содержит листа '{options.SheetName}'");
|
||
|
||
return ParseSheet(sheet);
|
||
}
|
||
|
||
private static IEnumerable<RowDto> ParseSheet(IXLWorksheet sheet)
|
||
{
|
||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
|
||
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
|
||
|
||
var count = sheet.RowsUsed().Count() - DefaultTemplateInfo.HeaderRowsCount;
|
||
|
||
switch (count)
|
||
{
|
||
case > 1024:
|
||
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций.");
|
||
case <= 0:
|
||
return Enumerable.Empty<RowDto>();
|
||
}
|
||
|
||
var rows = new RowDto[count];
|
||
|
||
var cellValuesErrors = new List<string>();
|
||
|
||
for (int i = 0; i < rows.Length; i++)
|
||
{
|
||
try
|
||
{
|
||
var xlRow = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount);
|
||
|
||
rows[i] = ParseRow(xlRow);
|
||
}
|
||
catch (FileFormatException ex)
|
||
{
|
||
cellValuesErrors.Add(ex.Message);
|
||
}
|
||
}
|
||
|
||
if (cellValuesErrors.Any())
|
||
throw new FileFormatException(string.Join("\r\n", cellValuesErrors));
|
||
|
||
return rows;
|
||
}
|
||
|
||
private static RowDto ParseRow(IXLRow xlRow)
|
||
{
|
||
return new RowDto
|
||
{
|
||
Number = xlRow.RowNumber(),
|
||
Section = GetCellValue<string>(xlRow.Cell(DefaultTemplateInfo.ColumnSection)),
|
||
Category = GetCellValue<string>(xlRow.Cell(DefaultTemplateInfo.ColumnCategory)),
|
||
CategoryInfo = GetCellValue<string>(xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo)),
|
||
DepthStart = GetCellValue<double>(xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart)),
|
||
DepthEnd = GetCellValue<double>(xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd)),
|
||
Date = GetCellValue<DateTime>(xlRow.Cell(DefaultTemplateInfo.ColumnDate)),
|
||
Duration = GetCellValue<double>(xlRow.Cell(DefaultTemplateInfo.ColumnDuration)),
|
||
Comment = GetCellValue<string>(xlRow.Cell(DefaultTemplateInfo.ColumnComment))
|
||
};
|
||
}
|
||
|
||
//TODO: вынести в метод расширения
|
||
private static T GetCellValue<T>(IXLCell cell)
|
||
{
|
||
try
|
||
{
|
||
return (T)Convert.ChangeType(cell.Value, typeof(T));
|
||
}
|
||
catch
|
||
{
|
||
throw new FileFormatException(
|
||
$"Лист '{cell.Worksheet.Name}'. Ячейка: ({cell.Address.RowNumber},{cell.Address.ColumnNumber}) содержит некорректное значение");
|
||
}
|
||
}
|
||
} |