using System.IO; namespace RhSolutions.Services; public class GuessReader : IReader { private readonly Application _application; private ProgressBar _progressBar; public GuessReader(Application application) { _application = application; } public Dictionary ReadProducts(Range range) { _progressBar = new("Поиск возможных пар артикул-количество...", range.Columns.Count); int? productColumnIndex = null; List amountColumnIndeces = new(); for (int column = 1; column < range.Columns.Count + 1; column++) { _progressBar.Update(); if (productColumnIndex == null && IsProductColumn(range.Columns[column])) { productColumnIndex = column; } else if (IsAmountColumn(range.Columns[column])) { amountColumnIndeces.Add(column); } } if (productColumnIndex == null) { throw new ArgumentException("Колонка с артикулом не определена"); } if (amountColumnIndeces.Count == 0) { throw new ArgumentException("Колонка с количеством не определена"); } else if (amountColumnIndeces.Count == 1) { return GetDictionaryFromColumns(range.Columns[productColumnIndex], range.Columns[amountColumnIndeces.First()]); } else { int amountColumnIndex = amountColumnIndeces .Where(i => i > productColumnIndex) .FirstOrDefault(); if (amountColumnIndex == 0) { amountColumnIndex = amountColumnIndeces .OrderBy(i => i) .Where(i => i < productColumnIndex) .LastOrDefault(); } if (amountColumnIndex == 0) { throw new ArgumentException("Колонка с количеством не определена"); } return GetDictionaryFromColumns(range.Columns[productColumnIndex], range.Columns[amountColumnIndex]); } } private bool IsProductColumn(Range column) { int successCounter = 0; var cells = column.Value2; if (cells == null) { return false; } for (int row = 1; row < column.Rows.Count + 1; row++) { object currentCell = column.Rows.Count == 1 ? cells : cells[row, 1]; if (currentCell == null) { continue; } if (ProductSku.TryParse(currentCell.ToString(), out IEnumerable skus)) { successCounter++; } if (successCounter > 2) { return true; } } return successCounter > 0; } private bool IsAmountColumn(Range column) { int successCounter = 0; var cells = column.Value2; if (cells == null) { return false; } for (int row = 1; row < column.Rows.Count + 1; row++) { object currentCell = column.Rows.Count == 1 ? cells : cells[row, 1]; if (currentCell == null) { continue; } double value = 0.0; if (currentCell.GetType() == typeof(double)) { value = (double)currentCell; } else if (currentCell.GetType() == typeof(string)) { double.TryParse((string)currentCell, out value); } if (value == 0) { continue; } if (value > 30000) { return false; } successCounter++; if (successCounter > 5) { return true; } } return successCounter > 0; } private Dictionary GetDictionaryFromColumns(Range productColumn, Range amountColumn) { Dictionary result = new(); _progressBar = new("Заполняю словарь значений...", productColumn.Rows.Count); for (int row = 1; row < productColumn.Rows.Count + 1; row++) { _progressBar.Update(); var amountCells = amountColumn.Value2; object currentAmountCell = productColumn.Rows.Count == 1 ? amountCells : amountCells[row, 1]; var productCells = productColumn.Value2; object currentProductCell = productColumn.Rows.Count == 1 ? productCells : productCells[row, 1]; double amountValue = 0.0; if (currentAmountCell == null || currentProductCell == null) { continue; } if (ProductSku.TryParse(currentProductCell.ToString(), out IEnumerable skus)) { Product p = new(skus.First()) { Name = "Распознанный артикул" }; if (currentAmountCell.GetType() == typeof(double)) { amountValue = (double)currentAmountCell; } else if (currentAmountCell.GetType() == typeof(string)) { double.TryParse((string)currentAmountCell, out amountValue); } if (result.ContainsKey(p)) { result[p] += amountValue; } else { result.Add(p, amountValue); } } } return result; } public List<(string, Dictionary)> ReadProducts(IEnumerable worksheets) { List<(string, Dictionary)> result = new(); foreach (Worksheet worksheet in worksheets) { string wbName = Path.GetFileNameWithoutExtension( worksheet.Parent.Name); Range range = worksheet.UsedRange; var productsDict = ReadProducts(range); result.Add((wbName, productsDict)); } return result; } public List<(string, Dictionary)> ReadProducts(string[] files) { _progressBar = new("Открываю исходные файлы...", files.Length); List worksheets = new(); _application.ScreenUpdating = false; foreach (string file in files) { Workbook wb = _application.Workbooks.Open(file); worksheets.Add(wb.ActiveSheet); _progressBar.Update(); } _application.ScreenUpdating = true; var result = ReadProducts(worksheets); foreach (var ws in worksheets) { ws.Parent.Close(); } return result; } public void Dispose() { _progressBar?.Dispose(); } }