пятница, 6 июля 2018 г.

Урок 18. Размещение на своей вкладке уже имеющейся в приложении кнопки

На этом уроке я хочу продемонстрировать простейший пример размещения на своей вкладке кнопки, уже имеющуюся в приложении, а также собственной кнопки, выполняющей ту же команду, но вызываемую через VBA из функции обратного вызова.

На этот раз рассмотрим задачу на примере Excel. Насколько я могу судить, под это приложение чаще разрабатывают интерфейсы, чем под другие приложения офиса. Замечу, что в других приложениях всё делается абсолютно аналогично.

Открываем в Ribbon XML Editor документ Excel и вставляем в окно кода интерфейса 2007 версии следующий код:

<customui xmlns="http://schemas.microsoft.com/office/2006/01/customui">
    <ribbon startFromScratch="false">
        <tabs>
            <tab id="МояВкладка" label="Моя вкладка" insertBeforeMso="TabHome">
                <group id="УдалениеСтрок" label="Удаление строк">
                    <control idMso="SheetRowsDelete" />
                    <button id="SheetRowsDelete" imageMso="SheetRowsDelete" label="Удалить строки через VBA" onAction="SheetRowsDelete" />
                </group>
            </tab>
        </tabs>
    </ribbon>
</customui>

Если мы внимательно его почитаем, то увидим, что этим кодом мы вставляем на собственную вкладку «Моя вкладка» (размещаемую перед вкладкой «Главная») группу «Удаление строк», в которую помещаем два элемента. Первый элемент является клоном штатной кнопки «Удалить строки с листа», а второй — нашей собственной кнопкой, которая выполняет ту же команду, но через вызов функции обратного вызова, имя которой прописано в параметре onAction.

В данном случае при создании первой кнопки мы ограничились простым клонированием, но при желании мы можем задать ей и свой текст, и своё изображение, и свою подсказку, используя соответствующие параметры. Заметьте, что вместо тега конкретного типа элемента (например, button) мы пишем тег «control». Это даёт нам возможность не ломать голову над типом клонируемого элемента, поскольку он может оказаться не только button.

Идентификаторы имеющихся в приложении элементов прописываются не в параметре id, а в параметре idMso. Подробнее про это различие было написано в уроке 3.

Узнать идентификатор элемента можно просто посмотрев его во всплывающей подсказке в окне штатных настроек ленты в самом приложении: «Файл → Параметры → Настроить ленту». У всех элементов он написан в конце подсказки в скобках. Идентификаторы же групп и вкладок можно посмотреть в справке Ribbon XML Editor (четыре последних пункта оглавления).

Для того, чтобы заработала вторая кнопка, нам надо сгенерировать шаблон функции обратного вызова (Alt + F11) и полученный модуль внедрить в документ, после чего открыть его в Excel, нажать уже там Alt + F11 чтобы открыть редактор VBA и, открыв в нём внедрённый модуль, поместить в тело шаблона функции «SheetRowsDelete» строчку «CommandBars.ExecuteMso ("SheetRowsDelete")», которая запустит команду удаления строки на выполнение. В итоге функция должна выглядеть так:

'SheetRowsDelete (компонент: button, атрибут: onAction), 2007
Sub SheetRowsDelete(control As IRibbonControl)
    CommandBars.ExecuteMso ("SheetRowsDelete")
End Sub

Замечу, что название функции не обязательно должно совпадать с названием команды. Но ничто не мешает нам это сделать.

Сохраняем изменения, закрываем редактор VBA и проверяем работу кнопок. Если вы всё сделали правильно, то обе кнопки будут удалять строки. Кстати, в выполнении команд через VBA имеется небольшое отличие — они выполняются без визуальных эффектов.

Ещё небольшое замечание. Напоминаю, что не все команды доступны в том или ином случае. Так, вышеиспользованная команда SheetRowsDelete удаляет строки в любом случае, но есть схожая команда TableRowsDeleteExcel, которая делает то же самое, но только внутри «умной таблицы». Вне её она даже не показывается на ленте, а её клон просто не выполняет никаких действий. Если же выполнить эту команду из VBA, возникнет ошибка Run-tome error: Method 'ExecuteMso' of object '_CommandBars' failed:


