Появление нового пакета Microsoft Office 97 открывает новые возможности не только перед обычными пользователями, но и перед программистами.


Объекты, объекты, объекты...
Среда разработки
Первая программа
Вторая программа
Третья программа

Да, да, уважаемый читатель, это не описка, хотя, вероятно, предложение разработать программу на основе Office вызовет некоторое недоумение. А между тем во многих странах этот пакет применяют для написания приложений, чему даже служат два специальных продукта Microsoft: Office Developer Edition и Office Developer Kit. Однако чаще всего результатом разработок являются решения - целый комплекс программ для работы с информацией, которые тесно связаны друг с другом. Новая версия пакета Office 97 обрела новые возможности для создания решений на его основе. Причем изменения коснулись не только среды разработчика, но и объектно-ориентированной модели, лежащей в основе всех компонентов Office 97.

Объекты, объекты, объекты...

Программирование в среде Office ведется на специальном диалекте единого для всего пакета Office языка Visual Basic, называемом Visual Basic For Applications (VBA). Во многом VBA совпадает с полной версией языка Visual Basic, являясь подмножеством последнего. Но, конечно же, несколько слабее своего старшего брата. Зато VBA поддерживает великое множество различных программных объектов. Программный объект VBA - это главный элемент при построении приложений. Обычно каждый объект представляет собой программное отражение какого-либо элемента документа или среды той программы, которая работает с документами. Так, например, в среде текстового процессора Word есть такие объекты, как "документ", "параграф", "символ" и т. д. Но все это из области представления данных. А для элементов самого Word имеются другие объекты: "программа", "диалоговая панель" и т. п. Это уже объекты среды.

Каждый объект имеет атрибуты, называемые свойствами. Свойства знакомят со многими параметрами объекта и дают возможность управлять его поведением. К примеру, изменяя свойство "шрифт" объекта "документ", можно управлять текущим отображением шрифта, которым выполнен текст документа. С другой стороны, программа может узнать текущие параметры шрифта, установленные пользователем. Так что свойства - вещь обоюдоострая. Свойства обозначаются в тексте программы как имя, написанное через точку после имени объекта. Приводимый ниже пример показывает, как включить отслеживание изменений в документе:

Documents("FileName.doc").TrackRevisions _ = True

В данном случае имеется коллекция (это набор объектов) Documents, из которой мы выбрали нужный документ по имени FileName.doc. Далее упоминается свойство TrackRevisions, отвечающее за включение и отключение слежения за изменениями. Присвоив этому свойству значение True (истина), мы включили его. Данный пример показывает использование свойства, которое может быть изменено. Но могут быть свойства, доступные только для чтения. И, кстати говоря, их достаточно много.

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

ActiveDocument.PrintOut From:=1, To:=3

Здесь PrintOut - имя вызываемого метода. Как и раньше, имя слева от точки обозначает объект, для которого вызывается метод. Обратите внимание на слова From и To. Это параметры, которые передаются методу. Считывая их, метод определяет, какие страницы он должен распечатать.

Надо отметить, что для различных компонентов пакета Office 97 набор объектов различается. Это вполне естественно: разная работа требует разного подхода. Но существуют отдельные объекты, которые можно найти в разных составляющих Office. Как правило, это общие классы, ответственные не столько за выполнение задачи, сколько за функционирование приложений, выполненных с помощью Office. Примером могут служить классы Application, System и Window, задача которых - предоставление программисту данных о программе и глобальное управление программами на VBA.

Среда разработки

Познакомившись с базовыми понятиями языка VBA и среды Office, перейдем к другой стороне программирования - визуальной среде разработчика. Для примера возьмем текстовый процессор Word. Заметим, что в предыдущих версиях Office среды разработчика не было как таковой. Существовали лишь окна редактирования и панели инструментов. Поэтому, когда видишь Visual Basic Editor, невольно радуешься: "Неужели это наконец-то случилось!" Да, действительно, после долгих лет разработчики получили в подарок самостоятельную среду программирования высокого качества. В ней есть все: окно менеджера проектов, окно инспектора свойств, окно редактирования исходного текста программы и набор инструментов и команд, расположенных на линейке инструментов.

Начнем, пожалуй, с окна менеджера проектов, где представлены все проекты для разработчика. Понятно, что проектом является всякий открытый в Word документ. И стандартный шаблон NORMAL.DOT, содержащий глобальные настройки и макросы пользователя, не исключение: как известно, Word открывает его каждый раз при запуске, но не создает для него отдельного окна. В нашем случае имеется четыре проекта: NORMAL, EXAMPLE, OFFICE и PODRIS. Каждый из них - открытый документ в главном окне текстового процессора Word. Что из этого следует? А то, что каждый раз, когда вам нужно создать программы, общие для всех документов, вы должны использовать проект NORMAL. Если же речь идет об отдельном проекте, то сначала формируется новый документ.

