понедельник, 4 июля 2016 г.

Урок 14. Автоматическое открытие заданной вкладки ленты при запуске документа.

По умолчанию при открытии документа в ленте всегда открывается первая вкладка (псевдовкладку «файл», открывающую закулисье, мы не считаем). Если мы расположили нашу вкладку не первой, но хотим автоматически её открывать при запуске документа, можно использовать следующий трюк.
  1. В xml-коде присвоим нашей вкладке символы клавиатурного доступа (keytip). Для этого используем атрибут keytip для тега tab нашей вкладки. Можно задать последовательность от одного до трёх символов, например, так: keytip="ЁПТ". Теперь, если в документе нажать и отпустить Alt, у ярлыка нашей вкладки появится заданная нами последовательность «ЁПТ», набрав которую вы откроете эту вкладку.
  2. В тег customUI нашего интерфейса добавим атрибут onLoad="ВыборВкладки". Этот атрибут задаёт процедуру, которая будет вызываться сразу после окончания загрузки интерфейса. В ней мы и будем переключать вкладку.
  3. Генерируем шаблон процедуры обратного вызова "ВыборВкладки" (кнопка VBA), и вставляем его в код макросов нашего документа. Внутри этой процедуры программно сэмулируем набор символов клавиатурного доступа командой SendKeys "%ЁПТ{F6}".
Процедура должна выглядеть так:
' (компонент: customUI, атрибут: onLoad), 2007
Sub ВыборВкладки(ribbon As IRibbonUI)
    SendKeys "%ЁПТ{F6}"
End Sub
Знак «%» означает клавишу Alt. Буквы ЁПТ означают сами знаете что. Конструкция {F6} означает клавишу F6. Нажатие на эту клавишу снимает подсказки с элементов внутри открывшейся вкладки.

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


Список доступных первых символов для Word 2016:

Б, Г, Ё, Ж, З, Й, Н, С, У, Х, Ц, Ш, Щ, Ъ, Ы, Ь.
Также доступны те же символы в нижнем регистре плюс следующие: д, и, к, л, о, р, ф, ч, э, ю, я. Однако некоторые из дополнительно перечисленных символов дублируют уже использующиеся клавиши верхнего регистра, и их использовать не стоит.

Список доступных первых символов для Excel 2016:

Б, Г, Ё, Ж, З, И, Й, К, Н, С, Т, У, Х, Ц, Ш, Щ, Ъ, Ь.
Также доступны те же символы в нижнем регистре плюс следующие: л, о, р, ф, ч, ы, э, ю, я. Однако некоторые из дополнительно перечисленных символов дублируют уже использующиеся клавиши верхнего регистра, и их использовать не стоит.

