Changed Drilling program creation to ClosedXML lib

This commit is contained in:
KharchenkoVV 2021-09-23 11:37:57 +05:00
parent 68eca5fdef
commit 9e89f87d47
6 changed files with 218 additions and 26 deletions

View File

@ -0,0 +1,11 @@
using AsbCloudApp.Data;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
public interface IDrillingProgramApacheService
{
Task<FileInfoDto> GetAsync(int idWell, CancellationToken token = default);
}
}

View File

@ -9,6 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.95.4" />
<PackageReference Include="itext7" Version="7.1.15" />
<PackageReference Include="Mapster" Version="7.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />

View File

@ -40,6 +40,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<IWellOperationsStatService, WellOperationsStatService>();
services.AddTransient<IMeasureService, MeasureService>();
services.AddTransient<IDrillingProgramService, DrillingProgramService>();
services.AddTransient<IDrillingProgramApacheService, DrillingProgramApacheService>();
// admin crud services:
services.AddTransient<ICrudService<DepositDto>, CrudServiceBase<DepositDto, Deposit>>();

View File

@ -0,0 +1,92 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
public class DrillingProgramApacheService : IDrillingProgramApacheService
{
private readonly IFileService fileService;
private readonly IWellService wellService;
private const int idFileCategoryDrillingProgramItems = 13;
private const int idFileCategoryDrillingProgram = 14;
public DrillingProgramApacheService(IFileService fileService, IWellService wellService)
{
this.fileService = fileService;
this.wellService = wellService;
}
public async Task<FileInfoDto> GetAsync(int idWell, CancellationToken token = default)
{
var filesInfos = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgramItems, token)
.ConfigureAwait(false);
var well = await wellService.GetAsync(idWell, token)
.ConfigureAwait(false);
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
var matchFiles = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgram, token)
.ConfigureAwait(false);
if (matchFiles is not null && matchFiles.Any())
{
matchFiles = matchFiles.OrderByDescending(f => f.UploadDate);
var matchFilesIterator = matchFiles.GetEnumerator();
matchFilesIterator.MoveNext();
var matchFile = matchFilesIterator.Current;
while (matchFilesIterator.MoveNext())
await fileService.DeletedAsync(matchFilesIterator.Current.Id, token)
.ConfigureAwait(false);
if (filesInfos.All(f => f.UploadDate <= matchFile.UploadDate))
return matchFile;
else
await fileService.DeletedAsync(matchFile.Id, token)
.ConfigureAwait(false);
}
var fileNames = filesInfos
.Where(f => f.Name != resultFileName)
.Select(f => fileService.GetFileName(f));
var stream = new MemoryStream(1024 * 1024);
UniteExcelFiles(fileNames, stream);
var buffer = stream.ToArray();
var fileStream = new MemoryStream(buffer);
return await fileService.SaveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, fileStream, token)
.ConfigureAwait(false);
}
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, Stream stream)
{
IWorkbook product = new XSSFWorkbook();
foreach (var excelFileName in excelFilesNames)
{
IWorkbook book = new XSSFWorkbook(new FileStream(excelFileName, FileMode.Open));
for (int i = 0; i < book.NumberOfSheets; i++)
{
ISheet sheet = book.GetSheetAt(i);
try
{
sheet.CopyTo(product, sheet.SheetName, true, true);
}
catch
{
//what can't be done - can't be done. ignore it.
}
}
}
product.Write(stream);
}
}
}

View File

