C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 240 - АВТОМАТИЗАЦИЯ приложений MS Office / MFC шаг за шагом / Visual C++

Шаг 240 - АВТОМАТИЗАЦИЯ приложений MS Office

Предыстория:

Зашел на работу к своему научному, увидел, понравилось... Но у него - Дельфи, а у меня - Visual ! Значит, будем учиться !

Начало.

В этом разделе речь пойдет об автоматизации. Кто читал шаги о VBA, тот уже знает, что это такое, а кто не читал - надеюсь, поймет сейчас. Для простоты скажем так - автоматизация - это возможность управлять поведением других программ (серверов автоматизации) или их элементов из своей программы (контроллера). Например - вам хотелось бы, чтобы данные из вашей программы сами собой преобразовывались в отчет MS Word'a? Или считались в таблице Excel'я? Это реально, потому что все приложения MS Office представляют собой серверы автоматизации, и мы можем этим пользоваться.

ВАЖНОЕ ЗАМЕЧАНИЕ! Все, что рассматривается ниже, подразумевает наличие 2000 офиса. Для обладателей 97-ого будут особые пометки.

1. Подготовка.

Как всегда в ClassWizard'е подготовим проект (почти как в "Шаг 30 - Первый проект с AppWizard"). Запускаем 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. Все это проделывалось ранее и не должно вызывать трудностей.

240_1.gif (4855 b)

Опять-таки с помощью ClassWizard'а зададим обработчик нажатия на эту кнопку и назовем его OnButtonreport().

240_2.gif (5147 b)

После того, как мы подготовили проект, необходимо добыть у Word'a сведения о имеющихся в нашем распряжении его ресурсах (о как!). Каждое приложение МС-Офиса имеет при себе специальный файл, называемый "библиотекой типов". Именно в нем хранятся все сведения об объектах сервера автоматизации. Внутри себя приложения имеют иерархическую структуру. Самым верхним уровнем является Application (приложение), ниже которого лежат объекты и коллекции объектов. Объектами можно управлять напрямую, а из коллекции сначала нужно извлечь экземпляр, затем уже работать с ним. Но для нас все объекты и коллекции будут выглядеть просто как классы.

Для начала нам понадобятся такие объекты, как приложение и документ (Application и Document). Импортируем эти классы из библиотеки:

Вызовем ClassWizard, и нажмем кнопку AddClass.

240_3.gif (2537 b)

Как мы видим, класс можно создать заново (New...), а можно извлечь его из библиотеки типов (From type library...). Выберите этот пункт, раскроется диалог выбора файла.

240_4.gif (4833 b)

Найдите и выберите файл, который называется MSWORD9.OLB (для тех, у кого 97 офис - MSWORD8.OLB). Это и есть библиотека типов Word'а. Перед вами откроется окошко вида:

240_5.gif (5196 b)

В нем в левом списке будут находиться все объекты 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("Мой первый текст!");

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

Шаг прислал Yegor A. Blackheel (blackheel@rlt.ru)


| |
Автор Каев Артем.
[AD]