Автор Мирончик Игорь – независимый разработчик и преподаватель курсов по Delphi, C++Builder, Oracle. E-
maile EKSKHQ@Elsite.ru, тел. (09657) 334-22
В статье рассматривается вопрос доступа к общеизвестным приложениям Microsoft Office, таким как Word, Excel,
Outlook и другим, через новый набор компонент, представленных в Delphi 5. Для начала работы нам предстоит
установить на компьютере приложения Microsoft Office 97 – Excel, Word, Outlook, PowerPoint. Если считаете
необходимым, то можно добавить и Access (но с ним у меня особые счеты). Ну и конечно устанавливается новый
продукт Delphi 5. Кроме множества изменений в нем имеется одно, для нас сейчас необходимое – новая
закладка на палитре инструментов – Servers.Через эти компоненты мы будем получать доступ к COM серверам
приложений Office, использующих автоматизацию (прежде известную как OLE Automation).
Мы рассмотрим несколько примеров построения контроллеров автоматизации для создания отчетов в MS Word,
производство расчетов и построение диаграмм в MS Excel, а так же формирование рассылки писем адресатам
через MS Outlook.
Office – это среда, в которой большинство задач можно решать без какого либо программирования. Но вся
ценность приложений Office для разработчика заключается в том, что все, что можно сделать руками, можно
сделать программным путем с использованием средств VBA (Visual Basic for Application). Кроме того, приложения
Office поставляют сервера COM, которые предоставляют интерфейс доступа к приложению и его объектам.
Благодаря этому, разработчик в среде Delphi имеет возможность, создав контроллер автоматизации, управлять
сервером. Так как устроено приложение в Office? На самом деле приложение рассматривается как совокупность
объектов со своими методами, свойствами, событиями, которые обеспечивают скелет приложения. Программист
Office является не создателем приложения, как например это делается в Delphi, а он принимает участие в
создании системы документов. Таким образом ДОКУМЕНТ, а не программа являются целью разработки.
Наследование – мощный инструмент построения нового класса, однако программистам известен еще один
способ получения класса – встраивание. Как и наследование, встраивание транзитивное отношение. В объектной
модели Office нет наследования в полном смысле этого слова, а есть только встраивание.
Всегда существует задающий приложение корневой объект, он всегда называется Application. Каждое
приложение Office имеет свой собственный окорневой обект – Word.Application, Excel.Application. Outlook
приложение само является корневым объектом, несмотря на это в объект Application встраиваются все
остальные объекты (участники), которые являются свойствами главного объекта. У участником могут быть свои
участники и так далее. В документе методов очень много, причем самых разных, но имеются и одинаковые
методы в различных приложениях Office. Среди таковых – Run, Quit, Activate; но даже и они в разных
приложениях имеют различный набор параметров, а зачастую выполняют не адекватные действия. Такое
многообразие различных реализаций классов отпугивало программистов контроллеров автоматизации. Однако
используя компоненты доступа к серверам автоматизации – положение резко улучшилось. На следующем
рисунке показан очень маленький фрагмент структуры объекта Microsoft Word Objects. Более полное
представление об объектной архитектуре приложений Office можно найти в соответствующих файлах помощи.
Я наверное утомил читателя устройством приложений Office. Но все-таки необходимо еще раз отметить, что всех
объектов этого семейства не перечесть, но главные необходимо знать и уметь ими пользоваться.
Фундаментальным объектом любого приложения является Application. Давайте получим к нему доступ из Delphi.
Создаем новый проект
На главную форму выкладываем компоненту с закладки Servers, которая называется WordApplication
Устанавливаем свойства компоненты AutoConnect и AutoQuit в True
После запуска приложения будет автоматически загружен Word, создайте в нем несколько новых документов и
переключайтесь между ними с помощью меню Window. Вы увидите, что контроллер автоматизации добавляет
новые строки в текущий активный документ. Аналогично можно управлять и сервером ExcelApplication. При
создании новой рабочей книги на сервере, в контроллере будет проинициализировано событие onNewWorkBook,
которое можно обработать аналогично предыдущему примеру.
Теперь давайте заглянем во внутренний мир компонент закладки Servers. Как мы уже убедились, все классы
унаследованы от ToleObject. Кроме того, еще наследуется и интерфейс из библиотеки TLB. Как это происходит?
Проведем следующее упражнение:
Из среды программирования Delphi удаляем пакет с
компонентами COM серверов (Component | Install
Packages | Borland Sample Automation Servers
Component | Remove). После этого закладка Servers
удалилась.
Создаем новый пакет с использованием библиотеки типов
Выберите Project | Type library
Из списка зарегистрированных серверов выберите
библиотеку типов Excel (Microsoft Excel 8.0 Object Library)
Укажите имя закладки палитры компонент (Pallete Page),
куда будут установлены новые классы – TexcelQueryTable,
TexcelApplication, TexcelChart, TexcelWorksheet,
TexcelWorkbook, TExcelOLEObject . Выберите закладку
Servers.
В боксе - General Component Wraper установите флажок
для генерации компонеты на основе библиотеки типов и
размещении ее на палитре компонент.
Нажмите кнопку Install
Специфицируйте имя пакета, где будет сгенерирован новый
класс
Установите сервер на палитру компонент.
После проделанных манипуляций вам стал доступен COM
сервер Excel, в состав которого входят шесть классов. Аналогичным образом восстановите компоненты для
сервера Word и Outlook.
Теперь мы можем посмотреть на объявление класса TwordApplication и его предка -ToleServer :
Благодаря такому объявлению, класс TwordApplication наследует свойства и методы класса Tcomponent
(способен устанавливаться на палитре компонент и прочие…), а так же знает все о доступе к интерфейсам COM
серверов, благодаря наследованию интерфейса IUNknown. В библиотеке типов прописаны все доступные
методы и свойсва COM сервера. Когда создается контроллер автоматизации (выкладываем на форму
соответствующий компонент из палитры), то приложение получает доступ к Dual Interface описанный в
библиотеке типов. Dual интерфейс – есть совокупность пользовательского интерфейса, описанного в библиотеке
типов и dispinterface, который доступен в момент выполнения приложения. Это реализовано с помощью COM
VTABLE интерфейса, унаследованного от IDISPATCH. Использование Vtable интерфейса имеет ряд
преимуществ:
Передаваемые параметры, их типы и количество проверяется на стадии проектирования и редактор кода
сопровождает разработчика всевозможными
хинтами и подсказками.
Через Vtable интерфейс осуществляется
значительно быстрый доступ к серверу
автоматизации, чем через DispInterface
В то же время, не всегда разработчик получает
доступ к библиотеке типов и соответственно к V –
таблице, поэтому приходится иногда
пользоваться Idispatch интерфейсом
Пример использования интерфейса с поздним связыванием был показан в начале этой статьи, когда доступ к
COM серверу был осуществлен с помощью функции CreateOleObject. Компилятор в этом случае ничего не знает
о методах и параметрах сервера, информация о них извлекается на стадии выполнения приложения, отсюда и
потеря скорости выполнения приложения и всевозможные ошибки, которые компилятор не в состоянии
обработать. При такой разработке приложения программист достает SDK от Microsoft office и начинает
старательно изучать большие тома литературы.
Подводя итог можно говорить о том, что для доступа к COM серверу автоматизации существует три способа
Vtable
Idispatch
Позднее связывание (CreateOleObject)
Наиболее прогрессивный – первый способ, через который работают компоненты Delphi 5 для доступа к COM
серверам приложений Office.
Постановка задачи: Имеется шаблон документа – shablon.DOC, подготовленный в MS Word, поля, которые
должны быть заменены, помечены символом @. Необходимо прочитать данные из источника информации и
заменить метки, на реальные данные, после чего распечатать полученный документ.
Воспользуемся методом Vtable . Выложим на форму компоненту WordApplication, WordDocument и кнопку Button.
Для события OnClick компоненты Button1 пропишем следующий код:
Описание методов в библиотеке типов заставляет нас очень аккуратно соблюдать порядок передачи параметром,
это несколько затрудняет процесс программирования, но зато Dual интерфейс работает значительно быстрее
чем передача именованных параметров при позднем связывании сервера и контроллера автоматизации.
Постановка задачи: получить информацию о документе, который открывается MS Word, при этом не должны
использоваться никакие компоненты для доступа к серверам автоматизации.
Создадим новое приложение и выложим на форму кнопку. Пропишем событие onDoubleClick для кнопки
следующим образом:
procedure TForm1.Button1Click(Sender: TObject);
var
Shablon:OleVariant;
word:_ApplicationDisp;
begin
Shablon:=ExtractFilePath(Application.EXEName)+'shablon.DOC';
word:=CoWordapplicaTion.Create as _ApplicationDisp;
(Word.Documents as DocumentsDisp).Open(Shablon,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam);
showmessage((Word.Application as _application).Get_Name+#13+
((Word.Application as _application).ActiveDocument as _documentDisp).Path );
word.quit(EmptyParam,EmptyParam,EmptyParam);
end;
Подводя итог выше сказанному, можно отметить, что действительно использование компонент для доступа к
COM серверам через Vtable интерфейс значительно ускоряет работу приложения и ограждает разработчика от
ошибок.
Теперь поговорим о сервере Excel. После импортирования библиотеки типов, на закладке палитры компонент
появились шесть иконок, основная из них ExcelApplication - компонента, обеспечивающая доступ к объекту
Application сервера Excel. Следующий пример демонстрирует работу с объектом Application и WorkBook сервера
Excel. Параметры серверу передаются по значению, кроме того, библиотека типов предоставляет все основные
константы для работы с сервером:
const
xlDays = $00000000;
xlMonths = $00000001;
xlYears = $00000002;
Так же как и в других серверах, в Outlook имеется класс Application, в который встраивается класс NameSpace.
Последний предоставляет доступ к данным через объект класса MAPIFolders, представляющий собой коллекцию
папок пользователя. Получив доступ к Outlook через компоненту OutLookApplication, извлекается объект доступа
к MAPI папкам.
mapi:=OutlookApplication1.GetNamespace('MAPI');
for i:=1 to mapi.Folders.Count do
ListBox1.Items.Add(mapi.Folders.Item(i).Name);
Добраться до соответствующей папки теперь, нет проблем, так как мы имеем дело с вложенными объектами. В
приложении к статье имеется пример извлечения содержимого всех папок сервера Microsoft OutLook.
Следующий пример производит рассылку писем, извлекая адреса из таблицы базы данных. Я вам предлагаю его
самостоятельно доработать и привести к “товарному виду”.
iDispatch));
//Наполняем новое письмо информацией
MailItem1.Subject:='test for '+Table1Common_Name.Value;
MailItem1.to_:=Table1Category.Value+'@elsite.ru';
Table1Graphic.SaveToFile(Table1SpeciesNo.AsString+'.BMP');
MailItem1.Attachments.Add(ExtractFilePath(Application.EXEName)+Table1SpeciesNo.AsString+
'.BMP',1,1,Table1SpeciesName.Value);
MailItem1.Body:=#13#13+'Письмо с вложенным документом '+#13+ MailItem1.SenderName;
MailItem1.Sensitivity:=olConfidential ;
MailItem1.FlagStatus:=olFlagMarked;
//Сохраняем письмо. OutLook самостоятельно его отошлет по почте
MailItem1.Save;
Table1.next;
end;
end;
В заключении хочется еще раз подчеркнуть, что использование Vtable интерфейса значительно упростило
процесс разработки контроллеров автоматизации COM серверов.
Используя мощный язык Delphi 5 и открытый интерфейс серверов MS Office можно строить очень большие и
серьезные приложения, работающие совместно.