oldi

Delphi: заметки программиста

Часть 3. Использование COM-серверов Microsoft Office

Валерий Фаронов

Основные объекты серверов Excel и Word

   Объекты Excel

   Объекты Word

Позднее связывание

Раннее связывание

 

Практика показывает, что приложения Microsoft Office (Excel, Word, Power Point и т.п.) являются одними из наиболее часто используемых Windows-приложений. Каждое  из них является СОМ-сервером, а следовательно, любой входящий в него объект может быть использован вашей программой как собственный.

Существуют два способа обращения к методам и свойствам СОМ-объекта: путем ссылки на его библиотеку типов (раннее связывание) и по имени (позднее связывание). Для Object Pascal предпочтительным является раннее связывание, так как в этом случае компилятор может проконтролировать правильность обращения к свойствам и методам внешних объектов, а создаваемый им код исполняется, как правило, быстрее. В то же время базовый язык обращения к серверам Microsoft Office — Visual Basic for Application (VBA)  не поддерживает работу с указателями и, следовательно, не может использовать интерфейсы. Специально для такого рода языков (помимо VBA c указателями не работают также языки JavaScript, SmallTalk и некоторые другие) в технологию СОМ введены диспинтерфейсы, позволяющие обращаться к методам и свойствам по имени, а не по адресу. При инсталлировании Office можно установить справку по VBA, в которой детально описываются интерфейсы серверов Microsoft Office с указанием назначения методов и свойств, а также параметров обращения к ним. Фактически это единственные доступные программисту документы, на которые ему следует опираться при программировании доступа к мощным возможностям серверов Microsoft Office. Замечу, что при стандартном инсталлировании Microsoft Office справки по VBA не устанавливаются. Если в каталоге Program Files | Microsoft Office | Office вы не найдете файлов vbaxl8.hlp1 (справка по Excel), vbawrd8.hlp (справка по Word) и т. п., вы должны их добавить с помощью аплета Пуск | Настройка | Панель управления | Установка и удаление программ.

В версию 5 Delphi включены компоненты страницы Servers, позволяющие обращаться к СОМ-объектам этих серверов с помощью библиотек типов, однако эти компоненты практически не документированы. Более того, сами библиотеки уже внедрены в пакет dclaxserver50, так что с помощью этой версии Delphi мне так и не удалось получить их тексты. Во всех случаях изучение обширных текстов библиотек (например, файл Excel_TLB.pas содержит более 20 тыс. строк) мало что дает даже опытному программисту.

В этом разделе приводятся краткое описание основных объектов двух наиболее популярных серверов — Excel и Word, а также примеры использования Excel в стиле VBA (по имени) и с помощью компонентов страницы Servers. Поскольку специально для версии MS Office 97 язык VBA был существенно расширен, этот материал нельзя использовать для работы с более ранними версиями пакета.

Основные объекты серверов Excel и Word

В терминологии VBA используются понятия «объект» и «коллекция». Объект — это обычный интерфейсный объект СОМ, имеющий свойства, методы и события. Коллекция — это группа однотипных объектов. Например, главный объект сервера Excel — Application  определяет основные свойства и методы сервера, а коллекция Worksheets представляет  собой набор табличных страниц в текущей рабочей книге и т.д. Представленные ниже иерархии объектов и коллекций взяты из файлов vbaXXX.hlp. В отличие от объектов VCL они построены не по принципу наследования, а по функциональной подчиненности.

В начало В начало

Объекты Excel

Сервер Excel — это мощный табличный процессор, реализующий размещение и обработку различного рода данных (как числовых, так и текстовых), в том числе  построение на их основе графиков и диаграмм. При работе с Excel создается так называемая рабочая книга (файл данных) с одним или несколькими листами. Все листы одной рабочей книги могут быть связаны друг с другом, что позволяет организовать совместные вычисления над размещенными на них данными.

На рис. 1 представлена функциональная структура объектов и коллекций Excel.

Объект Application имеет многочисленные свойства, методы и события, управляющие сервером в целом. Только с его помощью, например, можно визуализировать полнофункциональное окно текстового процессора. Его центральное свойство Workbooks предоставляет доступ ко всем открытым в процессоре рабочим книгам.

