Чернопятов Е.А. Автоматизация приложений MS Office. Часть 1.
Начало.
В этом разделе речь пойдет об автоматизации. Кто читал шаги о VBA на
сайте Первые шаги, тот
уже знает, что это такое, а кто не читал - надеюсь, поймет сейчас. Для простоты
скажем так - автоматизация - это возможность управлять поведением других
программ (серверов автоматизации) или их элементов из своей программы
(контроллера). Например - вам хотелось бы, чтобы данные из вашей программы сами
собой преобразовывались в отчет MS Word'a? Или считались в таблице Excel'я?
Это реально, потому что все приложения MS Office
представляют собой серверы автоматизации, и мы можем этим пользоваться.
ВАЖНОЕ ЗАМЕЧАНИЕ! Все, что рассматривается ниже, подразумевает
наличие 2000 офиса. Для обладателей 97-ого будут особые пометки.
1. Подготовка.
Как всегда в ClassWizard'е подготовим проект
. Запускаем VC++. Выбираем меню File и New. Далее Project
и тип создаваемого приложения MFC AppWizard. В поле Project Name необходимо
указать название проекта. Пусть это будет WordTest. В Step 1 выберем тип Dialog
Based, в Step 2 "дополнительные параметры". Отключите About Box -
он нам не нужен, также отключаем 3D Control, а это для красоты.
Отключаем ActiveX Control, у нас очень простое приложение. Идем дальше.
В Step 3 устанавливаем любую компоновку и нажимаем Finish. Проект готов.
С помощью редактора ресурсов добавим на форму диалога кнопку. Назовем ее
"Отчет", и зададим идентификатор ID_BUTTONREPORT
. Все это проделывалось ранее и не должно вызывать трудностей.
Опять-таки с помощью ClassWizard'а зададим обработчик нажатия на эту
кнопку и назовем его OnButtonreport().
После того, как мы подготовили проект, необходимо добыть у Word'a
сведения о имеющихся в нашем распряжении его ресурсах (о как!). Каждое
приложение МС-Офиса имеет при себе специальный файл, называемый "библиотекой
типов". Именно в нем хранятся все сведения об объектах сервера автоматизации.
Внутри себя приложения имеют иерархическую структуру. Самым верхним уровнем
является Application
(приложение), ниже которого лежат объекты и коллекции объектов. Объектами можно
управлять напрямую, а из коллекции сначала нужно извлечь экземпляр, затем уже
работать с ним. Но для нас все объекты и коллекции будут выглядеть просто как
классы.
Для начала нам понадобятся такие объекты, как приложение и документ (Application
и Document). Импортируем эти классы из библиотеки:
Вызовем ClassWizard, и нажмем кнопку AddClass.
Как мы видим, класс можно создать заново (New...), а можно извлечь его из
библиотеки типов (From type library...
). Выберите этот пункт, раскроется диалог выбора файла.
Найдите на вашем компьютере папку "х:\Program Files\Microsoft Office\Office\"
(название может отличаться, если при установке вы выбрали иной каталог) и
выберите файл, который называется MSWORD9.OLB (для тех, у кого 97 офис - MSWORD8.OLB).
Это и есть библиотека типов Word
'а. Перед вами откроется окошко вида:
В нем в левом списке будут находиться все объекты Word'а. Выберите _Application,
_Document и Documents, и нажмите кнопку Ok.
ClassWizard сгенерил классы по нашему запросу, и записал их в файлы,
которые называются msword9.cpp и msword9.h
. Файлы эти были автоматически включены в проект.
Подведем итоги: Приложения офиса представляют собой набор объектов, которыми
можно управлять. Мы рассматриваем их как набор классов. Информация об объектах
хранится в "библиотеке типов". С помощью
ClassWizard'а на основе
информации из этой библиотеки мы можем сгенерировать классы, содержащие данные
и методы для работы с объектами
Word'а.
2. Поехали!
Прежде чем мы поедем, хотим сказать, что в данных шагах не будет теоретического
изложения
СОМ и
OLE. Хотя на самом деле это НЕОБХОДИМО знать, мы
умышленно избегаем теории. Все наши шаги даются чисто с утилитарными целями -
сделать, чтоб работало. Теорию можно изучить самостоятельно, и поверьте - это
более продуктивно и интересно. Самое первое, что нужно сделать - это запусть
приложение. Откуда мы знаем, что и как нам запускать? Очень просто. Сервера
автоматизации заносят данные о себе и своих объектах в реестр, и к ним можно
ображаться по символьным именам. Для
Word'а (любого, независимо от
версии) это "
Word.Application". Вот так:
HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\IndependentProgID = Word.Application
А если нам нужна какая-то специфичная версия - можно использовать еще одно имя
"
Word.Application.НомерВерсии". Вот оно:
HKEY_CLASSES_ROOT\CLSID\{000209FF-0000-0000-C000-000000000046}\ProgID = Word.Application.9.
Но нам в реестр лезть не надо, за нас это сделает MFC
.
В файл
WordTest.cpp в функцию
InitInstance() перед вызовом
AfxEnableControlContainer(),
т.е. в самом начале добавляем строки:
if(!AfxOleInit()) // Your addition starts here
{
AfxMessageBox("Could not initialize COM dll");
return FALSE;
} // End of your addition
Это заставит проинициализироваться систему
OLE. Если этого не сделать,
то вызов
CreateDispatch не сработает. В файл
WordTestDlg.cpp добавим
строчку:
#include "msword9.h"
а в нашу функцию
OnButtonreport добавляем следующий код:
_Application app; // app - это объект _Application, т.е. Word 9
if(!app.CreateDispatch("Word.Application")) //запустить сервер
{
AfxMessageBox("Ошибка при старте Wordа!");
return;
}
else
app.SetVisible(TRUE); //и сделать его видимым
В принципе, можно компилировать и запускать.
Для работы с автоматизацией необходимо проинициализировать
OLE (
Object
linking and embedding) функцией
AfxOleInit. Это делается при
инициализации нашего приложения в
InitInstance. Далее, мы создаем
экземпляр
Word'а -
app.CreateDispatch, и делаем его видимым
app.SetVisible.
3. Ваши документы, пожалуйста!
Теперь мы умеем запускать Word. Прямо скажем, хорошо, но неинтересно. Word
, вообще говоря, предназначен для создания и редактирования текстовых
документов, а их пока что не наблюдается. Давайте-ка что-нибудь создавать.
В Word'е все документы являются членами коллекции Documents.
Прежде, чем начинать работу с документом (или вообще с элементом коллекции),
надо коллекцию получить, элемент добавить, а затем получить добавленный
элемент. Это в VBA доступ к объектам осуществляется через точку,
перечислением. А здесь сложнее :(. Добавляем в нашу функцию следующие строки:
Documents oDocs;
_Document oDoc;
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
//наша коллекция документов
oDocs = app.GetDocuments();
//добавить к ней новый документ
//Внимание! Если у вас Word 97 - то строчка будет такая:
//oDocs.Add(covOptional,covOptional); //97
oDocs.Add(covOptional,covOptional,covOptional,covOptional); //2000
//и получить его как экзепляр коллекции с номером 1
oDoc = oDocs.Item(COleVariant(long(1)));
//активизировать документ
oDoc.Activate();
Все общение с функциями осуществляется с помощью переменных OLE.
Например, чтобы извлечь документ с номером 1, мы пишем "COleVariant(long(1))".
Переменная CovOptional
, созданная с такими параметрами, используется для указания необязятельных
параметров при создании объекта.
Теперь добавим текст в наш документ. Для этого придется вернуться к первому
пункту, и точно как в нем написано, добавить следующие классы:
Paragraphs, Paragraph, Selection
Документ разбит на параграфы, текст (и картинки вставляются) печатается на место
выделенного участка. Теперь добавляем код.
Paragraphs oPars;
Paragraph oPar;
Selection oSel;
//получить выделение. Поскольку его нет, это будет позиция курсора
oSel = app.GetSelection();
//параграфов в документе много, возникает коллекция.
//получить текущюю коллекцию
oPars = oSel.GetParagraphs();
//добавить новый параграф с установками по умолчанию
oPar = oPars.Add(covOptional);
// напечатать текст
oSel.TypeText("Мой первый текст!");
Если внутри приложения может быть несколько однотипных объектов (например,
документов), то они объединяются в коллекции. Прежде, чем начинать работу с
элементом коллекции, надо коллекцию получить, элемент добавить, а затем
получить добавленный элемент. После чего вызывать функции-члены этого класса.
Следующая часть | Оглавление
Последние изменения от 09.08.2013