Составляющие проекта расположены по папкам, каждая из которых хранит свой тип объектов. Первая папка содержит сам документ Word, на базе которого пишется программа. Вторая папка хранит формы диалоговых панелей. Третья - модули с исходным текстом программ на языке VBasic. В четвертой папке сложены модули классов (ведь Visual Basic - объектно-ориентированный язык). И в последней, пятой папке лежит ссылка на другие проекты. Как минимум, здесь располагается ссылка на основной шаблон NORMAL.DOT. Разумеется, компоненты могут быть добавлены в проект или удалены из него. Это делается командами либо главного, либо контекстного меню, вызываемого щелчком правой кнопки мыши или же нажатием кнопки на линейке инструментов.

Следующее интересующее нас окно - инспектор свойств. Оно позволяет задавать начальные свойства выбранных объектов еще на этапе разработки программы. Те из вас, кто писал программы с использованием таких продуктов, как Visual Basic, Delphi или Optima++, не удивятся этому объектно-ориентированному нововведению.

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

При отладке программ можно вызвать еще несколько окон, связанных с просмотром переменных и памяти. Однако до начала отладки эти окошки спрятаны от пользователя.

Первая программа

Насколько просто писать на VBA? Все зависит от задачи. Начнем следующим образом: в главном окне Word создадим новый документ и сохраним его под именем Example, после чего выберем из меню Tools пункт Macro. Из этого меню, в свою очередь, запустим пункт Visual Basic Editor. И вот мы в среде разработки программ.

Откроем папку Word Objects и дважды щелкнем на объекте ThisDocument. Система распахнет нам окно для написания кода. Наберем следующий исходный текст:

Private Sub Document_Open()
        Hello
End Sub

Эта процедура вызывается каждый раз, когда открывается документ Example. В нем всего одна строчка, которая запускает процедуру с именем Hello. Ее еще нет, но сейчас мы ее создадим. Для этого командой Insert·New Module сначала надо создать модуль. По умолчанию система присвоит ему имя Module1. Теперь дважды щелкнем мышью на пиктограмме модуля и в появившемся окне редактирования наберем следующий код:

Sub Hello()
        MsgBox "Привет, писатель!",vbOKOnly
End Sub

Единственная строка в процедуре Hello открывает диалоговую панель с надписью "Привет, писатель!" Константа vbOKOnly указывает, что в диалоговой панели должна быть кнопка OK. Если теперь сохранить документ, закрыть его и открыть снова, то на экране отобразится запрограммированная нами диалоговая панель, которую можно убрать нажатием кнопки OK.

Вторая программа

Рассмотрим пример посложнее. Но сначала небольшое отступление. Когда вы создаете программу, интенсивно использующую элементы интерфейса или команды меню, имеет смысл записать свои действия командой Tools-Macro-Record New Macro. После этого вы проделываете те операции, которые хотите запрограммировать. По завершении действий вы останавливаете запись и получаете готовый код на языке Visual Basic. Впоследствии вы сможете поправить код в любом месте. Так вы сэкономите время и научитесь программированию на Visual Basic.

Перейдем к новому примеру. Это реальная задача, которую поставил для себя автор. А именно: сделать процедуру Visual Basic для создания колонтитулов документа. Верхний колонтитул должен содержать имя файла, предваренное словом "Файл", и имя автора. Текст нижнего колонтитула будет состоять из номера страницы документа в нижнем правом углу. Просто запустив запись нового макроопределения, я проделал необходимые действия и остановил запись. Результат, после некоторого редактирования, вы видите:

Sub Form_Header_and_Footer()
        ActiveWindow.ActivePane.View.Type _
= wdPageView
    ActiveWindow.ActivePane.View.SeekView _
= wdSeekCurrentPageHeader
        Selection.TypeText Text:=ChrW(1060) _ & ChrW(1072) & ChrW(1081) & ChrW(1083) _
& " " Selection.Fields.Add _
Range:=Selection.Range, _
Type:=wdFieldFileName
Selection.TypeText Text:=".doc" & vbTab _
 & ChrW(1056) & ChrW(1072) & ChrW( _
        1084) & ChrW(1086) &  _
ChrW(1076) & ChrW(1080) & ChrW(1085)
        ActiveWindow.ActivePane.View.SeekView _
= wdSeekCurrentPageFooter
Selection.TypeText Text:=vbTab & vbTab
Selection.Fields.Add _
Range:=Selection.Range, _
Type:=wdFieldPage
    ActiveWindow.ActivePane.View.SeekView _ 
= wdSeekMainDocument
    ActiveWindow.ActivePane.View.Type _
= wdNormalView
End Sub

