DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/Trajectory/TrajectoryImportService.cs
2023-11-22 21:23:23 +05:00

157 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudApp.Services;
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services.Trajectory
{
public abstract class TrajectoryImportService<T> where T : TrajectoryGeoDto
{
private readonly IWellService wellService;
private readonly ITrajectoryRepository<T> trajectoryService;
protected abstract void AddCoordinatesToRow(IXLRow row, T trajectory);
protected abstract T ParseRow(IXLRow row);
public abstract string templateFileName { get; set; }
public abstract string usingTemplateFile { get; set; }
public abstract string sheetNamePlannedTrajectory { get; set; }
public abstract int headerRowsCount { get; set; }
public abstract int ColumnWellboreDepth { get; set; }
public abstract int ColumnZenithAngle { get; set; }
public abstract int ColumnAzimuthGeo { get; set; }
public abstract int ColumnAzimuthMagnetic { get; set; }
public abstract int ColumnVerticalDepth { get; set; }
public abstract int ColumnRadius { get; set; }
public abstract int ColumnComment { get; set; }
public TrajectoryImportService(ITrajectoryRepository<T> trajectoryService, IWellService wellService)
{
this.trajectoryService = trajectoryService;
this.wellService = wellService;
}
public Stream GetTemplateFile()
{
var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream($"{usingTemplateFile}.{templateFileName}");
if (stream is null)
throw new Exception($"Область {usingTemplateFile} не содержит файла с названием {templateFileName}");
return stream;
}
public async Task<Stream> ExportAsync(int idWell, CancellationToken token)
{
var trajectorys = await trajectoryService.GetAsync(idWell, token);
return MakeExelFileStream(trajectorys);
}
private Stream MakeExelFileStream(IEnumerable<T> trajectories)
{
using Stream ecxelTemplateStream = GetTemplateFile();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
AddTrajecoryToWorkbook(workbook, trajectories);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private void AddTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable<T> trajectories)
{
if (trajectories.Any())
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheet is null)
throw new FileFormatException($"Лист с именем {sheetNamePlannedTrajectory} отсутствует, либо имеет некорректное название");
AddTrajecoryToSheet(sheet, trajectories);
}
}
private void AddTrajecoryToSheet(IXLWorksheet sheet, IEnumerable<T> trajectories)
{
var rowList = trajectories.ToList();
for (int i = 0; i < rowList.Count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddCoordinatesToRow(row, rowList[i]);
}
}
public async Task<string> GetFileNameAsync(int idWell, CancellationToken token)
{
var caption = await wellService.GetWellCaptionByIdAsync(idWell, token);
return string.Format("{0}_{1}", caption, templateFileName);
}
public async Task<IEnumerable<T>> ImportAsync(int idWell, int idUser, Stream stream, CancellationToken token)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
var trajectoryRows = ParseFileStream(stream);
foreach (var row in trajectoryRows)
{
row.IdWell = idWell;
row.IdUser = idUser;
}
return trajectoryRows;
}
private IEnumerable<T> ParseFileStream(Stream stream)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkbook(workbook);
}
private IEnumerable<T> ParseWorkbook(IXLWorkbook workbook)
{
var sheetTrajectory = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheetTrajectory is null)
throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlannedTrajectory}.");
var trajectoryRows = ParseSheet(sheetTrajectory);
return trajectoryRows;
}
private IEnumerable<T> ParseSheet(IXLWorksheet sheet)
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var count = sheet.RowsUsed().Count() - headerRowsCount;
if (count > 1024)
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество строк.");
if (count <= 0)
throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой");
var trajectoryRows = new List<T>(count);
var parseErrors = new List<string>();
for (int i = 0; i < count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
try
{
var trajectoryRow = ParseRow(row);
trajectoryRows.Add(trajectoryRow);
}
catch (FileFormatException ex)
{
parseErrors.Add(ex.Message);
}
}
if (parseErrors.Any())
throw new FileFormatException(string.Join("\r\n", parseErrors));
return trajectoryRows;
}
}
}