Compare commits
41 Commits
Author | SHA1 | Date | |
---|---|---|---|
a065c4c699 | |||
a73b2441b3 | |||
06e47d3135 | |||
5c50e6bc8e | |||
87f030e0f9 | |||
6d3f2bf55c | |||
8cb8f58714 | |||
c8a5824add | |||
38011f165e | |||
46b8468628 | |||
7a7c703aa7 | |||
3b3e37b1c3 | |||
a6e5ed1476 | |||
dfe4ef7b5b | |||
dc1e8616a6 | |||
e71636f5f8 | |||
a6a0f104c5 | |||
cc32e4792c | |||
678bdb47b9 | |||
0292348f03 | |||
9b205a5b3e | |||
5c8c5f5736 | |||
339cd65dee | |||
b931809534 | |||
964bb01a80 | |||
f0fca06beb | |||
ed47fd38f6 | |||
556bb3778e | |||
d71ad65c80 | |||
2def24c9af | |||
56112eae51 | |||
c6f6551e4e | |||
84001e050c | |||
7b2a5955d8 | |||
fe58c854ea | |||
822398e286 | |||
634f91dd13 | |||
03146a6561 | |||
17e1a1681e | |||
e73c97e1f8 | |||
61f679f52e |
27
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": ".NET Core Launch (console)",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
"program": "C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE",
|
||||||
|
"args": [
|
||||||
|
"${workspaceFolder}\\RhSolutions.AddIn\\bin\\Debug\\net6.0-windows\\RhSolutions-AddIn64.xll"
|
||||||
|
],
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"console": "internalConsole",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"requireExactSource": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
12
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "dotnet",
|
||||||
|
"task": "build ${workspaceFolder}\\RhSolutions.AddIn\\RhSolutions.AddIn.csproj",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"label": "build"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
14
Install.ps1
@ -1,14 +0,0 @@
|
|||||||
$object = Invoke-WebRequest -Uri "https://gitea.cebotari.ru/api/v1/repos/chebser/RhSolutions-AddIn/releases/latest" | ConvertFrom-Json
|
|
||||||
$download_link = $object.assets[1].browser_download_url
|
|
||||||
Invoke-WebRequest -Uri $download_link -OutFile "$env:appdata\Microsoft\AddIns\RhSolutions-AddIn-packed.xll"
|
|
||||||
|
|
||||||
$excel = New-Object -ComObject Excel.Application
|
|
||||||
foreach ($addin in $excel.AddIns2)
|
|
||||||
{
|
|
||||||
$title = $addin.Title
|
|
||||||
if ($title -eq 'RhSolutions Add-In')
|
|
||||||
{
|
|
||||||
$addin.Installed = $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$excel.Quit()
|
|
@ -8,12 +8,13 @@
|
|||||||
- Объединение нескольких прайс-листов в один файл
|
- Объединение нескольких прайс-листов в один файл
|
||||||
- Поиск пар артикул-количество в любой сторонней таблице и экспорт в таблицу заказов
|
- Поиск пар артикул-количество в любой сторонней таблице и экспорт в таблицу заказов
|
||||||
- Подбор монтажных гильз для фитингов RAUTITAN
|
- Подбор монтажных гильз для фитингов RAUTITAN
|
||||||
|
- Подбор ремонтных муфт по количеству трубы
|
||||||
- Экспорт таблицы заказов в девятиграфку по ГОСТ
|
- Экспорт таблицы заказов в девятиграфку по ГОСТ
|
||||||
|
|
||||||
*Для работы функций "Экспорт", "Актуализация" и "Объединение" требуется указать путь к файлу пустого прайс-листа РЕХАУ*
|
*Для работы функций "Экспорт", "Актуализация" и "Объединение" требуется указать путь к файлу пустого прайс-листа РЕХАУ*
|
||||||
|
|
||||||
## Реализованные формулы для работы с артикулами
|
## Реализованные формулы для работы с артикулами
|
||||||
- ```=RHSOLUTIONS()``` и ```=РЕХАУ()``` - поиск в удаленной базе данных
|
- ```=РЕХАУ()``` - поиск артикула РЕХАУ по произвольному запросу в сервисе [RhSolutions-Api](https://gitea.cebotari.ru/chebser/RhSolutions-Api)
|
||||||
- ```=РЕХАУАРТИКУЛ()``` - экстракция артикула РЕХАУ из любой строки по регулярному выражению
|
- ```=РЕХАУАРТИКУЛ()``` - экстракция артикула РЕХАУ из любой строки по регулярному выражению
|
||||||
- ```=РЕХАУИМЯ()``` - поиск названия артикула по номеру
|
- ```=РЕХАУИМЯ()``` - поиск названия артикула по номеру
|
||||||
- ```=РЕХАУЦЕНА()``` - поиск цены в евро по номеру артикула
|
- ```=РЕХАУЦЕНА()``` - поиск цены в евро по номеру артикула
|
||||||
|
27
RhSolutions.AddIn/AddIn/CurrencyFunctions.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
namespace RhSolutions.AddIn;
|
||||||
|
|
||||||
|
public static class CurrencyFunctions
|
||||||
|
{
|
||||||
|
private static readonly ICurrencyClient currencyClient =
|
||||||
|
RhSolutionsAddIn.ServiceProvider.GetRequiredService<ICurrencyClient>();
|
||||||
|
|
||||||
|
[ExcelFunction(Name = "КУРСЕВРО")]
|
||||||
|
public static object GetEuroCurrencyRate(double dateField)
|
||||||
|
{
|
||||||
|
DateTime date = dateField == 0 ? DateTime.Today : DateTime.FromOADate(dateField);
|
||||||
|
var functionName = nameof(GetEuroCurrencyRate);
|
||||||
|
var parameters = new object[] { date };
|
||||||
|
|
||||||
|
var exchangeRate = ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
|
{
|
||||||
|
var requestResult = await currencyClient.GetExchangeRate(date); return requestResult ?? -1m;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (exchangeRate is not decimal)
|
||||||
|
{
|
||||||
|
return "Загрузка...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (decimal)exchangeRate < 0 ? ExcelError.ExcelErrorNA : exchangeRate;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,7 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using ExcelDna.IntelliSense;
|
|
||||||
#if !NET472
|
|
||||||
using System.Runtime.Versioning;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace RhSolutions.AddIn;
|
namespace RhSolutions.AddIn;
|
||||||
|
|
||||||
#if !NET472
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
#endif
|
|
||||||
public sealed class RhSolutionsAddIn : IExcelAddIn
|
public sealed class RhSolutionsAddIn : IExcelAddIn
|
||||||
{
|
{
|
||||||
public static Application Excel { get; private set; }
|
public static Application Excel { get; private set; }
|
||||||
@ -55,22 +48,13 @@ public sealed class RhSolutionsAddIn : IExcelAddIn
|
|||||||
|
|
||||||
EventsUtil.Initialize();
|
EventsUtil.Initialize();
|
||||||
|
|
||||||
if (Environment.GetEnvironmentVariable("ISTESTING") == "false")
|
|
||||||
{
|
|
||||||
IntelliSenseServer.Install();
|
|
||||||
}
|
|
||||||
|
|
||||||
ServicePointManager.SecurityProtocol =
|
ServicePointManager.SecurityProtocol =
|
||||||
SecurityProtocolType.Tls12;
|
SecurityProtocolType.Tls12;
|
||||||
|
ServicePointManager.DefaultConnectionLimit = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AutoClose()
|
public void AutoClose()
|
||||||
{
|
{
|
||||||
EventsUtil.Uninitialize();
|
EventsUtil.Uninitialize();
|
||||||
|
|
||||||
if (Environment.GetEnvironmentVariable("ISTESTING") == "false")
|
|
||||||
{
|
|
||||||
IntelliSenseServer.Uninstall();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,99 +1,76 @@
|
|||||||
#if !NET472
|
namespace RhSolutions.AddIn;
|
||||||
using System.Runtime.Versioning;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
public static class RhSolutionsFunctions
|
||||||
|
{
|
||||||
|
private static readonly IDatabaseClient databaseClient =
|
||||||
|
RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
|
||||||
|
private static readonly ICurrencyClient currencyClient =
|
||||||
|
RhSolutionsAddIn.ServiceProvider.GetRequiredService<ICurrencyClient>();
|
||||||
|
|
||||||
namespace RhSolutions.AddIn;
|
[ExcelFunction(Name = "РЕХАУ")]
|
||||||
|
public static object ProductSearch(object[,] values)
|
||||||
#if !NET472
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
#endif
|
|
||||||
public class RhSolutionsFunctions
|
|
||||||
{
|
{
|
||||||
[ExcelFunction(Description = "Поиск артикула в базе данных")]
|
List<string> strings = new();
|
||||||
public static object RHSOLUTIONS([ExcelArgument(Name = "СТРОКА", Description = "Ячейка с артикулом РЕХАУ или поисковый запрос в свободной форме")] string line)
|
int rows = values.GetLength(0);
|
||||||
|
int columns = values.GetLength(1);
|
||||||
|
for (int row = 0; row < rows; row++)
|
||||||
{
|
{
|
||||||
IDatabaseClient databaseClient = RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
|
for (int column = 0; column < columns; column++)
|
||||||
|
|
||||||
ProductSku.TryParse(line, out var skus);
|
|
||||||
|
|
||||||
if (ExcelAsyncUtil.Run(nameof(RHSOLUTIONS), line, delegate
|
|
||||||
{
|
{
|
||||||
return databaseClient.GetProducts(line)
|
object value = values[row, column];
|
||||||
.GetAwaiter()
|
strings.Add(value.ToString());
|
||||||
.GetResult();
|
|
||||||
}) is not IEnumerable<Product> requestResult)
|
|
||||||
{
|
|
||||||
if (skus.Any())
|
|
||||||
{
|
|
||||||
return $"{skus.First()} ...";
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
string query = string.Join(" ", strings.ToArray());
|
||||||
|
var functionName = nameof(ProductSearch);
|
||||||
|
var parameters = new object[] { query };
|
||||||
|
if (ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
|
{
|
||||||
|
return await databaseClient.GetProducts(query);
|
||||||
|
}) is not IEnumerable<Product> products)
|
||||||
{
|
{
|
||||||
return "Загрузка...";
|
return "Загрузка...";
|
||||||
}
|
}
|
||||||
}
|
else if (!products.Any())
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!requestResult.Any() && !skus.Any())
|
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
else if (!requestResult.Any())
|
|
||||||
{
|
|
||||||
return $"{skus.First()}";
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var firstProduct = requestResult.First();
|
var product = products.First();
|
||||||
return $"{firstProduct.ProductSku} {firstProduct.Name}";
|
return $"{product.Id} {product.Name}";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ExcelFunction(Description = "Поиск артикула в базе данных")]
|
[ExcelFunction(Name = "РЕХАУАРТИКУЛ")]
|
||||||
public static object РЕХАУ([ExcelArgument(Name = "СТРОКА", Description = "Ячейка с артикулом РЕХАУ или поисковый запрос в свободной форме")] string line)
|
public static object SkuSearch(string query)
|
||||||
=> RHSOLUTIONS(line);
|
|
||||||
|
|
||||||
[ExcelFunction(Description = "Выделить артикул РЕХАУ из ячейки")]
|
|
||||||
public static object РЕХАУАРТИКУЛ([ExcelArgument(Name = "СТРОКА", Description = "Ячейка содержащая артикул РЕХАУ")] string line)
|
|
||||||
{
|
{
|
||||||
if (ProductSku.TryParse(line, out var skus))
|
if (ProductSku.TryParse(query, out var skus))
|
||||||
{
|
{
|
||||||
return skus.First().Id;
|
return skus.First().Id;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[ExcelFunction(Description = "Поиск названия по артикулу РЕХАУ")]
|
[ExcelFunction(Name = "РЕХАУИМЯ")]
|
||||||
public static object РЕХАУИМЯ([ExcelArgument(Name = "АРТИКУЛ", Description = "Ячейка содержащая артикул РЕХАУ")] string line)
|
public static object GetProductName(string query)
|
||||||
{
|
{
|
||||||
if (!ProductSku.TryParse(line, out var skus))
|
if (!ProductSku.TryParse(query, out var skus))
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var article = skus.First().Id;
|
var article = skus.First().Id;
|
||||||
IDatabaseClient databaseClient = RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
|
var functionName = nameof(GetProductName);
|
||||||
|
var parameters = new object[] { query };
|
||||||
if (ExcelAsyncUtil.Run(nameof(РЕХАУИМЯ), line, delegate
|
if (ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
{
|
{
|
||||||
return databaseClient.GetProducts(article)
|
return await databaseClient.GetProducts(article);
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
}) is not IEnumerable<Product> requestResult)
|
}) is not IEnumerable<Product> requestResult)
|
||||||
{
|
{
|
||||||
return "Загрузка...";
|
return "Загрузка...";
|
||||||
}
|
}
|
||||||
else
|
else if (!requestResult.Any())
|
||||||
{
|
|
||||||
if (!requestResult.Any())
|
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
@ -103,33 +80,26 @@ public class RhSolutionsFunctions
|
|||||||
return firstProduct.Name;
|
return firstProduct.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ExcelFunction(Description = "Поиск цены артикула РЕХАУ в евро")]
|
[ExcelFunction(Name = "РЕХАУЦЕНА")]
|
||||||
public static object РЕХАУЦЕНА([ExcelArgument(Name = "АРТИКУЛ", Description = "Ячейка содержащая артикул РЕХАУ")] string line)
|
public static object GetProductPrice(string query)
|
||||||
{
|
{
|
||||||
if (!ProductSku.TryParse(line, out var skus))
|
if (!ProductSku.TryParse(query, out var skus))
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var article = skus.First().Id;
|
var article = skus.First().Id;
|
||||||
IDatabaseClient databaseClient = RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
|
var functionName = nameof(GetProductPrice);
|
||||||
|
var parameters = new object[] { article };
|
||||||
|
|
||||||
if (ExcelAsyncUtil.Run(nameof(РЕХАУЦЕНА), line, delegate
|
if (ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
{
|
{
|
||||||
return databaseClient.GetProducts(article)
|
return await databaseClient.GetProducts(article);
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
}) is not IEnumerable<Product> requestResult)
|
}) is not IEnumerable<Product> requestResult)
|
||||||
{
|
{
|
||||||
return "Загрузка...";
|
return "Загрузка...";
|
||||||
}
|
}
|
||||||
else
|
else if (!requestResult.Any())
|
||||||
{
|
|
||||||
if (!requestResult.Any())
|
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
@ -139,65 +109,42 @@ public class RhSolutionsFunctions
|
|||||||
return Math.Round(firstProduct.Price * 1.2m, 2);
|
return Math.Round(firstProduct.Price * 1.2m, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ExcelFunction(Description = "Поиск цены артикула РЕХАУ в рублях")]
|
[ExcelFunction(Name = "РЕХАУЦЕНАРУБ")]
|
||||||
public static object РЕХАУЦЕНАРУБ([ExcelArgument(Name = "АРТИКУЛ", Description = "Ячейка содержащая артикул РЕХАУ")] string line,
|
public static object GetProductPriceRub(string query, double dateField)
|
||||||
[ExcelArgument(Name = "ДАТА", Description = "Дата в формате Excel (необязательно)")] double dateField)
|
|
||||||
{
|
{
|
||||||
if (!ProductSku.TryParse(line, out var skus))
|
if (!ProductSku.TryParse(query, out var skus))
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
IDatabaseClient databaseClient = RhSolutionsAddIn.ServiceProvider.GetService<IDatabaseClient>();
|
|
||||||
ICurrencyClient currencyClient = RhSolutionsAddIn.ServiceProvider.GetRequiredService<ICurrencyClient>();
|
|
||||||
IMemoryCache memoryCache = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IMemoryCache>();
|
|
||||||
var article = skus.First().Id;
|
var article = skus.First().Id;
|
||||||
DateTime date = dateField == 0 ? DateTime.Today : DateTime.FromOADate(dateField);
|
DateTime date = dateField == 0 ? DateTime.Today : DateTime.FromOADate(dateField);
|
||||||
|
|
||||||
if (!memoryCache.TryGetValue(date, out decimal exchangeRate))
|
|
||||||
{
|
|
||||||
var result = ExcelAsyncUtil.Run(nameof(КУРСЕВРО), dateField, delegate
|
|
||||||
{
|
|
||||||
var requestResult = currencyClient.GetExchangeRate(date)
|
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
|
|
||||||
|
var functionName = nameof(GetProductPriceRub);
|
||||||
|
var parameters = new object[] { date };
|
||||||
|
|
||||||
|
if (ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
|
{
|
||||||
|
var requestResult = await currencyClient.GetExchangeRate(date);
|
||||||
return requestResult ?? -1m;
|
return requestResult ?? -1m;
|
||||||
});
|
}) is not decimal exchangeRate)
|
||||||
|
|
||||||
if (result is not decimal)
|
|
||||||
{
|
{
|
||||||
return "Загрузка...";
|
return "Загрузка...";
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
exchangeRate = (decimal)result;
|
|
||||||
var cacheEntryOptions = new MemoryCacheEntryOptions()
|
|
||||||
.SetSlidingExpiration(TimeSpan.FromHours(1));
|
|
||||||
memoryCache.Set(date, exchangeRate, cacheEntryOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExcelAsyncUtil.Run(nameof(РЕХАУЦЕНАРУБ), line, delegate
|
parameters = new object[] { query };
|
||||||
|
if (ExcelAsyncUtil.RunTask(functionName, parameters, async () =>
|
||||||
{
|
{
|
||||||
var product = databaseClient.GetProducts(article)
|
var products = await databaseClient.GetProducts(article);
|
||||||
.GetAwaiter()
|
var product = products.FirstOrDefault();
|
||||||
.GetResult()
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
return product == null ? -1m :
|
return product == null ? -1m :
|
||||||
product.Price * exchangeRate * 1.2m;
|
product.Price * (decimal)exchangeRate * 1.2m;
|
||||||
}) is not decimal requestResult)
|
}) is not decimal requestResult)
|
||||||
{
|
{
|
||||||
return "Загрузка...";
|
return "Загрузка...";
|
||||||
}
|
}
|
||||||
else
|
else if (requestResult < 0 || exchangeRate < 0)
|
||||||
{
|
|
||||||
if (requestResult < 0)
|
|
||||||
{
|
{
|
||||||
return ExcelError.ExcelErrorNA;
|
return ExcelError.ExcelErrorNA;
|
||||||
}
|
}
|
||||||
@ -207,39 +154,3 @@ public class RhSolutionsFunctions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[ExcelFunction(Description = "Получить курс евро по ЦБ")]
|
|
||||||
public static object КУРСЕВРО([ExcelArgument(Name = "ДАТА", Description = "Дата в формате Excel (необязательно)")] double dateField)
|
|
||||||
{
|
|
||||||
ICurrencyClient currencyClient = RhSolutionsAddIn.ServiceProvider.GetRequiredService<ICurrencyClient>();
|
|
||||||
IMemoryCache memoryCache = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IMemoryCache>();
|
|
||||||
DateTime date = dateField == 0 ? DateTime.Today : DateTime.FromOADate(dateField);
|
|
||||||
|
|
||||||
if (!memoryCache.TryGetValue(date, out decimal exchangeRate))
|
|
||||||
{
|
|
||||||
var result = ExcelAsyncUtil.Run(nameof(КУРСЕВРО), dateField, delegate
|
|
||||||
{
|
|
||||||
var requestResult = currencyClient.GetExchangeRate(date)
|
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
|
|
||||||
return requestResult ?? -1m;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result is not decimal)
|
|
||||||
{
|
|
||||||
return "Загрузка...";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exchangeRate = (decimal)result;
|
|
||||||
var cacheEntryOptions = new MemoryCacheEntryOptions()
|
|
||||||
.SetSlidingExpiration(TimeSpan.FromHours(1));
|
|
||||||
memoryCache.Set(date, exchangeRate, cacheEntryOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return exchangeRate < 0 ? ExcelError.ExcelErrorNA : exchangeRate;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,11 @@
|
|||||||
using ExcelDna.Integration.CustomUI;
|
using ExcelDna.Integration.CustomUI;
|
||||||
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
#if! NET472
|
|
||||||
using System.Runtime.Versioning;
|
|
||||||
#endif
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace RhSolutions.Controllers;
|
namespace RhSolutions.Controllers;
|
||||||
|
|
||||||
#if !NET472
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
#endif
|
|
||||||
[ComVisible(true)]
|
[ComVisible(true)]
|
||||||
public class RibbonController : ExcelRibbon
|
public class RibbonController : ExcelRibbon
|
||||||
{
|
{
|
||||||
@ -114,7 +109,7 @@ public class RibbonController : ExcelRibbon
|
|||||||
public string GetPriceListPathLabel(IRibbonControl control)
|
public string GetPriceListPathLabel(IRibbonControl control)
|
||||||
{
|
{
|
||||||
string name = RhSolutionsAddIn.Configuration.GetPriceListFileName();
|
string name = RhSolutionsAddIn.Configuration.GetPriceListFileName();
|
||||||
return string.IsNullOrEmpty(name) ? "Шаблонный файл" : name;
|
return string.IsNullOrEmpty(name) ? "Указать шаблонный файл" : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateWorkbookValidation()
|
public static void UpdateWorkbookValidation()
|
||||||
@ -128,4 +123,13 @@ public class RibbonController : ExcelRibbon
|
|||||||
_workbookIsValid = worksheet.IsValidSource();
|
_workbookIsValid = worksheet.IsValidSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EnsurePriseListExists()
|
||||||
|
{
|
||||||
|
string pricelistPath = RhSolutionsAddIn.Configuration.GetPriceListPath();
|
||||||
|
if (!File.Exists(pricelistPath))
|
||||||
|
{
|
||||||
|
RhSolutionsAddIn.Configuration.SetPriceListPath(string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 900 B |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 7.3 KiB |
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.9.0.0")]
|
[assembly: AssemblyVersion("1.9.5.1")]
|
||||||
[assembly: AssemblyFileVersion("1.9.0.0")]
|
[assembly: AssemblyFileVersion("1.9.5.1")]
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"Excel": {
|
"Excel": {
|
||||||
"commandName": "Executable",
|
"commandName": "Executable",
|
||||||
"executablePath": "C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE",
|
"executablePath": "C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE",
|
||||||
"commandLineArgs": "RhSolutions-AddIn64.xll"
|
"commandLineArgs": "/x \"RhSolutions-AddIn64.xll\""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<DnaLibrary Name="RhSolutions Add-In" RuntimeVersion="v4.0" xmlns="http://schemas.excel-dna.net/addin/2020/07/dnalibrary">
|
<DnaLibrary Name="RhSolutions Add-In" RuntimeVersion="v4.0" xmlns="http://schemas.excel-dna.net/addin/2020/07/dnalibrary">
|
||||||
<ExternalLibrary Path="RhSolutions.AddIn.dll" ExplicitExports="false" LoadFromBytes="true" Pack="true" IncludePdb="false" />
|
<ExternalLibrary Path="RhSolutions.AddIn.dll" ExplicitExports="false" LoadFromBytes="true" Pack="true" IncludePdb="false" />
|
||||||
|
<Reference Path="ExcelDna.Registration.dll" Pack="true" />
|
||||||
<Reference Path="Microsoft.Bcl.AsyncInterfaces.dll" Pack="true" />
|
<Reference Path="Microsoft.Bcl.AsyncInterfaces.dll" Pack="true" />
|
||||||
<Reference Path="Microsoft.Bcl.HashCode.dll" Pack="true" />
|
<Reference Path="Microsoft.Bcl.HashCode.dll" Pack="true" />
|
||||||
<Reference Path="Microsoft.Extensions.Caching.Abstractions.dll" Pack="true" />
|
<Reference Path="Microsoft.Extensions.Caching.Abstractions.dll" Pack="true" />
|
||||||
@ -12,7 +13,6 @@
|
|||||||
<Reference Path="Microsoft.Extensions.Logging.dll" Pack="true" />
|
<Reference Path="Microsoft.Extensions.Logging.dll" Pack="true" />
|
||||||
<Reference Path="Microsoft.Extensions.Options.dll" Pack="true" />
|
<Reference Path="Microsoft.Extensions.Options.dll" Pack="true" />
|
||||||
<Reference Path="Microsoft.Extensions.Primitives.dll" Pack="true" />
|
<Reference Path="Microsoft.Extensions.Primitives.dll" Pack="true" />
|
||||||
<Reference Path="ExcelDna.IntelliSense.dll" Pack="true" />
|
|
||||||
<Reference Path="Newtonsoft.Json.dll" Pack="true" />
|
<Reference Path="Newtonsoft.Json.dll" Pack="true" />
|
||||||
<Reference Path="netDxf.dll" Pack="true" />
|
<Reference Path="netDxf.dll" Pack="true" />
|
||||||
<Reference Path="RhSolutions.ProductSku.dll" Pack="true" />
|
<Reference Path="RhSolutions.ProductSku.dll" Pack="true" />
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0-windows</TargetFrameworks>
|
||||||
<LangVersion>10</LangVersion>
|
<LangVersion>10</LangVersion>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<RootNamespace>RhSolutions</RootNamespace>
|
<RootNamespace>RhSolutions</RootNamespace>
|
||||||
@ -8,35 +8,17 @@
|
|||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||||
<ExcelDnaPackCompressResources>false</ExcelDnaPackCompressResources>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<StartupObject />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net472|AnyCPU'">
|
|
||||||
<NoWarn>1701;1702</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
|
|
||||||
<NoWarn>1701;1702</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows7.0|AnyCPU'">
|
|
||||||
<NoWarn>1701;1702</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows7.0|AnyCPU'">
|
|
||||||
<NoWarn>1701;1702</NoWarn>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ExcelDna.AddIn" Version="1.6.0">
|
<PackageReference Include="ExcelDna.AddIn" Version="1.8.0" />
|
||||||
<TreatAsUsed>true</TreatAsUsed>
|
<PackageReference Include="ExcelDna.Integration" Version="1.8.0" />
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="ExcelDna.Integration" Version="1.6.0" />
|
|
||||||
<PackageReference Include="ExcelDna.IntelliSense" Version="1.6.0" />
|
|
||||||
<PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
|
<PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" />
|
<PackageReference Include="ExcelDna.Registration" Version="1.8.0" />
|
||||||
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.1" />
|
||||||
<PackageReference Include="netDxf" Version="2022.11.2" />
|
<PackageReference Include="netDxf" Version="2022.11.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
<PackageReference Include="System.Buffers" Version="4.5.1" />
|
||||||
|
@ -38,11 +38,11 @@ public class CouplingsCalculator : IFittingsCalculator
|
|||||||
.ToDictionary(kvp =>
|
.ToDictionary(kvp =>
|
||||||
kvp.Key switch
|
kvp.Key switch
|
||||||
{
|
{
|
||||||
"16" => new Product("11600111001"),
|
"16" => new Product("11080111001"),
|
||||||
"20" => new Product("11600121001"),
|
"20" => new Product("11080121001"),
|
||||||
"25" => new Product("11600131001"),
|
"25" => new Product("11080131001"),
|
||||||
"32" => new Product("11600141001"),
|
"32" => new Product("11080141001"),
|
||||||
"40" => new Product("11600151001"),
|
"40" => new Product("11080151001"),
|
||||||
"50" => new Product("14563021001"),
|
"50" => new Product("14563021001"),
|
||||||
"63" => new Product("14563031001"),
|
"63" => new Product("14563031001"),
|
||||||
_ => throw new Exception($"Неизвестный диаметр {kvp.Key}")
|
_ => throw new Exception($"Неизвестный диаметр {kvp.Key}")
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Net;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
@ -8,15 +9,19 @@ namespace RhSolutions.Services;
|
|||||||
public class CurrencyClient : ICurrencyClient
|
public class CurrencyClient : ICurrencyClient
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
|
private readonly IMemoryCache _memoryCache;
|
||||||
private const string _requestAddress = @"https://www.cbr.ru/scripts/XML_daily.asp?date_req=";
|
private const string _requestAddress = @"https://www.cbr.ru/scripts/XML_daily.asp?date_req=";
|
||||||
public HttpStatusCode StatusCode { get; private set; }
|
public HttpStatusCode StatusCode { get; private set; }
|
||||||
|
|
||||||
public CurrencyClient(HttpClient httpClient)
|
public CurrencyClient(HttpClient httpClient, IMemoryCache memoryCache)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
|
_memoryCache = memoryCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<decimal?> GetExchangeRate(DateTime date)
|
public async Task<decimal?> GetExchangeRate(DateTime date)
|
||||||
|
{
|
||||||
|
if (!_memoryCache.TryGetValue(date, out decimal exchangeRate))
|
||||||
{
|
{
|
||||||
string request = $"{_requestAddress}{date.Date:dd/MM/yyyy}";
|
string request = $"{_requestAddress}{date.Date:dd/MM/yyyy}";
|
||||||
HttpResponseMessage response = await _httpClient.GetAsync(request);
|
HttpResponseMessage response = await _httpClient.GetAsync(request);
|
||||||
@ -25,11 +30,13 @@ public class CurrencyClient : ICurrencyClient
|
|||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
string xml = await response.Content.ReadAsStringAsync();
|
string xml = await response.Content.ReadAsStringAsync();
|
||||||
XElement valCourses = XElement.Parse(xml);
|
XElement valCourses = XElement.Parse(xml);
|
||||||
|
exchangeRate = decimal.Parse(valCourses.Elements("Valute")
|
||||||
decimal? exchangeRate = decimal.Parse(valCourses.Elements("Valute")
|
|
||||||
.Where(e => e.Element("Name").Value == "Евро")
|
.Where(e => e.Element("Name").Value == "Евро")
|
||||||
.FirstOrDefault()
|
.FirstOrDefault()
|
||||||
.Element("Value").Value);
|
.Element("Value").Value);
|
||||||
|
var cacheEntryOptions = new MemoryCacheEntryOptions()
|
||||||
|
.SetSlidingExpiration(TimeSpan.FromHours(1));
|
||||||
|
_memoryCache.Set(date, exchangeRate, cacheEntryOptions);
|
||||||
return exchangeRate;
|
return exchangeRate;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -38,4 +45,6 @@ public class CurrencyClient : ICurrencyClient
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return exchangeRate;
|
||||||
|
}
|
||||||
}
|
}
|
@ -79,7 +79,7 @@ public class ExcelReader : IReader, IDisposable
|
|||||||
return readResult;
|
return readResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(string, Dictionary<Product, double>)>
|
public IEnumerable<(string, Dictionary<Product, double>)>
|
||||||
ReadProducts(IEnumerable<Worksheet> worksheets)
|
ReadProducts(IEnumerable<Worksheet> worksheets)
|
||||||
{
|
{
|
||||||
List<(string, Dictionary<Product, double>)> result = new();
|
List<(string, Dictionary<Product, double>)> result = new();
|
||||||
@ -151,11 +151,15 @@ public class ExcelReader : IReader, IDisposable
|
|||||||
|
|
||||||
result.Add((wbName, readResult));
|
result.Add((wbName, readResult));
|
||||||
}
|
}
|
||||||
return result;
|
return result.OrderBy(x => x.Item1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(string, Dictionary<Product, double>)> ReadProducts(string[] files)
|
public IEnumerable<(string, Dictionary<Product, double>)> ReadProducts(string[] files)
|
||||||
{
|
{
|
||||||
|
HashSet<string> openedFiles = RhSolutionsAddIn.Excel.Workbooks
|
||||||
|
.Cast<Workbook>()
|
||||||
|
.Select(wb => wb.FullName)
|
||||||
|
.ToHashSet();
|
||||||
_progressBar = new("Открываю исходные файлы...", files.Length);
|
_progressBar = new("Открываю исходные файлы...", files.Length);
|
||||||
List<Worksheet> worksheets = new();
|
List<Worksheet> worksheets = new();
|
||||||
|
|
||||||
@ -170,7 +174,11 @@ public class ExcelReader : IReader, IDisposable
|
|||||||
var result = ReadProducts(worksheets);
|
var result = ReadProducts(worksheets);
|
||||||
foreach (var ws in worksheets)
|
foreach (var ws in worksheets)
|
||||||
{
|
{
|
||||||
ws.Parent.Close();
|
string file = (string)ws.Parent.FullName;
|
||||||
|
if (!openedFiles.Contains(file))
|
||||||
|
{
|
||||||
|
ws.Parent.Close(SaveChanges: false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ namespace RhSolutions.Services
|
|||||||
.Insert(XlInsertShiftDirection.xlShiftToRight, XlInsertFormatOrigin.xlFormatFromRightOrBelow);
|
.Insert(XlInsertShiftDirection.xlShiftToRight, XlInsertFormatOrigin.xlFormatFromRightOrBelow);
|
||||||
|
|
||||||
Range newColumnHeader = _worksheet.Cells[_amountCell.Row, _amountCell.Column - 1];
|
Range newColumnHeader = _worksheet.Cells[_amountCell.Row, _amountCell.Column - 1];
|
||||||
|
newColumnHeader.NumberFormat = "@";
|
||||||
newColumnHeader.Value2 = $"{product.Item1}";
|
newColumnHeader.Value2 = $"{product.Item1}";
|
||||||
newColumnHeader.WrapText = true;
|
newColumnHeader.WrapText = true;
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ public class GuessReader : IReader
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(string, Dictionary<Product, double>)> ReadProducts(IEnumerable<Worksheet> worksheets)
|
public IEnumerable<(string, Dictionary<Product, double>)> ReadProducts(IEnumerable<Worksheet> worksheets)
|
||||||
{
|
{
|
||||||
List<(string, Dictionary<Product, double>)> result = new();
|
List<(string, Dictionary<Product, double>)> result = new();
|
||||||
foreach (Worksheet worksheet in worksheets)
|
foreach (Worksheet worksheet in worksheets)
|
||||||
@ -206,7 +206,7 @@ public class GuessReader : IReader
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(string, Dictionary<Product, double>)> ReadProducts(string[] files)
|
public IEnumerable<(string, Dictionary<Product, double>)> ReadProducts(string[] files)
|
||||||
{
|
{
|
||||||
_progressBar = new("Открываю исходные файлы...", files.Length);
|
_progressBar = new("Открываю исходные файлы...", files.Length);
|
||||||
List<Worksheet> worksheets = new();
|
List<Worksheet> worksheets = new();
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
public interface IReader : IDisposable
|
public interface IReader : IDisposable
|
||||||
{
|
{
|
||||||
public Dictionary<Product, double> ReadProducts(Range range);
|
public Dictionary<Product, double> ReadProducts(Range range);
|
||||||
public List<(string, Dictionary<Product, double>)> ReadProducts(IEnumerable<Worksheet> worksheets);
|
public IEnumerable<(string, Dictionary<Product, double>)> ReadProducts(IEnumerable<Worksheet> worksheets);
|
||||||
public List<(string, Dictionary<Product, double>)> ReadProducts(string[] files);
|
public IEnumerable<(string, Dictionary<Product, double>)> ReadProducts(string[] files);
|
||||||
new void Dispose();
|
new void Dispose();
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,11 @@ public class SleevesCalculator : IFittingsCalculator
|
|||||||
["40"] = 0,
|
["40"] = 0,
|
||||||
["50"] = 0,
|
["50"] = 0,
|
||||||
["63"] = 0,
|
["63"] = 0,
|
||||||
|
["16PX"] = 0,
|
||||||
|
["20PX"] = 0,
|
||||||
|
["25PX"] = 0,
|
||||||
|
["32PX"] = 0,
|
||||||
|
["40PX"] = 0
|
||||||
};
|
};
|
||||||
var rautitanProducts = products.Where(kvp => kvp.Key.ProductLines.Contains("RAUTITAN"));
|
var rautitanProducts = products.Where(kvp => kvp.Key.ProductLines.Contains("RAUTITAN"));
|
||||||
|
|
||||||
@ -30,9 +35,16 @@ public class SleevesCalculator : IFittingsCalculator
|
|||||||
{
|
{
|
||||||
CaptureCollection collection = doubleCollection[0].Groups["Sleeve"].Captures;
|
CaptureCollection collection = doubleCollection[0].Groups["Sleeve"].Captures;
|
||||||
foreach (Capture sleeve in collection)
|
foreach (Capture sleeve in collection)
|
||||||
|
{
|
||||||
|
if (kvp.Key.Name.Contains("PX"))
|
||||||
|
{
|
||||||
|
result[$"{sleeve.Value}PX"] += kvp.Value * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
result[sleeve.Value] += kvp.Value * 2;
|
result[sleeve.Value] += kvp.Value * 2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var singleCollection = Regex.Matches(kvp.Key.Name, singlePattern);
|
var singleCollection = Regex.Matches(kvp.Key.Name, singlePattern);
|
||||||
@ -40,23 +52,35 @@ public class SleevesCalculator : IFittingsCalculator
|
|||||||
{
|
{
|
||||||
CaptureCollection collection = singleCollection[0].Groups["Sleeve"].Captures;
|
CaptureCollection collection = singleCollection[0].Groups["Sleeve"].Captures;
|
||||||
foreach (Capture sleeve in collection)
|
foreach (Capture sleeve in collection)
|
||||||
|
{
|
||||||
|
if (kvp.Key.Name.Contains("PX"))
|
||||||
|
{
|
||||||
|
result[$"{sleeve.Value}PX"] += kvp.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
result[sleeve.Value] += kvp.Value;
|
result[sleeve.Value] += kvp.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
.ToDictionary(kvp =>
|
.ToDictionary(kvp =>
|
||||||
kvp.Key switch
|
kvp.Key switch
|
||||||
{
|
{
|
||||||
"16" => new Product("11600011001"),
|
"16" => new Product("11080011001"),
|
||||||
"20" => new Product("11600021001"),
|
"20" => new Product("11080021001"),
|
||||||
"25" => new Product("11600031001"),
|
"25" => new Product("11080031001"),
|
||||||
"32" => new Product("11600041001"),
|
"32" => new Product("11080041001"),
|
||||||
"40" => new Product("11600051001"),
|
"40" => new Product("11080051001"),
|
||||||
"50" => new Product("11397711002"),
|
"50" => new Product("11397713002"),
|
||||||
"63" => new Product("11397811002"),
|
"63" => new Product("11397813002"),
|
||||||
|
"16PX" => new Product("11600011001"),
|
||||||
|
"20PX" => new Product("11600021001"),
|
||||||
|
"25PX" => new Product("11600031001"),
|
||||||
|
"32PX" => new Product("11600041001"),
|
||||||
|
"40PX" => new Product("11600051001"),
|
||||||
_ => throw new Exception($"Неизвестный диаметр {kvp.Key}")
|
_ => throw new Exception($"Неизвестный диаметр {kvp.Key}")
|
||||||
}, kvp => kvp.Value);
|
}, kvp => kvp.Value);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
using RhSolutions.Controllers;
|
using RhSolutions.Controllers;
|
||||||
#if !NET472
|
|
||||||
using System.Runtime.Versioning;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace RhSolutions.Tools;
|
namespace RhSolutions.Tools;
|
||||||
|
|
||||||
#if !NET472
|
|
||||||
[SupportedOSPlatform("windows")]
|
|
||||||
#endif
|
|
||||||
internal static class EventsUtil
|
internal static class EventsUtil
|
||||||
{
|
{
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
|
RibbonController.EnsurePriseListExists();
|
||||||
RhSolutionsAddIn.Excel.SheetSelectionChange += RefreshExportButton;
|
RhSolutionsAddIn.Excel.SheetSelectionChange += RefreshExportButton;
|
||||||
RhSolutionsAddIn.Excel.SheetActivate += RefreshButtons;
|
RhSolutionsAddIn.Excel.SheetActivate += RefreshButtons;
|
||||||
RhSolutionsAddIn.Excel.WorkbookActivate += RefreshButtons;
|
RhSolutionsAddIn.Excel.WorkbookActivate += RefreshButtons;
|
||||||
|
@ -17,9 +17,12 @@ internal class MergeTool : Tool
|
|||||||
{
|
{
|
||||||
IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IFileDialog>();
|
IFileDialog dialog = RhSolutionsAddIn.ServiceProvider.GetRequiredService<IFileDialog>();
|
||||||
string[] files = dialog.GetFiles();
|
string[] files = dialog.GetFiles();
|
||||||
|
if (files.Length > 0)
|
||||||
|
{
|
||||||
_reader = _readerFactory.GetReader("Excel");
|
_reader = _readerFactory.GetReader("Excel");
|
||||||
var products = _reader.ReadProducts(files);
|
var products = _reader.ReadProducts(files);
|
||||||
_writer = _writerFactory.GetWriter("NewPrice");
|
_writer = _writerFactory.GetWriter("NewPrice");
|
||||||
_writer.WriteProducts(products);
|
_writer.WriteProducts(products);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -28,11 +28,10 @@ public class CanFillCouplings : IDisposable
|
|||||||
var products = _reader.ReadProducts(new[] { _worksheet });
|
var products = _reader.ReadProducts(new[] { _worksheet });
|
||||||
var couplings = _calculator.Calculate(products.First().Item2);
|
var couplings = _calculator.Calculate(products.First().Item2);
|
||||||
_writer.WriteProducts(couplings);
|
_writer.WriteProducts(couplings);
|
||||||
|
for (int i = 2; i < 14; i++)
|
||||||
Assert.Equal(7, _worksheet.Range["E2"].Value);
|
{
|
||||||
Assert.Equal(1, _worksheet.Range["E3"].Value);
|
Assert.Equal(_worksheet.Range[$"F{i}"].Value, _worksheet.Range[$"E{i}"].Value);
|
||||||
Assert.Equal(1, _worksheet.Range["E5"].Value);
|
}
|
||||||
Assert.Equal(1, _worksheet.Range["E7"].Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -28,14 +28,10 @@ public class CanFillSleeves : IDisposable
|
|||||||
var products = _reader.ReadProducts(new[] { _worksheet });
|
var products = _reader.ReadProducts(new[] { _worksheet });
|
||||||
var sleeves = _calculator.Calculate(products.First().Item2);
|
var sleeves = _calculator.Calculate(products.First().Item2);
|
||||||
_writer.WriteProducts(sleeves);
|
_writer.WriteProducts(sleeves);
|
||||||
|
for (int i = 2; i < 14; i++)
|
||||||
Assert.Equal(25, _worksheet.Range["E2"].Value);
|
{
|
||||||
Assert.Equal(15, _worksheet.Range["E3"].Value);
|
Assert.Equal(_worksheet.Range[$"F{i}"].Value, _worksheet.Range[$"E{i}"].Value);
|
||||||
Assert.Equal(7, _worksheet.Range["E4"].Value);
|
}
|
||||||
Assert.Equal(8, _worksheet.Range["E5"].Value);
|
|
||||||
Assert.Equal(1, _worksheet.Range["E6"].Value);
|
|
||||||
Assert.Equal(3, _worksheet.Range["E7"].Value);
|
|
||||||
Assert.Equal(4, _worksheet.Range["E8"].Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
|
<PackageReference Include="ExcelDna.Interop" Version="15.0.1" />
|
||||||
<PackageReference Include="ExcelDna.Testing" Version="1.6.0" />
|
<PackageReference Include="ExcelDna.Testing" Version="1.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|