У каждой рабочей книги есть свойства Worksheets и Charts, представляющие собой коллекции листов и диаграмм. Первоначально коллекция Workbooks пуста. Чтобы создать хотя бы одну рабочую книгу, нужно обратиться к методу Workbook.Add, который создает рабочую книгу с количеством пустых листов, определяемым значением свойства Application.SheetsInNewWorkbook. У каждого рабочего листа есть свойство Cells(I,J), определяющее содержимое ячейки, лежащей на пересечении I-го ряда с J-м столбцом (нумерация рядов и столбцов начинается с 1). Если при обращении к Cells номера столбца и ряда опущены, считается, что речь идет о текущем диапазоне ячеек, заданном значением свойства Worksheets.Range. Если необходимо изменить умалчиваемые свойства столбца или ряда, используются объекты Worksheets.Columns и Worksheets.Rows. Помимо рабочих листов с рабочей книгой связывается объект Charts, представляющий собой коллекцию диаграмм. С каждой диаграммой связывается объект SeriesCollection, хранящий данные, по которым строится диаграмма.

В начало В начало

Объекты Word

Текстовый процессор Word является популярнейшим средством создания и оформления (форматирования) текстовых документов. При работе с Word фундаментальными понятиями являются документ, абзац и стиль. Документ определяет файл данных. Абзац — это совокупность символов, обрамленная служебными символами конца строк, разрыва колонки или разрыва раздела. Наконец, стиль — это совокупность признаков оформления текста: его шрифт, положение на странице, выравнивание и т.п. Стиль — непременный атрибут каждого абзаца, то есть изменение стиля абзаца автоматически приводит к его переформатированию. Однако стиль может изменяться внутри абзаца — для выделения группы символов шрифтом, цветом символов и (или) фона и т.п.

На рис. 2 показана функциональная иерархия объектов Word.

Центральный объект Application имеет такое же назначение, что и одноименный объект Excel, – он определяет свойства, методы и события на уровне всего сервера. Его свойство Documents представляет собой коллекцию открытых документов. Посредством метода Open этого объекта можно открыть ранее созданный документ, а метода Add — создать новый документ, основанный на стандартном шаблоне Normal.dot. Каждый документ имеет коллекцию абзацев Paragraphs. С помощью таких методов этого объекта, как Add, InsertParagraph, InsertParagraphAfter, InsertParagraphBefore, можно вставить новый абзац в уже существующий текст или добавить абзац в конец документа. В свою очередь, каждый абзац имеет многочисленные свойства, позволяющие нужным образом отформатировать текст. Как и в Excel, важную роль в иерархии объектов Word играет объект Range, определяющий диапазон абзацев. Свойство Text этого объекта содержит текст диапазона.

В начало В начало

Позднее связывание

Приведенный ниже пример взят из моей практики и, думаю, сможет пригодиться и вам. В нем прайс-лист крупного оптового поставщика книг создается с помощью Excel. Необходимость в обращении к Excel возникла по той причине, что прайс-лист периодически (примерно раз в две недели) рассылается многочисленным покупателям, которые составляют на его основе заказы на поставку книг. У получателей прайс-листов нет средств прочтения отчетов в стандартном для Delphi формате Quick Report (файлы с расширением qrp). Экспорт прайс-листов в файлы других форматов не позволяет получать документы высокого качества, поэтому я решил для создания прайс-листов использовать средства Excel.

На рис. 3 показан прайс-лист в окне Excel, а на рис. 4 — вид формы примера на этапе конструирования.

Перед началом работы над проектом следует скопировать все файлы BOOKS.* в отдельную папку на жестком диске (потребуется чуть больше 800 Кбайт свободного пространства) и связать с папкой псевдоним BDE BIBLDATA типа Standard. Эту процедуру упростит программа SetupBooks.exe, расположенная в том же каталоге CD-ROM.

Начните новый проект и поместите на форму компоненты Query1, Label1, Button1 и ProgressBar1. Для компонента Query1 измените значение свойства Name на Books, свяжите его с псевдонимом BIBLDATA и поместите в свойство SQL такой запрос:

SELECT  
  BookID, bName, bAuthor, bPublish, bOpt, bPages, bYear  
FROM   
  Books  
WHERE  
  bQuan>0  
ORDER BY  
  bName  

Создайте для него все объекты-поля. В свойство Caption компонента Label1 поместите значение Щелкните по кнопке Пуск, чтобы создать таблицу Excel, в такое же свойство кнопки — значение Пуск и измените имя компонента ProgressBar1 на pb.

В окне кода в разделе private класса TForm1 поместите поле Excel типа Variant. В предложении uses укажите ссылку на модуль COMObj и напишите следующий обработчик события OnClick кнопки Button1 (см. листинг 1).