Поэтому такие команды следует заключать в «On Error», например:

'SheetRowsDelete (компонент: button, атрибут: onAction), 2007
Sub SheetRowsDelete(control As IRibbonControl)
    ...                     ' Можем вставить сюда какой-нибудь код, если нужно.
    On Error GoTo Error1    ' Начинаем защищённый блок.
        CommandBars.ExecuteMso ("TableRowsDeleteExcel") ' Пробуем выполнить команду.
    On Error GoTo 0         ' Заканчиваем защищённый блок.
    ...                     ' Можем вставить сюда какой-нибудь код, если нужно.
    Exit Sub                ' Завершаем функцию.
Error1:                     ' Обработка ошибки.
    MsgBox ("Эта команда предназначена для выполнения внутри «Умной таблицы».") 
    Resume Next             ' Продолжаем выполнение функции.
End Sub 

13 комментариев:

  1. Большое спасибо за уроки! Совершенно случайно натолкнулась и вовремя: как раз назрела проблема по созданию собственной надстройки. А тут не только уроки получила, но ещё и программу. Буду изучать и осваиваться сейчас.

    ОтветитьУдалить
  2. Вы уш извините но "Ribbon XML Editor" ругается даже на лишнюю точку. XML-код стоило бы подправить:
    https://my-files.ru/yxebjx

    Цитата:
    Кстати, в выполнении команд через VBA имеется небольшое отличие — они выполняются без визуальных эффектов.

    ...про визуальные эффекты я не понял?

    ОтветитьУдалить
    Ответы
    1. Ну, удаление строки в Экселе идёт с плавной анимацией процесса этого удаления. Когда это делается макросом, то почему-то анимации не происходит.

      Удалить
    2. За исправление кода в статье спасибо, поправил.

      Удалить
  3. Можно ли поместить свою кнопку в системную вкладку в системную группу? Например, во вкладку ДАННЫЕ в группу Работа с данными.
    Такой код создаёт новую вкладку:
    tab id="TabData" label="ДАННЫЕ"
    group id="GroupDataTools" label="Работа с данными"
    button id="buttonFB" label="Parse!" imageMso="AccessOnlineLists" onAction="runParseRequests" /
    /group
    /tab

    ОтветитьУдалить
    Ответы
    1. «tab id="TabData" и group id="GroupDataTools"» — системные элементы указываются не через id а через idMso. Насчёт вашего первого вопроса — там много ограничений на изменение системных элементов, я их чётко не знаю, поскольку не занимаюсь разработкой интерфейсов на постоянной основе. Попробуйте, но иногда проще создать свою вкладку и разместить на ней системные группы, а модифицируемую группу опять же создать самостоятельно.

      Удалить
    2. Спасибо, это сработало.
      А вы не знаете, можно ли в группу, кроме кнопки, добавлять ссылки? На Help, например.

      Удалить
    3. Нет. Элемент ссылки доступен только в закулисье. Посмотрите встроенную справку Ribbon XML Editor, там много чего полезного, в том числе и схемы, где и какие элементы можно использовать.

      Удалить
    4. Этот комментарий был удален автором.

      Удалить
    5. Да, я посмотрел и в backstage (только 2010+) есть hyperlink. Это оно?
      https://support.office.com/ru-ru/article/что-такое-представление-microsoft-backstage-и-где-оно-находится-04610088-406c-43d0-98a0-c1999ab4ef53

      Удалить
    6. Заработало. Добавил кнопку в xml и назначил ей такой код :
      Sub RunLink(control As IRibbonControl)
      ActiveWorkbook.FollowHyperlink Address:="https://site.ru"
      End Sub

      Удалить
    7. Ну так это вы на кнопку повесили VBA-код, вызывающий переход. Так то да. Я думал, вы именно про гиперссылку как элемент управления спрашиваете.

      Удалить
  4. Этот комментарий был удален автором.

    ОтветитьУдалить