Чернопятов Е.А. Автоматизация приложений MS Office. Часть 4.
И снова начало.
Вторым офисным приложением, автоматизацию которого мы рассмотрим, будет MS
Excel. Это сделано в связи с тем, что автор получает много писем с
просьбой рассказать именно об этой теме.
Предполагается, что читатель уже ознакомился с первыми тремя частями статьи и
имеет представление об автоматизации, зачем она нужна, с чем её едят и т.д.
ВАЖНОЕ ЗАМЕЧАНИЕ! В связи с тем, что прогресс не стоит на
месте, всё, что рассматривается ниже, подразумевает наличие Офиса ХР. А также
из любви к новым технологиям пример разбирается для Visual C++
7.0
4.1. Подготовка проекта.
Готовим проект так, как об этом рассказываалось в первой части статьи. Тип
проекта - диалоговое окно, назовем его ExcelTest, с
помощью редактора ресурсов добавим на форму диалога 2 кнопки - Test
и Cancel . Кнопке Test зададим идентификатор IDС_TEST
. Нечто подобное проделывалось ранее и не должно вызывать трудностей.
Поскольку ClassWizard'а в Visual C++ 7.0 больше не
существует, зададим обработчик нажатия на эту кнопку простым даблкликом на
кнопке. Сохраним название по умолчанию OnBnClickedTest()
.
Также как и в случае Word'a нам необходима библиотека типов. На этот раз
в качестве такой библиотеки выступит сам Excel. Структура
объектов сервера автоматизации Excel схожа с о структуров
объектов Word'a. Напомним, что самым верхним уровнем является Application
(приложение), ниже которого лежат объекты и коллекции объектов. Объектами можно
управлять напрямую, а из коллекции сначала нужно извлечь экземпляр, затем уже
работать с ним. Но для нас все объекты и коллекции будут выглядеть просто как
классы.
Для начала нам понадобятся такие объекты, как приложение, рабочая книга и лист
рабочей книги (Application, Workbook и WorkSheet
), а также коллекции двух последних. Импортируем эти классы из библиотеки
типов:
Вместо ClassWizard'a выбираем Project|Add
class...
а в нём - создать класс MFC из библиотеки типов:
Теперь среда разработки сама показывает нам доступные библиотеки типов. Больше
не надо рыскать по диску в поисках olb, tlb, dll и прочих exe :).
Как мы видим, в левом списке Interfaces находятся
доступные интерфейсы объектов Excel'я. Перенесите _Application,
_Workbook, Workbooks, Worksheets и _Worksheet в правый список Generated
classes. По окончании нажмите кнопку Finish.
Add class From Typelib Wizard
сгенерил классы по нашему запросу, и записал их в .h файлы с соответсвующими
именами. Файлы эти были автоматически включены в проект.
Теперь все готово к старту.
4.2. Пуск!
Также как и Word, Excel заносит данные о себе
и своих объектах в реестр, и к ним можно ображаться по символьным именам. Для
Excel'а (любого, независимо от версии) это "Excel.Application".
В файл ExcelTest.cpp в функцию InitInstance() перед
вызовом AfxEnableControlContainer(), т.е. в самом начале добавляем
строки:
if(!AfxOleInit()) // Your addition starts here
{
AfxMessageBox("Could not initialize COM dll");
return FALSE;
} // End of your addition
Это заставит проинициализироваться систему OLE. Если этого не сделать, то
вызов CreateDispatch не сработает. В файл ExcelTestDlg.h добавим
необходимые .h файлы. В класс CExcelTestDlg добавми
переменную app типа CApplication,
а в нашу функцию OnBnClickedTest добавляем следующий код:
if(!app.CreateDispatch("Excel.Application")) //запустить сервер
{
AfxMessageBox("Ошибка при старте Excel!");;
return;
}
else
app.put_Visible(TRUE); //и сделать его видимым
CWorkbooks oBooks;
CWorkbook oBook;
COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
COleVariant covTrue((short)TRUE), covFalse((short)FALSE);
//наша коллекция рабочих книг
oBooks = app.get_Workbooks();
//добавить к ней новую книгу с шаблоном по умолчанию
oBooks.Add(covOptional); //для Office XP
//и получить её как экзепляр коллекции с номером 1
oBook = oBooks.get_Item(COleVariant(long(1)));
//активизировать документ
oBook.Activate();
Если все сделано правильно, то скомпилировав и запустив приложение
вы откроете Excel с новой рабочей книгой с шаблоном
по умолчанию, то есть "книга с тремя пустыми рабочими листами".
4.3. Падают, падают, падают листья...
Добавми к нашей рабочей книге новый рабочий лист. Как мы уже знаем, в Excel'е
все рабочие листы являются членами коллекции CWorksheets, которая, в
свою очередь, принадлежит объекту CWorkbook - рабочая
книга. Поэтому лист добавляем к коллекции листов вновь созданной рабочей
книги:
CWorksheets oSheets;
CWorksheet oSheet;
//наша коллекция рабочих листов
oSheets = oBook.get_Worksheets();
// добавить еще один рабочий лист (добавляем в начало, 1 лист,
//тип "Рабочий лист")
oSheet = oSheets.Add(covOptional,covOptional, COleVariant(long(1)),
COleVariant(long(xlWorksheet))); //для Office XP
//активизировать лист
oSheet.put_Name("Мой рабочий лист");
oSheet.Activate();
4.4. Детки в клетке.
Теперь мы можем оперировать с ячейками нашего рабочего листа. Для примера
давайте занесём несколько числовых значений в ячейки, просуммируем их, поменяем
стил границ и сольём четыре ячейки вместе. Для помещения текста в ячейки
воспользуемся механизмом диапазонов, сходным с тем, что мы использовали в Word
'e. Добавьте классы CRange, CBorders, CBorder
также, как описано в пункте 1.
// данные и формулы занесть....
CRange oRange = oSheet.get_Range(COleVariant("A1"),COleVariant("A1"));
oRange.put_Formula(COleVariant("123"));
oRange = oSheet.get_Range(COleVariant("A2"),COleVariant("A2"));
oRange.put_Formula(COleVariant("456"));
oRange = oSheet.get_Range(COleVariant("A3"),COleVariant("A3"));
//суммируем данные первых двух ячеек
oRange.put_Formula(COleVariant("=SUM(A1:A2)"));
// границы поменять на двойные....
oRange = oSheet.get_Range(COleVariant("A1"),COleVariant("A3"));
CBorders oBorders;
CBorder oBorder;
oBorders = oRange.get_Borders();
oBorders.put_LineStyle(COleVariant(long(xlDouble)));
// ... и внутрение убрать
oRange = oSheet.get_Range(COleVariant("A1"),COleVariant("A3"));
oBorders = oRange.get_Borders();
oBorder = oBorders.get_Item(long(xlInsideHorizontal));
oBorder.put_LineStyle(COleVariant(long(xlLineStyleNone)));
// слить ячейки с С2 по D4 в одну
oRange = oSheet.get_Range(COleVariant("C2"),COleVariant("D4"));
oRange.Merge(covFalse);
// включить перенос длинных строк и добавить длинный текст
oRange.put_WrapText(covTrue);
oRange.put_Formula(COleVariant("Длинный текст с переносом строк при достижении правой границы"));
Если все сделано правильно, то мы получим вот такой вид:
4.5. ...чертили чёрными чернилами чертёж....
И, наконец, рассмотрим, как добавить еще один важный объект - диаграмму.
Используя Add class From Typelib Wizard (как описано в пункте 1) добавим
еще несколько классов, а именно: CCharts, CChart
и CChartTitle.
Наша диаграмма будет располагаться на отдельном рабочем листе, содержать в
качестве данных числа из ячеек A1:A3 , иметь тип
"столбчатая", заголовок и называться "Моя диаграмма".
// диаграмма
CCharts oCharts;
CChart oChart;
oCharts = oBook.get_Charts();
// добавить новую диаграмму
oChart = oCharts.Add(covOptional,covOptional,COleVariant(long(1)));
// установить тип диаграммы
oChart.put_ChartType(long(xlBarClustered));
oChart.put_Name("Моя диаграмма");
// данные для диаграммы
oRange = oSheet.get_Range(COleVariant("A1"),COleVariant("A3"));
// связать диаграмму с данными
oChart.SetSourceData(oRange,covOptional);
//заголовок
oChart.put_HasTitle(TRUE);
CChartTitle oChartTitle;
oChartTitle = oChart.get_ChartTitle();
oChartTitle.put_Caption("Заголовок моей диаграммы");
// активизировать лист с диаграммой
oChart.Activate();
4.6. Чисто там, где убирают!
После того, как мы поработали с Excel-ем, его надо корректно
закрыть. Корректно, это значит не просто вызвать метод Quit(),
а еще и отпустить все интерфейсы. В сети постоянно задается вопрос "Я закрываю
Excel, а он остается висеть в памяти, что делать?". У меня тоже
этот вопрос появился, когдa я обнаружил, что закрывая программно Excel
я вовсе не выгружаю его из памяти! Часовой поиск в инете, в частности, по
форумам RSDN дал ключ. Итак, корректное
закрытие всего и вся + выгрузка Excel-я:
oBook.Close(covFalse, covOptional, covOptional);
oBook.ReleaseDispatch();
oBooks.Close();
oBooks.ReleaseDispatch();
app.Quit();
app.ReleaseDispatch();
Замечание - пункт 4.6 включен в исходники в виде комментария. Поместите код в нужное место программы и снимите комментарий.
Исходники
Здесь вы можете загрузить иллюстрирующий проект.
Скачать исходники - архив ZIP,~70 Кб
Оглавление |
Следующая часть
Последние изменения от 09.08.2013