суббота, 7 марта 2015 г.

Урок 10. Создание простейшей надстройки.

Конструирование интерфейсов чаще всего используется при создании надстроек. Надстройка представляет собой невидимый документ со встроенным VBA-кодом и с собственными дополнениями к интерфейсу, автоматически открываемый приложением при запуске. При запуске он не показывает своё тело (т.е. содержимое документа текст, рисунки и пр.), а проявляется только своими изменениями в интерфейсе и подключенными макросами. Таким образом, приложение Microsoft Office дополняет свой функционал, и позволяет редактировать другие документы, используя вновь полученные функции.

Документ надстройки для Word имеет расширение .dotm. Фактически, надстройка для Word является обычным шаблоном с поддержкой макросов. Для надстроек Excel и PowerPoint имеются отдельные расширения — .xlam и .ppam соответственно.

Замечу, что надстройки .xlam и .ppam просто так не открываются в приложениях в качестве документа для редактирования, поэтому пока такая надстройка не готова, её сохраняют как обычный документ с поддержкой макросов. А вот шаблон .dotm можно открыть в Word именно как шаблон (по крайней мере, Ribbon XML Editor это делает), поэтому его можно сохранять шаблоном и в процессе разработки надстройки. Однако, я всё же рекомендую действовать единообразно, и исходники надстроек всегда держать в формате обычных документов с поддержкой макросов, и переводить их в шаблоны или надстройки только после полного окончания их разработки.

Итак, давайте попробуем построить надстройку Word, которая будет выглядеть, как отдельная вкладка, и содержать группу с кнопками, выполняющими некоторые действия. Пусть это будут некие действия с пробелами. Замечу, что процесс создания надстройки Excel ничем не отличается от создания надстройки Word и, умея создавать одно, вы будете уметь создавать другое.

Откроем Ribbon XML Editor, откроем в нём наш подопытный документ, и в окно для 2007-го интерфейса скопируем текст интерфейса нашей надстройки:

<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="WordArtSpacingMenu" 
                        size="large" 
                        screentip="Удалить повторяющиеся пробелы" 
                        supertip="Найти и заменить все повторяющиеся пробелы одним"/>
                    <button 
                        id="ПробелыВПереносыСтрок" 
                        onAction="ПробелыВПереносыСтрок" 
                        label="Пробелы в переносы строк" 
                        keytip="ПС" 
                        imageMso="PivotExpandField" 
                        size="large" 
                        screentip="Пробелы в переносы строк" 
                        supertip="Найти и заменить все пробелы переносом строки"/>
                    <button 
                        id="ПереносыСтрокВПробелы" 
                        onAction="ПереносыСтрокВПробелы" 
                        label="Переносы строк в пробелы" 
                        keytip="СП" 
                        imageMso="PivotCollapseField" 
                        size="large" 
                        screentip="Переносы строк в пробелы" 
                        supertip="Найти и заменить все переносы строк пробелами"/>                        
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

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

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

Сгенерируем функции обратного вызова (Alt+F11). Скопируем шаблоны в буфер обмена (обращаем внимание на раскладку клавиатуры во избежание появления кракозябр). Закроем окно шаблонов и запустим документ. Перейдём в редактор Бейсика (Alt+F11) и вставим взятые в буфер обмена шаблоны функций вместо наших старых функций модуля RibbonCallbacks.

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

Итак, вставляем в код новую функцию:

'НайтиИЗаменить (компонент: 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)
Dim NumCharsBefore As Long, NumCharsAfter As Long
    Do
        NumCharsBefore = ActiveDocument.Characters.Count
        Call НайтиИЗаменить("  ", " ")
        NumCharsAfter = ActiveDocument.Characters.Count
    Loop Until NumCharsBefore = NumCharsAfter
End Sub

'ПробелыВПереносыСтрок (компонент: button, атрибут: onAction), 2007
Sub ПробелыВПереносыСтрок(control As IRibbonControl)
    Call НайтиИЗаменить(" ","^p")
End Sub

'ПереносыСтрокВПробелы (компонент: button, атрибут: onAction), 2007
Sub ПереносыСтрокВПробелы(control As IRibbonControl)
    Call НайтиИЗаменить("^p", " ")
    Call НайтиИЗаменить("^w^p", "")
End Sub

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

Две последние функции ещё более элементарны. Там просто вызывается наша функция по поиску и замене, которая меняет пробел на символ абзаца (^p) или наоборот. В последнем случае мы ещё и удаляем появившийся в конце текста из-за неубирающегося символа абзаца лишний пробел (^w — чистое пространство, например, пробелы или табуляция).

Сохраняем код, закрываем редактор Бейсика и сразу проверяем работу кнопок в документе. Замечу, что закрывать редактор Бейсика не обязательно, можно просто сохранить в нём изменения и переключиться в окно документа. Если кнопки заработали, как надо, сохраняем документ как шаблон с макросами (.dotm) в папку:

C:\Users\[ИмяПользователя]\AppData\Roaming\Microsoft\Word\STARTUP

Теперь добавим нашу надстройку. Закрываем всё, открываем Word, лезем в Файл -> Параметры -> Надстройки -> Управление, выбираем «Надстройки Word» и нажимаем кнопку «Перейти». В открывшемся окне на первой же вкладке нажимаем «Добавить…» и выбираем наш файл. Нажимаем «ОК», и наша надстройка начинает действовать.

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

  1. Анонимный17 июня, 2015 14:28

    В функциях ПробелыВПереносыСтрок и ПереносыСтрокВПробелы какие то проблемы с кавычками.
    VBA они почему то не нравятся, возможно что то со шрифтом, у Вас на сайте ^p тоже выделились как то не правильно
    Вообще ресурс отличный, большое спасибо ;-)

    ОтветитьУдалить
    Ответы
    1. Спасибо за замеченную ошибку, исправил!

      Удалить
  2. Такой интересный вопрос: а как отключить надстройку. Если снимать галочку, она пропадает, но при перезагрузке появляется. Кнопка Удалить... не активна.
    Файл удалять что ли?

    ОтветитьУдалить
    Ответы
    1. Я тоже столкнулся с этим. Можно создать вложенную папку, и перемещать файлы туда. Я в это глубоко не вникал, но, вероятно, можно создавать файлы не в STARTUP а в другой папке, и тогда они не будут подключаться автоматически при перезагрузке. По крайней мере, это было бы логично.

      Удалить
    2. Если поместить в другое место например сюда:
      C:\Users\[ИмяПользователя]\AppData\Roaming\Microsoft\AddIns\
      Нужно в настройках выставлять галочку и будет подключаться. После перезапуска "WORD" она пропадает и нужно заного подключать.
      Я держу надстройку в папке "STARTUP" если мне не нужно добавляю а архив. Как понадобиться распакую и использую.
      Как то так, возможно поможет :-)

      Удалить