forked from ddrilling/AsbCloudServer
157 lines
6.3 KiB
C#
157 lines
6.3 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|