diff --git a/OcrClient/Models/OcrResponse.cs b/OcrClient/Models/OcrResponse.cs
index 2afc041..2b26ab7 100644
--- a/OcrClient/Models/OcrResponse.cs
+++ b/OcrClient/Models/OcrResponse.cs
@@ -2,4 +2,27 @@ namespace OcrClient.Models;
public class OcrResponse
{
-}
\ No newline at end of file
+ public Result? Result { get; set; }
+}
+public class Result
+{
+ public TextAnnotation? TextAnnotation { get; set; }
+}
+public class TextAnnotation
+{
+ public List
? Tables { get; set; }
+}
+
+public class Table
+{
+ public string? RowCount { get; set; }
+ public string? ColumnCount { get; set; }
+ public List? Cells { get; set; }
+}
+
+public class Cell
+{
+ public string? RowIndex { get; set; }
+ public string? ColumnIndex { get; set; }
+ public string? Text { get; set; }
+}
diff --git a/OcrClient/OcrClient.csproj b/OcrClient/OcrClient.csproj
index 4f78021..cdd654f 100644
--- a/OcrClient/OcrClient.csproj
+++ b/OcrClient/OcrClient.csproj
@@ -8,6 +8,7 @@
+
diff --git a/OcrClient/Services/IOcrClient.cs b/OcrClient/Services/IOcrClient.cs
index c8b1a86..9b281c9 100644
--- a/OcrClient/Services/IOcrClient.cs
+++ b/OcrClient/Services/IOcrClient.cs
@@ -4,5 +4,5 @@ namespace OcrClient.Services;
public interface IOcrClient
{
- public Task ProcessImage(string base64Image);
+ public Task> ProcessImage(string base64Image, string xFolderId, string apiKey);
}
diff --git a/OcrClient/Services/OcrClient.cs b/OcrClient/Services/OcrClient.cs
deleted file mode 100644
index e4cfef3..0000000
--- a/OcrClient/Services/OcrClient.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using OcrClient.Models;
-using System.Net.Http;
-
-namespace OcrClient.Services;
-
-public class YandexOcrClient : IOcrClient
-{
- private readonly HttpClient _httpClient;
-
- public YandexOcrClient(HttpClient httpClient)
- {
- _httpClient = httpClient;
- }
-
- public Task ProcessImage(string base64Image)
- {
- throw new NotImplementedException();
- }
-}
\ No newline at end of file
diff --git a/OcrClient/Services/YandexOcrClient.cs b/OcrClient/Services/YandexOcrClient.cs
new file mode 100644
index 0000000..8568e38
--- /dev/null
+++ b/OcrClient/Services/YandexOcrClient.cs
@@ -0,0 +1,70 @@
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using Newtonsoft.Json;
+using OcrClient.Models;
+
+namespace OcrClient.Services;
+
+public class YandexOcrClient : IOcrClient
+{
+ private readonly HttpClient _httpClient;
+ public YandexOcrClient(HttpClient httpClient)
+ {
+ _httpClient = httpClient;
+ _httpClient.BaseAddress = new Uri("https://ocr.api.cloud.yandex.net/ocr/v1/");
+ }
+
+ public async Task> ProcessImage(string base64Image, string xFolderId, string apiKey)
+ {
+ using StringContent jsonContent = new(
+ JsonConvert.SerializeObject(new
+ {
+ mimeType = "PNG",
+ languageCodes = new string[] { "ru", "en" },
+ model = "table",
+ content = base64Image
+ }),
+ Encoding.UTF8,
+ "application/json");
+ _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Api-Key", apiKey);
+ _httpClient.DefaultRequestHeaders.Add("x-folder-id", xFolderId);
+ _httpClient.DefaultRequestHeaders.Add("x-data-logging-enable", "true");
+
+ using HttpResponseMessage response = await _httpClient.PostAsync("recognizeText", jsonContent);
+ response.EnsureSuccessStatusCode();
+
+ string jsonResponse = await response.Content.ReadAsStringAsync();
+ OcrResponse? deserialized = JsonConvert.DeserializeObject(jsonResponse);
+
+ if (deserialized != null)
+ {
+ var tables = deserialized?.Result?.TextAnnotation?.Tables ?? Enumerable.Empty();
+ if (tables.Any())
+ {
+ List result = new();
+ foreach (var table in tables)
+ {
+ if (table.Cells == null || table.Cells.Count == 0)
+ {
+ continue;
+ }
+ int columnCount = int.Parse(table.ColumnCount);
+ int rowCount = int.Parse(table.RowCount);
+ object[,] cells = new object[rowCount, columnCount];
+
+ foreach (Cell cell in table.Cells)
+ {
+ int rowIndex = int.Parse(cell.RowIndex);
+ int columnIndex = int.Parse(cell.ColumnIndex);
+ cells[rowIndex, columnIndex] = double.TryParse(cell.Text, out double v) ?
+ v : cell.Text ?? string.Empty;
+ }
+ result.Add(cells);
+ }
+ return result;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/RhSolutions.AddIn/Controllers/RibbonController.cs b/RhSolutions.AddIn/Controllers/RibbonController.cs
index 310f0fe..cc58586 100644
--- a/RhSolutions.AddIn/Controllers/RibbonController.cs
+++ b/RhSolutions.AddIn/Controllers/RibbonController.cs
@@ -33,7 +33,7 @@ public class RibbonController : ExcelRibbon
-
+
@@ -102,6 +102,13 @@ public class RibbonController : ExcelRibbon
return selection.Columns.Count == 2;
}
}
+
+ public bool GetOcrEnabled(IRibbonControl control)
+ {
+ return RhSolutionsAddIn.Excel.ActiveWorkbook != null &&
+ !string.IsNullOrEmpty(RhSolutionsAddIn.Configuration["x-folder-id"]) &&
+ !string.IsNullOrEmpty(RhSolutionsAddIn.Configuration["apiKey"]);
+ }
public string GetVersionLabel(IRibbonControl control)
{
diff --git a/RhSolutions.AddIn/Properties/AssemblyInfo.cs b/RhSolutions.AddIn/Properties/AssemblyInfo.cs
index a71a4ad..e74d00e 100644
--- a/RhSolutions.AddIn/Properties/AssemblyInfo.cs
+++ b/RhSolutions.AddIn/Properties/AssemblyInfo.cs
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
+using Microsoft.Extensions.Configuration.UserSecrets;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -33,3 +34,4 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.9.5.1")]
[assembly: AssemblyFileVersion("1.9.5.1")]
+[assembly: UserSecretsId("d4bb704e-14a5-421f-8f2d-0ffb66d090a2")]
diff --git a/RhSolutions.AddIn/RhSolutions.AddIn.csproj b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
index ca11644..9ba0622 100644
--- a/RhSolutions.AddIn/RhSolutions.AddIn.csproj
+++ b/RhSolutions.AddIn/RhSolutions.AddIn.csproj
@@ -2,12 +2,11 @@
net472;net6.0-windows
10
- Library
- RhSolutions
- RhSolutions.AddIn
+ false
false
+ true
true
- true
+ d4bb704e-14a5-421f-8f2d-0ffb66d090a2
CA1416
@@ -21,6 +20,9 @@
+
+
+
@@ -28,9 +30,9 @@
-
-
-
+
+
+
diff --git a/RhSolutions.AddIn/Services/AddInConfiguration.cs b/RhSolutions.AddIn/Services/AddInConfiguration.cs
index 73b9a5b..860b6c1 100644
--- a/RhSolutions.AddIn/Services/AddInConfiguration.cs
+++ b/RhSolutions.AddIn/Services/AddInConfiguration.cs
@@ -1,43 +1,58 @@
-using Microsoft.Win32;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Win32;
using System.IO;
namespace RhSolutions.Services;
public class AddInConfiguration : IAddInConfiguration
{
- private RegistryKey _rootKey;
- private string _priceListPath;
- private Dictionary _priceListHeaders;
+ private IConfiguration _configuration;
+ private RegistryKey _rootKey;
+ private string _priceListPath;
+ private Dictionary settingsValues;
- public event IAddInConfiguration.SettingsHandler OnSettingsChange;
+ public string this[string key]
+ {
+ get => _configuration[key];
+ }
- public AddInConfiguration()
- {
- _rootKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\RhSolutions\RhSolutions-AddIn");
- _priceListPath = (string)_rootKey.GetValue("PriceListPath");
- _priceListHeaders = new()
- {
- ["Amount"] = "Кол-во",
- ["OldSku"] = "Прежний материал",
- ["Sku"] = "Актуальный материал",
- ["ProductLine"] = "Программа",
- ["Name"] = "Наименование",
- ["Measure"] = "Ед. изм."
- };
- }
+ public event IAddInConfiguration.SettingsHandler OnSettingsChange;
- public string GetPriceListFileName() => Path.GetFileName(_priceListPath);
- public Dictionary GetPriceListHeaders() => _priceListHeaders;
- public string GetPriceListPath() => _priceListPath;
+ public AddInConfiguration()
+ {
+ // EmbeddedFileProvider embeddedProvider = new (typeof(RhSolutionsAddIn).Assembly);
+ // using Stream stream = embeddedProvider.GetFileInfo("appsettings.json").CreateReadStream();
- public void SaveSettings()
- {
- _rootKey.SetValue("PriceListPath", _priceListPath);
- OnSettingsChange.Invoke();
- }
+ _configuration = new ConfigurationBuilder()
+ .AddUserSecrets()
+ // .AddJsonStream(stream)
+ .Build();
- public void SetPriceListPath(string value)
- {
- _priceListPath = value;
- }
+ _rootKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\RhSolutions\RhSolutions-AddIn");
+ _priceListPath = (string)_rootKey.GetValue("PriceListPath");
+ settingsValues = new()
+ {
+ ["Amount"] = "Кол-во",
+ ["OldSku"] = "Прежний материал",
+ ["Sku"] = "Актуальный материал",
+ ["ProductLine"] = "Программа",
+ ["Name"] = "Наименование",
+ ["Measure"] = "Ед. изм."
+ };
+ }
+
+ public string GetPriceListFileName() => Path.GetFileName(_priceListPath);
+ public Dictionary GetPriceListHeaders() => settingsValues;
+ public string GetPriceListPath() => _priceListPath;
+
+ public void SaveSettings()
+ {
+ _rootKey.SetValue("PriceListPath", _priceListPath);
+ OnSettingsChange.Invoke();
+ }
+
+ public void SetPriceListPath(string value)
+ {
+ _priceListPath = value;
+ }
}
\ No newline at end of file
diff --git a/RhSolutions.AddIn/Services/IAddInConfiguration.cs b/RhSolutions.AddIn/Services/IAddInConfiguration.cs
index e19da3d..9f06e73 100644
--- a/RhSolutions.AddIn/Services/IAddInConfiguration.cs
+++ b/RhSolutions.AddIn/Services/IAddInConfiguration.cs
@@ -1,12 +1,15 @@
-namespace RhSolutions.Services;
+using Microsoft.Extensions.Configuration;
+
+namespace RhSolutions.Services;
public interface IAddInConfiguration
{
- public string GetPriceListPath();
- public void SetPriceListPath(string value);
- public string GetPriceListFileName();
- public Dictionary GetPriceListHeaders();
- public delegate void SettingsHandler();
- public event SettingsHandler OnSettingsChange;
- public void SaveSettings();
+ string this[string key] { get; }
+ public string GetPriceListPath();
+ public void SetPriceListPath(string value);
+ public string GetPriceListFileName();
+ public Dictionary GetPriceListHeaders();
+ public delegate void SettingsHandler();
+ public event SettingsHandler OnSettingsChange;
+ public void SaveSettings();
}
\ No newline at end of file
diff --git a/RhSolutions.AddIn/Tools/EventsUtil.cs b/RhSolutions.AddIn/Tools/EventsUtil.cs
index 5522c10..31063e4 100644
--- a/RhSolutions.AddIn/Tools/EventsUtil.cs
+++ b/RhSolutions.AddIn/Tools/EventsUtil.cs
@@ -4,40 +4,41 @@ namespace RhSolutions.Tools;
internal static class EventsUtil
{
- public static void Initialize()
- {
- RibbonController.EnsurePriseListExists();
- RhSolutionsAddIn.Excel.SheetSelectionChange += RefreshExportButton;
- RhSolutionsAddIn.Excel.SheetActivate += RefreshButtons;
- RhSolutionsAddIn.Excel.WorkbookActivate += RefreshButtons;
- RhSolutionsAddIn.Configuration.OnSettingsChange += RefreshSettingTitle;
- }
+ public static void Initialize()
+ {
+ RibbonController.EnsurePriseListExists();
+ RhSolutionsAddIn.Excel.SheetSelectionChange += RefreshExportButton;
+ RhSolutionsAddIn.Excel.SheetActivate += RefreshButtons;
+ RhSolutionsAddIn.Excel.WorkbookActivate += RefreshButtons;
+ RhSolutionsAddIn.Configuration.OnSettingsChange += RefreshSettingTitle;
+ }
- public static void Uninitialize()
- {
- RhSolutionsAddIn.Excel.SheetSelectionChange -= RefreshExportButton;
- RhSolutionsAddIn.Excel.SheetActivate -= RefreshButtons;
- RhSolutionsAddIn.Excel.WorkbookActivate -= RefreshButtons;
- RhSolutionsAddIn.Configuration.OnSettingsChange -= RefreshSettingTitle;
- }
+ public static void Uninitialize()
+ {
+ RhSolutionsAddIn.Excel.SheetSelectionChange -= RefreshExportButton;
+ RhSolutionsAddIn.Excel.SheetActivate -= RefreshButtons;
+ RhSolutionsAddIn.Excel.WorkbookActivate -= RefreshButtons;
+ RhSolutionsAddIn.Configuration.OnSettingsChange -= RefreshSettingTitle;
+ }
- private static void RefreshButtons(object sh)
- {
- RibbonController.UpdateWorkbookValidation();
- RibbonController.RefreshControl("convert");
- RibbonController.RefreshControl("dxfexport");
- RibbonController.RefreshControl("guess");
- RibbonController.RefreshControl("fillsleeves");
- RibbonController.RefreshControl("fillcouplings");
- }
+ private static void RefreshButtons(object sh)
+ {
+ RibbonController.UpdateWorkbookValidation();
+ RibbonController.RefreshControl("convert");
+ RibbonController.RefreshControl("dxfexport");
+ RibbonController.RefreshControl("guess");
+ RibbonController.RefreshControl("fillsleeves");
+ RibbonController.RefreshControl("fillcouplings");
+ RibbonController.RefreshControl("ocr");
+ }
- private static void RefreshExportButton(object sh, Range target)
- {
- RibbonController.RefreshControl("export");
- }
+ private static void RefreshExportButton(object sh, Range target)
+ {
+ RibbonController.RefreshControl("export");
+ }
- private static void RefreshSettingTitle()
- {
- RibbonController.RefreshControl("setPriceList");
- }
+ private static void RefreshSettingTitle()
+ {
+ RibbonController.RefreshControl("setPriceList");
+ }
}
diff --git a/RhSolutions.AddIn/Tools/OcrTool.cs b/RhSolutions.AddIn/Tools/OcrTool.cs
index 4579984..89a6fee 100644
--- a/RhSolutions.AddIn/Tools/OcrTool.cs
+++ b/RhSolutions.AddIn/Tools/OcrTool.cs
@@ -1,14 +1,19 @@
using System.Threading.Tasks;
using SnippingTool;
using OcrClient.Services;
+using System.Windows.Forms;
+using Application = Microsoft.Office.Interop.Excel.Application;
namespace RhSolutions.Tools;
internal class OcrTool : ITool
{
private IOcrClient client = RhSolutionsAddIn.ServiceProvider.GetService();
+ private Application app = RhSolutionsAddIn.Excel;
+ private string xFolderId = RhSolutionsAddIn.Configuration["x-folder-id"];
+ private string apiKey = RhSolutionsAddIn.Configuration["apiKey"];
- public void Execute()
+ public async void Execute()
{
try
{
@@ -19,7 +24,46 @@ internal class OcrTool : ITool
}).Wait();
string shot = Snipper.SnipBase64();
- var result = client.ProcessImage(shot);
+ RhSolutionsAddIn.Excel.Visible = true;
+
+ if (shot != null)
+ {
+ IEnumerable tables = await client.ProcessImage(shot, xFolderId, apiKey);
+ if (tables != null)
+ {
+ foreach (var table in tables)
+ {
+ int rowCount = table.GetLength(0);
+ int columnCount = table.GetLength(1);
+
+ Range currentCell = app.ActiveCell;
+ Range tableRange = app.ActiveSheet.Range(currentCell,
+ app.ActiveSheet.Cells(currentCell.Row + rowCount - 1, currentCell.Column + columnCount - 1));
+
+ if (app.WorksheetFunction.CountA(tableRange) > 0)
+ {
+ MessageBox.Show(@"На листе отсустствует диапазон для вставки распознанной таблицы.Попробуйте в другом месте или на пустом листе.",
+ "Ошибка",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ RhSolutionsAddIn.Excel.Visible = true;
+ return;
+ }
+ tableRange.Borders.LineStyle = XlLineStyle.xlContinuous;
+
+ for (int row = 0; row < rowCount; row++)
+ for (int column = 0; column < columnCount; column++)
+ {
+ Range excelCell = app.ActiveSheet.Cells(currentCell.Row + row,
+ currentCell.Column + column);
+ excelCell.Value2 = table[row,column];
+ excelCell.EntireColumn.AutoFit();
+ excelCell.EntireRow.AutoFit();
+ }
+ app.ActiveSheet.Cells(currentCell.Row + rowCount + 1, currentCell.Column).Activate();
+ }
+ }
+ }
}
catch (Exception)
{
|