Serghei Cebotari
6fe0a5e92b
commit 688c5426e8793b808b9c75c9a19733af0a402fcb Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 16:25:14 2024 +0300 Switch to port 8080 commit c39249f6528ec76686a9382d1dc375c07d1d5044 Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 16:24:59 2024 +0300 Switch to alpine image commit 5318d7ec3f4f3d205549cf6732fa5b066a1d0a36 Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 15:40:14 2024 +0300 Add docker commit b6cd60a973da26bc92cf1fb45b4d2396b7ce56ea Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 15:00:12 2024 +0300 Delete asynchrony commit 44a194e6d27312f3b8dd0b9c9c02d873e06e0b22 Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 14:59:29 2024 +0300 Add Equals and GetHasCode methods overrides to ProductQuantity class commit a274eadd313e12f11cc84d32e5030bbc5b187f8c Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 14:58:37 2024 +0300 Add parsers tests commit 4f969e70d9716d8ddb4f4efedd466846289d7e2b Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sun Jul 21 14:57:55 2024 +0300 Update product tests commit 2485e20d0e93bed562f929055b6867dc2574a95b Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sat Jul 20 19:34:19 2024 +0300 Implement Excel parser commit30f2e28c87
Author: Serghei Cebotari <serghei@cebotari.ru> Date: Sat Jul 20 16:58:35 2024 +0300 Implement csv parser commit08e86b43c0
Author: Serghei Cebotari <serghei@cebotari.ru> Date: Thu Jul 18 21:01:28 2024 +0300 Edit port number
77 lines
2.2 KiB
C#
77 lines
2.2 KiB
C#
using ClosedXML.Excel;
|
||
using RhSolutions.SkuParser.Models;
|
||
|
||
namespace RhSolutions.SkuParser.Services;
|
||
|
||
public class ExcelParser : ISkuParser
|
||
{
|
||
public IEnumerable<ProductQuantity> ParseProducts(IFormFile file)
|
||
{
|
||
using XLWorkbook workbook = new(file.OpenReadStream());
|
||
IXLWorksheet ws = workbook.Worksheet(1);
|
||
|
||
var leftTop = ws.FirstCellUsed()?.Address;
|
||
var rightBottom = ws.LastCellUsed()?.Address;
|
||
if (new object?[] { leftTop, rightBottom }.Any(x => x == null))
|
||
{
|
||
throw new ArgumentException($"Таблица пуста: {file.FileName}");
|
||
}
|
||
|
||
var lookupRange = ws.Range(leftTop, rightBottom).RangeUsed();
|
||
var columns = lookupRange.Columns();
|
||
|
||
var skuColumnQuantity = columns
|
||
.Select(column => new
|
||
{
|
||
Column = column,
|
||
Products = column.CellsUsed()
|
||
.Select(cell => !cell.HasFormula && Product.TryParse(cell.Value.ToString(), out Product? p) ? p : null)
|
||
})
|
||
.Select(c => new { c.Column, SkuCount = c.Products.Count(p => p != null) })
|
||
.Aggregate((l, r) => l.SkuCount > r.SkuCount ? l : r);
|
||
var skuColumn = skuColumnQuantity.SkuCount > 0 ? skuColumnQuantity.Column : null;
|
||
|
||
if (skuColumn == null)
|
||
{
|
||
throw new ArgumentException($"Столбец с артикулом не определен: {file.FileName}");
|
||
}
|
||
|
||
var quantityColumn = lookupRange.Columns().Skip(skuColumn.ColumnNumber())
|
||
.Select(column => new
|
||
{
|
||
Column = column,
|
||
IsColumnWithNumbers = column.CellsUsed()
|
||
.Count(cell => cell.Value.IsNumber == true) > column.CellsUsed().Count() / 4
|
||
})
|
||
.First(x => x.IsColumnWithNumbers)
|
||
.Column;
|
||
|
||
if (quantityColumn == null)
|
||
{
|
||
throw new ArgumentException($"Столбец с количеством не определен: {file.FileName}");
|
||
}
|
||
|
||
List<ProductQuantity> result = new();
|
||
var rows = quantityColumn.CellsUsed().Select(x => x.Address.RowNumber);
|
||
|
||
foreach (var row in rows)
|
||
{
|
||
var quantity = quantityColumn.Cell(row).Value;
|
||
var sku = skuColumn.Cell(row).Value;
|
||
|
||
if (quantity.IsNumber
|
||
&& Product.TryParse(sku.ToString(), out Product? p))
|
||
{
|
||
ProductQuantity pq = new()
|
||
{
|
||
Product = p!,
|
||
Quantity = quantity.GetNumber()
|
||
};
|
||
result.Add(pq);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|