RhSolutions-AddIn/RhSolutions.AddIn/Services/ExcelWriter.cs
2023-05-12 09:54:28 +03:00

256 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if !NET472
using System.Runtime.Versioning;
using RhSolutions.Tools;
#endif
namespace RhSolutions.Services;
#if !NET472
[SupportedOSPlatform("windows")]
#endif
public class ExcelWriter : IWriter, IDisposable
{
private readonly Application _application;
private Worksheet _worksheet;
private readonly ResultBar _resultBar;
private readonly Dictionary<string, string> _headers;
private readonly string _pricelistPath;
private ProgressBar _progressBar;
private Range _amountCell,
_skuCell,
_programLineCell,
_nameCell,
_oldSkuCell;
public ExcelWriter(Application application, IAddInConfiguration configuration)
{
_application = application;
_pricelistPath = configuration.GetPriceListPath();
_resultBar = new();
_headers = configuration.GetPriceListHeaders();
}
public void WriteProducts(Dictionary<Product, double> products)
{
WriteProducts(new[] { (string.Empty, products) });
}
public void WriteProducts(IEnumerable<(string, Dictionary<Product, double>)> products)
{
_worksheet = OpenNewPrice();
if (!_worksheet.IsValidSource())
{
_application.ActiveWorkbook.Close();
throw new ArgumentException(
$"Целевой файл {_application.ActiveWorkbook.Name} не является прайс-листом.");
}
_amountCell = _worksheet.Cells.Find(_headers["Amount"]);
_skuCell = _worksheet.Cells.Find(_headers["Sku"]);
_programLineCell = _worksheet.Cells.Find(_headers["ProductLine"]);
_nameCell = _worksheet.Cells.Find(_headers["Name"]);
_oldSkuCell = _worksheet.Cells.Find(_headers["OldSku"]);
_progressBar = new("Заполняю строки...", products
.Select(p => p.Item2)
.Sum(set => set.Count));
if (products.Count() == 1)
{
foreach (var kvp in products.First().Item2)
{
FillPositionAmountToColumns(kvp, _amountCell.Column);
_progressBar.Update();
}
FilterByAmount();
_resultBar.Update();
}
else
{
foreach (var product in products)
{
_worksheet.Columns[_amountCell.Column]
.EntireColumn
.Insert(XlInsertShiftDirection.xlShiftToRight, XlInsertFormatOrigin.xlFormatFromRightOrBelow);
Range newColumnHeader = _worksheet.Cells[_amountCell.Row, _amountCell.Column - 1];
newColumnHeader.Value2 = $"{product.Item1}";
newColumnHeader.WrapText = true;
foreach (var kvp in product.Item2)
{
FillPositionAmountToColumns(kvp, _amountCell.Column - 1, _amountCell.Column);
_progressBar.Update();
}
}
FilterByAmount();
_resultBar.Update();
}
}
private Worksheet OpenNewPrice()
{
if (_application.Workbooks
.Cast<Workbook>()
.FirstOrDefault(w => w.FullName == _pricelistPath) != null)
{
throw new ArgumentException("Шаблонный файл редактируется в другом месте");
}
return _application.Workbooks.Open(_pricelistPath, null, true).ActiveSheet;
}
private void FillPositionAmountToColumns(KeyValuePair<Product, double> positionAmount, params int[] columns)
{
Range worksheetCells = _worksheet.Cells;
Range skuColumn = _skuCell.EntireColumn;
int? row = GetPositionRow(skuColumn, positionAmount.Key.ProductSku.ToString(), positionAmount.Key.ProductLines.First());
if (row != null)
{
foreach (int column in columns)
{
Range cell = worksheetCells[row, column];
cell.AddValue(positionAmount.Value);
}
_resultBar.IncrementSuccess();
return;
}
if (_oldSkuCell != null)
{
row = GetPositionRow(_oldSkuCell.EntireColumn, positionAmount.Key.ProductSku.ToString(), positionAmount.Key.ProductLines.First());
if (row != null)
{
foreach (int column in columns)
{
Range cell = worksheetCells[row, column];
cell.AddValue(positionAmount.Value);
}
_resultBar.IncrementReplaced();
return;
}
}
string sku = positionAmount.Key.ProductSku.Article;
row = GetPositionRow(skuColumn, sku, positionAmount.Key.ProductLines.First());
if (row != null)
{
foreach (int column in columns)
{
Range cell = worksheetCells[row, column];
cell.AddValue(positionAmount.Value);
}
_resultBar.IncrementReplaced();
return;
}
FillMissing(positionAmount, columns);
_resultBar.IncrementNotFound();
}
private void FillMissing(KeyValuePair<Product, double> positionAmount, params int[] columns)
{
Range worksheetCells = _worksheet.Cells;
Range worksheetRows = _worksheet.Rows;
int skuColumn = _skuCell.Column;
int groupColumn = _programLineCell.Column;
int nameColumn = _nameCell.Column;
int row = worksheetCells[worksheetRows.Count, skuColumn]
.End[XlDirection.xlUp]
.Row + 1;
worksheetRows[row]
.EntireRow
.Insert(XlInsertShiftDirection.xlShiftDown, XlInsertFormatOrigin.xlFormatFromLeftOrAbove);
Range previous = worksheetRows[row - 1];
Range current = worksheetRows[row];
previous.Copy(current);
current.ClearContents();
worksheetCells[row, groupColumn].Value2 = positionAmount.Key.ProductLines.First();
worksheetCells[row, nameColumn].Value2 = positionAmount.Key.Name;
if (_oldSkuCell != null)
{
worksheetCells[row, skuColumn].Value2 = "Не найден";
worksheetCells[row, _oldSkuCell.Column].Value2 = positionAmount.Key.ProductSku;
}
else
{
worksheetCells[row, skuColumn].Value2 = positionAmount.Key.ProductSku;
}
foreach (int column in columns)
{
Range cell = worksheetCells[row, column];
cell.AddValue(positionAmount.Value);
}
}
private int? GetPositionRow(Range range, string sku, string group)
{
Range found = range.Find(sku);
string foundGroupValue;
if (found == null)
{
return null;
}
int firstFoundRow = found.Row;
if (string.IsNullOrEmpty(group))
{
return found.Row;
}
while (true)
{
foundGroupValue = _worksheet.Cells[found.Row, _programLineCell.Column].Value2.ToString();
if (group.Equals(foundGroupValue))
{
return found.Row;
}
found = range.FindNext(found);
if (found.Row == firstFoundRow)
{
return null;
}
}
}
private void FilterByAmount()
{
AutoFilter filter = _worksheet.AutoFilter;
int startColumn = filter.Range.Column;
filter.Range.AutoFilter(_amountCell.Column - startColumn + 1, "<>0", XlAutoFilterOperator.xlAnd, "<>");
_worksheet.Range["A1"].Activate();
}
public void Dispose()
{
_progressBar?.Dispose();
_resultBar?.Dispose();
}
}