23 комментария:

  1. Если для вкладки прописать - keytip="ЁПТ"
    То и без доп. вставки кода в "VBA" работает.
    Работает и "ALT" и "F6" и заданные Hotkey тоже работают.

    А вот чтобы после запуска открывалась нужная мне вкладка не понял технологию. Вкладка у меня называется так "My Macros":


    В тег customUI добавил onLoad="ВыборВкладки".
    Тестировал для "Excel 2019".

    ОтветитьУдалить
    Ответы
    1. Что работает без VBA, автоматическое открытие нужной вкладки? Читайте внимательнее, статья посвящена автоматическому открытию вкладки. То, что вручную вкладка открывается без VBA, это естественно, для этого и созданы keytip. Технология автоматического открытия в том, чтобы нажать эти клавиши программно при загрузке ленты, когда срабатывает событие, прописанное в onLoad.

      Удалить
    2. У меня что то не получается и так .docm и так .dotm пробовал сохранять (вылазит какая то ошибка в самом "Ribbon XML Editor").
      Хочу XML-код (возможно я не так пишу onLoad="ВыборВкладки" и keytip="ЁПТ") !?

      Удалить
    3. Так какая именно ошибка вылезает?

      Удалить
    4. Получил ваше письмо. Ошибка «EOleException: Отсутствует доверие к программируемому доступу к проекту Visual Basic» может говорить, наверное, о том, что у вас в где-то стоят какие-то дополнительные защиты доступа к объектной модели Word'а. Или просто глюк OLE, может, файл, в который идёт внедрение, открыт или занят, фиг знает. Если модуль не внедряется автоматически с помощью OLE-технологии, сохраните его в виде файла кнопочкой рядом и импортируйте его в VBA-редакторе Word'а.

      Удалить
    5. Проверьте, установлена ли у вас в Word галочка «Файл → Параметры → Центр управления безопасностью → Параметры центра управления безопасностью → Параметры макросов → Доверять доступ к объектной модели проектов VBA».

      Удалить
  2. ...UPD
    Открытие Книги на той вкладке на которой остался. Такое можно реализовать?
    Или кнопка для "Quick access toolbar" - ***закрыть книгу + сохранить всё + оставаться на последней вкладке***.

    ОтветитьУдалить
    Ответы
    1. Не знаю. К работе с лентой это не относится. Нужно изучать VBA и объектную модель Excel. Я в ней не силён.

      Удалить
  3. Немного дополню. Открывать заданную вкладку можно и без сочетания клавиш. Для этого использовать метод ActivateTab или ActivateTabMso у объекта ribbon, который передаётся параметром в колбэке onLoad. Например, переключиться на вкладку "Рассылки"в Word можно так:
    Sub customUI_onLoad(ribbon As IRibbonUI)
    ribbon.ActivateTabMso "TabMailings"
    End Sub

    ОтветитьУдалить
    Ответы
    1. Хорошо! Вот это работает без проблем:
      ribbon.ActivateTabMso "TabMailings"

      А как открыть свою надстройку? Она у меня называется `My Macros`. Пробовал так:
      ribbon.ActivateTab "TabMy Macros"
      ribbon.ActivateTab "TabMy_Macros"
      ribbon.ActivateTab "My Macros"
      ribbon.ActivateTab "My_Macros"
      НИЧЕГО НЕ РОБИТ! :(

      Удалить
    2. Итак... разобрался. Инфу нашёл на японском сайте. Значит имеем вкладку:

      Далее нам нудно использовать не `НАЗВАНИЕ` вкладки а её `ID` !
      ### Пример 1 (думаю этот по проще):

      Sub onLoad(ribbon As IRibbonUI)
      ribbon.ActivateTab "Tab1"
      End Sub

      ### Пример 2:

      Sub onLoad(ribbon As IRibbonUI) ' Начальная обработка ленты
      Set myRibbon = ribbon ' Установите ленту, чтобы можно было обновить отображение ленты.
      myRibbon.ActivateTab ("Tab1") ' Активируйте вкладку.
      End Sub

      Удалить
    3. Спасибо! Отличный вариант!

      Удалить
    4. ыра, конечно надо id использовать! Я и не заметил, что вы по названию пытались открывать...

      Удалить
    5. Подскажите плз куда нужно вставить сей код для того чтобы он обрабатывался автоматически при открытии файла? Пробовал в RibbonCallbacks - не получается :( у меня Excel 2010
      Спасибо огромное!

      Удалить
    6. В уроке описано создания события атрибута onLoad. Поменяйте его содержимое на то, что написано в примере комментария.

      Удалить
    7. В тег customUI добавил onLoad="ВыборВкладки".
      В VBA файла добавил этот код:
      ' (компонент: customUI, атрибут: onLoad), 2007
      Sub ВыборВкладки(ribbon As IRibbonUI)
      SendKeys "%ЁПТ{F6}"
      End Sub

      По этой схеме работает, но хотелось бы по этой:
      Sub onLoad(ribbon As IRibbonUI)
      ribbon.ActivateTab "Tab1"
      End Sub

      Просто если ставлю этот код вместо первого , ничего не происходит... Поясните на пальцах, плз!

      Удалить
  4. Выше описанный метод не работает в «Office 2019» о чём свидетельствует инфа:
    1) https://stackoverflow.com/questions/56623675/vba-iribbonui-activatetab-not-working-in-office-2019

    2) http://qaru.site/questions/17839734/having-an-issues-with-vba-iribbonuiactivatetab-in-office-2019

    ОтветитьУдалить
    Ответы
    1. Итак... только что установил «Office 2016» метод работает! Ура, ха ха :-)

      Удалить
    2. Сегодня установил «Office 365» с последними обновлениями. И тут тоже метод работает без нареканий!

      Удалить
    3. Что-то они сломали в 2019-м...

      Удалить
  5. МимоКрокодил11 ноября, 2019 00:00

    Дополню материал. Столкнулся с проблемой, нашёл решение.
    Моя задача отличается от стандартной, описанной в этом посте, следующим:
    1. Я для своей ленты использовал пространство имён
    2. Свою вкладку (которую хочу научить активироваться при старте) обозначаю идентификатором не через свойство "id", а через "idQ"
    Что такое пространство имен, и зачем нужно "idQ" - можете поискать в этом блоге

    Ну так вот...
    у меня тег CustomUI выглядит так:

    Т.е. пространство имен называется "somename". Тут же видите, что указано, что при загрузке ленты должна выполняться процедура "LoadRibbon"
    Тег вкладки, которую хочу научить активироваться при загрузке ленты - такой:

    Видите, да? Идентификатор у неё MyTab (перед ним, как положено по правилам, стоит ссылка на пространство имен), заданный через свойство "idQ".
    Теперь для выполнения задачи остаётся вставить в код документа процедуру "LoadRibbon" (которая в теге CustomUI задана как процедура, выполняемая при загрузке ленты):

    Sub LoadRibbon(ribbon As IRibbonUI) 'загружаем ленту
    Set MyRibbon = ribbon 'присваваем ссылку на ленту переменной MyRibbon
    MyRibbon.ActivateTabQ "MyTab", "somename" 'активируем нашу вкладку
    End Sub

    Обращаю внимание, что в нашем случае не поможет метод ActivateTab (здесь его приводили в комментах), а нужен именно ActivateTabQ (с "Q" на конце).
    И в аргументах задается не только имя вкладки, но и название пространства имен("somename"), оба аргумента обязательны.
    P.S.
    Кстати, это всё у меня сработало в Excel 2019.
    P.P.S.
    Возможно будет вопрос, почему я не объявил переменную MyRibbon (хотя OptionExplicit у меня включен). Она у меня объявлена на уровне модуля, как публичная, т.к. она у меня требуется не только в этой процедуре, но и вызывается из других процедур в определенных целях во время работы с данным документом. Т.е. она объявлена вверху модуля вот так:
    Public MyRibbon as IRibbonUI

    ОтветитьУдалить
  6. МимоКрокодил11 ноября, 2019 00:04

    Извините, текст тегов не попал почему-то в комментарий, поэтому дублирую его, заменив стрелочковые скобки, в которые обычно берутся теги, на квадратные

    Дополню материал. Столкнулся с проблемой, нашёл решение.
    Моя задача отличается от стандартной, описанной в этом посте, следующим:
    1. Я для своей ленты использовал пространство имён
    2. Свою вкладку (которую хочу научить активироваться при старте) обозначаю идентификатором не через свойство "id", а через "idQ"
    Что такое пространство имен, и зачем нужно "idQ" - можете поискать в этом блоге

    Ну так вот...
    у меня тег CustomUI выглядит так:
    [customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" xmlns:МПИ="somename" onLoad="LoadRibbon"]
    Т.е. пространство имен называется "somename". Тут же видите, что указано, что при загрузке ленты должна выполняться процедура "LoadRibbon"
    Тег вкладки, которую хочу научить активироваться при загрузке ленты - такой:
    [tab idQ="МПИ:MyTab" label="Моя вкладка"]
    Видите, да? Идентификатор у неё MyTab (перед ним, как положено по правилам, стоит ссылка на пространство имен), заданный через свойство "idQ".
    Теперь для выполнения задачи остаётся вставить в код документа процедуру "LoadRibbon" (которая в теге CustomUI задана как процедура, выполняемая при загрузке ленты):

    Sub LoadRibbon(ribbon As IRibbonUI) 'загружаем ленту
    Set MyRibbon = ribbon 'присваваем ссылку на ленту переменной MyRibbon
    MyRibbon.ActivateTabQ "MyTab", "somename" 'активируем нашу вкладку
    End Sub

    Обращаю внимание, что в нашем случае не поможет метод ActivateTab (здесь его приводили в комментах), а нужен именно ActivateTabQ (с "Q" на конце).
    И в аргументах задается не только имя вкладки, но и название пространства имен("somename"), оба аргумента обязательны.
    P.S.
    Кстати, это всё у меня сработало в Excel 2019.
    P.P.S.
    Возможно будет вопрос, почему я не объявил переменную MyRibbon (хотя OptionExplicit у меня включен). Она у меня объявлена на уровне модуля, как публичная, т.к. она у меня требуется не только в этой процедуре, но и вызывается из других процедур в определенных целях во время работы с данным документом. Т.е. она объявлена вверху модуля вот так:
    Public MyRibbon as IRibbonUI

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