using AsbCloudApp.Data.ProcessMaps.Report; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudApp.Services.ProcessMaps.WellDrilling; using ClosedXML.Excel; using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.ProcessMaps.Report; public class ProcessMapReportDataSaubStatExportService : IProcessMapReportDrillingExportService { private const int firstColumn = 2; private const int lastColumn = 35; private const int headerRowsCount = 5; private const string TemplateName = "ProcessMapReportDataSaubStatTemplate.xlsx"; private const string sheetName = "Отчёт"; private readonly IWellService wellService; private readonly IProcessMapReportDrillingService processMapReportDrillingService; public ProcessMapReportDataSaubStatExportService(IWellService wellService, IProcessMapReportDrillingService processMapReportDrillingService) { this.wellService = wellService; this.processMapReportDrillingService = processMapReportDrillingService; } public async Task<(string Name, Stream File)?> ExportAsync(int idWell, DataSaubStatRequest request, CancellationToken cancellationToken) { var well = await wellService.GetOrDefaultAsync(idWell, cancellationToken); if (well is null) return null; var stream = Assembly.GetExecutingAssembly().GetTemplateCopyStream(TemplateName); using var workbook = new XLWorkbook(stream); var data = await processMapReportDrillingService.GetAsync(idWell, request, cancellationToken); FillProcessMapToWorkbook(workbook, data); MemoryStream memoryStream = new(); workbook.SaveAs(memoryStream, new SaveOptions { }); memoryStream.Seek(0, SeekOrigin.Begin); var name = $"РТК бурение. Отчёт по скважине {well.Caption} куст {well.Cluster}.xlsx"; return (name, memoryStream); } private static void FillProcessMapToWorkbook(XLWorkbook workbook, IEnumerable data) { var sheet = workbook.GetWorksheet(sheetName); var startRow = headerRowsCount + 1; foreach (var item in data) { startRow = FillRow(sheet, item, startRow); } } private static int FillRow(IXLWorksheet sheet, ProcessMapReportDataSaubStatDto item, int startRow) { var endRow = FillIntervalData(sheet, item, startRow); var sectionStyle = sheet.Range(startRow, firstColumn, endRow - 1, lastColumn).Style; SetStyle(sectionStyle); return endRow; } private static int FillIntervalData(IXLWorksheet sheet, ProcessMapReportDataSaubStatDto interval, int row) { const int columnSection = firstColumn + 1; const int columnDepthStart = firstColumn + 2; const int columnDepthEnd = firstColumn + 3; const int columnDeltaDepth = firstColumn + 4; const int columnDrilledTime = firstColumn + 5; const int columnMode = firstColumn + 6; double? deltaDepth = interval.DeltaDepth.HasValue ? Math.Round(interval.DeltaDepth.Value, 1) : null; sheet.Cell(row, firstColumn).SetCellValue(interval.DateStart, "DD.MM.YYYY HH:MM"); sheet.Cell(row, columnSection).SetCellValue(interval.WellSectionTypeName); sheet.Cell(row, columnDepthStart).SetCellValue(Math.Round(interval.DepthStart, 2)); sheet.Cell(row, columnDepthEnd).SetCellValue(Math.Round(interval.DepthEnd, 2)); sheet.Cell(row, columnDeltaDepth).SetCellValue(deltaDepth); sheet.Cell(row, columnDrilledTime).SetCellValue(Math.Round(interval.DrilledTime, 2)); sheet.Cell(row, columnMode).SetCellValue(interval.DrillingMode); row = FillIntervalModeData(sheet, interval, columnMode, row); return row; } private static int FillIntervalModeData(IXLWorksheet sheet, ProcessMapReportDataSaubStatDto modeData, int column, int row) { int columnPressure = column + 1; int columnLoad = columnPressure + 5; int columnTorque = columnLoad + 5; int columnSpeed = columnTorque + 5; int columnTopDriveSpeed = columnSpeed + 4; int columnFlow = columnTopDriveSpeed + 2; int columnRopPlan = columnFlow + 3; int columnRopFact = columnRopPlan + 1; FillIntervalModeDataParam(sheet, modeData.PressureDiff, columnPressure, row); FillIntervalModeDataParam(sheet, modeData.AxialLoad, columnLoad, row); FillIntervalModeDataParam(sheet, modeData.TopDriveTorque, columnTorque, row); FillIntervalModeDataSpeed(sheet, modeData.SpeedLimit, columnSpeed, row); FillIntervalModeTopDriveSpeed(sheet, modeData.TopDriveSpeed, columnTopDriveSpeed, row); FillIntervalModeFlow(sheet, modeData.Flow, columnFlow, row); double? ropPlan = modeData.Rop.Plan.HasValue ? Math.Round(modeData.Rop.Plan.Value, 1) : null; double? ropFact = modeData.Rop.Fact.HasValue ? Math.Round(modeData.Rop.Fact.Value, 1) : null; sheet.Cell(row, columnRopPlan).SetCellValue(ropPlan); sheet.Cell(row, columnRopFact).SetCellValue(ropFact); return row + 1; } private static void FillIntervalModeDataParam(IXLWorksheet sheet, ProcessMapReportDataSaubStatParamsDto dataParam, int column, int row) { const int columnOffsetSpPlan = 0; const int columnOffsetSpFact = 1; const int columnOffsetFact = 2; const int columnOffsetLimit = 3; const int columnOffsetPercent = 4; double? setpointPlan = dataParam.SetpointPlan.HasValue ? Math.Round(dataParam.SetpointPlan.Value) : null; double? setpointFact = dataParam.SetpointFact.HasValue ? Math.Round(dataParam.SetpointFact.Value, 1) : null; double? factWavg = dataParam.FactWavg.HasValue ? Math.Round(dataParam.FactWavg.Value, 1) : null; double? limit = dataParam.Limit.HasValue ? Math.Round(dataParam.Limit.Value, 1) : null; double? setpointUsage = dataParam.SetpointUsage.HasValue ? Math.Round(dataParam.SetpointUsage.Value, 1) : null; sheet.Cell(row, column + columnOffsetSpPlan).SetCellValue(setpointPlan); sheet.Cell(row, column + columnOffsetSpFact).SetCellValue(setpointFact); sheet.Cell(row, column + columnOffsetFact).SetCellValue(factWavg); sheet.Cell(row, column + columnOffsetLimit).SetCellValue(limit); sheet.Cell(row, column + columnOffsetPercent).SetCellValue(setpointUsage); } private static void FillIntervalModeDataSpeed(IXLWorksheet sheet, ProcessMapReportDataSaubStatParamsDto dataParam, int column, int row) { const int columnOffsetSpPlan = 0; const int columnOffsetSpFact = 1; const int columnOffsetFact = 2; const int columnOffsetPercent = 3; double? setpointPlan = dataParam.SetpointPlan.HasValue ? Math.Round(dataParam.SetpointPlan.Value) : null; double? setpointFact = dataParam.SetpointFact.HasValue ? Math.Round(dataParam.SetpointFact.Value, 1) : null; double? factWavg = dataParam.FactWavg.HasValue ? Math.Round(dataParam.FactWavg.Value, 1) : null; double? setpointUsage = dataParam.SetpointUsage.HasValue ? Math.Round(dataParam.SetpointUsage.Value, 1) : null; sheet.Cell(row, column + columnOffsetSpPlan).SetCellValue(setpointPlan); sheet.Cell(row, column + columnOffsetSpFact).SetCellValue(setpointFact); sheet.Cell(row, column + columnOffsetFact).SetCellValue(factWavg); sheet.Cell(row, column + columnOffsetPercent).SetCellValue(setpointUsage); } private static void FillIntervalModeTopDriveSpeed(IXLWorksheet sheet, ProcessMapReportDataSaubStatParamsDto dataParam, int column, int row) { const int columnOffsetSpPlan = 0; const int columnOffsetFact = 1; double? setpointPlan = dataParam.SetpointPlan.HasValue ? Math.Round(dataParam.SetpointPlan.Value) : null; double? factWavg = dataParam.FactWavg.HasValue ? Math.Round(dataParam.FactWavg.Value, 1) : null; sheet.Cell(row, column + columnOffsetSpPlan).SetCellValue(setpointPlan); sheet.Cell(row, column + columnOffsetFact).SetCellValue(factWavg); } private static void FillIntervalModeFlow(IXLWorksheet sheet, ProcessMapReportDataSaubStatParamsDto dataParam, int column, int row) { const int columnOffsetSpPlan = 0; const int columnOffsetFact = 1; const int columnOffsetLimit = 2; double? setpointPlan = dataParam.SetpointPlan.HasValue ? Math.Round(dataParam.SetpointPlan.Value) : null; double? factWavg = dataParam.FactWavg.HasValue ? Math.Round(dataParam.FactWavg.Value, 1) : null; double? limit = dataParam.Limit.HasValue ? Math.Round(dataParam.Limit.Value, 1) : null; sheet.Cell(row, column + columnOffsetSpPlan).SetCellValue(setpointPlan); sheet.Cell(row, column + columnOffsetFact).SetCellValue(factWavg); sheet.Cell(row, column + columnOffsetLimit).SetCellValue(limit); } private static void SetStyle(IXLStyle style) { style.Border.RightBorder = XLBorderStyleValues.Thin; style.Border.LeftBorder = XLBorderStyleValues.Thin; style.Border.TopBorder = XLBorderStyleValues.Thin; style.Border.BottomBorder = XLBorderStyleValues.Thin; style.Border.InsideBorder = XLBorderStyleValues.Thin; style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; } }