2025-01-14 05:59:55 +00:00
|
|
|
|
using ClosedXML.Excel;
|
2025-01-14 14:01:01 +00:00
|
|
|
|
using RhSolutions.SkuParser.Abstractions;
|
2025-01-14 05:59:55 +00:00
|
|
|
|
using RhSolutions.SkuParser.Models;
|
|
|
|
|
|
|
|
|
|
namespace RhSolutions.SkuParser.Services;
|
|
|
|
|
|
2025-01-14 14:01:01 +00:00
|
|
|
|
public class CommonExcelParser : ISkuParser
|
2025-01-14 05:59:55 +00:00
|
|
|
|
{
|
2025-01-14 14:01:01 +00:00
|
|
|
|
public Dictionary<Product, double> ParseProducts(IFormFile file)
|
2025-01-14 05:59:55 +00:00
|
|
|
|
{
|
|
|
|
|
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}");
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-14 14:01:01 +00:00
|
|
|
|
Dictionary<Product, double> result = new();
|
2025-01-14 05:59:55 +00:00
|
|
|
|
var rows = quantityColumn.CellsUsed().Select(x => x.Address.RowNumber);
|
2025-01-14 14:01:01 +00:00
|
|
|
|
|
2025-01-14 05:59:55 +00:00
|
|
|
|
foreach (var row in rows)
|
|
|
|
|
{
|
|
|
|
|
var quantity = quantityColumn.Cell(row).Value;
|
|
|
|
|
var sku = skuColumn.Cell(row).Value;
|
2025-01-14 14:01:01 +00:00
|
|
|
|
|
|
|
|
|
if (quantity.IsNumber
|
|
|
|
|
&& Product.TryParse(sku.ToString(), out Product? p)
|
|
|
|
|
&& p != null)
|
2025-01-14 05:59:55 +00:00
|
|
|
|
{
|
2025-01-14 14:01:01 +00:00
|
|
|
|
if (result.ContainsKey(p))
|
|
|
|
|
{
|
|
|
|
|
result[p] += (double)quantity;
|
|
|
|
|
}
|
|
|
|
|
else
|
2025-01-14 05:59:55 +00:00
|
|
|
|
{
|
2025-01-14 14:01:01 +00:00
|
|
|
|
result.Add(p, (double)quantity);
|
|
|
|
|
}
|
2025-01-14 05:59:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|