using ClosedXML.Excel; using ClosedXML.Excel.Drawings; using System.Collections.Generic; using System.IO; using System.Linq; namespace AsbCloudInfrastructure.Services.DrillingProgram { #nullable enable internal class DrillingProgramMaker { private const int maxAllowedColumns = 256; public static void UniteExcelFiles(IEnumerable excelFilesNames, string resultExcelPath, IEnumerable parts, AsbCloudApp.Data.WellDto well) { var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled); var titleSheet = resultExcelFile.AddWorksheet("Титульный лист"); var marks = parts .Where(p => p.File is not null) .SelectMany(p => p.File!.FileMarks); var titleSheetMaker = new TitleListSheet(marks, well); titleSheetMaker.Draw(titleSheet); var contentSheet = resultExcelFile.AddWorksheet("Содержание"); var contentListSheetMaker = new ContentListSheet(parts); contentListSheetMaker.Draw(contentSheet); var filteredFileNames = excelFilesNames.Distinct(); foreach (var excelFileName in filteredFileNames) { using var workbookSrc = new XLWorkbook(excelFileName, XLEventTracking.Disabled); foreach (var sheet in workbookSrc.Worksheets) { if (sheet.Visibility == XLWorksheetVisibility.Visible) CopySheet(resultExcelFile, sheet); } } resultExcelFile.SaveAs(resultExcelPath, new SaveOptions { EvaluateFormulasBeforeSaving = true }); } private static void CopySheet(XLWorkbook workbookDst, IXLWorksheet sheetSrc) { var newSheetName = sheetSrc.Name; var suffix = ""; int index = 1; while (workbookDst.Worksheets.Contains(newSheetName)) { newSheetName = sheetSrc.Name; suffix = $"_{index++}"; if (newSheetName.Length + suffix.Length >= 31) newSheetName = newSheetName[..(31 - suffix.Length)]; newSheetName += suffix; } var imagesInfos = sheetSrc.Pictures.Select(p => new ImageInfo { Id = p.Id, Data = p.ImageStream.GetBuffer(), Height = p.Height, Width = p.Width, TopLeftCellAddress = p.TopLeftCell.Address, Left = p.Left, Top = p.Top }).ToList(); IXLWorksheet resultSheet; if (sheetSrc.Columns().Count() > maxAllowedColumns) { resultSheet = workbookDst.Worksheets.Add(newSheetName); var rngData = GetCellsRange(sheetSrc); rngData.CopyTo(resultSheet.Cell(1, 1)); var lastRowWithData = rngData.LastRowUsed().RangeAddress .LastAddress.RowNumber; for (int i = 1; i < lastRowWithData; i++) { resultSheet.Row(i).Height = sheetSrc.Row(i).Height; resultSheet.Column(i).Width = sheetSrc.Column(i).Width; } } else { RemovePicturesFromSheet(sheetSrc); resultSheet = sheetSrc.CopyTo(workbookDst, newSheetName); } CopyImagesToAnotherSheet(imagesInfos, resultSheet); } private static IXLWorksheet CopyImagesToAnotherSheet(IEnumerable imagesInfos, IXLWorksheet resultSheet) { foreach (var image in imagesInfos) { var stream = new MemoryStream(); stream.Write(image.Data, 0, image.Data.Length); resultSheet.AddPicture(stream) .WithPlacement(XLPicturePlacement.Move) .WithSize(image.Width, image.Height) .MoveTo(resultSheet.Cell(image.TopLeftCellAddress), image.Left, image.Top); } return resultSheet; } private static void RemovePicturesFromSheet(IXLWorksheet sheet) { var filteredPics = sheet.Pictures.Select(p => p.Name).Distinct().ToList(); foreach (var n in filteredPics) sheet.Pictures.Delete(n); } private static IXLRange GetCellsRange(IXLWorksheet sheet) { var firstTableCell = sheet.FirstCellUsed(); var lastTableCell = sheet.LastCellUsed(); var rngData = sheet.Range(firstTableCell.Address, lastTableCell.Address); return rngData; } } #nullable disable }