На этом уроке мы попробуем написать вторую надстройку, которая могла бы использоваться как независимо от первой, так и располагаться вместе с ней на той-же вкладке. Пусть это будет надстройка работы со строками.
Создадим в Word новый документ и сохраним его как документ с макросами (.doсm). Убедимся, что в новом документе работает надстройка, сделанная нами на прошлом уроке. Закроем документ, и откроем его через Ribbon XML Editor.
Кстати, документы можно открывать в Ribbon XML Editor как непосредственно из этого редактора, так и из контекстного меню самого документа, что очень удобно. Но для этого нужно вначале добавить в эти контекстные меню соответствующий пункт. Это легко делается со страницы настроек Ribbon XML Editor.
Откройте вкладку настроек, и обратите внимание на раздел в правой части «Добавление «Открыть в Ribbon XML Editor» в контекстное меню проводника». Отметьте галочками те документы, для которых в контекстное меню проводника должен быть добавлен соответствующий пункт. В нашем случае достаточно одной галочки в столбце «Для файлов Word» напротив «Документ с макросами», но можно отметить и все галочки. Затем нажмите кнопку «Установить».
Обязательно прочтите всплывающую подсказку на кнопке, там есть много полезной информации. В частности, то, что документ будет открываться в той копии Ribbon XML Editor, из которой была осуществлена установка. Перед удалением программы, для того, чтобы убрать ненужные уже пункты контекстных меню, не забудьте снять все установленные галочки и снова нажать кнопку «Установить» для установки отменённого состояния пунктов контекстного меню.
Откройте вкладку настроек, и обратите внимание на раздел в правой части «Добавление «Открыть в Ribbon XML Editor» в контекстное меню проводника». Отметьте галочками те документы, для которых в контекстное меню проводника должен быть добавлен соответствующий пункт. В нашем случае достаточно одной галочки в столбце «Для файлов Word» напротив «Документ с макросами», но можно отметить и все галочки. Затем нажмите кнопку «Установить».
Обязательно прочтите всплывающую подсказку на кнопке, там есть много полезной информации. В частности, то, что документ будет открываться в той копии Ribbon XML Editor, из которой была осуществлена установка. Перед удалением программы, для того, чтобы убрать ненужные уже пункты контекстных меню, не забудьте снять все установленные галочки и снова нажать кнопку «Установить» для установки отменённого состояния пунктов контекстного меню.
Напишем интерфейс, аналогичный прежней надстройке:
<?xml version="1.0" standalone="yes"?> <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"> <ribbon startFromScratch="false"> <tabs> <tab id="Вкладка1" label="Полезные надстройки" insertBeforeMso="TabHome" keytip="Н"> <group id="РаботаСоСтроками" label="Работа со строками"> <button id="ДублироватьТекущуюСтроку" onAction="ДублироватьТекущуюСтроку" label="Дублировать" keytip="Д" imageMso="QuickStylesSets" size="large" screentip="Дублировать текущую строку" supertip="Сопировать текущую строку в строку ниже"/> <button id="УдалитьСдвоенныеПустыеСтроки" onAction="УдалитьСдвоенныеПустыеСтроки" label="Удалить повторные пустые строки" keytip="С" imageMso="RecordsCollapseAllSubdatasheets" size="large" screentip="Удалить повторные пустые строки" supertip="Найти и заменить все повторяющиеся пустые строки одной"/> <button id="УдалитьПустыеСтроки" onAction="УдалитьПустыеСтроки" label="Удалить пустые строки" keytip="В" imageMso="GroupQuerySetup" size="large" screentip="Удалить все пустые строки" supertip="Найти и удалить все пустые строки"/> </group> </tab> </tabs> </ribbon> </customUI>
Сгенерируем процедуры обратного вызова и сохраним их в файле. Запустим документ на выполнение. Ожидаем, что на уже существующую вкладку «Вкладка1» добавится новая группа. Попробуем запустить документ (F9). Запустили? Вот те на…
Вместо того, чтобы группа добавилась на вкладку с указанным идентификатором, мы увидели, что создалась ещё одна вкладка с тем же именем, куда и была помещена новая группа! Что же произошло не так?
По всей видимости, приложения офиса всё же различают внутри себя одинаковые идентификаторы. Очевидно, им автоматически присваиваются разные пространства имён (о которых мы говорили на первых наших уроках). Какой же из этого выход? Принудительно присвоить нашим идентификаторам одинаковое пространство имён. Для этого нам придётся произвести небольшую модификацию кода в обеих надстройках и вспомнить, что такое idQ.
Закроем Word, и удалим нашу прежнюю надстройку из папки:
C:\Users\[ИмяПользователя]\AppData\Roaming\Microsoft\Word\STARTUP
В текущей надстройке, открытой в Ribbon XML Editor, добавим в тег customUI второй атрибут xmlns с указанием идентификатора нашего собственного пространства имён, например, МПИ (Моё Пространство Имён), и присвоим значение этому идентификатору, например, http://customui.blogspot.ru (интернет-адрес этого блога), как показано в строке ниже:
xmlns:МПИ="http://customui.blogspot.ru"
Этим самым мы объявим новое пространство имён, в дополнение к пространству по умолчанию, которое выражалось строкой
xmlns="http://schemas.microsoft.com/office/2006/01/customui"
Теперь в теге tab заменим атрибут id на атрибут idQ, чтобы иметь возможность включить в идентификатор вкладки префикс пространства имён, и перед идентификатором «Вкладка1» вставим этот префикс нашего нового пространства. Замечу, что как только мы добавляем новое пространство имён в тег интерфейса (customUI), оно сразу появляется в автодополнении, поэтому вставку префикса мы можем осуществить прямо из него. Итак, мы получили строку:
<tab idQ="МПИ:Вкладка1" insertBeforeMso="TabHome" keytip="Н" label="Полезные надстройки">
Запускаем документ на выполнение (F9) и видим нашу вкладку в интерфейсе. Она будет единственной, потому что старую нашу надстройку, которую мы ещё не модифицировали аналогичным образом, мы удалили. Переходим в редактор Бейсика (Alt+F11) и открываем в нём ранее сохранённые нами шаблоны процедур обратного вызова для этой надстройки. Затем заполняем их следующим образом:
'НайтиИЗаменить (компонент: button, атрибут: onAction), 2007 Sub НайтиИЗаменить(findString As String, replaceString As String) With Selection.Find .ClearFormatting .Replacement.ClearFormatting .Text = findString .Replacement.Text = replaceString .Forward = True .Wrap = wdFindContinue .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False .MatchAllWordForms = False .Execute Replace:=wdReplaceAll End With End Sub 'ДублироватьТекущуюСтроку (компонент: button, атрибут: onAction), 2007 Sub ДублироватьТекущуюСтроку(control As IRibbonControl) With Selection .HomeKey Unit:=wdLine .MoveDown Unit:=wdLine, Count:=1, Extend:=wdExtend .Copy .HomeKey Unit:=wdLine .PasteAndFormat (wdFormatOriginalFormatting) End With End Sub 'УдалитьСдвоенныеПустыеСтроки (компонент: button, атрибут: onAction), 2007 Sub УдалитьСдвоенныеПустыеСтроки(control As IRibbonControl) Dim NumCharsBefore As Long, NumCharsAfter As Long Do NumCharsBefore = ActiveDocument.Characters.Count Call НайтиИЗаменить("^p^p^p", "^p^p") NumCharsAfter = ActiveDocument.Characters.Count Loop Until NumCharsBefore = NumCharsAfter End Sub 'УдалитьПустыеСтроки (компонент: button, атрибут: onAction), 2007 Sub УдалитьПустыеСтроки(control As IRibbonControl) Dim NumCharsBefore As Long, NumCharsAfter As Long Do NumCharsBefore = ActiveDocument.Characters.Count Call НайтиИЗаменить("^p^p", "^p") NumCharsAfter = ActiveDocument.Characters.Count Loop Until NumCharsBefore = NumCharsAfter End Sub
В этих функциях мы реализовываем функционал кнопок. Мы можем увидеть здесь уже знакомую нам по первой надстройке функцию «НайтиИЗаменить», а также функции обратного вызова для кнопок. Функция дублирования строки создана методом записи макроса с последующей небольшой корректировкой, а две оставшиеся функции в цикле меняют одно количество символов абзаца (^p) на другое, в зависимости от задачи.
Замечу, что предложенная реализация функций не является эталонной. Напротив, это первое и самое простое, что пришло в голову. Напомню, что задачей этих уроков является построение интерфейса, а не программирование на VBA.
Сохраним код, перейдём в окно документа и проверим работу кнопок. Если всё работает так, как надо, то сохраняем документ как шаблон с поддержкой макросов (.dotm) в папку:
C:\Users\[ИмяПользователя]\AppData\Roaming\Microsoft\Word\STARTUP
Эта надстройка готова. В Word пока не включаем её, чтобы не мешалась. Теперь открываем в Ribbon XML Editor документ со старой надстройкой, и правим её аналогично новой. Добавляем то же самое пространство имён, у вкладки меняем атрибут id на idQ и добавляем наш префикс перед идентификатором. Запускаем документ (F9), проверяем функционал и сохраняем его как шаблон рядом со второй надстройкой в папке
C:\Users\[ИмяПользователя]\AppData\Roaming\Microsoft\Word\STARTUP
Закрываем сохранённый шаблон в Word и открытый документ в Ribbon XML Editor. Обе надстройки готовы к работе. Запускаем Word, лезем в настройки, и включаем обе надстройки, установив напротив них галочки. После сохранения изменений в настройках у нас появляется одна вкладка, содержащая две группы, сформированные разными надстройками! То, что нам и было нужно.
А можно ли как-то регулировать порядок групп на вкладке? Чтобы группа из второй надстройки располагалась после, а не до группы из первой надстройки.
ОтветитьУдалитьНу вообще, у групп тоже есть атрибуты insertBeforeMso и insertAfterMso.
УдалитьА также insertBeforeQ и insertAfterQ.
УдалитьСпасибо
УдалитьПожалуйста! :-)
УдалитьА в чём фишка такой группировки? Не проще использовать в той же надстройке в XML-коде
Удалить- для создания групп в той же вкладке?
Использовать при надобности "Separator".
А можете написать пример записи - insertBeforeQ и insertAfterQ в XML-коде.
- для создания групп в той же вкладке? использовать тэг "group".
Удалить(этот блог удаляет записи походу).
ыра, Как я понимаю, фишка в том, что надстройки для одной вкладки могут писаться разными людьми и в разное время.
УдалитьТо есть если я для себя делаю надстройку то этот урок мне и не нужен правильно?
УдалитьНу бывает так, что вы не хотите трогать первую надстройку по какой-то причине. Тогда делаете вторую, которая просто дополняет первую. Вариантов уйма может быть. Вы сами решаете, нужна вам эта возможность в каждом конкретном случае, или нет.
УдалитьЧто-то не получается. А какие значения необходимо задать этим атрибутам?
ОтветитьУдалитьКаким именно атрибутам? В статье приведён полный код. А в xml-разметке в качестве значения атрибута просто прописывается имя функции.
УдалитьНе добавляет пункты в "Конт. Меню". Появляется такое окно - http://tiny.cc/7rxm6y
ОтветитьУдалитьФайл - "RibbonXMLEditor_AddInContextMenu.exe" имеется и он лежит рядом с "RibbonXMLEditor.exe".
Напишите мне на почту (мейл указан в программе). Вышлю патченый файл. А старую версию можно попробовать заставить работать так: откройте в проводнике корневую папку программы и запустите оттуда RibbonXMLEditor.exe. То есть, смысл такой — директория по умолчанию должна быть корневой директорией папки программы. Должно сработать. Напишите мне, сработало ли.
УдалитьДобрый вечер!
ОтветитьУдалитьПодскажите, как с помощью программы выполнять макрос https://www.planetaexcel.ru/techniques/3/45/
Просто вставить в надстройку и добавить процедуру вызова - ничего не вышло, создается только шапка списка.
Если тема обсуждалась - прошу направить.
Спасибо!
А не из надстройки, а просто, как макрос, вы его смогли запустить?
УдалитьА из надстройки просто генерите шаблон обратного вызова и вставляете в него вызов этого макроса.
Да, как простой макрос - все работает.
УдалитьКак только вставляю макрос между
Sub FileList(control As IRibbonControl)
End Sub
- отрабатывает только первая часть, до процедуры ListFilesInFolder (как я понял, к ней обращается основной макрос при переборе файлов в папке и подпапках).
Или я что-то делаю не так?
А процедура ListFilesInFolder находится в том же модуле, рядом с FileList?
УдалитьЯ бы сначала вызвал FileList() просто из сгенерированной процедуры обратного вызова, а процедуры FileList и ListFilesInFolder положил бы рядом с этой процедурой без изменений.
Да, процедура в том же модуле.
УдалитьНе понял идею "процедуры FileList и ListFilesInFolder положил бы РЯДОМ с этой процедурой без изменений."
Может быть такое, что не поддерживается рекурсия?
Ну это роли не играет, но попробуйте вызвать FileList() из процедуры обратного вызова, а не делать сам FileList() процедурой обратного вызова.
УдалитьЕсли макрос работает прямым вызовом, то он должен работать и через кнопку.
Спасибо огромное! Изначально не понял, что процедура обратного вызова нужна для вызова макроса, сам макрос в нее не нужно запихивать.
УдалитьТеперь все работает, всего вам наилучшего!!!
Рад, что всё получилось. Вообще, основную процедуру макроса можно оформить и как процедуру обратного вызова, но вы, видимо, при этом что-то сделали неправильно. А сейчас сам макрос не подвергается никакой модификации вообще, поэтому вероятность ошибки снижается.
УдалитьПри использовании idQ вместо id, для этого элемента пропадает возможность подгружать значения атрибутов из VBA (getVisible перестаёт работать). Можно ли это как-то обойти?
ОтветитьУдалитьЯ не спец в этом, но вообще-то такого не должно быть... Странно. Если найдёте причину или решение, сообщите пожалуйста!
УдалитьЗдравствуйте! Подскажите пожалуйста как создать новую надстройку? У меня при открытии Editor-а открывается предыдущий проект. Спасибо
ОтветитьУдалитьТак закройте его соответствующей кнопочкой на верхней панели. Там у каждой кнопки всплывающая подсказка есть.
Удалить