Как уже было сказано, текст макроопределения Form_Header_and_Footer был слегка поправлен. Из него были удалены несколько операторов if для проверки режима отображения документа. Они не нужны, но Word все равно вставляет их, как говорится, впрок. Поэтому нередактированный вариант макроопределения был в два раза больше.

Разберем полученный пример построчно. Наверняка ключевые слова Sub и End Sub вам уже знакомы. Они обозначают начало и конец процедуры и задают ей имя. Во второй строке кода режим отображения переключается в просмотр страницы. Это необходимая мера для того, чтобы увидеть колонтитулы. Методика переключения сложновата, но логична. Все действия происходят над объектом ActiveWindow. В объектной модели пакета Office этот объект предназначен для работы с активным окном. В нашем случае это окно документа Example. Свойство ActivePane объекта ActiveWindow возвращает ссылку на активную панель текущего окна. Такое усложнение вызвано тем, что у окна может быть несколько панелей. Вторая панель может появиться как результат использования разделителя окна. Далее у нас идет свойство View, возвращающее ссылку на рабочее поле активной панели окна. Ну и наконец, всему этому объектному "пирогу" присваивается константное значение wdPageView, что приводит к немедленному переключению окна в режим просмотра страницы.

Следующая строка похожа на предыдущую, за исключением того, что она управляет свойством SeekView, находя у активного документа область верхнего колонтитула. Для этого используется константа wdSeekCurrentPageHeader. В арсенале объектной модели имеются также константы для нижнего колонтитула, области ссылок и прочих составляющих документа. Третья строка печатает слово "Файл" в открытой области верхнего колонтитула. И делает она это довольно хитро. Вызывается объект Selection, относящийся к выделенному участку текста или, если такового нет, к точке, где в момент вызова находится курсор. У объекта Selection производится вызов метода TypeText, печатающего текст. Этот метод принимает параметр Text, содержащий строку, которую требуется напечатать. Пусть вас не пугает абракадабра, которую мы передаем для параметра Text, - это всего лишь слово "Файл", разбитое по символам в кодировке UNICODE. Стандартная функция ChrW берет код символа в UNICODE и возвращает сам символ. А операция соединения (+) склеивает символы в строку. В конце к строке добавляется пробел.

На следующей строке вы обнаружите код, вставляющий автоматическое поле имени файла. Для этого вызывается объект Selection и у него запрашивается свойство Fields, возвращающее коллекцию всех имеющихся в документе полей. (Для сведения: коллекция - это объект для хранения данных, во многом похожий на массив, но имеющий удобные методы управления и поиска хранимой информации.) Затем вызывается метод Add. Он добавляет поле, обозначенное параметром Type (в данном случае это wdFieldFileName - код поля имени файла), в то место документа, которое определяется параметром Range. В нашем примере в качестве этого параметра задано место текущей позиции курсора.

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

Третья программа

Теперь давайте создадим такой пример, который бы использовал столь популярные сейчас объекты. Допустим, что при открытии документа Example надо вставить объект-таблицу Excel. Для этого в окне проекта дважды щелкнем на пиктограмме ThisDocument внутри проекта Example. В открывшемся окне нужно набрать исходный текст процедуры, которая будет автоматически вызвана при открытии документа:

Private Sub Document_Open()
  If MsgBox("Вставим таблицу Excel?",_
 vbYesNo, "Товарищ!") = vbYes Then
        
  ActiveDocument.Shapes.AddOLEObject 
  Anchor:=Selection.Range, _
  ClassType:="Excel.Sheet.8",_ 
  FileName:=" ", LinkToFile:=False, _
            DisplayAsIcon:=False
  End If
End Sub

Первая строчка откроет диалоговую панель с предложением вставить таблицу. Если вы нажмете кнопку No, то дальше забота о документе падет на ваши плечи. Но если вы согласитесь с предложением и нажмете кнопку Yes, то в документ будет вставлена таблица, которую можно отредактировать по месту. Обратите внимание: линейки инструментов текстового процессора Word заменились на линейки инструментов электронной таблицы Excel. По окончании редактирования таблицы достаточно щелкнуть за ее пределами, чтобы вернуться обратно в привычную среду Word и увидеть готовый документ. По сути дела, мы получили маленькое решение на базе Office. Вся работа была проделана одной-единственной строкой кода, вставившей объект класса "Excel. Sheet.8" в коллекцию Shapes объекта текущего документа. Весь оставшийся код представляет собой параметры настройки вставляемого объекта.

* * *

Как вы смогли убедиться, новая версия пакета Microsoft Office 97 внесла новое в процесс создания программ на его основе. Изменилась объектная модель, добавилась удобная среда разработки. Для многих программистов, пишущих приложения на Visual Basic for Applications, наступает новое время. Кто знает, может, когда-нибудь и вы решите воспользоваться Office 97 не для подготовки бумажек, а для самого настоящего программирования.