Введение
Это продолжение статьи о создании надстройки для Excel с помощью библиотеки Excel-DNA о сборке простой надстройки с пользовательской формулой. Здесь рассмотрим как сделать свою панель с кнопками, взаимодействовать с рабочей книгой, выводить уведомления, а также получить доступ к элементам интерфейса Excel.
Создание панели
Панели Ribbon описываются в XML. Простейшая выглядит так:
<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'> <ribbon> <tabs> <tab id='MyAddinTab' label='My Addin Tab'> <group id='MyAddinGroup' label='My Addin Group'> <button id='Button1' label='Button 1' size='large' imageMso='HappyFace' /> <button id='Button2' label='Button 2' size='large' imageMso='SadFace' /> <button id='Button3' label='Button 3' size='large' imageMso='Piggy' /> </group> </tab> </tabs> </ribbon> </customUI>
Тег tab описывает вкладки на панели инструментов, group — группы элементов, которые визуально отделяются друг от друга вертикальной чертой, button — элементы кнопок.
Для того чтобы отобразить такую панель в Excel нужно наследовать классу ExcelRibbon и переопределить метод GetCustomUI в котором возвращаем XML панели.
using ExcelDna.Integration.CustomUI; namespace ExcelAddIn.Controllers; public class RibbonController : ExcelRibbon { public override string GetCustomUI(string ribbonID) { return @"<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'> <ribbon> <tabs> <tab id='MyAddinTab' label='My Addin Tab'> <group id='MyAddinGroup' label='My Addin Group'> <button id='Button1' label='Button 1' size='large' imageMso='HappyFace' /> <button id='Button2' label='Button 2' size='large' imageMso='SadFace' /> <button id='Button3' label='Button 3' size='large' imageMso='Piggy' /> </group> </tab> </tabs> </ribbon> </customUI>"; } }
Фабрика инструментов
Определим абстрактный класс инструмента, который будет вызываться кнопкой:
namespace ExcelAddIn.Tools; public abstract class Tool : IDisposable { public abstract void Execute(); public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected abstract void Dispose(bool disposing); }
И фабрику этих инструментов:
using ExcelDna.Integration.CustomUI; namespace ExcelAddIn.Tools; public static class ToolFactory { public static Tool GetTool(IRibbonControl control) { return control.Id switch { "Button1" => new Button1Tool(), "Button2" => new Button2Tool(), "Button3" => new Button3Tool(), _ => throw new NotImplementedException(control.Id) }; } }
Чтобы кнопка заработала, нужно добавить в её описание атрибут onAction с именем метода который будем выполнять.
using ExcelDna.Integration.CustomUI; using ExcelAddIn.Tools; namespace ExcelAddIn.Controllers; public class RibbonController : ExcelRibbon { public override string GetCustomUI(string ribbonID) { return @"<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'> <ribbon> <tabs> <tab id='MyAddinTab' label='My Addin Tab'> <group id='MyAddinGroup' label='My Addin Group'> <button id='Button1' label='Button 1' size='large' imageMso='HappyFace' onAction='OnToolPressed'/> <button id='Button2' label='Button 2' size='large' imageMso='SadFace' onAction='OnToolPressed'/> <button id='Button3' label='Button 3' size='large' imageMso='Piggy' onAction='OnToolPressed'/> </group> </tab> </tabs> </ribbon> </customUI>"; } public void OnToolPressed(IRibbonControl control) { using var tool = ToolFactory.GetTool(control); tool.Execute(); } }
Первый инструмент
Пусть первая кнопка просто покажет нам сообщение в MessageBox.
Чтобы надстройка смогла работать с Windows Forms нужно добавить в .csproj строку:
<PropertyGroup> ... <UseWindowsForms>true</UseWindowsForms> </PropertyGroup>
Теперь сделаем класс-наследник абстрактного класса Tool:
namespace ExcelAddIn.Tools; public class Button1Tool : Tool { public override void Execute() { MessageBox.Show($"Message from {nameof(Button1Tool)}"); } protected override void Dispose(bool disposing) { } }
Получаем доступ к рабочей книге
Взаимодействие с Excel — его рабочими книгами, листами, интерфейсом — осуществляется через интерфейс Application.
Чтобы получить к нему доступ нужно установить пакет ExcelDna.Interop:
dotnet add package ExcelDna.Interop
Объект Application является свойством класса ExcelDnaUtil.
Пусть вторая кнопка инкрементирует текущую ячейку:
using Application = Microsoft.Office.Interop.Excel.Application; namespace ExcelAddIn.Tools; public class Button2Tool : Tool { private readonly Application app; public Button2Tool() { app = (Application)ExcelDnaUtil.Application; } public override void Execute() { if (app.ActiveCell == null) { return; } double? cellValue = app.ActiveCell.Cells.Value2; if (cellValue != null) { app.ActiveCell.Cells.Value2 = ++cellValue; } } protected override void Dispose(bool disposing) { } }
Строка состояния
В нижней части окна Excel есть строка состояния, куда можно выводить сервисную информацию.
Это бывает полезно для отображения процесса какой-либо ресурсоемкой задачи.
После окончания работы необходимо сбросить строку, передав ей значение false. Это вернет контроль над ней приложению Excel, иначе в ней зависнет последнее переданное нами сообщение.
using Application = Microsoft.Office.Interop.Excel.Application; namespace ExcelAddIn.Tools; public class Button3Tool : Tool { private readonly Application app; public Button3Tool() { app = (Application)ExcelDnaUtil.Application; } public override void Execute() { for (int i = 0; i < 10;) { Thread.Sleep(400); app.StatusBar = $"Выполнено {++i * 10}%..."; } } protected override void Dispose(bool disposing) { app.StatusBar = false; } }
Заключение
В этой статье описываются основы создания собственной панели инструментов надстройки и её взаимодействие с Excel.
Код к этой и предыдущей статье лежит в репозитории https://gitea.cebotari.ru/chebser/ExcelAddIn
ссылка на оригинал статьи https://habr.com/ru/articles/741732/
Добавить комментарий