@ -1,7 +1,7 @@
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using ClosedXML.Excel;
using ClosedXML.Excel.Drawings;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -31,8 +31,6 @@ namespace AsbCloudInfrastructure.Services
var well = await wellService.GetAsync(idWell, token)
.ConfigureAwait(false);
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
var matchFiles = await fileService.GetInfosByCategoryAsync(idWell, idFileCategoryDrillingProgram, token)
.ConfigureAwait(false);
@ -53,40 +51,124 @@ namespace AsbCloudInfrastructure.Services
.ConfigureAwait(false);
}
var resultFileName = $"Программа бурения {well.Cluster} {well.Caption}.xlsx";
var fileNames = filesInfos
.Where(f => f.Name != resultFileName)
.Select(f => fileService.GetFileName(f));
var stream = new MemoryStream(1024 * 1024);
UniteExcelFiles(fileNames, stream);
var buffer = stream.ToArray();
var fileStream = new MemoryStream(buffer);
return await fileService.SaveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, fileStream, token)
var resultExcelPath = Path.Combine(fileService.RootPath,
$"{idWell}", $"{idFileCategoryDrillingProgram}",
resultFileName);
UniteExcelFiles(fileNames, resultExcelPath);
return await fileService.SaveAsync(idWell, null, idFileCategoryDrillingProgram,
resultExcelPath, null, token)
.ConfigureAwait(false);
}
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, Stream stream)
private static void UniteExcelFiles(IEnumerable<string> excelFilesNames, string resultExcelPath)
{
IWorkbook product = new XSSFWorkbook();
var resultExcelFile = new XLWorkbook(XLEventTracking.Disabled);
const int maxAllowedColumns = 256;
foreach (var excelFileName in excelFilesNames)
{
IWorkbook book = new XSSFWorkbook(new FileStream(excelFileName, FileMode.Open));
using var sourceExcelFile = new XLWorkbook(excelFileName, XLEventTracking.Disabled);
for (int i = 0; i < book.NumberOfSheets; i++)
foreach (var sheet in sourceExcelFile.Worksheets)
{
ISheet sheet = book.GetSheetAt(i);
try
var imagesInfos = sheet.Pictures.Select(p => new ImageInfo
{
sheet.CopyTo(product, sheet.SheetName, true, true);
Id = p.Id,
Data = p.ImageStream.GetBuffer(),
Height = p.Height,
Width = p.Width,
TopLeftCellAddress = p.TopLeftCell.Address,
Left = p.Left,
Top = p.Top
}).ToList();
if (sheet.Columns().Count() > maxAllowedColumns)
{
var resultSheet = resultExcelFile.Worksheets.Add(sheet.Name);
var rngData = GetCellsRange(sheet);
rngData.CopyTo(resultSheet.Cell(1, 1));
var lastRowWithData = rngData.LastRowUsed().RangeAddress
.LastAddress.RowNumber;
for (int i = 1; i < lastRowWithData; i++)
{
resultSheet.Row(i).Height = sheet.Row(i).Height;
resultSheet.Column(i).Width = sheet.Column(i).Width;
}
CopyImagesToAnotherSheet(imagesInfos, resultSheet);
}
catch
else
{
//what can't be done - can't be done. ignore it.
RemovePicturesFromSheet(sheet);
var resultSheet = sheet.CopyTo(resultExcelFile, sheet.Name);
CopyImagesToAnotherSheet(imagesInfos, resultSheet);
}
}
}
product.Write(stream);
resultExcelFile.SaveAs(resultExcelPath,
new SaveOptions { EvaluateFormulasBeforeSaving = true});
}
private static IXLWorksheet CopyImagesToAnotherSheet(IEnumerable<ImageInfo> 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;
}
}
class ImageInfo
{
public int Id { get; set; }
public byte[] Data { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public IXLAddress TopLeftCellAddress { get; set; }
public int Left { get; set; }
public int Top { get; set; }
}
}

View File

@ -29,7 +29,9 @@ namespace AsbCloudInfrastructure.Services
.ThenInclude(c => c.CompanyType);
}
public async Task<FileInfoDto> SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default)
public async Task<FileInfoDto> SaveAsync(int idWell, int? idUser,
int idCategory, string fileFullName, Stream fileStream,
CancellationToken token = default)
{
//save info to db
var fileInfo = new AsbCloudDb.Model.FileInfo()
@ -40,21 +42,24 @@ namespace AsbCloudInfrastructure.Services
Name = Path.GetFileName(fileFullName),
UploadDate = DateTime.Now,
IsDeleted = false,
Size = fileStream.Length,
Size = fileStream?.Length ?? 0
};
var entry = db.Files.Add(fileInfo);
db.SaveChanges();
var fileId = entry.Entity.Id;
//save stream to disk
var relativePath = Path.Combine(RootPath, $"{idWell}",
if(fileStream is not null)
{
var relativePath = Path.Combine(RootPath, $"{idWell}",
$"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
Directory.CreateDirectory(Path.GetDirectoryName(relativePath));
Directory.CreateDirectory(Path.GetDirectoryName(relativePath));
using (var newfileStream = new FileStream(relativePath, FileMode.Create))
{
await fileStream.CopyToAsync(newfileStream);
using (var newfileStream = new FileStream(relativePath, FileMode.Create))
{
await fileStream.CopyToAsync(newfileStream, token);
}
}
var dto = entry.Entity.Adapt<FileInfoDto>();