Теперь небольшие пояснения. Переменные Sheet и Range введены только для сокращения текста программы: везде вместо Sheet, например, можно писать Excel.Workbooks[1].Sheets[1]. С версией Delphi 4 поставлялись файлы XLCONST.PAS и XLCONST.DCU, в которых определены используемые в документации vbaxl8.hlp константы xlXXX. С версией 5 эти файлы не поставляются, поэтому я использую их числовые эквиваленты. Ширина полей печатного документа Excel задается во внутренних единицах, соответствующих приблизительно 3,5 мм, так что указанные в операторах Sheet.PageSetup.ХХХMargin значения установят левое, нижнее и правое поля шириной 1,1 см, а верхнее — 1,4 см. Ширина столбца определяется в символах текста, умещающегося в столбце без отсечения.

Переменная Excel определяет поле класса TForm1. При создании класса в него автоматически помещается значение VarEmpty. После завершения работы с Excel пользователь может закрыть его. Но в моей программе Excel не визуализировался, его работа проходила «за кулисами», а созданная таблица записывалась в указанный пользователем файл с помощью оператора Excel.Workbooks[1].SaveAs(FileName).

После этого Excel закрывался. Поскольку в нашем случае Excel показывает свое окно, а пользователь может его не закрыть, полезно написать такой обработчик события OnDestroy формы:

procedure   TForm1.FormDestroy(Sender: TObject);      
begin  
  if not VarIsEmpty(Excel) then  
    Excel.Quit  
end;      

Запуская пример, помните, что создание прайс-листа с помощью Excel — процесс достаточно длительный. На моем компьютере (400 МГц, 64 Мбайт) он занял около минуты (для примера — аналогичный прайс-лист средствами Quick Report создается менее чем за 2 с). В конце обработчика в метку lb помещается общее время работы.

В начало В начало

Раннее связывание

Следующий пример в функциональном плане повторяет предыдущий. В нем также с помощью Excel создается прайс-лист, но на этот раз используется доступ непосредственно через интерфейсы сервера. Вас ожидает «сюрприз»: время выполнения второго примера на 40 с больше! Я не смог найти разумного объяснения этому феномену, но оба примера находятся на сопровождающем диске, так что вы в любой момент можете убедиться в этом сами.

Поскольку форма второго примера в точности повторяет форму первого, я не буду объяснять, что нужно сделать для ее создания. Добавьте только на форму компонент TExcelApplication и настройте его свойства: Name=Excel, AutoConnect=True, AutoQuit=True. Если вы используете форму предыдущего примера как шаблон, не вставляйте поле Excel в класс TForm1. Обработчик Button1Click должен выглядеть так (см. листинг 2).

Как видите, он во многом напоминает обработчик предыдущего примера. Поэтому остановлюсь на различиях.

При обращении к свойству SheetsInNewWorkbook, как и во многих других случаях обращения к интерфейсным свойствам и методам, требуется указание идентификатора языка локализации (lcid). Значением 0 кодируется умалчиваемый язык. Этот же идентификатор передается вторым параметром обращения к методу Excel.Workbooks.Add. Первым параметром нужно указать имя файла (в формате WideString), если рабочая книга уже была ранее создана, или «пустой» параметр EmptyParam, если книга создается впервые.

Все мои попытки работать с объектами Range оказались неудачными. Чтобы вы не слишком осуждали меня, я поместил библиотеку типов Excel_TLB.pas в каталог размещения примера — полистайте ее на досуге и попробуйте найти нужное решение для изменения ширины колонок и полей листа, а также для раскрашивания диапазона, выравнивания текста и т.п.

Есть свои нюансы и при обращении к ячейкам. Во-первых, ими владеет объект Application, а не Sheet. Во-вторых, обращение к конкретному элементу коллекции Cells (как и любой другой коллекции) возможно только через ее свойство Item.

Подводя итоги, еще раз хочу обратить ваше внимание на то, что по времени выполнения позднее связывание хотя бы не проигрывает раннему — во всяком случае, для рассмотренных примеров. Если учесть, что единственными доступными подавляющему большинству программистов документами по серверам MS Office являются справочные файлы vbaXXX.hlp, можно сделать вывод: использование вариантов (позднее связывание) проще, удобнее, а главное — намного понятнее, чем непосредственная работа с интерфейсами (раннее связывание).

КомпьютерПресс 6'2001