Введение в программирование на примере VBA
Часть II. Создание макроса-приложения
Занятие 6. Запуск и остановкаВ ходе этого занятия нам придется выполнить две задачи. Во-первых, мы создадим документ, который будет использоваться при написании и отладке приложения. Эта работа не займет много времени, поэтому нет смысла выделять ее в отдельное занятие. Во-вторых, мы спроектируем, реализуем и отладим минимальный код, обеспечивающий работоспособность приложения. Имеется в виду деятельность по запуску и останову приложения. Ценность этой работы в том, что деятельность по запуску и останову присуща любому приложению, вне зависимости от назначения и реализации, и концепции данного занятия пригодятся вам далее, каким видом программирования бы вы не занимались. Подцикл 2. Создание минимально полезного кодаВы, конечно, обратили внимание, что заготовка нашего приложения не совершает никаких полезных действий, и даже не выводит осмысленных надписей. Это естественно – мы ничего не сделали для этого. Задачей второго подцикла разработки и будет создание кода, обеспечивающего минимальную функциональность приложения – а именно, процедур запуска и останова. Как вы вскоре увидите, работы будет достаточно, чтобы выделить ее в отдельный подцикл. Кроме того, мы создадим набор «тестовых» данных, который будем использовать при отладке программы. Вывод данных приложением оставим для следующего подцикла. Создание набора тестовых данных для отладки приложенияСоздадим набор тестовых «вопросов» и «ответов», предназначенный для отладки приложения, тем более что структура данных уже спроектирована нами.
Как видите, книга состоит из нескольких листов (в Office 2000, к примеру, из трех). Для простоты дальнейшей работы удалите лишние листы. Для этого надо:
Excel предупредит вас о том, что отменить удаление будет невозможно. Подтвердите свое решение, щелкнув OK в диалоговом окошке.
Последний лист удалить не удастся – можете попробовать. С последним оставшимся листом и будем работать.
Например, так:
Следующей задачей будет привязка данных к контролам приложения. Но прежде следует получить понятия об объектной структуре приложения-субстрата. Объектная модель Excel Способы получения информации те же, что и для Word. Вспомните, как мы делали это раньше. Итак, основой «дерева» объектов Excel является объект Application. Application Этот объект представляет собою сам Excel. Как и корневой объект дерева Word, он применяется как «диспетчер» для работы с другими объектами. Основной объект, содержащийся в данном – Workbook (РабочаяКнига). Как правило, объект Application явно не указывается. Workbook Это – основной объект Excel. Его «физическое» представление – файл, содержащий таблицы, макросы и другие данные. В нашем случае файл test.xls как раз и является файлом рабочей книги Excel. Аналогично Word, книга, с которой идет работа, имеет особое наименование ActiveWorkbook – АктивнаяРабочаяКнига. Одновременно могут существовать несколько рабочих книг. То есть, объект Workbook образует набор Workbooks. Основной объект, включенный в данный – Worksheet – РабочийЛист. Worksheet «Видимое» представление этого объекта – таблица Excel. Также как и Workbook, этот объект может обозначаться ActiveSheet – Активный(Рабочий)Лист, и образует набор Worksheets. Основной объект, содержащийся в данном – Range – Регион. Range Как и в Word, этот объект может представлять собою различный области рабочего листа. Как написано в справке, он «представляет ячейку, ряд, колонку, выделение ячеек, содержащее один или более непрерывных блоков ячеек, или трехмерный регион». Наборы объектов Range, упрощающие работу, таковы: Cells – Ячейки. Этот набор представляет собой ячейки таблицы. Rows – Ряды, – ряды ячеек таблицы, Columns – Колонки, – колонки (столбцы) ячеек таблицы. Внимание! У объекта Range есть свойства Row и Column. Это – не единичные объекты из наборов, как можно было бы предположить. Свойства Row и Column используются для адресации ячеек, об этом следует помнить. Схема дерева объектов Excel Схематическое изображение дерева объектов такое:
Как видите, это дерево немного проще, чем у Word. На схемах допускается применение дополнительных обозначений, уточняющих те или иные качества объектов. На этой схеме уточняется характеристика «набор». Проектирование функций запуска и остановаВернемся к проектированию приложения, чтобы определить основные функции и порядок их выполнения. На первом этапе добавления функциональности следует решить, как будет происходить запуск приложения и его остановка. Эти действия общи для всех приложений, поэтому анализ можно производить не так подробно, как в других случаях. Запуск На этой стадии происходит создание объектов приложения, считывание данных из внешних источников и, если приложение имеет интерфейс пользователя – создание этого интерфейса. Больше никаких действий на этом этапе производить не следует. Остановка На этой стадии следует производить действия, противоположные тем, что происходили при инициализации приложения – и в обратном порядке. Обратите внимание, что специально созданные при запуске приложения объекты должны уничтожаться явным образом. Соблюдение этого требования предотвратит ошибки особого рода, связанные с оставлением в памяти неуничтоженных участков приложения. Если при запуске приложения считывались данные, то остановка подходит для сохранения изменений. Хотя в общем случае не следует обращаться к данным на этих этапах, подобное поведение подходит для очень маленьких и простых приложений, таких, как наше. В нашем случае добавление отдельного механизма обращения к данным сильно усложнит задачу. На нашем начальном этапе ограничимся обработкой создания объектов приложения. Имеется в виду основной объект – форма. Следует решить, когда будет происходить запуск приложения-макроса и когда (и как) будет создаваться основной объект. Акцент на том, что приложение является макросом, не случаен. Запуск обычного приложения однозначен и производится операционной системой в ответ на пользовательские манипуляции в проводнике Windows или в командной строке. А макросы «включаются» приложением-субстратом, и условия запуска более разнообразны. К примеру, можно запускать макрос в ответ на щелчок кнопки, на нажатие особого сочетания клавиш, при открытии документа, содержащего макрос и так далее и тому подобное. Очевидно, что следует предусмотреть более-менее универсальный механизм запуска макроса, чтобы при помощи минимальных модификаций макрос «приспосабливался» к различным условиям запуска. На начальном этапе для запуска приложения будем применять панель кнопок. Создание ее было описано ранее, в первой части учебника. Но, если помните, вновь создающейся кнопке требовалось назначить какой-то макрос. Объект-включательТаким образом, приложение-макрос, вне зависимости от внутреннего устройства, должно иметь видимый извне «включатель». Поясним на схеме:
Можно было бы уточнить схему так:
Очевидно, что ничего нового подобное уточнение не даст. И так понятно, что «включатель» будет включать объект, с которым связан, а удобочитаемость схемы может пострадать. Не стремитесь к излишней детализации схем. Приложение-субстрат не должно менять своего поведения при модификации приложения-макроса и наоборот, способы взаимодействия должны быть неизменными. Теперь давайте предположим, что через 3-4 версии нашего макроса мы захотим, предположим, проиграть музыку, а затем уже показывать основное окно приложения. Уже на начальных этапах следует предусматривать подобные модификации и делать так, чтобы требуемые изменения программы были минимальны. Не правда ли, задача кажется сложной? Но решение достижимо. Для этого сделаем так. Добавим к проекту приложения-макроса отдельный модуль, в который поместим «включатель». А уж этот «включатель», в свою очередь, будет запускать объекты далее. Тогда при модификации способа запуска будет достаточно изменить одну-две строки внутри «включателя». Почему бы не поместить «включатель» в код формы? Да потому что, чтобы заработал код формы, эта форма должна быть загружена – «включена». То есть задачу мы не решим, надо выносить код вовне. Для подобных решений служат особые компоненты проектов – модули. Добавление модуля в проект
В окне Project Explorer появится новый компонент с именем Module1:
Это – вновь созданный модуль.
Как видите, он пуст – никакого кода еще нет. Обратите внимание на окно Properties, в нем появится единственное свойство модуля, доступное нам – Name.
Например, пусть он зовется basShell – от Shell – Оболочка.
Обратите внимание, что изменится надпись в окне Project Explorer. Теперь давайте создадим «оболочку» для нашей программы. Для управления приложением нужно две точки доступа – для запуска и для останова. Запуск – Start, остановка – Stop. Но такие названия не подойдут. Во-первых, слово Stop – служебное слово VBA, и использовать его для других целей нельзя, во-вторых, непонятно, что именно запускается и останавливается. Давайте назовем точки входа так: StartTest и StopTest. Проектирование точек запуска и остановаВ принципе, точка StopTest нам и не особо нужна, остановка программы возможна другими способами. Но для «чистоты эксперимента» создадим ее. Вот схема:
Решим, с каким компонентом будут взаимодействовать данные сущности. Вероятно, с формой – других объектов в проекте нет. Модуль с точки зрения VBA – не объект, а хранилище для процедур проекта.
А теперь следует определиться, с какими именно сущностями формы будет происходить взаимодействие. Можно было бы дать инструкции, но цель данного учебника – научить мыслить, а не дать несколько готовых рецептов. Давайте поищем решение самостоятельно. Изучение формыДля поиска решения используем очень полезное средство, имеющееся в составе IDE VBA. К сожалению, в литературе практически нет описания работы с этим средством, в данной книге делается попытка восполнить недостаток. Это средство называется Object Browser. Object Browser Для вызова окна Object Browser:
Появится окно:
Это – особый компонент IDE, называемый Object Browser – Просмотрщик Объектов. Он применяется для получения информации о компонентах проекта. Вверху слева – список объектных библиотек, доступных в проекте:
Под ним – текстовое поле со списком, применяемое для поиска в библиотеках:
Ниже – список объектов, содержащихся в выбранной объектной библиотеке:
Справа вверху – кнопки для выполнения некоторых действий:
Кнопки со стрелочками применяются для перехода назад-вперед по уже просмотренным объектам. Далее – кнопка для копирования названия выбранного объекта в буфер обмена. Далее – кнопка для перехода в то место текста программы, где происходит определение данной сущности. Следующая кнопка предназначена для вызова справки по выбранной в списках сущности (если такая справка есть). В нижнем ряду слева кнопка для поиска в библиотеках – согласно введенной в текстовое поле строке. Результаты поиска отображаются в специальном окне, включение которого происходит следующей кнопкой (двойная стрелка вниз). Под набором кнопок список, отображающий атрибуты объекта, выбранного в левом списке:
И, наконец, внизу – поле с кратким описанием атрибута, выбранного в предыдущем списке:
Как видите, в этом поле попадаются гиперссылки, ведущие к другим объектам в Object Browser. Давайте исследуем нашу форму и попробуем найти способ «включить» ее. Изучение формы в Object Browser
Как видите, содержимое списков Object Browser изменилось:
Жирным шрифтом в списках Object Browser выделяются те компоненты, которые были добавлены вами. Так их легко отличить от компонентов, встроенных в VBA. В левом списке найдите строку frmTest.
Содержимое правого списка изменилось. Теперь здесь находятся атрибуты объекта frmTest – нашей формы. Значки в правом списке обозначают виды атрибутов:
Очевидно, мы будем искать метод, позволяющий начать работать с формой.
Атрибуты формы VBA, отвечающие за запуск и останов Единственный более-менее подходящий для наших целей метод – Show (Показать):
Описание внизу Object Browser довольно невнятно и не дает представления о назначении метода. Воспользуемся кнопкой с «вопросительным знаком» для получения справки по этому методу:
Перед вами справка по методу Show объекта UserForm – наша форма является объектом типа UserForm. Как можно прочитать в справке, данный метод показывает объект UserForm. Что и требовалось. У этого метода есть необязательный параметр. Мы его использовать пока не будем. Однако в списках мы не находим методов уничтожения формы. Здесь – подсказка. Для выгрузки некоторых объектов VBA, в том числе для форм используется метод языка Unload (Выгрузить). Синтаксис этого метода таков: Unload <объект> В справке вы можете найти метод языка Load (Загрузить). Синтаксис аналогичен: Load <объект> Этот метод применяется для загрузки объекта. Разница между методами Load и Show такова. При помощи метода Load объект будет загружен. Но вывод его на экран может и не случиться, в зависимости от структуры программы. Это может использоваться для каких-то действий, требуемых в промежутке между созданием объекта и его выводом на экран. Метод Show показывает объект. Если объект не был загружен – он загружается, иначе – просто выводится на экран. Точно так же в паре с методом Unload существует метод Hide – Скрыть. Он есть и у форм, к сожалению, в окне Object Browser он почему-то не выводится (в программах Microsoft иногда встречаются ошибки, это – одна из них). Разница аналогична, Unload уничтожает объект, а Hide просто делает его невидимым. Выбор и определение последовательности методов для запуска и останова приложенияВернемся к осмыслению процесса загрузки формы. Предположительно, при пуске программы будет происходить считывание данных из хранилища. Есть смысл использовать методы Load и Show. Значит, при остановке мы также применим Hide и Unload. Вот схема:
У нас готовы эскизы программного кода! На месте многоточий затем можно будет вставить дополнительный код. При помощи «листочка с уголком» на схемы помещаются комментарии. Если нужно, они могут соединяться с элементами схемы при помощи пунктирной линии. Как будет понятно потом, в комментариях на схеме помещены очень коротенькие схемы последовательности действий. В общем случае следует создавать их отдельно. Реализация процедур запуска и остановаПерейдем к реализации спроектированного кода.
Создание заготовки стартовой процедуры Вспомните синтаксис процедуры, рассмотренный в первой части книги. Заготовка стартовой процедуры будет иметь вид: Sub StartTest ()
Это будет выглядеть примерно так:
Теперь давайте сделаем уточнение и введем понятие видимости. Процедуры, как и некоторые другие компоненты проекта, могут иметь различную видимость. Так, процедура может быть публичной. Это значит, что вызвать эту процедуру можно не только в том модуле, где она записана, но и из других модулей программы. Противоположность публичной – приватная (частная) видимость. Процедуры приватного типа видны только внутри того модуля, в котором они записаны. Процедура в обычном модуле считается публичной, даже если тип видимости не указан. Но чтобы не путаться, рекомендуется всегда явно указывать тип видимости.
Public Sub
StartTest () Теперь добавим собственно исполнимые строки, которые мы уже составили ранее. Внесение исполнимого кода
Как видите, после введения пробела появляется подсказка с описанием вызова этого метода. Нечто подобное мы видели раньше. Обратите внимание, что load введено без соблюдения регистра. Если строка будет введена синтаксически верно, то VBA самостоятельно изменит регистр на верный. Это один из способов убедиться в правильности ввода.
Public Sub
StartTest ()
Попробуйте запустить процедуру StartTest. Проще всего поместить текстовый курсор куда-нибудь в текст этой процедуры и нажать [F5].
Как видите, ничего не произошло. Вернее сказать, произошла загрузка формы, но на экран она не вывелась – не было указаний.
Продолжим ввод кода.
После ввода точки, – которая является разделителем имени объекта и его атрибутов, – появляется список всех атрибутов объекта. Можете пролистать список и ознакомиться с атрибутами объекта.
Как видите, по мере ввода начальных букв происходит перемещение по списку. Мы уже на нужной строке списка.
Если нажать [Enter], то слово завершится и курсор перейдет на новую строку. Итак, текст процедуры приобрел вид: Public Sub
StartTest ()
Как видите, теперь на экране появляется наша форма. Реализация процедуры останова
Подсказка. Листинг процедуры такой: Public Sub StopTest () Тестировать ее пока не будем. Заметьте, что метод Hide для формы в списке не показан. Как уже говорилось, это – одна из прискорбных ошибок в IDE VBA. Об это просто надо помнить. Создание панели кнопок для запуска приложения При создании любой программы следует предусмотреть возможность быстрого запуска программы при ее создании – так называемого отладочного запуска. Иначе говоря, следует создать возможность быстро и легко запускать и быстро и легко останавливать программу – реальные условия запуска могут быть сложнее, но в начале на этом не следует останавливаться. Создадим новую панель кнопок Excel и поместим на нее кнопки для пуска и остановки нашего тест-макроса.
Перед вам окно, аналогичное тому, с которым мы работали в Word в первой части учебника.
До сих пор работа не отличалась от создания панели кнопок в Word. Далее – небольшие различия, характерные для Excel.
Как видите, в правом списке всего два пункта, тогда как в Word здесь находился перечень всех макросов, доступных вам.
На новой панельке должно появиться две кнопки с одинаковым рисунком:
Это – заготовки кнопок вообще, полезных действий они еще не выполняют. Теперь надо назначить им процедуры.
Кнопка выделится «квадратом» и появится контекстное меню:
В поле Имя можно изменить название кнопки. Сделайте это, если хотите. Нас интересует нижний пункт контекстного меню .
Перед вами – диалоговое окно назначения макроса:
Как видите, в списке всего два пункта. И это – созданные нами «управляющие» процедуры!
Теперь левая кнопка на новой панельке отвечает за запуск приложения.
Если хотите, можете изменить внешний вид кнопок, назначить им другие рисунки и тому подобное. Для этого используется все то же контекстное меню. Поэкспериментируйте с ним сами. Для возможности работы с созданной панелью кнопок следует закрыть диалоговое окно настройки панели кнопок.
Теперь вновь созданная панелька кнопок готова к работе. Отладка. Пробный запускПротестируем работу нашего приложения. Вначале не забудьте сохраниться.
Как видите, появилось окно нашего приложения. Запуск работает.
Не тут-то было. Созданная нами панель кнопок недоступна!
В чем же причина? Проанализируем код макроса StartTest, благо, там всего две строки.
Изучение кода процедуры запуска Первая строка отвечает за загрузку формы, вряд ли причина в этом. Во второй строке происходит вывод формы на экран. Может быть, здесь?
Метод Show. Модальность формы Появится справка по методу Show для формы.
Обратите внимание на этот отрывок:
Здесь описываются значения параметра и даются краткие описания результатов его применения – в колонке Description. Как видите, при значении параметра vbModal (или 1, что то же самое) форма модальна (что бы это не значило). Слово default означает, что это значение параметра принято по умолчанию. Иначе говоря, если вы не указываете значения, это равнозначно тому, если бы вы указали значение по умолчанию. Значение параметра vbModeless (или 0) делает форму немодальной. Как вы уже убедились, значение по умолчанию не позволяет приложению работать так, как хотелось бы. Изменим значение аргумента и посмотрим, что получится. Давайте попробуем.
Load frmTest
Теперь панель доступна и при работе приложения! Видимо, при состоянии формы модальна она блокирует вызывающее приложение-субстрат и не позволяет обращаться к нему. Прочитав справку, вы найдете подтверждение нашей догадке.
Если все сделано правильно – форма исчезнет. Как вы уже заметили, VBA выводит созданные при визуальном редактировании элементы управления без какого-то либо дополнительного кода. Так что наша задача упрощается. Не забудьте сохранить проект. В следующий раз мы начнем добавлять в проект «по-настоящему» полезную функциональность. Итог занятияДанное занятие было большей частью практическим, но в то же время оно проиллюстрировало несколько концепций. Сперва вы увидели, как устроена объектная модель MS Excel. Нет нужды зазубривать или конспектировать ее – важнее понять принципы. Детали вы всегда можете уточнить в справочной системе. Гораздо важнее уяснить парадигму запуска-останова приложения. Здесь следует обратить внимание на следующее. Действия по запуску приложения «зеркально» повторяются при останове. При останове выполняются действия, противоположные тем, что производились при запуске – и в обратном порядке. Так, если при запуске приложения был создан какой-то объект – при останове следует этот объект уничтожить. Если были открыты файлы – следует их закрыть. Стоит написать конспект, описывающий процессы запуска и останова абстрактного приложения. Вот примерный план:
Как всегда, ответы – своими словами. Не заглядывайте в книгу во время составления конспекта, лучше перечитайте материал и напишите конспект заново! |