aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--RhSolutions.AddIn/AddIn/ResetBarFunction.cs10
-rw-r--r--RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs14
-rw-r--r--RhSolutions.AddIn/AddIn/RhSolutionsFunction.cs26
-rw-r--r--RhSolutions.AddIn/Controllers/CombineTool.cs59
-rw-r--r--RhSolutions.AddIn/Controllers/ConvertTool.cs27
-rw-r--r--RhSolutions.AddIn/Controllers/ExportTool.cs97
-rw-r--r--RhSolutions.AddIn/Controllers/MergeTool.cs56
-rw-r--r--RhSolutions.AddIn/Controllers/RibbonController.cs34
-rw-r--r--RhSolutions.AddIn/Controllers/ToolBase.cs183
-rw-r--r--RhSolutions.AddIn/Models/PriceListBase.cs15
-rw-r--r--RhSolutions.AddIn/Models/ProgressBar.cs22
-rw-r--r--RhSolutions.AddIn/Models/ResultBar.cs45
-rw-r--r--RhSolutions.AddIn/Models/SourcePriceList.cs112
-rw-r--r--RhSolutions.AddIn/Models/StatusbarBase.cs18
-rw-r--r--RhSolutions.AddIn/Models/TargetPriceList.cs39
-rw-r--r--RhSolutions.AddIn/RhSolutions.AddIn.csproj3
-rw-r--r--RhSolutions.AddIn/Services/ExcelFileDialog.cs45
-rw-r--r--RhSolutions.AddIn/Services/IAddInConfiguration.cs2
-rw-r--r--RhSolutions.AddIn/Services/IExcelReader.cs8
-rw-r--r--RhSolutions.AddIn/Services/IExcelWriter.cs7
-rw-r--r--RhSolutions.AddIn/Services/IFileDialog.cs7
-rw-r--r--RhSolutions.AddIn/Services/RhAddInConfiguration.cs (renamed from RhSolutions.AddIn/Services/AddInConfiguration.cs)16
-rw-r--r--RhSolutions.AddIn/Services/RhExcelReader.cs169
-rw-r--r--RhSolutions.AddIn/Services/RhExcelWriter.cs256
-rw-r--r--RhSolutions.AddIn/Services/WorksheetExtensions.cs (renamed from RhSolutions.AddIn/Models/WorksheetExtensions.cs)13
-rw-r--r--RhSolutions.AddIn/Tools/ConvertTool.cs20
-rw-r--r--RhSolutions.AddIn/Tools/EventsUtil.cs (renamed from RhSolutions.AddIn/Services/EventsUtil.cs)8
-rw-r--r--RhSolutions.AddIn/Tools/ExportTool.cs20
-rw-r--r--RhSolutions.AddIn/Tools/MergeTool.cs23
-rw-r--r--RhSolutions.AddIn/Tools/ProgressBar.cs28
-rw-r--r--RhSolutions.AddIn/Tools/ResultBar.cs49
-rw-r--r--RhSolutions.AddIn/Tools/StatusbarBase.cs24
-rw-r--r--RhSolutions.AddIn/Tools/ToolBase.cs22
-rw-r--r--RhSolutions.AddIn/Usings.cs4
-rw-r--r--RhSolutions.ExcelExtensions/Cell.cs26
-rw-r--r--RhSolutions.ExcelExtensions/Column.cs60
-rw-r--r--RhSolutions.ExcelExtensions/ColumnEnumerator.cs54
-rw-r--r--RhSolutions.ExcelExtensions/Columns.cs24
-rw-r--r--RhSolutions.ExcelExtensions/ColumnsEnumerator.cs16
-rw-r--r--RhSolutions.ExcelExtensions/Row.cs51
-rw-r--r--RhSolutions.ExcelExtensions/RowEnumerator.cs54
-rw-r--r--RhSolutions.ExcelExtensions/Rows.cs23
-rw-r--r--RhSolutions.ExcelExtensions/RowsEnumerator.cs17
-rw-r--r--RhSolutions.ExcelExtensions/Table.cs35
-rw-r--r--RhSolutions.ExcelExtensions/TableCell.cs24
-rw-r--r--RhSolutions.Tests/ExcelTablesTests.cs65
-rw-r--r--RhSolutions.sln6
47 files changed, 926 insertions, 1010 deletions
diff --git a/RhSolutions.AddIn/AddIn/ResetBarFunction.cs b/RhSolutions.AddIn/AddIn/ResetBarFunction.cs
index a1a34fa..32bddfa 100644
--- a/RhSolutions.AddIn/AddIn/ResetBarFunction.cs
+++ b/RhSolutions.AddIn/AddIn/ResetBarFunction.cs
@@ -1,9 +1,15 @@
-namespace RhSolutions.AddIn;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+namespace RhSolutions.AddIn;
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
public static class ResetBarFunction
{
[ExcelFunction]
- public static void _ResetStatusBar()
+ public static void StatusBarReset()
{
RhSolutionsAddIn.Excel.StatusBar = false;
}
diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
index 796e540..0ef2d69 100644
--- a/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
+++ b/RhSolutions.AddIn/AddIn/RhSolutionsAddIn.cs
@@ -1,8 +1,15 @@
using ExcelDna.IntelliSense;
+using RhSolutions.Tools;
using System.Net;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
namespace RhSolutions.AddIn;
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
public sealed class RhSolutionsAddIn : IExcelAddIn
{
public static Application Excel { get; private set; }
@@ -14,9 +21,12 @@ public sealed class RhSolutionsAddIn : IExcelAddIn
IServiceCollection Services = new ServiceCollection();
Services.AddHttpClient()
+ .AddSingleton((Application)ExcelDnaUtil.Application)
.AddSingleton<IDatabaseClient, RhDatabaseClient>()
- .AddSingleton<IAddInConfiguration, AddInConfiguration>()
- .AddSingleton((Application)ExcelDnaUtil.Application);
+ .AddSingleton<IAddInConfiguration, RhAddInConfiguration>()
+ .AddTransient<IFileDialog, ExcelFileDialog>()
+ .AddTransient<IExcelReader, RhExcelReader>()
+ .AddTransient<IExcelWriter, RhExcelWriter>();
ServiceProvider = Services.BuildServiceProvider();
Configuration = ServiceProvider.GetService<IAddInConfiguration>();
diff --git a/RhSolutions.AddIn/AddIn/RhSolutionsFunction.cs b/RhSolutions.AddIn/AddIn/RhSolutionsFunction.cs
index bb7bba5..d45ed10 100644
--- a/RhSolutions.AddIn/AddIn/RhSolutionsFunction.cs
+++ b/RhSolutions.AddIn/AddIn/RhSolutionsFunction.cs
@@ -1,23 +1,29 @@
-namespace RhSolutions.AddIn;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+namespace RhSolutions.AddIn;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
public class RhSolutionsFunction
{
[ExcelFunction(Description = "Распознать артикул и попробовать найти его в прайс-листе")]
public static object RHSOLUTIONS([ExcelArgument(Name = "\"Строка с названием материала\"")] string line)
{
IDatabaseClient databaseClient = RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
- IEnumerable<Product> requestResult = ExcelAsyncUtil.Run("Database request", line, delegate
+
+ Sku.TryParse(line, out var skus);
+
+ if (ExcelAsyncUtil.Run("Database request", line, delegate
{
return databaseClient.GetProducts(line)
.GetAwaiter()
.GetResult();
- }) as IEnumerable<Product>;
-
- Sku.TryParse(line, out var skus);
-
- if (requestResult == null)
+ }) is not IEnumerable<Product> requestResult)
{
- if (skus.Count() > 0)
+ if (skus.Any())
{
return $"{skus.First()} ...";
}
@@ -29,12 +35,12 @@ public class RhSolutionsFunction
else
{
- if (requestResult.Count() == 0 && skus.Count() == 0)
+ if (!requestResult.Any() && !skus.Any())
{
return ExcelError.ExcelErrorNA;
}
- else if (requestResult.Count() == 0)
+ else if (!requestResult.Any())
{
return $"{skus.First()}";
}
diff --git a/RhSolutions.AddIn/Controllers/CombineTool.cs b/RhSolutions.AddIn/Controllers/CombineTool.cs
deleted file mode 100644
index 355539f..0000000
--- a/RhSolutions.AddIn/Controllers/CombineTool.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using RhSolutions.AddIn;
-
-namespace RhSolutions.Controllers;
-
-internal class CombineTool : ToolBase
-{
- private List<SourcePriceList> SourceFiles { get; set; }
-
- public CombineTool()
- {
- var dialog = RhSolutionsAddIn.Excel.FileDialog[Microsoft.Office.Core.MsoFileDialogType.msoFileDialogFilePicker];
- dialog.AllowMultiSelect = true;
- dialog.Filters.Add("Файлы Excel", "*.xls; *.xlsx; *.xlsm");
-
- if (dialog.Show() < 0)
- {
- List<string> files = new();
-
- foreach (string file in dialog.SelectedItems)
- {
- files.Add(file);
- }
-
- SourceFiles = SourcePriceList.GetSourceLists(files.ToArray());
- }
-
- else
- {
- throw new Exception("Не выбраны файлы");
- }
- }
-
- public override void FillTarget()
- {
- using (ProgressBar = new ProgressBar("Заполняю строки...", SourceFiles.Sum(file => file.PositionAmount.Count)))
- using (ResultBar = new ResultBar())
- {
- foreach (SourcePriceList source in SourceFiles)
- {
- TargetFile.Sheet.Columns[TargetFile.AmountCell.Column]
- .EntireColumn
- .Insert(XlInsertShiftDirection.xlShiftToRight, XlInsertFormatOrigin.xlFormatFromRightOrBelow);
-
- Range newColumnHeader = TargetFile.Sheet.Cells[TargetFile.AmountCell.Row, TargetFile.AmountCell.Column - 1];
- newColumnHeader.Value2 = $"{source.Name}";
- newColumnHeader.WrapText = true;
-
- foreach (var kvp in source.PositionAmount)
- {
- FillPositionAmountToColumns(kvp, TargetFile.AmountCell.Column - 1, TargetFile.AmountCell.Column);
- ProgressBar.Update();
- }
- }
-
- FilterByAmount();
- ResultBar.Update();
- }
- }
-}
diff --git a/RhSolutions.AddIn/Controllers/ConvertTool.cs b/RhSolutions.AddIn/Controllers/ConvertTool.cs
deleted file mode 100644
index 754fde1..0000000
--- a/RhSolutions.AddIn/Controllers/ConvertTool.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace RhSolutions.Controllers;
-
-internal class ConvertTool : ToolBase
-{
- private SourcePriceList Current { get; set; }
-
- public ConvertTool()
- {
- Current = new SourcePriceList(ExcelApp.ActiveWorkbook);
- }
-
- public override void FillTarget()
- {
- using (ProgressBar = new ProgressBar("Заполняю строки...", Current.PositionAmount.Count))
- using (ResultBar = new ResultBar())
- {
- foreach (var kvp in Current.PositionAmount)
- {
- FillPositionAmountToColumns(kvp, TargetFile.AmountCell.Column);
- ProgressBar.Update();
- }
-
- FilterByAmount();
- ResultBar.Update();
- }
- }
-} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Controllers/ExportTool.cs b/RhSolutions.AddIn/Controllers/ExportTool.cs
deleted file mode 100644
index 16b51aa..0000000
--- a/RhSolutions.AddIn/Controllers/ExportTool.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using RhSolutions.Models;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace RhSolutions.Controllers;
-
-internal class ExportTool : ToolBase
-{
- private Dictionary<Product, double> PositionAmount;
- private readonly Range Selection;
-
- public ExportTool()
- {
- Selection = ExcelApp.Selection;
- GetSelected();
-
- if (PositionAmount.Count == 0)
- {
- throw new Exception("В выделенном диапазоне не найдены позиции для экспорта");
- }
- }
-
- public override void FillTarget()
- {
- using (ProgressBar = new ProgressBar("Заполняю строки...", PositionAmount.Count))
- using (ResultBar = new ResultBar())
- {
- foreach (var kvp in PositionAmount)
- {
- FillPositionAmountToColumns(kvp, TargetFile.AmountCell.Column);
- ProgressBar.Update();
- }
-
- FilterByAmount();
- ResultBar.Update();
- }
- }
-
- private void GetSelected()
- {
- object[,] cells = Selection.Value2;
- PositionAmount = new Dictionary<Product, double>();
-
- int rowsCount = Selection.Rows.Count;
-
- for (int row = 1; row <= rowsCount; row++)
- {
- if (cells[row, 1] == null || cells[row, 2] == null)
- continue;
-
- string sku = null;
- double? amount = null;
-
- for (int column = 1; column <= 2; column++)
- {
- object current = cells[row, column];
-
- if (Sku.TryParse(current.ToString(), out var rauSku))
- {
- sku = rauSku.FirstOrDefault().ToString() ?? null;
- }
-
- else if (current.GetType() == typeof(string)
- && double.TryParse(current.ToString(), out _))
- {
- amount = double.Parse((string)current);
- }
-
- else if (current.GetType() == typeof(double))
- {
- amount = (double)current;
- }
- }
-
- if (sku == null || amount == null)
- {
- continue;
- }
-
- Product position = new Product
- {
- ProductSku = sku
- };
-
- if (PositionAmount.ContainsKey(position))
- {
- PositionAmount[position] += amount.Value;
- }
-
- else
- {
- PositionAmount.Add(position, amount.Value);
- }
- }
- }
-}
-
diff --git a/RhSolutions.AddIn/Controllers/MergeTool.cs b/RhSolutions.AddIn/Controllers/MergeTool.cs
deleted file mode 100644
index 8566ee7..0000000
--- a/RhSolutions.AddIn/Controllers/MergeTool.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using RhSolutions.AddIn;
-using RhSolutions.Models;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace RhSolutions.Controllers
-{
- internal class MergeTool : ToolBase
- {
- private List<SourcePriceList> SourceFiles { get; set; }
-
- public MergeTool()
- {
- var dialog = RhSolutionsAddIn.Excel.FileDialog[Microsoft.Office.Core.MsoFileDialogType.msoFileDialogFilePicker];
- dialog.AllowMultiSelect = true;
- dialog.Filters.Add("Файлы Excel", "*.xls; *.xlsx; *.xlsm");
-
- if ( dialog.Show() < 0)
- {
- List<string> files = new();
-
- foreach (string file in dialog.SelectedItems)
- {
- files.Add(file);
- }
-
- SourceFiles = SourcePriceList.GetSourceLists(files.ToArray());
- }
-
- else
- {
- throw new Exception("Не выбраны файлы");
- }
- }
-
- public override void FillTarget()
- {
- using (ProgressBar = new ProgressBar("Заполняю строки...", SourceFiles.Sum(x => x.PositionAmount.Count)))
- using (ResultBar = new ResultBar())
- {
- foreach (SourcePriceList source in SourceFiles)
- {
- foreach (var kvp in source.PositionAmount)
- {
- FillPositionAmountToColumns(kvp, TargetFile.AmountCell.Column);
- ProgressBar.Update();
- }
- }
-
- FilterByAmount();
- ResultBar.Update();
- }
- }
- }
-}
diff --git a/RhSolutions.AddIn/Controllers/RibbonController.cs b/RhSolutions.AddIn/Controllers/RibbonController.cs
index 978732d..880d49f 100644
--- a/RhSolutions.AddIn/Controllers/RibbonController.cs
+++ b/RhSolutions.AddIn/Controllers/RibbonController.cs
@@ -1,11 +1,17 @@
using ExcelDna.Integration.CustomUI;
-using RhSolutions.AddIn;
+using RhSolutions.Tools;
using System.Reflection;
using System.Runtime.InteropServices;
+#if! NET472
+using System.Runtime.Versioning;
+#endif
using System.Windows.Forms;
namespace RhSolutions.Controllers;
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
[ComVisible(true)]
public class RibbonController : ExcelRibbon
{
@@ -21,10 +27,7 @@ public class RibbonController : ExcelRibbon
<group id='priceList' label='Прайс-лист'>
<button id='export' getEnabled='GetExportEnabled' label='Экспорт в новый файл' size='normal' imageMso='PivotExportToExcel' onAction='OnToolPressed'/>
<button id='convert' getEnabled='GetConvertEnabled' label='Актуализировать' size='normal' imageMso='FileUpdate' onAction='OnToolPressed'/>
- <menu id='conjoinMenu' label='Объединить' imageMso='Copy'>
- <button id='merge' label='Сложить' onAction='OnToolPressed'/>
- <button id='combine' label='По колонкам' onAction='OnToolPressed'/>
- </menu>
+ <button id='merge' label='Объединить' size='normal' imageMso='Copy' onAction='OnToolPressed'/>
</group>
<group id='rausettings' getLabel='GetVersionLabel'>
<button id='setPriceList' getLabel='GetPriceListPathLabel' size='large' imageMso='TableExcelSpreadsheetInsert' onAction='OnSetPricePressed'/>
@@ -42,22 +45,17 @@ public class RibbonController : ExcelRibbon
public static void RefreshControl(string id)
{
- if (ribbonUi != null)
- {
- ribbonUi.InvalidateControl(id);
- }
+ ribbonUi?.InvalidateControl(id);
}
public void OnSetPricePressed(IRibbonControl control)
{
- var dialog = RhSolutionsAddIn.Excel
- .FileDialog[Microsoft.Office.Core.MsoFileDialogType.msoFileDialogFilePicker];
- dialog.AllowMultiSelect = false;
- dialog.Filters.Add("Файлы Excel", "*.xls; *.xlsx; *.xlsm");
+ IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetService<IFileDialog>();
+ string file = dialog.GetFile();
- if (dialog.Show() < 0)
+ if (!string.IsNullOrEmpty(file))
{
- RhSolutionsAddIn.Configuration.SetPriceListPath(dialog.SelectedItems.Item(1));
+ RhSolutionsAddIn.Configuration.SetPriceListPath(file);
RhSolutionsAddIn.Configuration.SaveSettings();
}
}
@@ -71,11 +69,9 @@ public class RibbonController : ExcelRibbon
"export" => new ExportTool(),
"convert" => new ConvertTool(),
"merge" => new MergeTool(),
- "combine" => new CombineTool(),
_ => throw new Exception("Неизвестный инструмент"),
};
- tool.OpenNewPrice();
- tool.FillTarget();
+ tool.Execute();
}
catch (Exception exception)
@@ -122,6 +118,6 @@ public class RibbonController : ExcelRibbon
public string GetPriceListPathLabel(IRibbonControl control)
{
string name = RhSolutionsAddIn.Configuration.GetPriceListFileName();
- return string.IsNullOrEmpty(name) ? "Нет файла шаблона!" : name;
+ return string.IsNullOrEmpty(name) ? "Шаблонный файл" : name;
}
}
diff --git a/RhSolutions.AddIn/Controllers/ToolBase.cs b/RhSolutions.AddIn/Controllers/ToolBase.cs
deleted file mode 100644
index 3f9d82d..0000000
--- a/RhSolutions.AddIn/Controllers/ToolBase.cs
+++ /dev/null
@@ -1,183 +0,0 @@
-using RhSolutions.AddIn;
-
-namespace RhSolutions.Controllers
-{
- internal abstract class ToolBase
- {
- protected Application ExcelApp = RhSolutionsAddIn.Excel;
- protected IAddInConfiguration Configuration = RhSolutionsAddIn.Configuration;
- protected TargetPriceList TargetFile { get; set; }
- protected ResultBar ResultBar { get; set; }
- protected ProgressBar ProgressBar { get; set; }
- public abstract void FillTarget();
-
- public void OpenNewPrice()
- {
- if (ExcelApp.Workbooks
- .Cast<Workbook>()
- .FirstOrDefault(w => w.FullName == Configuration.GetPriceListPath()) != null)
- {
- throw new ArgumentException("Шаблонный файл редактируется в другом месте");
- }
-
- Workbook wb = ExcelApp.Workbooks.Open(Configuration.GetPriceListPath(), null, true);
-
- try
- {
- TargetFile = new TargetPriceList(wb);
- }
-
- catch (Exception exception)
- {
- if (wb != null)
- {
- wb.Close();
- }
-
- throw exception;
- }
- }
-
- protected void FillPositionAmountToColumns(KeyValuePair<Product, double> positionAmount, params int[] columns)
- {
- Range worksheetCells = TargetFile.Sheet.Cells;
- Range skuColumn = TargetFile.SkuCell.EntireColumn;
-
- int? row = GetPositionRow(skuColumn, positionAmount.Key.ProductSku, positionAmount.Key.ProductLine);
-
- if (row != null)
- {
- foreach (int column in columns)
- {
- Range cell = worksheetCells[row, column];
- cell.AddValue(positionAmount.Value);
- }
-
- ResultBar.IncrementSuccess();
- return;
- }
-
- if (TargetFile.OldSkuCell != null)
- {
- row = GetPositionRow(TargetFile.OldSkuCell.EntireColumn, positionAmount.Key.ProductSku, positionAmount.Key.ProductLine);
-
- 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.Substring(1, 6);
- row = GetPositionRow(skuColumn, sku, positionAmount.Key.ProductLine);
-
- 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();
- }
-
- protected void FillMissing(KeyValuePair<Product, double> positionAmount, params int[] columns)
- {
- Range worksheetCells = TargetFile.Sheet.Cells;
- Range worksheetRows = TargetFile.Sheet.Rows;
- int skuColumn = TargetFile.SkuCell.Column;
- int groupColumn = TargetFile.GroupCell.Column;
- int nameColumn = TargetFile.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.ProductLine;
- worksheetCells[row, nameColumn].Value2 = positionAmount.Key.Name;
-
- if (TargetFile.OldSkuCell != null)
- {
- worksheetCells[row, skuColumn].Value2 = "Не найден";
- worksheetCells[row, TargetFile.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);
- }
- }
-
- protected 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 = TargetFile.Sheet.Cells[found.Row, TargetFile.GroupCell.Column].Value2.ToString();
-
- if (group.Equals(foundGroupValue))
- {
- return found.Row;
- }
-
- found = range.FindNext(found);
-
- if (found.Row == firstFoundRow)
- {
- return null;
- }
- }
- }
-
- protected void FilterByAmount()
- {
- AutoFilter filter = TargetFile.Sheet.AutoFilter;
- int startColumn = filter.Range.Column;
-
- filter.Range.AutoFilter(TargetFile.AmountCell.Column - startColumn + 1, "<>0", XlAutoFilterOperator.xlAnd, "<>");
- TargetFile.Sheet.Range["A1"].Activate();
- }
- }
-} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Models/PriceListBase.cs b/RhSolutions.AddIn/Models/PriceListBase.cs
deleted file mode 100644
index 95f385d..0000000
--- a/RhSolutions.AddIn/Models/PriceListBase.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Microsoft.Office.Interop.Excel;
-
-namespace RhSolutions.Models
-{
- internal abstract class PriceListBase
- {
- public Range AmountCell { get; protected set; }
- public Range SkuCell { get; protected set; }
- public Range GroupCell { get; protected set; }
- public Range NameCell { get; protected set; }
-
- public Worksheet Sheet { get; protected set; }
- public string Name { get; protected set; }
- }
-} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Models/ProgressBar.cs b/RhSolutions.AddIn/Models/ProgressBar.cs
deleted file mode 100644
index 82012e5..0000000
--- a/RhSolutions.AddIn/Models/ProgressBar.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace RhSolutions.Models
-{
- internal class ProgressBar : StatusbarBase
- {
- private double CurrentProgress { get; set; }
- private readonly double TaskWeight;
- private readonly string Message;
-
- public ProgressBar(string message, int weight)
- {
- Message = message;
- TaskWeight = weight;
- CurrentProgress = 0;
- }
-
- public override void Update()
- {
- double percent = ++CurrentProgress / TaskWeight * 100;
- Excel.StatusBar = $"{Message} Выполнено {percent:#.#} %";
- }
- }
-}
diff --git a/RhSolutions.AddIn/Models/ResultBar.cs b/RhSolutions.AddIn/Models/ResultBar.cs
deleted file mode 100644
index 655540c..0000000
--- a/RhSolutions.AddIn/Models/ResultBar.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System;
-using System.Text;
-
-namespace RhSolutions.Models
-{
- internal class ResultBar : StatusbarBase
- {
- private int Success { get; set; }
- private int Replaced { get; set; }
- private int NotFound { get; set; }
-
- public ResultBar()
- {
- Success = 0;
- Replaced = 0;
- NotFound = 0;
- }
-
- public void IncrementSuccess() => Success++;
- public void IncrementReplaced() => Replaced++;
- public void IncrementNotFound() => NotFound++;
-
- public override void Update()
- {
- StringBuilder sb = new StringBuilder();
-
- if (Success > 0)
- {
- sb.Append($"Успешно экспортировано {Success} артикулов. ");
- }
-
- if (Replaced > 0)
- {
- sb.Append($"Заменено {Replaced} артикулов. ");
- }
-
- if (NotFound > 0)
- {
- sb.Append($"Не найдено {NotFound} артикулов.");
- }
-
- Excel.StatusBar = sb.ToString();
- }
- }
-}
diff --git a/RhSolutions.AddIn/Models/SourcePriceList.cs b/RhSolutions.AddIn/Models/SourcePriceList.cs
deleted file mode 100644
index db691ec..0000000
--- a/RhSolutions.AddIn/Models/SourcePriceList.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using RhSolutions.AddIn;
-using System.IO;
-
-namespace RhSolutions.Models;
-
-internal class SourcePriceList : PriceListBase
-{
- public Dictionary<Product, double> PositionAmount { get; private set; }
-
- public SourcePriceList(Workbook workbook)
- {
- if (workbook == null)
- {
- throw new ArgumentException($"Нет рабочего файла");
- }
-
- Sheet = workbook.ActiveSheet;
- Name = Path.GetFileNameWithoutExtension(workbook.FullName);
-
- var pricelistParameters = RhSolutionsAddIn.Configuration.GetPriceListParameters();
-
- Range[] cells = new[]
- {
- AmountCell = Sheet.Cells.Find(pricelistParameters["Amount"]),
- SkuCell = Sheet.Cells.Find(pricelistParameters["Sku"]),
- GroupCell = Sheet.Cells.Find(pricelistParameters["Group"]),
- NameCell = Sheet.Cells.Find(pricelistParameters["Name"])
- };
-
- if (cells.Any(x => x == null))
- {
- throw new ArgumentException($"Файл {Name} не распознан");
- }
-
- CreatePositionsDict();
- }
-
- public static List<SourcePriceList> GetSourceLists(string[] files)
- {
- var ExcelApp = (Application)ExcelDnaUtil.Application;
- ProgressBar bar = new ProgressBar("Открываю исходные файлы...", files.Length);
-
- List<SourcePriceList> sourceFiles = new List<SourcePriceList>();
-
- foreach (string file in files)
- {
- ExcelApp.ScreenUpdating = false;
- Workbook wb = ExcelApp.Workbooks.Open(file);
- try
- {
- SourcePriceList priceList = new SourcePriceList(wb);
- sourceFiles.Add(priceList);
- wb.Close();
- bar.Update();
- }
- catch (Exception ex)
- {
- System.Windows.Forms.MessageBox.Show
- (ex.Message,
- "Ошибка открытия исходного прайс-листа",
- System.Windows.Forms.MessageBoxButtons.OK,
- System.Windows.Forms.MessageBoxIcon.Information);
- wb.Close();
- bar.Update();
- }
- ExcelApp.ScreenUpdating = true;
- }
-
- return sourceFiles;
- }
-
- private void CreatePositionsDict()
- {
- PositionAmount = new Dictionary<Product, double>();
-
- for (int row = AmountCell.Row + 1; row <= Sheet.Cells[Sheet.Rows.Count, AmountCell.Column].End[XlDirection.xlUp].Row; row++)
- {
- double? amount = Sheet.Cells[row, AmountCell.Column].Value2 as double?;
-
- if (amount != null && amount.Value != 0)
- {
- object group = Sheet.Cells[row, GroupCell.Column].Value2;
- object name = Sheet.Cells[row, NameCell.Column].Value2;
- object sku = Sheet.Cells[row, SkuCell.Column].Value2;
-
- if (group == null || name == null || sku == null)
- continue;
-
- if (!Sku.TryParse(sku.ToString(), out _))
- continue;
-
- Product p = new Product
- {
- ProductSku = sku.ToString(),
- ProductLine = group.ToString(),
- Name = name.ToString()
- };
-
- if (PositionAmount.ContainsKey(p))
- {
- PositionAmount[p] += amount.Value;
- }
-
- else
- {
- PositionAmount.Add(p, amount.Value);
- }
- }
- }
- }
-}
-
diff --git a/RhSolutions.AddIn/Models/StatusbarBase.cs b/RhSolutions.AddIn/Models/StatusbarBase.cs
deleted file mode 100644
index fbec70e..0000000
--- a/RhSolutions.AddIn/Models/StatusbarBase.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Microsoft.Office.Interop.Excel;
-using RhSolutions.AddIn;
-using System;
-
-namespace RhSolutions.Models
-{
- internal abstract class StatusbarBase : IDisposable
- {
- protected Application Excel = RhSolutionsAddIn.Excel;
-
- public abstract void Update();
-
- public void Dispose()
- {
- Excel.OnTime(DateTime.Now + new TimeSpan(0, 0, 5), "_ResetStatusBar");
- }
- }
-}
diff --git a/RhSolutions.AddIn/Models/TargetPriceList.cs b/RhSolutions.AddIn/Models/TargetPriceList.cs
deleted file mode 100644
index 15ba066..0000000
--- a/RhSolutions.AddIn/Models/TargetPriceList.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using RhSolutions.AddIn;
-using System.IO;
-
-namespace RhSolutions.Models;
-
-internal class TargetPriceList : PriceListBase
-{
- public Range OldSkuCell { get; private set; }
-
- public TargetPriceList(Workbook workbook)
- {
- if (workbook == null)
- {
- throw new ArgumentException("Невозможно открыть книгу шаблонного файла. " +
- "Возможно открыт файл с именем, совпадающим с именем шаблонного файла.");
- }
-
- Sheet = workbook.ActiveSheet;
- Name = Path.GetFileNameWithoutExtension(workbook.FullName);
-
- var pricelistParameters = RhSolutionsAddIn.Configuration.GetPriceListParameters();
-
- Range[] cells = new[]
- {
- AmountCell = Sheet.Cells.Find(pricelistParameters["Amount"]),
- SkuCell = Sheet.Cells.Find(pricelistParameters["Sku"]),
- GroupCell = Sheet.Cells.Find(pricelistParameters["Group"]),
- NameCell = Sheet.Cells.Find(pricelistParameters["Name"])
- };
-
- OldSkuCell = Sheet.Cells.Find(pricelistParameters["OldSku"]);
-
- if (cells.Any(x => x == null))
- {
- throw new ArgumentException($"Шаблон {Name} не является прайс-листом");
- }
- }
-}
-
diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
index 536248e..81fcb6a 100644
--- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj
+++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
@@ -36,7 +36,4 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="RhSolutions.Sku" Version="0.1.1" />
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\RhSolutions.ExcelExtensions\RhSolutions.ExcelExtensions.csproj" />
- </ItemGroup>
</Project> \ No newline at end of file
diff --git a/RhSolutions.AddIn/Services/ExcelFileDialog.cs b/RhSolutions.AddIn/Services/ExcelFileDialog.cs
new file mode 100644
index 0000000..9e70d46
--- /dev/null
+++ b/RhSolutions.AddIn/Services/ExcelFileDialog.cs
@@ -0,0 +1,45 @@
+namespace RhSolutions.Services;
+
+public class ExcelFileDialog : IFileDialog
+{
+ private Application _application;
+
+ public ExcelFileDialog(Application application)
+ {
+ _application = application;
+ }
+
+ public string GetFile()
+ {
+ var dialog = _application.FileDialog[Microsoft.Office.Core.MsoFileDialogType.msoFileDialogFilePicker];
+ dialog.AllowMultiSelect = false;
+ dialog.Filters.Add("Файлы Excel", "*.xls; *.xlsx; *.xlsm");
+
+ if (dialog.Show() == -1)
+ {
+ return dialog.SelectedItems.Item(1);
+ }
+ else return string.Empty;
+ }
+
+ public string[] GetFiles()
+ {
+ var dialog = _application.FileDialog[Microsoft.Office.Core.MsoFileDialogType.msoFileDialogFilePicker];
+ dialog.AllowMultiSelect = true;
+ dialog.Filters.Add("Файлы Excel", "*.xls; *.xlsx; *.xlsm");
+
+ if (dialog.Show() == -1)
+ {
+ List<string> files = new();
+
+ foreach (string file in dialog.SelectedItems)
+ {
+ files.Add(file);
+ }
+
+ return files.ToArray();
+ }
+
+ else return Array.Empty<string>();
+ }
+}
diff --git a/RhSolutions.AddIn/Services/IAddInConfiguration.cs b/RhSolutions.AddIn/Services/IAddInConfiguration.cs
index 3c09007..4eb79f1 100644
--- a/RhSolutions.AddIn/Services/IAddInConfiguration.cs
+++ b/RhSolutions.AddIn/Services/IAddInConfiguration.cs
@@ -6,7 +6,7 @@ public interface IAddInConfiguration
{
public string GetPriceListPath();
public string GetPriceListFileName();
- public Dictionary<string, string> GetPriceListParameters();
+ public Dictionary<string, string> GetPriceListHeaders();
public event SettingChangingEventHandler OnSettingsChange;
public void SetPriceListPath(string value);
public void SaveSettings();
diff --git a/RhSolutions.AddIn/Services/IExcelReader.cs b/RhSolutions.AddIn/Services/IExcelReader.cs
new file mode 100644
index 0000000..a134e4c
--- /dev/null
+++ b/RhSolutions.AddIn/Services/IExcelReader.cs
@@ -0,0 +1,8 @@
+namespace RhSolutions.Services;
+
+public interface IExcelReader
+{
+ public Dictionary<Product, double> ReadProducts(Range range);
+ public List<(string, Dictionary<Product, double>)> ReadProducts(IEnumerable<Worksheet> worksheets);
+ public List<(string, Dictionary<Product, double>)> ReadProducts(string[] files);
+}
diff --git a/RhSolutions.AddIn/Services/IExcelWriter.cs b/RhSolutions.AddIn/Services/IExcelWriter.cs
new file mode 100644
index 0000000..5d2ea29
--- /dev/null
+++ b/RhSolutions.AddIn/Services/IExcelWriter.cs
@@ -0,0 +1,7 @@
+namespace RhSolutions.Services;
+
+public interface IExcelWriter
+{
+ public void WriteProducts(IEnumerable<(string, Dictionary<Product, double>)> products);
+ public void WriteProducts(Dictionary<Product, double> products);
+}
diff --git a/RhSolutions.AddIn/Services/IFileDialog.cs b/RhSolutions.AddIn/Services/IFileDialog.cs
new file mode 100644
index 0000000..6c85522
--- /dev/null
+++ b/RhSolutions.AddIn/Services/IFileDialog.cs
@@ -0,0 +1,7 @@
+namespace RhSolutions.Services;
+
+public interface IFileDialog
+{
+ public string[] GetFiles();
+ public string GetFile();
+}
diff --git a/RhSolutions.AddIn/Services/AddInConfiguration.cs b/RhSolutions.AddIn/Services/RhAddInConfiguration.cs
index 970cf52..620f9b7 100644
--- a/RhSolutions.AddIn/Services/AddInConfiguration.cs
+++ b/RhSolutions.AddIn/Services/RhAddInConfiguration.cs
@@ -3,18 +3,18 @@ using System.IO;
namespace RhSolutions.Services;
-public class AddInConfiguration : ApplicationSettingsBase, IAddInConfiguration
+public class RhAddInConfiguration : ApplicationSettingsBase, IAddInConfiguration
{
- private Dictionary<string, string> _priceListParameters;
+ private readonly Dictionary<string, string> _priceListHeaders;
- public AddInConfiguration()
+ public RhAddInConfiguration()
{
- _priceListParameters = new Dictionary<string, string>()
+ _priceListHeaders = new Dictionary<string, string>()
{
["Amount"] = AmountHeader,
["OldSku"] = OldSkuHeader,
["Sku"] = SkuHeader,
- ["Group"] = GroupHeader,
+ ["ProductLine"] = ProductLineHeader,
["Name"] = NameHeader
};
}
@@ -52,11 +52,11 @@ public class AddInConfiguration : ApplicationSettingsBase, IAddInConfiguration
[UserScopedSetting]
[DefaultSettingValue("Программа")]
- public string GroupHeader
+ public string ProductLineHeader
{
get
{
- return (string)this[nameof(GroupHeader)];
+ return (string)this[nameof(ProductLineHeader)];
}
}
@@ -99,5 +99,5 @@ public class AddInConfiguration : ApplicationSettingsBase, IAddInConfiguration
public string GetPriceListPath() => PriceListPath;
public void SetPriceListPath(string value) => PriceListPath = value;
public void SaveSettings() => base.Save();
- public Dictionary<string, string> GetPriceListParameters() => _priceListParameters;
+ public Dictionary<string, string> GetPriceListHeaders() => _priceListHeaders;
}
diff --git a/RhSolutions.AddIn/Services/RhExcelReader.cs b/RhSolutions.AddIn/Services/RhExcelReader.cs
new file mode 100644
index 0000000..0749482
--- /dev/null
+++ b/RhSolutions.AddIn/Services/RhExcelReader.cs
@@ -0,0 +1,169 @@
+using System.IO;
+using RhSolutions.Tools;
+#if !NET472
+using System.Runtime.Versioning;
+using RhSolutions.Tools;
+#endif
+
+namespace RhSolutions.Services;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+public class RhExcelReader : IExcelReader, IDisposable
+{
+ private ProgressBar _progressBar;
+ private readonly Dictionary<string, string> headers;
+ private readonly Application _application;
+
+ public RhExcelReader(Application application, IAddInConfiguration configuration)
+ {
+ _application = application;
+ headers = configuration.GetPriceListHeaders();
+ }
+
+ public Dictionary<Product, double> ReadProducts(Range range)
+ {
+ object[,] cells = range.Value2;
+ Dictionary<Product, double> readResult = new();
+
+ for (int row = 1; row <= range.Rows.Count; row++)
+ {
+ if (cells[row, 1] == null || cells[row, 2] == null)
+ continue;
+
+ string currentSku = null;
+ double? currentAmount = null;
+
+ for (int column = 1; column <= 2; column++)
+ {
+ object currentCell = cells[row, column];
+
+ if (Sku.TryParse(currentCell.ToString(), out var validSku))
+ {
+ currentSku = validSku.FirstOrDefault().ToString() ?? null;
+ }
+
+ else if (currentCell.GetType() == typeof(string)
+ && double.TryParse(currentCell.ToString(), out _))
+ {
+ currentAmount = double.Parse((string)currentCell);
+ }
+
+ else if (currentCell.GetType() == typeof(double))
+ {
+ currentAmount = (double)currentCell;
+ }
+ }
+
+ if (currentSku == null || currentAmount == null)
+ {
+ continue;
+ }
+
+ Product product = new() { ProductSku = currentSku };
+
+ if (readResult.ContainsKey(product))
+ {
+ readResult[product] += currentAmount.Value;
+ }
+
+ else
+ {
+ readResult.Add(product, currentAmount.Value);
+ }
+ }
+
+ return readResult;
+ }
+
+ public List<(string, Dictionary<Product, double>)>
+ ReadProducts(IEnumerable<Worksheet> worksheets)
+ {
+ List<(string, Dictionary<Product, double>)> result = new();
+ foreach (Worksheet worksheet in worksheets)
+ {
+ if (!worksheet.IsRehauSource())
+ {
+ continue;
+ }
+
+ string wbName = Path.GetFileNameWithoutExtension(
+ worksheet.Parent.Name);
+
+ Range AmountCell = worksheet.Cells.Find(headers["Amount"]),
+ SkuCell = worksheet.Cells.Find(headers["Sku"]),
+ ProductLineCelll = worksheet.Cells.Find(headers["ProductLine"]),
+ NameCell = worksheet.Cells.Find(headers["Name"]);
+ var lastRowIndex = worksheet.Cells[worksheet.Rows.Count, AmountCell.Column]
+ .End[XlDirection.xlUp].Row;
+
+ Dictionary<Product, double> readResult = new();
+
+ for (int row = AmountCell.Row + 1; row <= lastRowIndex; row++)
+ {
+ double? amount = worksheet.Cells[row, AmountCell.Column].Value2 as double?;
+
+ if (amount != null && amount.Value != 0)
+ {
+ object programLine = worksheet.Cells[row, ProductLineCelll.Column].Value2;
+ object name = worksheet.Cells[row, NameCell.Column].Value2;
+ object sku = worksheet.Cells[row, SkuCell.Column].Value2;
+
+ if (programLine == null || name == null || sku == null)
+ continue;
+
+ if (!Sku.TryParse(sku.ToString(), out _))
+ continue;
+
+ Product p = new()
+ {
+ ProductSku = sku.ToString(),
+ ProductLine = programLine.ToString(),
+ Name = name.ToString()
+ };
+
+ if (readResult.ContainsKey(p))
+ {
+ readResult[p] += amount.Value;
+ }
+
+ else
+ {
+ readResult.Add(p, amount.Value);
+ }
+ }
+
+ }
+
+ result.Add((wbName, readResult));
+ }
+ return result;
+ }
+
+ public List<(string, Dictionary<Product, double>)> ReadProducts(string[] files)
+ {
+ _progressBar = new("Открываю исходные файлы...", files.Length);
+ List<Worksheet> 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();
+ }
+} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Services/RhExcelWriter.cs b/RhSolutions.AddIn/Services/RhExcelWriter.cs
new file mode 100644
index 0000000..6fd43fc
--- /dev/null
+++ b/RhSolutions.AddIn/Services/RhExcelWriter.cs
@@ -0,0 +1,256 @@
+#if !NET472
+using System.Runtime.Versioning;
+using RhSolutions.Tools;
+#endif
+
+using RhSolutions.Tools;
+
+namespace RhSolutions.Services;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+public class RhExcelWriter : IExcelWriter, 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 RhExcelWriter(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.IsRehauSource())
+ {
+ _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, positionAmount.Key.ProductLine);
+
+ 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, positionAmount.Key.ProductLine);
+
+ 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.Substring(1, 6);
+ row = GetPositionRow(skuColumn, sku, positionAmount.Key.ProductLine);
+
+ 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.ProductLine;
+ 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();
+ }
+}
diff --git a/RhSolutions.AddIn/Models/WorksheetExtensions.cs b/RhSolutions.AddIn/Services/WorksheetExtensions.cs
index da38203..409cd5f 100644
--- a/RhSolutions.AddIn/Models/WorksheetExtensions.cs
+++ b/RhSolutions.AddIn/Services/WorksheetExtensions.cs
@@ -1,23 +1,28 @@
-using RhSolutions.AddIn;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
namespace RhSolutions.Services;
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
public static class WorksheetExtensions
{
public static bool IsRehauSource(this Worksheet worksheet)
{
Range amountCell;
Range skuCell;
- Range groupCell;
+ Range programLineCell;
Range nameCell;
- var pricelistParameters = RhSolutionsAddIn.Configuration.GetPriceListParameters();
+ var pricelistParameters = RhSolutionsAddIn.Configuration.GetPriceListHeaders();
Range[] cells = new[]
{
amountCell = worksheet.Cells.Find(pricelistParameters["Amount"]),
skuCell = worksheet.Cells.Find(pricelistParameters["Sku"]),
- groupCell = worksheet.Cells.Find(pricelistParameters["Group"]),
+ programLineCell = worksheet.Cells.Find(pricelistParameters["ProductLine"]),
nameCell = worksheet.Cells.Find(pricelistParameters["Name"])
};
diff --git a/RhSolutions.AddIn/Tools/ConvertTool.cs b/RhSolutions.AddIn/Tools/ConvertTool.cs
new file mode 100644
index 0000000..c9782a1
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/ConvertTool.cs
@@ -0,0 +1,20 @@
+using RhSolutions.AddIn;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal class ConvertTool : ToolBase
+{
+ public override void Execute()
+ {
+ Application app = RhSolutionsAddIn.Excel.Application;
+ Worksheet worksheet = app.ActiveWorkbook.ActiveSheet;
+ var products = _reader.ReadProducts(new[] { worksheet });
+ _writer.WriteProducts(products);
+ }
+} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Services/EventsUtil.cs b/RhSolutions.AddIn/Tools/EventsUtil.cs
index bd7dd7b..4bd6b89 100644
--- a/RhSolutions.AddIn/Services/EventsUtil.cs
+++ b/RhSolutions.AddIn/Tools/EventsUtil.cs
@@ -2,9 +2,15 @@
using RhSolutions.AddIn;
using RhSolutions.Controllers;
using System.Configuration;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
-namespace RhSolutions.Services
+namespace RhSolutions.Tools
{
+#if !NET472
+ [SupportedOSPlatform("windows")]
+#endif
internal static class EventsUtil
{
public static void Initialize()
diff --git a/RhSolutions.AddIn/Tools/ExportTool.cs b/RhSolutions.AddIn/Tools/ExportTool.cs
new file mode 100644
index 0000000..c943cf1
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/ExportTool.cs
@@ -0,0 +1,20 @@
+using RhSolutions.AddIn;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal class ExportTool : ToolBase
+{
+ public override void Execute()
+ {
+ Application app = RhSolutionsAddIn.Excel.Application;
+ var products = _reader.ReadProducts(app.Selection);
+ _writer.WriteProducts(products);
+ }
+}
+
diff --git a/RhSolutions.AddIn/Tools/MergeTool.cs b/RhSolutions.AddIn/Tools/MergeTool.cs
new file mode 100644
index 0000000..03cf104
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/MergeTool.cs
@@ -0,0 +1,23 @@
+#if !NET472
+using System.Runtime.Versioning;
+using RhSolutions;
+using RhSolutions.Models;
+using RhSolutions.Tools;
+#endif
+
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal class MergeTool : ToolBase
+{
+ public override void Execute()
+ {
+ IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IFileDialog>();
+ string[] files = dialog.GetFiles();
+ var products = _reader.ReadProducts(files);
+ _writer.WriteProducts(products);
+ }
+}
diff --git a/RhSolutions.AddIn/Tools/ProgressBar.cs b/RhSolutions.AddIn/Tools/ProgressBar.cs
new file mode 100644
index 0000000..709f28c
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/ProgressBar.cs
@@ -0,0 +1,28 @@
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal class ProgressBar : StatusbarBase
+{
+ private double CurrentProgress { get; set; }
+ private readonly double TaskWeight;
+ private readonly string Message;
+
+ public ProgressBar(string message, int weight)
+ {
+ Message = message;
+ TaskWeight = weight;
+ CurrentProgress = 0;
+ }
+
+ public override void Update()
+ {
+ double percent = ++CurrentProgress / TaskWeight * 100;
+ Excel.StatusBar = $"{Message} Выполнено {percent:#.#} %";
+ }
+}
diff --git a/RhSolutions.AddIn/Tools/ResultBar.cs b/RhSolutions.AddIn/Tools/ResultBar.cs
new file mode 100644
index 0000000..b14f307
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/ResultBar.cs
@@ -0,0 +1,49 @@
+using System.Text;
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal class ResultBar : StatusbarBase
+{
+ private int Success { get; set; }
+ private int Replaced { get; set; }
+ private int NotFound { get; set; }
+
+ public ResultBar()
+ {
+ Success = 0;
+ Replaced = 0;
+ NotFound = 0;
+ }
+
+ public void IncrementSuccess() => Success++;
+ public void IncrementReplaced() => Replaced++;
+ public void IncrementNotFound() => NotFound++;
+
+ public override void Update()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if (Success > 0)
+ {
+ sb.Append($"Успешно экспортировано {Success} артикулов. ");
+ }
+
+ if (Replaced > 0)
+ {
+ sb.Append($"Заменено {Replaced} артикулов. ");
+ }
+
+ if (NotFound > 0)
+ {
+ sb.Append($"Не найдено {NotFound} артикулов.");
+ }
+
+ Excel.StatusBar = sb.ToString();
+ }
+}
diff --git a/RhSolutions.AddIn/Tools/StatusbarBase.cs b/RhSolutions.AddIn/Tools/StatusbarBase.cs
new file mode 100644
index 0000000..fe30eaa
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/StatusbarBase.cs
@@ -0,0 +1,24 @@
+#if !NET472
+using System.Runtime.Versioning;
+using RhSolutions;
+using RhSolutions.Models;
+using RhSolutions.Tools;
+#endif
+
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal abstract class StatusbarBase : IDisposable
+{
+ protected Application Excel = RhSolutionsAddIn.Excel;
+
+ public abstract void Update();
+
+ public void Dispose()
+ {
+ Excel.OnTime(DateTime.Now + new TimeSpan(0, 0, 5), "StatusBarReset");
+ }
+}
diff --git a/RhSolutions.AddIn/Tools/ToolBase.cs b/RhSolutions.AddIn/Tools/ToolBase.cs
new file mode 100644
index 0000000..9c37bc3
--- /dev/null
+++ b/RhSolutions.AddIn/Tools/ToolBase.cs
@@ -0,0 +1,22 @@
+#if !NET472
+using System.Runtime.Versioning;
+#endif
+
+namespace RhSolutions.Tools;
+
+#if !NET472
+[SupportedOSPlatform("windows")]
+#endif
+internal abstract class ToolBase
+{
+ protected readonly IExcelReader _reader;
+ protected readonly IExcelWriter _writer;
+
+ public ToolBase()
+ {
+ _reader = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IExcelReader>();
+ _writer = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IExcelWriter>();
+ }
+
+ public abstract void Execute();
+} \ No newline at end of file
diff --git a/RhSolutions.AddIn/Usings.cs b/RhSolutions.AddIn/Usings.cs
index 929f09f..0196089 100644
--- a/RhSolutions.AddIn/Usings.cs
+++ b/RhSolutions.AddIn/Usings.cs
@@ -1,9 +1,11 @@
global using ExcelDna.Integration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Office.Interop.Excel;
+global using RhSolutions.AddIn;
global using RhSolutions.Models;
global using RhSolutions.Services;
+global using RhSolutions.Tools;
global using System;
global using System.Collections.Generic;
global using System.Linq;
-global using Range = Microsoft.Office.Interop.Excel.Range; \ No newline at end of file
+global using Range = Microsoft.Office.Interop.Excel.Range;
diff --git a/RhSolutions.ExcelExtensions/Cell.cs b/RhSolutions.ExcelExtensions/Cell.cs
new file mode 100644
index 0000000..19a2017
--- /dev/null
+++ b/RhSolutions.ExcelExtensions/Cell.cs
@@ -0,0 +1,26 @@
+namespace RhSolutions.ExcelExtensions;
+
+public sealed class Cell
+{
+ public Table ParentTable { get; }
+ public Row ParentRow
+ {
+ get => ParentTable.Rows[ParentTable.Range.Row - _range.Row];
+ }
+ public Column ParentColumn
+ {
+ get => ParentTable.Columns[ParentTable.Range.Column - _range.Column];
+ }
+ public object Value
+ {
+ get => _range.Cells[1, 1].Value2;
+ set => _range.Cells[1, 1].Value2 = value;
+ }
+ private Range _range;
+
+ public Cell(Range range, Table table)
+ {
+ _range = range;
+ ParentTable = table;
+ }
+}
diff --git a/RhSolutions.ExcelExtensions/Column.cs b/RhSolutions.ExcelExtensions/Column.cs
index 53a1f3d..341897c 100644
--- a/RhSolutions.ExcelExtensions/Column.cs
+++ b/RhSolutions.ExcelExtensions/Column.cs
@@ -1,44 +1,62 @@
-using System.Collections;
+namespace RhSolutions.ExcelExtensions;
-namespace RhSolutions.ExcelExtensions;
-
-public sealed class Column : Table, IEnumerable<TableCell>
+public sealed class Column
{
+ public Table ParentTable { get; }
public string Header
{
- get => Range.Cells[1, 1].Value.ToString();
+ get => _range.Cells[1, 1].Value2.ToString() ?? String.Empty;
}
public int Index
{
- get => Range.Column - ParentTable.Range.Column;
+ get => _range.Column - ParentTable.Range.Column;
}
public int Length
{
- get => Range.Rows.Count;
- }
-
- public Column(Range range, Table table) : base(range, table)
- {
- Range = range;
- ParentTable = table;
+ get => _range.Rows.Count;
}
+ private Cell[] _cells;
+ private readonly Range _range;
- public TableCell this[int index]
+ public Column(Range range, Table table)
{
- get => new(Range.Cells[index + 1, 1], ParentTable);
+ _cells = new Cell[range.Rows.Count];
+ _range = range;
+ ParentTable = table ??
+ throw new ArgumentNullException("table");
}
- public IEnumerator<TableCell> GetEnumerator()
+ public Cell this[int index]
{
- return new ColumnEnumerator(Range, ParentTable);
+ get
+ {
+ if (_cells[index] == null)
+ {
+ _cells[index] = new Cell(_range.Cells[index + 1, 1], ParentTable);
+ return _cells[index];
+ }
+ else
+ {
+ return _cells[index];
+ }
+ }
+ set
+ {
+ if (_cells[index] == null)
+ {
+ _cells[index] = new Cell(_range.Cells[index + 1, 1], ParentTable);
+ _cells[index].Value = value;
+ }
+ else
+ {
+ _cells[index].Value = value;
+ }
+ }
}
- IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
-
-
public Column AddLeft()
{
- Range.EntireColumn
+ _range.EntireColumn
.Insert(XlInsertShiftDirection.xlShiftToRight,
XlInsertFormatOrigin.xlFormatFromRightOrBelow);
diff --git a/RhSolutions.ExcelExtensions/ColumnEnumerator.cs b/RhSolutions.ExcelExtensions/ColumnEnumerator.cs
deleted file mode 100644
index 9880b5d..0000000
--- a/RhSolutions.ExcelExtensions/ColumnEnumerator.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections;
-
-namespace RhSolutions.ExcelExtensions;
-
-public class ColumnEnumerator : IEnumerator<TableCell>
-{
- public Range Range { get; }
- public Table ParentTable { get; }
- private int position = 0;
- object IEnumerator.Current
- {
- get
- {
- return Current;
- }
- }
-
- public TableCell Current
- {
- get
- {
- try
- {
- return new TableCell(Range.Cells[position, 1], ParentTable);
- }
- catch (IndexOutOfRangeException)
- {
- throw new InvalidOperationException();
- }
- }
- }
-
- public ColumnEnumerator(Range range, Table table)
- {
- Range = range;
- ParentTable = table;
- }
-
- public bool MoveNext()
- {
- position++;
- return (position <= Range.Rows.Count);
- }
-
- public void Reset()
- {
- position = 0;
- }
-
- public void Dispose()
- {
-
- }
-}
diff --git a/RhSolutions.ExcelExtensions/Columns.cs b/RhSolutions.ExcelExtensions/Columns.cs
index 1fbc0ef..014b755 100644
--- a/RhSolutions.ExcelExtensions/Columns.cs
+++ b/RhSolutions.ExcelExtensions/Columns.cs
@@ -4,35 +4,45 @@ namespace RhSolutions.ExcelExtensions;
public class Columns : IEnumerable<Column>
{
- public Range Range { get; }
public Table ParentTable { get; }
public int Length
{
- get => Range.Columns.Count;
+ get => _range.Columns.Count;
}
+ private Column[] _columns;
+ private Range _range;
- public Columns(Range range, Table parentTable)
+ public Columns(Table parentTable)
{
- Range = range;
ParentTable = parentTable;
+ _range = parentTable.Range;
+ _columns = new Column[Length];
}
public Column this[int index]
{
get
{
- if (index < 0 || index + 1 > Range.Columns.Count)
+ if (index < 0 || index >= Length)
{
throw new IndexOutOfRangeException();
}
- return new Column(Range.Columns[index + 1], ParentTable);
+ if (_columns[index] == null)
+ {
+ _columns[index] = new Column(_range.Columns[index + 1], ParentTable);
+ return _columns[index];
+ }
+ else
+ {
+ return _columns[index];
+ }
}
}
public IEnumerator<Column> GetEnumerator()
{
- return new ColumnsEnumerator(Range, ParentTable);
+ return new ColumnsEnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
diff --git a/RhSolutions.ExcelExtensions/ColumnsEnumerator.cs b/RhSolutions.ExcelExtensions/ColumnsEnumerator.cs
index 578e2b0..40ad4d6 100644
--- a/RhSolutions.ExcelExtensions/ColumnsEnumerator.cs
+++ b/RhSolutions.ExcelExtensions/ColumnsEnumerator.cs
@@ -4,9 +4,8 @@ namespace RhSolutions.ExcelExtensions;
public class ColumnsEnumerator: IEnumerator<Column>
{
- public Range Range { get; }
- public Table ParentTable { get; }
- private int position = 0;
+ private Columns _columns;
+ private int position = -1;
object IEnumerator.Current
{
get
@@ -21,7 +20,7 @@ public class ColumnsEnumerator: IEnumerator<Column>
{
try
{
- return new Column(Range.Columns[position], ParentTable);
+ return _columns[position];
}
catch (IndexOutOfRangeException)
{
@@ -30,21 +29,20 @@ public class ColumnsEnumerator: IEnumerator<Column>
}
}
- public ColumnsEnumerator(Range range, Table table)
+ public ColumnsEnumerator(Columns columns)
{
- Range = range;
- ParentTable = table;
+ _columns = columns;
}
public bool MoveNext()
{
position++;
- return (position <= Range.Columns.Count);
+ return (position < _columns.Length);
}
public void Reset()
{
- position = 0;
+ position = -1;
}
public void Dispose()
diff --git a/RhSolutions.ExcelExtensions/Row.cs b/RhSolutions.ExcelExtensions/Row.cs
index 32617b4..01df2e4 100644
--- a/RhSolutions.ExcelExtensions/Row.cs
+++ b/RhSolutions.ExcelExtensions/Row.cs
@@ -1,33 +1,54 @@
-using System.Collections;
+namespace RhSolutions.ExcelExtensions;
-namespace RhSolutions.ExcelExtensions;
-
-public sealed class Row : Table, IEnumerable<TableCell>
+public sealed class Row
{
+ public Table ParentTable { get; }
public int Index
{
- get => Range.Row - ParentTable.Range.Row;
+ get => _range.Row - ParentTable.Range.Row;
}
public int Length
{
- get => Range.Columns.Count;
+ get => _range.Columns.Count;
}
+ private readonly Cell[] _cells;
+ private readonly Range _range;
- public Row(Range range, Table table) : base(range, table)
+ public Row(Range range, Table table)
{
- Range = range;
- ParentTable = table;
+ _cells = new Cell[range.Columns.Count];
+ _range = range;
+ ParentTable = table ??
+ throw new ArgumentNullException("table");
}
- public TableCell this[int index]
+ public Cell this[int index]
{
- get => new(Range.Cells[1, index + 1], ParentTable);
+ get
+ {
+ if (index < 0 || index >= Length)
+ {
+ throw new IndexOutOfRangeException();
+ }
+
+ if (_cells[index] == null)
+ {
+ _cells[index] = new Cell(_range.Cells[1, index + 1], ParentTable);
+ return _cells[index];
+ }
+ else
+ {
+ return _cells[index];
+ }
+ }
}
- public IEnumerator<TableCell> GetEnumerator()
+ public Cell this[string header]
{
- return new RowEnumerator(Range, ParentTable);
+ get
+ {
+ int columnIndex = ParentTable.ColumnByHeader(header).Index;
+ return this[columnIndex];
+ }
}
-
- IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
diff --git a/RhSolutions.ExcelExtensions/RowEnumerator.cs b/RhSolutions.ExcelExtensions/RowEnumerator.cs
deleted file mode 100644
index fd56dcd..0000000
--- a/RhSolutions.ExcelExtensions/RowEnumerator.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections;
-
-namespace RhSolutions.ExcelExtensions;
-
-public class RowEnumerator : IEnumerator<TableCell>
-{
- public Range Range { get; }
- public Table ParentTable { get; }
- private int position = 0;
- object IEnumerator.Current
- {
- get
- {
- return Current;
- }
- }
-
- public TableCell Current
- {
- get
- {
- try
- {
- return new TableCell(Range.Cells[1, position], ParentTable);
- }
- catch (IndexOutOfRangeException)
- {
- throw new InvalidOperationException();
- }
- }
- }
-
- public RowEnumerator(Range range, Table parentTable)
- {
- Range = range;
- ParentTable = parentTable;
- }
-
- public bool MoveNext()
- {
- position++;
- return (position <= Range.Columns.Count);
- }
-
- public void Reset()
- {
- position = 0;
- }
-
- public void Dispose()
- {
-
- }
-} \ No newline at end of file
diff --git a/RhSolutions.ExcelExtensions/Rows.cs b/RhSolutions.ExcelExtensions/Rows.cs
index 1c0bc0d..c6d4c01 100644
--- a/RhSolutions.ExcelExtensions/Rows.cs
+++ b/RhSolutions.ExcelExtensions/Rows.cs
@@ -4,35 +4,40 @@ namespace RhSolutions.ExcelExtensions;
public class Rows : IEnumerable<Row>
{
- public Range Range { get; }
public Table ParentTable { get; }
public int Length
{
- get => Range.Rows.Count;
+ get => _range.Rows.Count;
}
+ private Row[] _rows;
+ private Range _range;
- public Rows(Range range, Table parentTable)
+ public Rows(Table parentTable)
{
- Range = range;
ParentTable = parentTable;
+ _range = parentTable.Range;
+ _rows = new Row[Length];
}
public Row this[int index]
{
get
{
- if (index < 0 || index + 1 > Range.Rows.Count)
+ if (_rows[index] == null)
{
- throw new IndexOutOfRangeException();
+ _rows[index] = new Row(_range.Rows[index + 1], ParentTable);
+ return _rows[index];
+ }
+ else
+ {
+ return _rows[index];
}
-
- return new Row(Range.Rows[index + 1], ParentTable);
}
}
public IEnumerator<Row> GetEnumerator()
{
- return new RowsEnumerator(Range, ParentTable);
+ return new RowsEnumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
diff --git a/RhSolutions.ExcelExtensions/RowsEnumerator.cs b/RhSolutions.ExcelExtensions/RowsEnumerator.cs
index b53db98..4d68a9c 100644
--- a/RhSolutions.ExcelExtensions/RowsEnumerator.cs
+++ b/RhSolutions.ExcelExtensions/RowsEnumerator.cs
@@ -4,9 +4,8 @@ namespace RhSolutions.ExcelExtensions;
public class RowsEnumerator : IEnumerator<Row>
{
- public Range Range { get; }
- public Table ParentTable { get; }
- private int position = 0;
+ private Rows _rows;
+ private int position = -1;
object IEnumerator.Current
{
get
@@ -21,7 +20,7 @@ public class RowsEnumerator : IEnumerator<Row>
{
try
{
- return new Row(Range.Rows[position], ParentTable);
+ return _rows[position];
}
catch (IndexOutOfRangeException)
{
@@ -30,26 +29,24 @@ public class RowsEnumerator : IEnumerator<Row>
}
}
- public RowsEnumerator(Range range, Table table)
+ public RowsEnumerator(Rows rows)
{
- Range = range;
- ParentTable = table;
+ _rows = rows;
}
public bool MoveNext()
{
position++;
- return (position <= Range.Rows.Count);
+ return (position < _rows.Length);
}
public void Reset()
{
- position = 0;
+ position = -1;
}
public void Dispose()
{
}
-
} \ No newline at end of file
diff --git a/RhSolutions.ExcelExtensions/Table.cs b/RhSolutions.ExcelExtensions/Table.cs
index a19a4b4..aad2151 100644
--- a/RhSolutions.ExcelExtensions/Table.cs
+++ b/RhSolutions.ExcelExtensions/Table.cs
@@ -6,29 +6,40 @@ public class Table
public Table ParentTable { get; protected set; }
public Rows Rows { get; }
public Columns Columns { get; }
+ private Dictionary<string, Column> _columnsByHeader;
public Table(Range range)
{
Range = range;
- ParentTable = null;
- Rows = new Rows(Range, this);
- Columns = new Columns(Range, this);
+ ParentTable = this;
+ Rows = new Rows(this);
+ Columns = new Columns(this);
+ _columnsByHeader = new();
+
+ foreach(var column in Columns)
+ {
+ if (_columnsByHeader.ContainsKey(column.Header))
+ {
+ throw new ArgumentException($"Заголовок столбца {column.Header} не уникален");
+ }
+ else
+ {
+ _columnsByHeader.Add(column.Header, column);
+ }
+ }
}
- public Table(Range range, Table table)
+ public Column ColumnByHeader(string header)
{
- Range = range;
- ParentTable = table;
- Rows = new Rows(Range, this);
- Columns = new Columns(Range, this);
+ return _columnsByHeader[header];
}
- public TableCell this[int row, int column]
+ public Cell this[int row, int column]
{
- get => new(Range.Cells[row + 1, column + 1], this);
+ get => this.Rows[row][column];
}
- public IEnumerable<TableCell> Find(object item)
+ public IEnumerable<Cell> Search(object item)
{
Range firstFound = Range.Find(item);
if (firstFound == null)
@@ -40,7 +51,7 @@ public class Table
while (true)
{
- yield return new TableCell(nextFound, ParentTable ?? this);
+ yield return this[nextFound.Row - ParentTable.Range.Row, nextFound.Column - ParentTable.Range.Column];
nextFound = Range.FindNext(nextFound);
if (nextFound.Row == firstFound.Row
diff --git a/RhSolutions.ExcelExtensions/TableCell.cs b/RhSolutions.ExcelExtensions/TableCell.cs
deleted file mode 100644
index 822673e..0000000
--- a/RhSolutions.ExcelExtensions/TableCell.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace RhSolutions.ExcelExtensions;
-
-public sealed class TableCell : Table
-{
- public Row ParentRow
- {
- get => ParentTable.Rows[ParentTable.Range.Row - Range.Row];
- }
- public Column ParentColumn
- {
- get => ParentTable.Columns[ParentTable.Range.Column - Range.Column];
- }
- public object Value
- {
- get => Range.Cells[1, 1].Value2;
- set => Range.Cells[1, 1].Value2 = value;
- }
-
- public TableCell(Range range, Table table) : base(range, table)
- {
- Range = range;
- ParentTable = table;
- }
-}
diff --git a/RhSolutions.Tests/ExcelTablesTests.cs b/RhSolutions.Tests/ExcelTablesTests.cs
deleted file mode 100644
index 78264ac..0000000
--- a/RhSolutions.Tests/ExcelTablesTests.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-namespace RhSolutions.Tests;
-
-[ExcelTestSettings(OutOfProcess = true, Workbook = @"TestWorkbooks\ExcelTableTest.xlsx")]
-public class ExcelTablesTests : IDisposable
-{
- ExcelExtensions.Table table;
-
- public ExcelTablesTests()
- {
- Util.Application.Workbooks.Add();
-
- Worksheet worksheet = Util.Workbook.Sheets[1];
- Range range = worksheet.Range["E7:G9"];
- table = new(range);
- }
-
- [ExcelFact]
- public void CanReadExcelTable()
- {
- Assert.Equal(3, table.Columns.Where(c => c.Header.StartsWith("Столбец")).Count());
- Assert.Equal("Столбец 1", table.Rows.First()[0].Value);
- Assert.Equal("Столбец 2", table[0, 1].Value);
- Assert.Equal(123d, table[1, 1].Value);
- Assert.Null(table[1, 2].Value);
- }
-
- [ExcelFact]
- public void CanModifyTableCells()
- {
- table[2, 1].Value = 1;
- table[1, 1].Value = (double)table[1, 1].Value + 123;
- Assert.Equal(1d, table[2, 1].Value);
- Assert.Equal(246d, table[1, 1].Value);
- }
-
- [ExcelFact]
- public void CanFindInTable()
- {
- table[2, 0].Value = "Find!";
- table[2, 1].Value = "Find this!";
- table[2, 2].Value = "Find that!";
-
-
- var cells = table.Find("Find");
- Assert.Collection(cells, item => Assert.Equal("Find!", item.Value),
- item => Assert.Equal("Find this!", item.Value),
- item => Assert.Equal("Find that!", item.Value));
- Assert.Equal(0, table.Find("Значение").First().ParentColumn.Index);
- Assert.Equal(3, table.Rows[2].Find("Find").Count());
- Assert.Empty(table.Columns[1].Find("Пусто"));
- }
-
- [ExcelFact]
- public void CanAddColumns()
- {
- int originalCount = table.Columns.Count();
- table.Columns[1].AddLeft();
- Assert.Equal(originalCount + 1, table.Columns.Count());
- }
-
- public void Dispose()
- {
- Util.Application.ActiveWindow.Close(SaveChanges: false);
- }
-}
diff --git a/RhSolutions.sln b/RhSolutions.sln
index 8db9bf3..8d94b9b 100644
--- a/RhSolutions.sln
+++ b/RhSolutions.sln
@@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.AddIn", "RhSolu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.Tests", "RhSolutions.Tests\RhSolutions.Tests.csproj", "{6EECCDDB-741C-404A-874F-BB8656265162}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.ExcelExtensions", "RhSolutions.ExcelExtensions\RhSolutions.ExcelExtensions.csproj", "{ADB862A8-5CC6-4509-A4F7-9907E84F5801}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -23,10 +21,6 @@ Global
{6EECCDDB-741C-404A-874F-BB8656265162}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EECCDDB-741C-404A-874F-BB8656265162}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EECCDDB-741C-404A-874F-BB8656265162}.Release|Any CPU.Build.0 = Release|Any CPU
- {ADB862A8-5CC6-4509-A4F7-9907E84F5801}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {ADB862A8-5CC6-4509-A4F7-9907E84F5801}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {ADB862A8-5CC6-4509-A4F7-9907E84F5801}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {ADB862A8-5CC6-4509-A4F7-9907E84F5801}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE