VBA для "чайников" [Стив Каммингс] (pdf) читать онлайн

-  VBA для "чайников"  [3-е издание] (пер. К. Б. Тарабров) (и.с. Для «чайников») 8.05 Мб, 449с. скачать: (pdf) - (pdf+fbd)  читать: (полностью) - (постранично) - Стив Каммингс

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]

by

Steve

Cummings

Hungry Minds™

HUNGRYMINDS,INC.
Bes-tSe
nilgBooks•Dg
ita
i lDownolads•eB
-ooks•AnswerNew
t ok
rs•e-Newsele
trs•Ba
rndedWebSe
tis•eL
-ean
rmg
NewYork,NY*Ce
l vea
l nd,OH•Indianapolis,IN

Стив Каммингс

ДИАЛЕКТИКА
Москва • Санкт-Петербург • Киев
2002

ББК 32.973.26-018.2.75
К18
УДК 681.3.07
Компьютерное издательство "Диалектика"
Зав. редакцией В. В. Александров
Перевод с английского и редакция КБ. Тараброва
По общим вопросам обращайтесь в издательство "Диалектика'
по адресу: info@dialektika.com, http://www.dialektika.com

Камминг, Стив.
К18

VBA для "чайников", 3-е издание. : Пер. с англ. — М. : Издательский дом
"Вильяме", 2001. — 448 с. : ил. — Парал. тит. англ.
ISBN 5-8459-0230-4 (рус.)
Эта книга поможет освоить интегрированную среду разработки VBA и научиться
программировать в VBA с использованием объектов, их свойств, методов и событий.
Обсуждаемые приемы программирования иллюстрируются примерами, которые можно
сразу же опробовать на практике. Полученные знания вы сможете применить как для
настройки и усовершенствования популярных офисных приложений, включая приложения Office XP, так и для создания собственных приложений.
Книга рассчитана на тех, кто собирается быстро и без лишних усилий научиться
программировать для Windows, используя VBA.
ББК 32.973.26-018.2.75

Вес названия программных продуктов являются зарегистрированными торговыми марками соответствующих фирм.
Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в какой бы то нн
было форме и какими бы то ни было средствами, будь то электронные или механические, включая фотокопирование и запись на магнитный носитель, если на это нет письменного разрешения издательства
Hungry Minds, Inc.
Copyright © 2002 by Dialektika Computer Publishing.
Original linglish language edition copyright © 2001 by Hungry Minds. Inc.
All rights reserved including the right of reproduction in whole or in part in any form.
This edition published by arrangement with the original publisher. Hungry Minds. Inc.
For Dummies and Dummies Man are trademarks under exclusive license to Hungry Minds, inc. Used by
permission.

ISBN 5-8459-0230-4 (рус.)
ISBN 0-7645-0856-3 (англ.)

© Компьютерное издательство "Диалектика". 2002
С Hungry Minds. Inc., 2001

Оглавление
Введение

18

ЧАСТЬ I. НАЧАЛЬНЫЕ СВЕДЕНИЯ О VBA

23

Глава 1. Уважайте теорию, теория — это все!

25

Глава 2. Не пишите программу, когда можно записать макрос

41

Глава 3. Основы программирования в VBA

50

Глава 4. Выполнение VBA-программ

71

Глава 5. Редактор Visual Basic к вашим услугам

86

ЧАСТЬ II. КУРС ПРОГРАММИРОВАНИЯ НА VBA

113

Глава 6. Анатомия выдающейся VBA-программы

115

Глава 7. Хранение и обработка информации

140

Глава 8. Управление потоком

164

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 185
Глава 10. Создание интерактивных VBA-форм

209

ЧАСТЬ III. ПРАКТИКУЕМСЯ В П Р О Г Р А М М И Р О В А Н И И
НА V B A

253

Глава 11. Инструменты встроенного оркестра VBA

255

Глава 12. Объектно-ориентированное программирование

283

Глава 13. Тонкости хранения данных: массивы и коллекции

303

ЧАСТЬ IV. ПРОФЕССИОНАЛЬНАЯ РАБОТА С VBA

321

Глава 14. VBA для Office

323

Глава 15. Программирование на VBA в Word

333

Глава 16. VBA-программирование в Excel

350

Глава 17. Программирование баз данных

364

Глава 18. Работа с файлами на диске

386

Глава 19. Еще о VBA-формах

390

ЧАСТЬ V. ВЕЛИКОЛЕПНЫЕ ДЕСЯТКИ

407

Глава 20. Десятка (без трех) эффектных решений с помощью VBA
Глава 21. Три десятка ресурсов VBA

409
427

Предметный указатель

433

Содержание
Об авторе
Посвящение
Благодарности

Введение
О чем эта книга
Не следовало бы делать предположений...
Разделяй и властвуй
Часть I, "Начальные сведения о VBA"
Часть II, "Курс программирования нэУВА"
Часть III. "Практикуемся в программировании HaVBA'
Часть IV. "Профессиональная работа с VBA"
Часть V. "Великолепные десятки"
Как использовать примеры
Пиктограммы, используемые в данной книге
Web-страница VBA для "чайников"

ЧАСТЬ I. НАЧАЛЬНЫЕ СВЕДЕНИЯ О VBA
Глава 1 . У в а ж а й т е т е о р и ю , т е о р и я - это все!
Зачем мучиться с VBA?
VBA - это штурвал, но к нему нужен еще и корабль
VBA-приложения третьих фирм
О распространенности VBA-приложений
Программирование на VBA
Что визуального в Visual Basic для приложений?
Главные события
Цикл создания программы
Подробнее о том, что можно сделать в VBA
Настройка пользовательского интерфейса
Добавление новых возможностей
Создание более сложных программ
Совсем не тот BASIC
Интегрированная среда разработки приложений VBA
Макросы и VBA
Элементы управления ActiveX и другие
Объектно-ориентированное программирование и VBA
VBA как стандарт (точнее, род стандарта)
УВА5противУВА6
Другие "диалекты" VBA
VBA против Visual Basic

Глава 2. Не пишите программу, когда можно записать макрос
Как работают макросы
Когда следует записывать макрос
Макрос - и вещь хорошая, и развитие стимулирует
Планирование макросов
Запись макросов
Запуск средства записи макросов

16
17
17

18
18
18
19
19
19
20
20
20
20
21
22

23
25
25
26
27
27
28
28
29
29
30
30
31
32
33
34
35
35
37
38
38
39
39

41
41
42
42
42
43
43

Содержание

Как выбрать имя для малютки
Другие опции диалогового окна Запись макроса
Кнопка, кнопка, ты чья?
Начало записи
Запись команд
Паузы во время записи и ее завершение
Выполнение макросов
Редактирование макросов как способ создания программного кода
Редактирование программного кода макроса в редакторе Visual Basic
Простейшие усовершенствования макросов

43
44
44
45
45
45
46
47
47
48

Глава 3. Основы программирования на VBA
Вызов редактора Visual Basic

50
50

Вызов редактора Visual Basic одним щелчком
Краткое знакомство с редактором Visual Basic
На помощь!
Скорая помощь VBA
Вызов справки VBA-приложения
Поиск в стоге справок
Контекстно-зависимая справка
Что особенного в разделах справки VBA
Установка всех файлов справки
Создание VBA-программы
1-й шаг. Проектирование программы-при мера
2-й шаг. Реализация проекта
3-й шаг. Тестирование программы
4-й шаг. Отладка
Вызов формы из VBA-приложения

50
51
53
53
54
54
55
56
57
58
58
59
67
69
69

Возвращение в VBA-приложение

70

Глава 4. Выполнение VBA-программ
Все определяется именем
Запуск из диалогового окна Макрос

71
71
72

Вызов диалогового окна Макрос
Выполнение макроса
Поиск макроса в диалоговом окне Макрос
Быстрый запуск программ
Кнопки запуска программ
Комбинации клавиш в Word, Excel и Access
Макросы для мыши Visio

72
73
73
74
75
80
83

Автоматический запуск VBA-программ

Глава 5. Редактор Visual Basic к вашим услугам
Пользовательский интерфейс редактора Visual Basic
Легкий завтрак с меню
Прогулка по панелям инструментов
Настройка панелей инструментов и меню
Комбинации клавиш
Управление окнами
Одни окна любят одиночество, другие - всегда в компании
Видимые и скрытые окна
Закрепленные и свободно перемещаемые окна
Сохранение структуры экрана

Содержание

83

86
86
87
87
88
91
93
93
93
94
95

7

Управление проектами с помощью проводника проектов
Вызов проводника проектов
Исследование проводника проектов
Установка свойств проекта
Использование обозревателя объектов
Вызов обозревателя объектов
Просмотр объектов
Поиск членов
Использование информации из окна обозревателя объектов в программном коде
Секреты кодирования
Вызов окна программного кода
Создание нового окна программного кода
Печатание программного кода
Созидательные возможности окна программного кода
Использование окна свойств
Вызов окна свойств
Изменение имени проекта или модуля в окне свойств
Краткое знакомство с окнами для отладки

ЧАСТЬ II. КУРС ПРОГРАММИРОВАНИЯ НА VBA
Глава 6. Анатомия выдающейся VBA-программы
Строительные блоки программы
Определение программы
Пример программы
Иерархия VBA
Откуда берутся проекты, мама?
Все о модулях
Планирование модулей
Добавление нового модуля в VBA-проект
Что к чему в новом модуле
Стандартные модули и модули с классом
Создание процедур
Каркас процедуры
Создание новой процедуры
Процедуры типа Sub
Процедуры типа Function
Привлекательные аргументы
Организация процедур
Обзор области видимости
Задание области видимости процедуры
Использование локальных процедур
Использование операторов
Объявления
Операторы присваивания
Выполняемые операторы
Параметры компилятора
Выбор имен •
Соглашения об именах в VBA
Сделайте программный код красивым
Отступы в программе
Правила для отступов

96
96
96
98
100
100
101
102
102
103
103
103
103
107
110
110
110
111

113
115
115
115
116
117
117
118
118
118
119
119
119
120
121
121
123
124
126
127
127
127
128
128
129
129
130
131
132
133
133
134

Содержание

Свободное пространство - это хорошо
Не пользуйтесь прокруткой без необходимости!
Замечания о комментариях
Как создавать комментарии
Когда использовать комментарии
Пространные комментарии
Убежище Rem для комментариев

Глава 7. Хранение и обработка информации
Работа с переменными
Объявление переменных
Где объявлять переменные
Когда объявлять переменные
Выбор и использование типов данных
Задание области видимости переменной
Объявление нескольких переменных в одной строке
Размещение информации в переменных
Выражен-и-я
Работа с постоянными значениями
Объявление констант
Плоды использования констант
Использование констант для атрибутов
Знаки операций
Получение приоритета
Вычисления с помощью арифметических операторов
Сравнение значений
Объединение текста
Дополнительные сведения о типах данных
Преобразование типов данных
Тип Variant
Выбор числового типа данных
Когда использовать логические переменные
Работа с денежными значениями
Работа с датами
Информацию - в строку
Кавычки в объявлениях строк
Строки фиксированной длины

Глава 8. Управление потоком
Укрощение диких программ с помощью управляющих структур
Анатомия управляющих структур
Вложенные управляющие структуры
Используйте отступы!
Курс на использование условных выражений
Как работает условное выражение
Условные выражения без операторов сравнения
Использование логических операций в условиях
Условные операторы If...Then
Основная форма If...Then
Однострочные операторы if...Щеп
Операторы If...Then...Else
Использование операторов If...Then
Использование операторов Select Case

Содержание

135
135
136
137
138
138
139

140
140
141
141
142
142
145
146
147
148
149
149
150
150
151
151
153
154
156
156
156
156
157
158
159
160
161
162
163

164
164
165
165
165
166
166
166
167
168
168
169
169
169
172

9

Проверка условий в операторах Select Case
Пример оператора Select Case
Оператор Case Bse
Дополнительные сведения об операторе Case
Повторение с помощью циклов
Циклы Do
Повторение под управлением циклов For...Next
Управление потоком с помощью Go To
Пример использования Go То
Оправдания Go То

172
173
173
174
174
175
180
183
183
184

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 185
Все возможные неприятности происходят обязательно
Исправление синтаксических ошибок
Энтомология для программистов
Тест, тест, тест
Комбинации клавиш для отладки
Сделайте паузу!
Сквозь программу по шагам
Основные приемы отладки
Автоматические подсказки
Немедленное вознаграждение в окне Immediate
Все переменные под присмотром в окне Locals
Механика процесса
Зачем редактировать значения переменных
Как редактировать значения переменных
Ключевое средство отладки: окно Watches
Добавление контролируемых выражений
Работа с окном Add Watch
Редактирование контролируемых выражений
Использование контролируемых выражений для назначения точек останова
Отлов "диких" ошибок с помощью On Error и Err
Откуда берутся ошибки выполнения
Как работает программный обработчик ошибок
Как создать обработчик ошибок

Глава 10. Создание интерактивных VBA-форм
Основы проектирования форм
Запуск форм
Формы и элементы управления ~ программируемые объекты
Планирование форм для программы
Печать форм в процессе проектирования
Дизайн новой формы
Работа со свойствами форм и элементов управления
Ключевые свойства форм
Форматирование элементов управления
Использование панели инструментов UserForm
Элементы управления, ведите себя хорошо!
Использование свойств Enabled и Locked
Настройка порядка перехода по нажатию клавиши табуляции
Назначение быстрых клавиш
Отправка сообщений с надписями
Сбор информации с помощью текстовых полей

10

185
186
186
186
187
188
192
194
195
196
197
198
199
199
200
201
201
202
203
204
204
204
204

209
209
209
210
210
211
212
214
216
221
222
225
226
226
227
228
230

Содержание

Использование кнопок
Использование рамок
Выбор элемента с помощью переключателя
Выбор параметров с помощью флажков и кнопок с фиксацией
Выбор параметров из списка и комбинированных окон
Программирование форм
Покажите то, что имеете!
Загрузка и отображение форм
Главные события
Щелкните здесь,..
Создание программного кода для события Change
Распознавание нажатий клавиш
Основные приемы программирования форм
Клавишная альтернатива
Проверка правильности вводимых данных

231
233
234
235
237
238
239
239
242
245
248
248
249
250
250

ЧАСТЬ III. ПРАКТИКУЕМСЯ В ПРОГРАММИРОВАНИИ
НА VBA

253

Глава 11. Инструменты встроенного оркестра VBA

255

Знакомство со встроенными командами

255

Форматирование данных
Работа с функцией Format
Использование встроенных форматов для функции Format
Создание собственных форматов
Использование функции llf
Работа с другими функциями форматирования

256
257
257
258
259
260

Конвертирование данных
Работа с шестнадцатеричными и восьмеричными значениями
Преобразование чисел в строки и наоборот
Работа со
строками
Отбрасывание символов в конце строк с помощью Len и Left
Извлечение символов из строк
Работа с датами и временем
Дата со временем
Исчисление дат
Простые контакты с внешним миром
Отображение окон сообщений
Получение информации от пользователя
Работа с логическими значениями
Забавы с математикой и деньгами
Математические функции
финансовые функции

260
261
261
262
264
265
265
267
267
270
270
273
274
274
274
277

Другие встроенные команды
Глава 12. Объектно-ориентированное программирование
Что такое объект
Объекты как компоненты VBA-приложениЙ
Объекты на уровне понятий
Практическое определение объекта
Классы объектов и конкретные объекты

Содержание

279
283
283

283
284
285
285

11

Коллекции объектов
Что такое объектная модель
Понимание еажнхти объектной модели
Расширение объектной модели
Формы в VBA - это тоже объекты
Использование объектов в программе
Основные правила программирования объектов
Использование объектных моделей
Выяснение и установка свойств объектов
Что нельзя делать с некоторыми свойствами
Установки свойств - это данные
Выяснение текущего значения свойства
Изменение значения свойства
Свойства, выбираемые по умолчанию
Объекты в роли свойств
Вверх по родовому дереву
Методы в действии
События
Идентификация объекта для использования
Понимание объектных выражений
Создание переменных для объектов
Создание новых объектов
Использование оператора Is
Эффективная работа с объектами в программе
Использование оператора With
Использование структуры For Each...Next

Глава 13. Тонкости хранения данных: массивы и коллекции
Знакомство с массивами
Ссылка на элемент массива
Данные массива
Использование многомерных массивов
Объявление массивов
Обращение к элементам массива
Заполнение массива данными... навалом
Копирование одного массива в другой
Управление наборами данных с помощью объектов Collection
Оценка преимуществ использования коллекций
Создание объектов Collection
Добавление данных в коллекцию
Удаление элементов
Подсчеты в коллекциях
Доступ кэлементам коллекций
Использование коллекций с базами данных
Определение своих собственных типов данных
Знакомство с пользовательскими типами данных
Объявление пользовательского типа данных
Объявление переменных пользовательского типа
Обработка информации, представленной пользовательским типом данных
Работа с переменными пользовательского типа данных

12

286
286
287
287
287
288
288
289
289
290
290
291
291
292
292
292
292
293
294
294
296
298
299
300
300
301

303
303
304
304
304
305
308
309
313
313
313
314
314
316
316
316
317
317
318
318
319
319
320

Содержание

ЧАСТЬ IV. ПРОФЕССИОНАЛЬНАЯ РАБОТА С VBA

321

Глава 14. VBA для Office

323

Контроль над панелями инструментов и меню
Отображение и размещение панелей инструментов
Настройка кнопок панелей инструментов
Программирование Помощника по Office
Контроль над Помощником
Программирование окна Помощника
Сохранение значений переменных на диске
Сохранение и получение значений переменных в Excel, PowerPoint и Project
Другие способы сохранения значений переменных

Глава 15. Программирование на VBA в Word
Знакомство с объектом Application
Доступ к документам Word с помощью VBA
Работа с активным документом
Указание конкретного документа
Создание, открытие, активизация и закрытие документов
Работа с разделами документов
Открытие окон с помощью VBA
Обращение к окнам из программного кода
Работа с областями окон
Изменение внешнего вида окна
Использование объекта View
Масштабирование документа с помощью программного кода
Использование объекта Selection
Знакомство с объектами Range
Использование свойства Range
Определение диапазонов с помощью метода Range
Работа с текстом в Word VBA
Выделение диапазонов и создание диапазонов на основе выделенных областей
Повторное определение диапазонов и выделенных областей
Удаление, копирование и вставка текста
Вставка нового текста
Форматирование текста
Поиск и замена текста с помощью VBA в Word
Работа с найденным текстом
Замена текста или форматирования
Поиск и замена форматирования
Использование переменных документа

Глава 16. VBA-программирование в Excel
Знакомство с объектной моделью Excel
Использование в коде объектов Range для работы с ячейками
Определение объекта Range
Использование свойств Cells для определения диапазона
Выполнение совместных действий с ячейками
Работа с отдельными ячейками диапазона
Работа с выделениями
Программирование пользовательских функций
Написание пользовательских функций рабочего листа

Содержание

323
323
324
327
327
327
330
331
332

333
333
334
334
334
334
335
335
336
336
336
337
337
338
339
339
340
341
342
342
344
345
345
346
346
347
348
348

350
350
351
351
352
353
354
354
356
357

13

Запуск пользовательских функций
Тестирование пользовательских функций
Профессиональное написание функций
Использование в коде встроенных функций
Программирование событий Excel
Выбор правильного объекта
Испозование процедур событий
Реагирование на изменения в рабочем листе
Программирование динамических диаграмм

Глава 17. Программирование баз данных
Программирование
баз
данных
на

357
358
359
359
359
360
360
361
362

VBA:

основные

О ядре баз данных
SQL и VBA
Все об объектах баз данных
Несколько связанных технологий баз данных
Программирование баз данных: доступные варианты выбора
Возможные варианты разработки баз данных
Программирование баз данных с помощью Access
Написание кода базы данных с помощью ADO
Обработка ошибок
Добавление ссылки на ADO
Установка соединения
Работа с объектами Recordset
Использование объекта Command
Работа с SQL
Как избежать SQL
Знакомство с диалектами SQL
Вставка инструкций SQL в VBA-код
Написание инструкций SELECT
Выполнение групповых обновлений и удалений в SQL

Глава 18. Работа с файлами на диске
Номер - это ключ
Выбора режима доступа к файлу
Не идите на поводу у номеров
Закрытие открытых файлов
Чтение и запись данных

Глава 19. Еще о VBA-формах
О внешнем виде форм и элементов управления
Выбор цветов
Выбор шрифтов
Простые фокусы с мышью
Добавление изображений
Удаление рисунков с помощью окна свойств
Другие возможности форматирования
Дополнительно о работе с элементами управления
Советы об использовании текстовых полей
Создание форм с несколькими вкладками
Совет о кнопках выбора
Флажки
Выбор значений с помощью полос прокрутки и кнопок со стрелками

14

термины

364
364
364
365
365
366
367
367
368
369
369
369
369
371
377
379
379
360
380
380
385

386
386
387
387
388
388

390
390
390
391
392
393
395
395
396
396
398
400
401
401

Содержание

Дополнительно о программировании форм

403

Использование переменных для ссылок на формы
Распознавание нажатий клавиш
Дополнительные приемы проверки

403
404
404

ЧАСТЬ V. ВЕЛИКОЛЕПНЫЕ ДЕСЯТКИ

407

Глава 20. Десятка (без трех) эффектных решений с помощью VBA
Сохранение информации в реестре Windows
Доступ к объектам других приложений
Основы межпрограммного взаимодействия
Добавление ссылки на внешнюю объектную модель
Объявление внешних объектов
Создание внешнего объекта
Использование внешних объектов
Управление базами данных с помощью VBA
Работа с файлами
Принципы работы с файлами в VBA
Ссылки на библиотеку Microsoft Scripting Runtime
Доступ к файлам
Работа со свойствами файлов
Копирование, изменение и удаление файлов
Чтение и запись данных
Использование объектов Dictionary
Базисные сведения об объектах Dictionary
Лучше, чем коллекции
Пользовательские объекты
Создание модулей классов
Компоненты определений класса
Использование своих собственных объектов
Использование элементов управления ActiveX
Добавление новых элементов в панель элементов управления
Использование элементов управления ActiveX в программах

Глава 21. Три десятка ресурсов VBA
Первая справочная инстанция
Возьмите готовый программный код
Ознакомьтесь с предложениями Microsoft
Журналы и газеты
Web-страницы, посвященные VBA
Галактика элементов управления ActiveX
Мания усовершенствования
Изобразительное искусство
Диаграммы и графики
Текстовые документы и электронные таблицы
Бери деньги, и вперед!
Разработка элементов управления
Разное
Вычислительная мощь
Помогите, помогите!

Предметный указатель
Содержание

_

409
409
410
411
411
411
412
412
413
413
414
414
415
415
415
416
419
420
420
420
421
421
423
424
424
426

427
427
427
427
428
428
429
429
429
430
430
431
431
431
431
432

433
15

Стив Кяммингс занимается программированием больше 20 лет, используя такие разные
языки программирования, как ассемблер, COBOL и C++, а также VBA и Visual Basic. Он автор и соавтор более десятка компьютерных книг, среди которых и книга Секреты Office 97,
выпушенная издательством "Диалектика". Кроме того, ему принадлежат сотни статей, опубликованных в известных компьютерных журналах, в том числе PC World, Macworld, PC
Magazine, PC/Computing и PC Week.

ТЕос&ящение
Моей бабушке по поводу 97-летия

Спасибо всем сотрудникам издательства Hungry Minds, а особенно моим редакторам:
Джеймсу Расселу (James Russel), который проявил немало внимания и терпения при работе
над настоящей книгой, а также Джейд Вильяме (Jade Williams) и Кэлли Оливер (Kelly Oliver).
Я благодарен компании VCommunications (www. v - c o m . com) за предоставление таких программных продуктов, как System Commander и Partition Commander. Это замечательные утилиты для настройки работы нескольких операционных систем на одном компьютере, что мне
требовалось при работе с beta-версиями Microsoft Office XP. Также спасибо Лизе Роббинс
(Lisa Robbins) из компании Waggener Edstrom, подразделения компании Microsoft, за помошь
при знакомстве с нюансами новой версии VBA, а также за предоставление пробных версий
программных продуктов компании Microsoft, необходимых мне при работе.

Введение
Да, это именно та книга, которая необходима для того, чтобы начать освоение VBA
(аббревиатура от Visual Basic for Applications, что означает Visual Basic для приложений).
Благодаря этой книге вы узнаете об основных принципах программирования в VBA и получите необходимые навыки для создания полезных программ. А самое главное, вы сможете
сделать это без лишних усилий.
В книге использовано много примеров, написана она легко и понятно, поскольку, кто знает, сколько скучных томов уже издано в этом мире! Я попытался изложить все самым обычным языком, по возможности исключив из употребления режущий ухо нормального человека
специальный жаргон. И с этого момента я начинаю отпускать (иногда не самые лучшие) шуточки, чтобы вам было на что направить свое раздражение.
С другой стороны, обсуждение рассматриваемых вопросов не слишком упрощено, иначе
оно было бы лишено всякой ценности. Если отбросить шутки в сторону, то эта книга— полноценное справочное пособие, охватывающее все основные разделы VBA.

О чем э/на книга
Вы, наверное, уже знаете, что VBA — это язык программирования, встроенный во множество программ, от приложений Microsoft Office, Microsoft Project, Visio и AutoCAD до многочисленных специализированных приложений, предназначенных для управления производственными процессами, учета финансовых ресурсов или информационной поддержки клиентов.
В этой книге рассмотрены все существенные аспекты программирования в VBA. Здесь вы
найдете достаточно полную информацию по следующим темам:
V •/ использование преимуществ визуальных средств программирования VBA;
;: S запись и редактирование макросов;
\ •/ запуск VBA-программ из других приложений;
- S создание приятных на вид диалоговых окон и других элементов интерфейса;
'i •/ работа с объектами, которая станет ключом к использованию всей силы VBAt
приложений.
В настоящей главе рассмотрены версии VBA с версии 6 по 6.3 (VBA6.3 входит в состав
приложений Microsoft Office ХР). Согласно данным компании Microsoft, все версии VBA, начиная с версии 6 и заканчивая версией 6.3, с точки зрения программиста совершенно идентичны.
Компания Microsoft исправила некоторые ошибки, улучшила производительность, но способы
написания программного кода или создания диалоговых окон не изменились. Поэтому, когда
я говорю о VBA б, это касается как VBA 6.0 и VBA 6.3, так и всех промежуточных версий.

Неследовало11Л V E A И^ : B L ЛИС
: = ' «jsi;u.:Keicn?.-K=m.Ki«4f

Запуск редактора Visual Basic

> Использование справочной системы VBA
г

Программирование в VBA — краткое и нестрогое руководство

ММакросы хороши до определенных пределов, но гораздо больше можно получить от
^Ущ/w полноценных VBA-программ. Эта глава послужит аварийным введением в рациональное VBA-программирование. После вводного обзора редактора Visual Basic и справочной системы VBA мы с вами на простом примере разберем по шагам процесс построения
VBA-программы. Эти знания станут тем солидным базисом, который потребуется для освоения всего остального материала книги.

Зшов fieqaxtnofta Visual Susie
Редактор Visual Basic служит командным центром для работы в VBA. В нем вы должны
находиться при разработке VBA-форм, создании VBA-кода, тестировании и отладке VBAпрограмм. Экспертом по использованию редактора Visual Basic вы станете после прочтения
главы 5, а пока вам нужно только знать, как вытянуть этот редактор на экран.
Если вы делали кое-что из того, о чем так много говорилось в предыдущей главе при обсуждении программного кода, создаваемого средством записи макросов, вы должны уже
знать один из способов вызова редактора Visual B a s i c — выбор макроса в диалоговом окне
Макрос с последующим щелчком на кнопке Изменить. Но, конечно же, можно запустить
редактор Visual Basic и непосредственно. В большинстве VBA-приложений можно воспользоваться одним из следующих методов.

| s Выбрать из меню Сервис^Макрос^Редактор Visual Basic.
с

'• •/ Нажать . Вы услышите, как затараторит жесткий диск, и через несколько
I
мгновений на экране появится редактор Visual Basic. Он должен хотя бы отдаленно
напоминать то, что изображено на рис. 3.1.
В некоторых приложениях вам понадобится проделать другой маршрут, чтобы добраться
до редактора Visual Basic. Однако вы в любом случае найдете необходимую команду гденибудь в меню Tools (Сервис).

Вызов редактора Visual Basic одним щелчком
Нслн в вашем приложении есть кнопка в панели инструментов для вызова редактора Visual
Lasic. используйте се. В VFi А-приложениях из пакета Microsoft Office (Word. Excel и
PowerPoint) эта кнопка помещена в панель инструментов Visual Basic (рис. 3.2). Наборы кнопок
в этой панели инструментов у разных приложений могут немного отличаться.

50

Часть I. Начальные сведения о VBA

Рис. 3.1. Редактор Visual Basic
Рис, 3.2. Вид панели инструментов
Visual Basic в приложении Word
Кнопки в этой панели инструментов, как правило, соответствуют пунктам подменю
Макрос из меню Сервис. Вот для чего предназначены некоторые из этих кнопок (слева
направо, см. рис. 3.2).
Первые две кнопки предназначены соответственно для выполнения и записи макросов.
Кнопка справа от кнопки Безопасность вызывает редактор Visual Basic. Если вы
часто используете редактор Visual Basic, а другие кнопки в этой панели инструментов
вам не нужны, скопируйте кнопку вызова редактора в другую панель. Чтобы скопировать кнопку в любом из приложений Office, перетащите ее на новое место, удерживая
при этом нажатой клавишу .
Кнопка с изображенными на ней молотком и гаечным ключом открывает панель
элементов управления, очень похожую на панель элементов управления VBA.
В Office вы можете поместить элементы управления VBA в сам документ, а не
только в VBA-форму.
Кнопка с изображенными на ней линейкой, треугольником и карандашом включает
режим проектирования, в котором вы можете редактировать элементы управления
VBA в своем документе.

Краткое знакомство с редактором Visual Basic
Первые обращения к редактору Visual Basic могут вас озадачить. Наверное, присутствие меню и панелей инструментов вверху экрана покажется вам привычным, но вот что означает это обилие окон? Предсказать их взаимное расположение практически невозможно,
поскольку они размещаются и комбинируются почти в бесконечном разнообразии вариантов (даже когда вы открываете редактор Visual Basic впервые, все равно предстающая перед вами картина допускает немало вариантов, в зависимости от того, как вы его открыли).
Кроме того, если вы не профессиональныйпрограммист, названия окон и их функции окажутся для вас наверняка непопятными.

Глава 3. Основы программирования на VBA

51

Научить вас уверенно обращаться со всеми этими окнами должна глава 5, здесь же я приведу только список их имен и функций (табл. 3.1).
Таблица 3.1. Имена и функции
Имя окна

Функциональное назначение

Project Explorer (окно проводника проекта)

Перемещение по компонентам VBA-проекта
и управление ими

Code (окно программного кода)

Просмотр, добавление и редактирование
программного кодаУВА

UserForm (окно формы)

Проектирование пользовательских форм (диалоговых
и других окон)

Toolbox (панель элементов управления)

Добавление элементов управления (текстовых полей
или кнопок} в формы, а во многих VBA-приложениях
и в документы

Properties (окно свойств)

Установка индивидуальных атрибутов выделенной
формы или элемента управления

W a t c h (окно контролируемых выражений)

Отслеживание значений выбранных переменных
программы и выражений

Locals (окно локальных переменных)

Отслеживание значений переменных текущей процедуры

Immediate (окно немедленного выполнения)

Выполнение отдельных строк программного кода для
немедленного получения результата

Object Browser (окно обозревателя объектов)

Исследование объектов, дгступных программам

Давайте поближе рассмотрим окно программного кола, предназначенное для печати и редактирования в нем VBA-кода, и окно пользовательской формы, предназначенное для визуального проектирования окон и форм. Примеры окон программного кода и пользовательской
формы показаны на рис. 3.3 и 3.4 соответственно.
- И д е к т и ф и к н ц и н П р о е к т о . р р ! - M o d u l e l (Code)
T j

| Getting StartedWHhVBA

Sub GettingStactedBithVBAO
Dim SomeMumbet As Single
Dun SomeText As T t r i n g
Dim SomeShape As AcadEntity
SomeNumber = 53Л456
SoraeText = "Работа заполняет все отпущенное на нее
Randomize
SomeNumber = EomeNumb&r + (1D0 * Rnd ())
End

Рис. 3.3. В окнах программного кода, подобных этому, печатается программныйкод VBA

52

Часть I. Начальные сведения о VBA

Рис. 3.4. Пример окна пользовательской формы с помещенным
в него диалоговым окном на стадии еще не завершенного
проектирования
С самого начала перед вами откроется несколько окон программного кода и окон пользовательской формы, а может случиться так, что их не будет на экране вообще. Но для нас это сейчас не имеет значения, поскольку после краткого обсуждения справочной систе-мы VBA нам с
вами понадобятся новые окна для программы-примера, которую вы почти готовы создать.

Напомощь/
Практически все современные приложения до отказа забиты говорящими сами за себя
пунктами меню, кнопками в панелях инструментов с красивыми маленькими пиктограммами,
ясно соответствующими выполняемым кнопками командам, а также всплывающими сообщениями-подсказками, которые объясняют функциональное назначение этих кнопок. Кому еще
при этом требуется какая-то справочная система? Например, вам, если вы собираетесь создавать VBA-программы.
Для начала вам потребуется справка о самом редакторе Visual Basic. Хотя меню и панели
инструментов этого редактора работают точно так же, как и во всех остальных приложениях,
поначалу многие из предлагаемых редактором команд выглядят совершенно непонятными.
Кроме того, редактор Visual Basic озадачивает вас сразу восемью-девятью типами окон,
и требуется немало времени, чтобы разобраться с ними.
Ясно, что с пользовательским интерфейсом редактора Visual Basic вы разберетесь довольно скоро. Но даже самым опытным программистам требуется помощь, когда дело касается деталей самого языка VBA. Из-за сотен объектов, методов, ключевых слов и Бог знает,
чего еще. что просто нельзя удержать в голове, без файлов справки VBA работа становится
практически невозможной.
Существует созданная Microsoft "бумажная" версия руководства по программированию в VBA, но комплект поставки далеко не всякого VBA-приложения
предполагает наличие печатной копии. Определенно можно сказать, что такая
копия руководства есть в комплекте пакета Office для разработчика.

Скорая помощь VBA
Окна справки VBA выглядят по-разному в различных VBA-приложениях. Справочная
система и старых программах использует старое и проверенное ядро WinHelp, своими истоками восходящее еще к Windows 3.11. Ядром же справки VBA 6 является HTML H e l p — новый стандарт Microsoft. Впервые представленная в Windows 98, система HTML Help больше
похожа ьа Web-броузер. К сожалению, те версии HTML Help, которые я использовал до настоящего времени, ведут себя временами довольно странно и непредсказуемо, а кроме того,
в них отсутствуют некоторые полезные возможности WinHelp, например возможность удерживать окно справки на экране перед другими окнами, когда активно другое приложение.

Глава 3. Основы программирования на VBA

53

Чтобы открыть главное окно справки VBA, выберите Не1р^Справка по Microsoft Visual
Basic — появится окно справки с описанием VBA в общем. Окно HTML Help для VBA 6 показано
на рис. 3.5. К сожалению, здесь вы не найдете справки о работе с конкретным приложением.

Рис. 3,5. Пользователи VBA 6'получают справку в окне HTML Help

Вызов справки VBA-приложения
Печально, но ф а к т — редактор Visual Basic не предлагает команду, обеспечивающую непосредственный доступ к файлам справки того VBA-приложения. из
которого он вызван. Не тратьте время на поиски — такой команды просто нет.
Если вам понадобится дополнительная информация о программировании в данном приложении, а не о VBA вообще, единственным решением будет следующий четырехшаговый процесс.
1. Откройте обозреватель объектов, нажав или выбрав В и д ^ О б о з р е в а т е л ь
о б ъ е к т о в (подробно обозреватель объектов рассмотрен в главе 6).
2.

Из раскрывающегося списка в верхнем левом углу окна обозревателя объектов
выберите имя вашего VBA-приложения.

3.

Выделите любой раздел в панели классов в левой части окна обозревателя объектов.

4.

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

Поиск в стоге справок
Работа справочной системы VBA организована в соответствии со стандартами Windows
как в WinHelp, так и в HTML Help. В обоих случаях вы можете сделать следующее.
% S Воспользоваться вкладкой Содержание, чтобы увидеть дерево разделов справки, по:
добное содержанию обычной книги.

54

ЧастьI.Начальныесведения

f S Воспользоваться вкладкой Предметный указатель, чтобы увидеть алфавитный спи\
сок ключевых слов, предлагаемый создателями справки.
Можно также воспользоваться вкладкой Поиск, чтобы найти практически любое слово,
встречающееся в файлах соответствующей справки. Следует, правда, заметить, что в справке
VBA для Office вместо вкладки Поиск есть вкладка Мастер ответов. Предполагается, что
вы можете теперь перейти к нужному разделу справки в ответ на целый введенный вами вопрос, но с тем же успехом вы можете просто ввести одно-два слова, а затем щелкнуть на
кнопке Найти.

Контекстно-зависимая справка
В редакторе Visual Basic клавиша вызывает контекстно-зависимую справку, т.е. открывает перед вами именно тот раздел справки, который соответствует работе, выполняемой
вами в момент вызова. То, что вы увидите, зависит от типа окна, которое будет в редакторе
при этом активным, а часто и от того, что именно вы делаете в этом окне.
Такая возможность оказывается действительно удобной при создании программного кода и проектировании форм. В окне программного кода клавиша
предоставит справку для термина, находящегося в точке ввода (точка
ввода задается текстовым курсором — мигающей вертикальной линией, определяющей место появления печатаемых вами символов). Не волнуйтесь,
если вы забыли, как используется какой-нибудь VBA-оператор. например
For . . . N e x t , или если не помните, какими свойствами и методами обладает нужный вам объект. Просто поместите текстовый курсор в соответствующий оператор и нажмите . Пример того, что вы можете при этом
увидеть, показан на рис. 3.6.

РИС. 3.6. Получение справки для метода Add в Visio. Если присмотреться, можно заметить, что точка ввода в окне программного
кода находится внутри ключевого слова Add

Подобным образом клавиша предоставит вам самую подробную справку о проектировании форм. В окне пользовательской формы можно получить справку о каждом из поме-

Глава 3. Основы программирования на VBA

55

щенных в форму элементов управления (рискуя показаться назойливым, я напомню, что элементы управления — это кнопки, флажки, фреймы и т.п.). Щелкните на элементе управления,
чтобы выделить его, а затем нажмите . Чтобы получить справку об определенном свойстве элемента управления, выделите этот элемент управления, щелкните в строке соответствующего свойства в окне свойств, а затем нажмите .
В других окнах клавиша работает следующим образом.
S В окне проводника проекта и окне пользовательской формы нажатие клавиши
вызывает раздел справки с описанием окна. Для окна пользовательской формы это
сработает, только если не выделен ни один из элементов управления.
S В окне контролируемых выражений, окне локальных переменных и в окне немедленного выполнения нажатие вызывает окно справки со множеством предлагаемых
в нем ссылок — подчеркнутых слов и словосочетаний, на которых надо щелкнуть,
чтобы перейти к соответствующему разделу справки. Лично мне совершенно не понятно, почему сделано так, что для этих окон подходящий раздел справки не появляется автоматически.
В окне обозревателя объектов при выделенных классе и члене класса нажатие
вызывает появление раздела справки, соответствующего выбранному объекту.

Что особенного в разделах справки VBA
При использовании справки VBA обращайте внимание на ссылки и кнопки ссылок,
вызывающие другие относящиеся к рассматриваемому вопросу разделы справки. Научитесь пользоваться ими! Подобно разделу, показанному на рис. 3.7, большинство разделов справки VBA предлагают такую возможность. Если показанный раздел не содержит
необходимой вам информации, вполне вероятно, что вы отыщете ее в разделах, предлагаемых ссылками.

РИС. 3.7. Подобно большинству других разделов, этот раздел
справки VBA в Word предлагает ряд ссылок на другие разделы справки
В табл. 3.2 приведены некоторые из ссылок, которые вы можете увидеть в окне
справки.

ЧастьI.Начальныесведения

Таблица 3.2. Ссылки и кнопки ссылок
Ссылка или кнопка

Назначение

See also (См. также)

Щелкните на этой ссылке, чтобы увидеть информацию о других
разделах справки, относящихся к рассматриваемому вопросу

Example (Пример)

Увидев кнопку или ссылку Example, без сомнения используйте
ее. Примеры существенно помогают в понимании порой
запутанных и неполных объяснений в файле справки. Кроме того,
вы можете скопировать пример в свою VBA-программу и
подправить его по своему усмотрению (врезка "Позаимствуйте
программный код из файла справки")
Эти ссылки имеются в разделах справки, описывающих объекты.
Позволяют ознакомиться с методами, свойствами и событиями,
которые можно использовать с данным объектом

Methods, Properties, Events
(Методы, свойства и события)
Applies to (Применяется к...)

Эта ссылка присутствует тогда, когда раздел справки относится
к свойству, методу или событию. Щелкните на ней, чтобы увидеть
список объектов, с которыми свойство, метод или событие можно
использовать

Позаимствуйте программный код из файла справки
Не упустите возможность использовать фрагменты программного кода, предлагаемые во многих разделах справки VBA. Нередко программный кодпредлагаемого примера после самых минимальных изменений будет в точности соответствовать тому, что требуется вам. Чтобы использовать примеры справки,
выделите нужные вам строки программного кода с помощью мыши, щелкните на выделенном правой
кнопкой мыши и в появившемся меню выберите Копировать. После этого перейдите в окно программного кода в редакторе Visual Basic и щелкните на кнопке Вставить в панели инструментов или
нажмите .

Установка всех файлов справки
В зависимости от приложения и от того, как вы его инсталлировали, на вашем жестком диске установлен, а, может быть, и не установлен полный комплект файлов
справки VBA. Из-за того, что любая серьезная работа в VBA без файлов справки
практически невозможна, убедитесь в том, что все они установлены.
Например, программа установки Office устанавливает не все, а только некоторые файлы
справочной системы VBA. Большинство пользователей при установке Office на свои компьютеры используют в программе установки кнопку Типичная. Это, конечно, очень удобно
(зачем думать?), но при этом не устанавливается целый ряд важных файлов справки VBA.
Если так же действовали и вы, снова запустите программу установки и выберите опцию
Выборочная. По очереди для каждого из приложений Office выберите пункты Справка
и Файлы примеров. Когда вы затем щелкнете на кнопке Применить, появится диалоговое
окно, подобное показанному на рис. 3.8. В этом окне отметьте флажок пункта Справка по
Visual Basic.

Глава 3. Основы программирования на VBA

57

Microsoft Oilier XP (|1(юфе1с-'Онл]*||НЧтг- п ы п у с х )

У п к н и м н п ы с ксянюнеит

—™—

i

дли
McS
-jE
tcon (N
M
o
u
e
i
P
c
r
a
e
r
0
Fe)MoosePoi
PEu
t-e N
(-W
nPicturePo
tsLc^e
*P
o
satln^'-f
nSpecialEM
sj|P
p
E
i
f
e
0

albn
ld»y °.1

Рис. 3.12. Для изменения установок любого
из свойств элемента управления используйте
окно свойств

Для надписи в нашей программе-примере нужно изменить лишь два свойства— Name
(Имя) и C a p t i o n (Заголовок). Замените имя элемента управления с L a b e l l на l b l N o w
(первые три буквы указывают на то, что имя принадлежит элементу управления надписью).
Чтобы сделать это, найдите свойство Name в самом верху списка свойств (оно представлено
как ( N a n . e } ) , — это единственное из свойств, заключенное в скобки. Двойным щелчком
в правом столбце строки этого свойства выберите его, а затем впечатайте новое имя. (Имена
элементов управления используются при создании программного кода, поэтому для них имеет смысл выбирать имена, которые напоминали бы о назначении элементов управления.
В главе 6 говорится о соглашениях, которые следует использовать в именах для идентификации создаваемых элементов управления.)
Затем опуститесь по списку ниже и найдите свойство C a p t i o n . Здесь просто удалите
значение свойства. Почему? Просто потому, что ваша программа сама обеспечит текст для
надписи во время выполнения.
Теперь ясно, что вам придется создавать некий программный код, если вы хотите, чтобы программа во время выполнения изменяла свойства элемента управления. Большинство свойств при этом остаются неизменными, а поэтому создание
такого программного кода не требует больших усилий. Раз уж вы меняете свойства, заодно измените и заголовок самой формы. Выберите форму, щелкнув на
полосе заголовка окна формы. В изменившемся при этом окне свойств найдите

Глава 3. Основы программирования на VBA

61

свойство C a p t i o n и измените его на что-нибудь типа Вы не видели моей
клавиатуры? или Моя п е р в а я программа в VBA. Этот новый заголовок появится в полосе заголовка формы.

Добавление кнопки команды
Элемент управления кнопкой команды (чаше называемый просто кнопкой) отличается от
надписи тем, что предполагает определенные действия со стороны пользователя программы.
Когда кто-нибудь щелкает на кнопке, ее изображение на экране изменяется так, что она выглядит нажатой, а программа в ответ выполняет какие-нибудь действия.
Нашей программе нужна всего одна кнопка, которая после щелчка на ней завершит выполнение программы. Чтобы поместить такую кнопку в форму, выполните следующее.
1. Щелкните в окне формы, чтобы сделать его активным снова.
При этом панель элементов управления, которая исчезла, когда вы перешли в окно
свойств, возникнет снова.
2. Щелкните на той пиктограмме в панели элементов управления, на которой изображена кнопка (см. рис. 3.11).
3. Начав немного левее середины формы и нажав левую кнопку мыши, перетащите указатель по диагонали вши, чтобы создать кнопку.
Теперь форма должна принять вид. как на рис. 3.13.

РИС. 3.13. ВИД формы после того,
как в нее добавили кнопку
Теперь вы должны установить нужные значения свойств кнопки. Используя окно свойств,
выполните следующие шаги.
1. Измените значение свойства (Name) на OKButton.
Напомню снова, что, поскольку при создании программного кода вам придется ссылаться на кнопку по ее имени, такое имя кнопки напомнит вам о ее назначении.
2. Измените значение свойства C a p t i o n на ОК. Этот текст увидит пользователь на
кнопке во время выполнения вашей программы.
Вот вы и создали форму для своей программы. Уже к этому моменту ваша программа стала вполне функционирующей VBA-программой -— она будет показывать очень симпатичное
только что созданное вами окно. Чтобы запустить программу на выполнение, нажмите
или щелкните на кнопке Выполнить в панели инструментов редактора Visual Basic. На этой
кнопке изображена маленькая направленная вправо стрелка.
Когда вы запустите эту наполовину испеченную программу, на экране появится форма на фоне вашего VBA-приложепня (а не на фоне окна редактора Visual Basic;
62

Часть I. Начальные сведения о VBA

рис. 3.14). Поле надписи будет пустым, и кнопка ОК ничего делать не будет —- не забывайте, что никакого программного кола мы еще не печатали. Чтобы завершить выполнение программы, щелкните на стандартной для Windows кнопке закрытия в правом конце
строки заголовка окна.
£} £•> £

Выпотнение программ и макросов из диалогового окна М а к р о с — надежно,
но не слишком интересно

> Запус-: макросов с помощью кнопок панели инструментов и пунктов меню
> Назначение для макросов комбинации клавиш
>

Автоматический запуск программ при наступлении определенных событий

Ь у бонная сила VBA-программы не значит ничего до тех пор, пока вы не нажмете ее
^ ^ с т е к о в о й крючок. Л в нашем случае ЭТОТ спусковой крючок сначала нужно еше найти.
Говоря более прозаическим языком, пока вы не найдете способ, с помощью которого сможете
запустить свою VBA-программу, программа остается бесполезной.
Во время создания программы в окне редактора Visual Basic вы всегда могли выполнить
ее, нажав или щелкнув на кнопке Run (Выполнить) в панели Standard (Стандартная)
редактора Visual Basic. Это вполне удобно при тестировании программы, но совершенно никуда не годится для реальной работы. После того как программа готова, ее нужно запускать
из соответствующего приложения.
В этой главе обсуждаются возможности, которые можно использовать для запуска
VBA-программ и макросов из VBA-приложений. (Еще раз напомню, что м а к р о с — это та
же VBA-программа, которой посчастливилось быть записанной средствами автоматической записи; подробности в главе 2. "Не пишите программу, когда можно записать макрос".) Одна из самых простых возможностей для запуска большинства программ обеспечивается диалоговым окном Макрос, но уж очень это неудобно. VBA-программа становится
действительно полезной, когда вы можете запустить ее командой меню, кнопкой в панели
инструментов или нажатием определенной комбинации клавиш, а еще лучше, предусмотрев автоматическое выполнение.
Попрактикуйтесь в этом с макросами, которые вы запишете, следуя указаниям главы 2, или
с процедурами, которые вы создадите с помощью редактора Visual Basic, используя либо краткие
инструкции из главы 6, либо подробные объяснения из частей II и III.

/Зсе

именем

Вызов VBA-программы осуществляется по имени.
Извините за то, что приходится начинать с технических подробностей, но другого выхода я не вижу. При вызове VBA-программы вы на самом деле запускаете одну специальную процедуру VBA. Ваша программа может содержать немало самых различных процедур, но только одна из них имеет первую строку кода, говорящую о том, что вы хотите выполнить программ). Эта первая процедура может запускать (вызывать) другие процедуры,

Глава 4. Выполнение VBA-программ

71

которые в свою очередь могут вызывать следующие и т.д. Для того чтобы выполнить программу, вы должны вызвать только первую процедуру — остальные выполнятся автоматически по мере выполнения программой своей задачи.
Хотите узнать что-нибудь более существенное по поводу процедур? Обратитесь к главе 6,
где вы получите полный ответ.
А в чем же здесь проблема? В том, что. запуская VBA-программу, вы должны знать
имя процедуры, которая "разбудит" эту программу. В программах, содержащих
больше одной процедуры, запускающая процедура обычно называется M a i n .

Запуск из диалогового окна Мсис/гос
Вполне надежно запускать VBA-программы из диалогового окна Макрос. Если вы не позаботились о том, чтобы приписать программу кнопке в панели инструментов или комбинации клавиш, либо если вы просто забыли, чему вы ее приписали, всегда можно воспользоваться диалоговым окном Макрос.

Вызов диалогового окна Макрос
Чтобы вызвать диалоговое окно Макрос в приложениях Office или в Visio, выполните одно из следующих действий.
- V Выберите команду С е р в и с ^ М а к р о с ^ М а к р о с ы .
[ S Нажмите .
Другие VBA-приложения предлагают иные возможности для того, чтобы открыть диалоговое окно Макрос.
Диалоговое окно Макрос должно выглядеть подобно изображенному на рис. 4.1. Как всегда,
некоторые детали могут быть другими, в зависимости от используемого вами VBA-приложения.

Рис. 4. /. Диалоговое окно Макрос
в приложении PowerPoint
Больше всего места в диалоговом окне Макрос выделено для списка доступных в данный
момент VBA-программ.

72

Часть I. Начальные сведения о VBA

Строго говоря, все процедуры, приведенные в списке диалогового окна Макрос,
являются процедурами типа Sub (т.е. подпрограммами) без аргументов.
(Загляните в главу 2, чтобы убедиться, что это и есть официальное определение
макроса.) После запуска такой процедуры от может вызывать процедуры других типов, включая процедуры типа F u n c t i o n (т.е. функции) и процедуры
Sub с аргументами. Подробности в главе 6.

Выполнение макроса
Запуск макроса из диалогового окна Макрос вряд ли можно назвать большим достижением.
Выполняемая при этом последовательность шагов должна быть такой.
1. Выберите макрос из списка ниже поля Имя.
2. Щелкните на кнопке Выполнить.
Ну как, круто? Как альтернативу можно использовать двойной щелчок на имени программы в списке.
Единственной сложностью при этом может оказаться поиск в списке диалогового окна
Макрос имени той программы, которую нужно выполнить. Если вы испытываете такие
трудности, обратитесь за помощью к следующему разделу.

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

K'tp a3

Вчаен

«ПорядкгЦиС pHSCK»атным
SofcH

в;

(Все открытые т и г и

Параметры;,,

Оги-аше
-- -Помогает ( рафжу У » в В текучей рабочий ПИП

Рис. 4.2. Диалоговое окно Макрос в Excel приводит имена ША-программ (макросов) из неактивных рабочих книг, любезно указывая перед именем программы имя содержащей ее книги

Глава 4. Выполнение VBA-программ

73

В диалоговом окне Макрос в Word процедуры приводятся в списке по их именам, за исключением того случая, когда две или несколько процедур имеют одно ii то же имя. В этом
случае имя состоит из имени содержащего процедуру модуля, за которым следуют сначала
точка, а затем уже имя процедуры. В качестве доказательства я поместил здесь рис. 4.3.

РИС. 4.3. Диалоговое окно Макрос в Word
Если программа, которую вы хот иге запустить, отсутствует, вам необходимо
выбрать и окне Макрос другой вариант. Для того чтобы это сделать,
воспользуйтесь списком Макросы из, в котором выберите вариат Активных
шаблонов.

запуск nftotfteuui
Может быть, диалоговое окно Макрос работает и идеально правильно, по оно так неэффективно! Ведь когда требуется что-то выполнить, обычно это нужно I-U-.V.'OAVUUO, КТО
захочет открывать диалоговое окно, искать в длинном списке приведенных MCIKHV шрифтом имен и шелк, щелк, щелк, щелк.
Есть и лучшие способы запуска VBA-программ. Назначьте каждой из СНОПУ очень
часто используемых программ кнопку в панели инструментов, пункт в меню или комбинацию клавиш. Тогда один-два щелчка или одна нажатая комбинация клавиш принесут вам желанное вознаграждение.
Как вы, наверное, помните (если, конечно, читали главу 2), многие VBAпрнложения позволяют связать макрос с кнопкой и панели инструментов или комбинацией клавиш уже при записи макроса. Это, кстати, довольно веская причина и пользу
того, чтобы начинать каждую новую VBA-программу как записываемый макрос, который затем нужно дополнить своим программным кодом. Если вам нужно обновить
в памяти информацию о тонкостях этого процесса, обратитесь к главе 2.
После того как макрос записан, у вас тоже должна быть возможность назначить ему
кнопку или комбинацию клавиш, а может быть, и пункт меню. Вся остальная часть материала этой главы посвящена обсуждению именно этих возможностей. К сожалению, техника выполнения этой задачи немного варьирует от приложения к приложению. На некоторые из таких вариаций я буду обращать ваше внимание в ходе следующего (довольно
долгого) раздела.

74

Часть I. Начальные сведения о VBA

Кнопки запуска программ
Какое приятное волнение испытываешь, щелкая на маленькой оригинальной кнопке на
экране и получая при этом немедленный ответ своего компьютера! Несомненно, существуют
и более приятные волнения, но и нажатие кнопки имеет свою прелесть. А если кнопка, на которой вы щелкаете, вызывает созданную лично вами VBA-программу, к этому волнению добавляется еще и небольшое головокружение от успеха.
В некоторых УВА-приложениях назначение кнопок для вызова VBA-программ происходит
очень просто, даже если вы создавали программу, не записывая ее в виде макроса. К таким приложениям относятся приложения из Office. В других УВА-приложениях, как в Visio, вам, вероятно, придется самому печатать программный код VBA, который добавит подходящую кнопку.
Ой! А я-то думал, что VBA предлагается в виде визуального средства разработки интерфейса!

Кнопки на панели инструментов или меню
Если вы никак ничего не можете решить по этому поводу, просто помните, что между
кнопкой на панели инструментов и элементом меню больших различий н е т — все они реагируют на щелчок мыши. Основное отличие состоит в том. что в меню отображается текст, а на
кнопке — картинка. Результат использования обоих элементов будет один и то же.
Приложения Office позволяют использовать приемы drag-and-drop для назначения VBAпрограми-е кнопки на панели инструментов или элемента меню.

Простое обращение с кнопками в Office
В Microsoft Word, Excel, PowerPoint, Access, а также Outlook назначать VBA-программе
новую кнопку в панели инструментов очень п р о с т о — перетащите с помощью мыши. После
того как кнопка займет предназначенное ей место, вы можете создать на этой кнопке еще
и подходящий рисунок.
Создание кнопки или команды меню в Word
Чтобы в Word создать кнопку для вызова VBA-программы, сделайте следующее.
1. Щелкните правой кнопкой мыши в любой из панелей инструментов.
После этого на экране возникнет контекстное меню.
2. В самом ншу этого меню выберите Настройка, чтобы открыть диалоговое окно
Настройка с вкладками, в котором будет изначально открыта вкладка Панели
инструментов.
Открыть диалоговое окно Настройка можно без выполнения п. 1, выбрав из меню
Сервис^Настройка.
3.
4.

В диалоговом окне Настройка шелкните на ярлыке вкладки Команды (рис. 4.4).
Прокрутите список Категории вниз и найдите пункт Макросы. Щелкните на
этом пункте, чтобы выбрать его.
Пои этом справа, в списке Команды, появятся все имеющиеся в вашем распоряжении
УЗА-программы. (Диалоговое окно Настройка на рис. 4.4 как раз и показывает макросы.)

5. Найдите необходимый макрос в списке (это может быть и VBA-программа, написанная вами с самого начала).
6. Если вы создаете кнопку, найдите в списке ту программу, которой нужно назначить кнопку. Затем перетащите имя этой программы в подходящую панель инструментов. Если вы создаете команду в меню, найдите в списке ту программу,
которой нужно назначить кнопку. Затем перетащите имя этой программы прямо в меню.

Глава 4. Выполнение VBA-программ

75

i JXssJ
Чтобы лобшпь ютнйу "* f * « J * ииструнвмгов, BuSepfna ка чгорню и перетащите
кпчачг ^5 "ого окна ** панель.
Кат*гар1*1г \
Команды
TenelatePreleet.TrinjliteBynigvfl.MAlK
TemplatePrO|ett,T4nsl9teWtird9».MAIN

J3JJ Содминтьс | Normal

Ряс. . Когда рядом с указателем мыши возникнет значок X, отпустите кнопку мыши, и удаление произойдет.

Настройка кнопок с помощью VBA-кода
Чувствую я, что ваше VBA-приложение как раз и не позволяет просто перетаскивать нужное при настройке кнопок. Необходимость использовать VBA при создании кнопок в самом
начале знакомства с VBA, наверное, выглядит устрашающе. Но на самом деле такой способ
создания кнопок не слишком сложен. Главное — выяснить, какими объектами в вашем VBAприложении представляются кнопки и панели инструментов и какие свойства и методы нужно использовать для изменений.

Глава 4. Выполнение VBA-программ

79

И они еще называют VBA стандартом!
В Office объекты кнопок называются C o r m a n d B a r B u t t o n s , а принадлежат они коллекции CommandBarControls. Объект CommandBar (панель инструментов, содержащая
коллекцию CcmmandBarControls) размещается в коллекции ComrnandBars, которое
может принадлежать объекту A p p l i c a t i o n или объекту Document.
А в Visio, например, отдельная кнопка представляется объектом T o o l b a r l t e m . Однако,
чтобы воспользоваться конкретным экземпляром объекта T o o l b a r l t e m , необходимо получить доступ к той коллекции T o o l b a r l t e m s , которой этот экземпляр объекта принадлежит.
Сама же коллекция T o o l b a r l t e m s принадлежит коллекции T o o l b a r s , в свою очередь
принадлежащей коллекции T o o l b a r S e t , а уж последняя принадлежит конкретному экземпляру объекта UlObj e c t (объект пользовательского интерфейса). Немного позже в этой же главе с помощью несложного программного кода я покажу, как все это реализуется практически.
Если все эти сложности вас пугают, успокойтесь: вам не придется создавать программный код для своих кнопок с чистого листа. Поишите в справочной системе своего
VBA-приложения разделы, посвященные настройке панелей инструментов, и вы наверняка обнаружите там пример, который после несложных модификаций можно использовать в вашем конкретном случае.

Комбинации клавиш в Word, Excel и Access
Если вы хоть немного умеете печатать, то часто используемые вами команды просто умоляют вас назначить им комбинации клавиш. В большинстве приложений, даже в тех, которые
ориентированы исключительно на работу с изображениями, нажать клавиши часто быстрее, чем
перемещать туда-сюда мышь и щелкать ее кнопками. Единственный недостаток комбинаций
клавиш -— необходимость запоминать их.
В любом случае некоторые VBA-приложения —- в том числе Word, Excel и Access — дают прямой доступ к клавиатуре, позволяя назначить комбинации клавиш VBA-программам. Если вам предлагают такой способ управления, используйте его, не сомневаясь.

Назначение комбинаций клавиш программам в Word
Если уж зашла речь о настройке клавиатуры, то изо всех VBA-приложений самым
гибким и простым в этом отношении является Word. Например, чтобы назначить в Word
программе с именем D o u b l e C u r r e n t F o n t S i z e комбинацию клавиш
(т.е. ), действуйте следующим образом.
1. Откройте диалоговое
окно
Настройка,
для
чего
либо
выберите
Сервис=ЖастрОЙка из меню, либо щелчком правой кнопкой мыши в любой из
панелей инструментов откройте контекстное меню и затем выберите пункт
Настройка в нем.
2. Щелкните на кнопке Клавиатура в нижней части вклалки Параметры.
Появится диалоговое окно Настройка клавиатуры (рис. 4.9).
3. В списке Категории выберите Макросы.
4. Найдите и выберите свою программу в появившемся справа списке Макросы.
Если программе уже была назначена комбинация клавиш, она будет в поле Текущие
сочетания клавиш.
5. Нажмите комбинацию клавиш, которую вы хотите назначить своей программе.
Если предложенная вами комбинация уже используется, диалоговое окно сообщит,
какую из команд она вызывает, и вы сможете либо оставить в силе имеющееся назначение, либо заменить его новым.

80

Часть I. Начальные сведения о VBA

Шрифт
Двтотвки
Стили

,
Xi

Укджнта сочаташв кпвенш
1«кринд ымдтажа;
Новая t

21
Cdtfawrt >Онв«ив в; .JNormal

Рис. 4.9. С помощью такого диалогового окна вы можете назначить своим VBA-программам комбинации
клавиш в Word

6. Щелкните сначала на кнопке Назначить, а затем на кнопке Закрыть, чтобы
выйти из диалогового окна.
С этого момента назначенная вами комбинация клавиш будет готова к действию.

Разместите свои программы в контекстных меню
Приложив совсем немного усилий, вы сможете поселить свою скромную VBA-программу в фешенебельных апартаментах любого контекстного (т.е. вызываемого щелчком правой кнопки мыши) меню.
В Office контекстные меню настраиваются в диалоговом окне Настройка. Сначала нужно сделать видимой панель инструментов Контекстные меню. Откройте диалоговое окно Настройка, выбрав
Сервис=>Настройка, и в нем перейдите на вкладку Панели инструментов (если она еще не открыта), щелкнув на соответствующем ярлыке в верхней части диалогового окна. Пролистайте вниз список панелей инструментов, найдите в нем пункт Контекстные меню и щелкните в маленьком квадратике около него.
Панель инструментов Контекстные меню станет видимой. С помощью этой панели инструментов вы
сможете получить доступ к любому контекстному меню, чтобы настроить его. Открыв таким образом
нужное вам контекстное меню, используйте обсуждавшиеся в начале этого раздела приемы перетаскивания макросов из вкладки Команды диалогового окна Настройка.
Например, Visio позволяет поместить макрос в контекстное меню любой из форм. Выделив форму, выберите Window^Show ShapeSheet. В окне ShapeSheet щелкните в ячейке Action. (Если нужно, вставьте перед этим раздел Actions, выбрав Insert^Section и отметив Actions.)
Затем выберите EditoAction. Вы получите возможность впечатать текст и определить другие свойства
пункта меню и назначить ему программу для выполнения. По окончании редактирования это контекстное
меню, вызываемое щелчком правой кнопки мыши на данной форме, уже будет включать и пункт для вашей VBA- программы.

Глава 4. Выполнение VBА-программ

81

Комбинации клавиш в Excel
Excel тоже позволяет назначить VBA-программам комбинации клавиш, но ограничивает долуешмыс комбинации сочетаниями клавиши с печатаемыми символами (буквами, числами
и знаками пунктуации). Чтобы назначить программе комбинацию клавиш, выполните следующее.
1. Откройте диалоговое окно Макросы (почему бы для этого не воспользоваться
комбинацией клавиш ?)
2. Найдите и выделите свою программу в списке.
3. Щелкните на кнопке Параметры.
4. В появившемся диалоговом окне (рис. 4.10) нажмите клавишу, которую хотите
скомбинировать с клавишей .
Excel при п о м различает буквы верхнего и нижнего регистров. (Другими словами,
клавиша с буквой, нажатая вместе с клавишей ^Shiff>. отличается от клавиши с буквой, нажатой без клавиши .)
5. Щелкшпс на кнопке ОК, чтобы вернуться в диалоговое окно Макросы*

Рис 4.10. Назначение VBAпрограмме комбинации клавиш в Excel

Комбинации клавиш в Access
В приложениях баз данных Access назначать комбинации клавиш совсем несложно. Приложения Access построены на использовании форм и элементов управления в этих формах. Все,
что вам потребуется сделать, это создать процедуры обработки событий для этих форм и элементов управления— процедуры, выполняемые при нажатии клавиши пользователем. Проце1уры обработки событии в мельчайших подробностях описываются в главе 10.
Другое дело, если вы работаете с базой данных Access напрямую, используя команды
меню и кнопки панелей инструментов. В этом случае для создания комбинаций клавиш,
вызывающих VBA-программы, вам придется назначать эти комбинации клавиш специальным макросам Access. (Напомню, что макросы Access не являются процедурами
VBA.) В Access нет средства записи макросов, поэтому вам придется строить макросы
вручную в соответствии со следующими инструкциями.
1. В окне базы данных выберите кнопку Макросы, а затем щелкните на кнопке
Создать.
Появится диалоговое окно Макрос (рис. 4.11).
2. В столбце Макрокоманда выберите ЗапускПрограммы, как показано на
рис. 4.11.
3. Выберите ВидОИмена макросов, чтобы в окне появился новый столбец Имя
макроса.
' Напечатайте в столбце Имя макроса комбинацию клавиш, которую вы хотите
на;ш:гнггь споен \'ВЛ~программе.

42

Часть I. Начальные сведения о VBA

Л

Используйте символ для обозначения клавшим . а символ + — для обозначения . Буквы и числа можно печатать как обычно, а вот функциональные клавиши нужно заключить в фигурные скобки. Например, для комбинации клавиш
А
J
нужно напечатать к , а для Design Mode

Комментарий
Это странное место для команды,
относящейся ко всему проекту, - я ожидал бы
найти ее в меню File

Команда Design Mode, похоже, относится к разметке форм, так почему же она тогда в меню Run?
Потому что она останавливает выполнение любой
программы. Эта команда не слишком полезна,
поскольку можно проектировать формы и без нее,
и совсем не обязательно выходить из режима
проектирования, чюбы выполнить программу

Прогулка по панелям инструментов
Если вы знакомы с Word, Excel или PowerPoint, вероятно, и района с панелями инструментов в редакторе Visual Basic покажется вам вполне удобной, Если же нет. по этому поводу
достаточно будет нескольких кратких комментариев.
Редактор Visual Basic предлагает четыре готовые панели инструментов.
. S
;;


Standard (Стандартная). Это единственная пане и, мп.ф) ментов, которую вы видите
при первом запуске редактора Visual Basic. Ее кнопки выполняют самые разнообразные функции: сохранение результатов вашей рабош, добавление новых форм и модулей, редактирование и выполнение программ.

. S Edit (Правка). Кнопки этой панели инструментов пригодятся при редактировании

программного кода. Они дублируют команды меню Edit.
:

I S
*

Debug (Отладка). Здесь размешаются кнопки для Кч-мапд. которые понадобятся вам
при вылавливании ошибок и программам.

: S UserForm (Пользовательская форма). Эта панель ш;е:п\ментов используется при проектировании форм. Большинство се кнопок дчблпруил команды из меню Format для
выравнивания, упорядочения и группировки .)лсмен'п.:н \ правления в форме.

Глава 5. Редактор Visual Basic к вашим услугам

87

Эти панели инструментов можно использовать в любой комбинации. Всего пара
щелчков отображает панель инструментов на экране (если она еще невидима) или прячет ее (если она присутствует на экране). Вот описание соответствующей процедуры.
1.

Сначала шелкните правой кнопкой мыши в любой панели управления.
Появится контекстное меню (рис. 5.1) со списком всех имеющихся панелей инструментов. Если панель инструментов видима, ее имя будет отмечено галочкой.

Debug
Рис. 5.1, С помощью этого контекстного
меню можно отображать на экране и
прятать панели инструментов
2. В этом меню выберите панель инструментов, которую хотите отобразить или
спрятать.
Как только вы отпустите кнопку мыши, на экране произойдут соответствующие изменения.
Панели инструментов редактора Visual Basic могут существовать в одном из трех состояний, как показано в следующей таблице.
Состояние панели инструментов

Вид панели инструментов на экране

Скрытая

Невидима на экране

Закрепленная

Прикреплена к одной из четырех сторон рабочей области
главного окна

Перемещаемая

Представлена в виде своего отдельного окна с полосой заголовка
и закрывающей окно кнопкой. Перемещаемые панели
инструментов можно разместить и вне окна редактора Visual Basic

На рис. 5.2 показано окно редактора Visual Basic с двумя закрепленными и двумя перемещаемыми панелями инструментов. Скрытыми, закрепленными или перемещаемыми могут
быть большинство основных окон редактора Visual Basic.
Чтобы сделать закрепленную панель инструментов перемещаемой, просто перетащите ее от
края рабочей области окна к его середине. Самос удобное место для захвата закрепленной панели инструментов — место с краю, где видны две вертикальные (или горизонтальные) полоски.
Эта область панели инструментов называется маркером перемещения. Сделать панель инструментов перемещаемой можно и иначе — дважды щелкнув в области маркера перемещения.
Обратное тоже верно: чтобы превратить перемещаемую панель инструментов в закрепленную,
перетащите ее полосу заголовка к любой из сторон рабочей области окна редактора Visual Basic.
Как только указатель мыши окажется достаточно близко, гравитационное поле окна притянет панель инструментов, как магнит. Этот эффект завораживает, но двойным щелчком панель инструментов закрепляется быстрее (она возвращается на то место, где была закреплена в последний раз).

Настройка панелей инструментов и меню
Предположим, что вас почему-то не устраивают панели инструментов, предлагаемые редактором Visual Basic. Ну, так создайте себе новые! Можно добавлять и убирать кнопки и
пункты меню в существующих панелях инструментов и меню, а если и этого для вас недостаточно, вы имеете возможность создать свою собственную панель инструментов просто "с нуля" (это делается точно так же, как и в приложениях Office).

88

Часть I. Начальные сведения о VBA

Microsoft Viauol Basic

С:\Мои iL«icyMBHTu\VisiQVBAvsd [ h l ' t a k j

Eife EOff liie* insert Format в

ELiwate Sub UseirFcrm_Activate ()
LisfBoxl .Addlteir. "Удивительно пр&крас
Li tBoxl .AddItem "Хранитель сревногте-'
Lx?"Eoxl.Addltem "Последняя элек^ричлLiatBoxl .Addltesn "Парусе над облакам;'
Li rBoxl .Addltem "ВИНОЕНИ; s 'iinf

| Fiivar.- ;;•.,!. ВечныйИдеал changed

Д/с. 5 2 По умолчанию панели инструментов редактора Visual Basic закреплены
под строкой меню, но их можно закрепить и вдоль других сторон главного окна или
сделать свободно перемещаемыми

Перемещение и удаление кнопок в панели инструментов
Если вам нужно только переместить или удалить уже имеющуюся кнопку, то все, что вам потребуется, это не забыть нажать и удерживать клавишу , пока вы будете перетаскивать кнопку на
новое место. При нажатой клавише вы можете сделать следующее.
It / Перетащить кнопку на новое место в той же или другой панели инструментов. Если
I
вам нужно поместить в новое место копню кнопки, во время перетаскивания удержиI
вайте нажатыми клавиши и .
I S Добавить линию разделителя между двумя кнопками, перетащив кнопку справа
I
еще чуть-чуть правее (если перетащить еше правее, кнопка перескочит за соседI
нюю). Чтобы убрать линию разделителя, перетащите правую кнопку немноI
го влево.
| •/ Удалить кнопку, перетащив ее на любое место, где нет панелей инструментов. Когда
I
рядом с указателем появится значок X, отпустите кнопку мыши, и кнопка из панели
I
инструментов уйдет в историю.

Добавление новой кнопки в панели инструментов
Для более изысканных модификаций потребуется открыть диалоговое окно Настройка.
Оно используется для добавления новых кнопок в панели инструментов и для любых изменений в меню.
Вот последовательность действий, необходимых для добавления новой кнопки в панели
инструментов.

Глава 5, Редактор Visual Basic к вашим услугам

89

1. Щелкните правой кнопкой мыши в любой панели инструментов и в самом низу
появившегося контекстного меню выберите Настройка.
Появится диалоговое окно Настройка (рис. 5.3).

Рис. 5.3. С помощью диалогового окна
настройки можно внести радикальные
изменения в пользовательский интерфейс редактора Visual Basic

2. Если панели инструментов, которую вы собираетесь изменить, нет на экране, перейдите в л налоговом окне Настройка на вкладку Панели
инструментов.
Установите флажок рядом с нужной вам панелью инструментов. Здесь же можно добавить и новую панель инструментов, для чего нужно щелкнуть на кнопке Создать
и набрать имя.
3. Когда панель инструментов, с коюрои вы собирались работать, появится на экране, перейдите на вкладку Команды.
Теперь можно перетаскивать объекты из списка в панели инструментов или меню.
4. После того как вид панели инструментов будет удовлетворять вас, закройте
диалоговое окно Настройка.
Обратите внимании, при открыюм дналотвом окне Настройка перетаскивать и удалять
кнопки из панелей инструментов можно и без помощи клавиши . Однако, чтобы скопировать, а не переместить выбранный обьскт. придется нажать клавишу .

Обезьянничание с меню
Чтобы изменить меню редактора Visual Basic, необходимо открыть диалоговое окно
Настройка (см. п. 1 в предыдущем раиеле). После пого вы сможете щелчком на меню открыть его. а затем перетащить интересующие вас пункты меню в другие позиции или другие
меню. Перетаскивая пункт меню в рабочую область окна, можно удалить этот пункт меню.
Чтобы добавить или удалить разделительную линию между двумя пунктами меню, перетащите нижний из этих пунктов немного ниже или немного выше.
Чтобы добавить в меню новые пункты, перетащите их с вкладки Команды диалогового
окна Настройка точно так же, как вы это делали при создании новых кнопок в панели инструментов (рис. 5.3 и 5 4>'.

90

Часть I. Начальные сведения о VBA

Щ
4n
Isert Fte.
%
r E
<
W
R 4s..
Rtfnoye ,,.
JprM,,.
_

a



Sebcrcd commeid:

И« Window

• !

Рис. 5.4. Настройка одною из контекстных меню редактора Visual Basic
Наверюе, считая возможность изменения системы главного меню недостаточной, редактор Visual Basic позволяет чакже изменять контекстные (т.е. вызываемые щелчком правой
кнопки мыши) меню. Для .шло нужно открыть лнгшоговое окно Настройка, перейти в нем
на вк.')адк> Панели инструментов и отметить флажок Контекстные меню.
В результате этих действий на экране появится небольшая панель инструментов, предназначенная только для настройки (см. рис. 5.4). Найдите в этой панели инструментов нужное
вам контекстное меню и щелкните на нем. После этого вы сможете перетаскивать к тго контекстное меню объекты с вкладки Команды.

Комбинации клавиш
В табл. 5.1 приведены все комбинации клавиш, задействованные в редакторе Visual Basic.
Кроме них, вы можете использовать клавишные команды Windows для управления курсором
и редактирования текста. Не забывайте и о том, что вызывает контекстное меню
для окна или другого объекта, активного в данный момент, — как будто вы щелкаете на этом
объекте правой кнопкой мыши.

Глава 5. Редактор Visual Basic к вашим услугам

91

Таблица 5 . 1 . Комбинации клавиш, предлагаемые редактором Visual Basic
Отображение окон
Для того чтобы,..

нажмите...

Открыть окно программного кода для данной формы или элемента управления



Отобразить форму, соответствующую активному окну программного кода



Перейти в следующее окно программного кода или в окно формы



Открыть окно обозревателя объектов



Открыть окно свойств

< F4>

Открыть окно немедленного выполнения команд



Открыть окно стека вызовов во время выполнения программы



Работа с программным кодом
Для того чтобы...

нажмите...

Перейти к определению объекта в точке ввода



Открыть диалоговое окно поиска



Найти далее (найти, где следующий раз появляется текст, заданный в окне поиска)
Найти предыдущее



Заменить



Перейти к предыдущей редактировавшейся строке



Отменить действие



Открыть список свойств/методов



Открыть список констант



Получить краткую справку о переменной или объекте в точке ввода



Отобразить информацию о параметрах функции в точке ввода



Автоматически дополнить печатаемое слово



Работа со свойствами
Для того чтобы...

нажмите...

Перейти в окне свойств к следующему свойству, начинающемуся с заданной
буквы



Выполнение программы
Для того чтобы...

нажмите...

Запустить процедуру или форму в активном окне



Приостановить выполнение программного кода и перейти в режим паузы



Начать выполнение программного кода с остановкой на строке, содержащей
текстовый курсор



12

Часть I. Начальные сведения о VBA

Уп/гавленмеокнами
Если ваш монитор не отличается гигантскими размерами экрана, приготовьтесь потратить
довольно много времени на перемещение окон редактора Visual Basic. Эти окна существуют
не столько для того, чтобы на них смотреть, сколько для того, чтобы оказать достаточно существенную помощь в вашей программистской работе. Проблема заключается в том, что
держать их все на экране открытыми нерационально-— вам совсем не останется места для
работы с формами и VBA-кодом.

Одни окна любят одиночество, другие - всегда в компании
Относительно окон редактора Visual Basic вы должны запомнить один основной факт:
окон форм и программного кода можно открыть столько, сколько вы пожелаете, а каждое из
окон остальных типов может присутствовать на экране только в единственном экземпляре.
Вероятно, вам такое ограничение сразу покажется вполне логичным, а вот лично мне, чтобы
разобраться, потребовалось некоторое время.
Несколько окон для программного кода и форм можно открыть потому, что обычно создаются несколько форм и один VBA-модуль. Имея для каждого из этих объектов свое окно,
вы получите быстрый доступ сразу ко всем своим формам и модулям.
Некоторые другие окна (а конкретно— окно свойств и окно локальных переменных) изменяют свое содержимое автоматически, когда вы переходите в окно другой формы или соответствующего программного кода. Это похоже на несколько окон по иене одного. Другие
же окна — например, окно обозревателя объектов, окно проводника проекта и окно немедленного выполнения •— применимы ко всему, что делается в редакторе Visual Basic, поэтому
можно открыть только по одному из них.

Видимые и скрытые окна
Почти для каждого окна редактора Visual Basic есть комбинация клавиш, которая открывает его. Это значит, что если окно невидимо, вы можете открыть его, не отрывая рук от клавиатуры. Все эти комбинации клавиш представлены в табл. 5.1. Если вам трудно их запомнить, всегда можно открыть любое из окон через меню View.
Жаль, что эти комбинации клавиш не работают, как выключатели. Если окно уже открыто, нажатие соответствующей комбинации клавиш не прячет его. Чтобы заставить окно уйти,
вам придется щелкнуть на маленькой кнопке закрытия X, которая расположена в правом
верхнем углу окна.
Чтобы открыть окно, которое уже отображено на экране, но затерялось за другими окнами, выберите имя этого окна из меню Window. В этом меню будут представлены только перемещаемые окна.
Как и во многих других приложениях Windows, для переключения от одного окна к другому вы можете использовать две стандартные комбинации клавиш —
и . Однако в редакторе Visual Basic в цикле таких переходов будут участвовать только перемещаемые окна.
Вы, наверное, спросите: "Что такое перемещаемые окна?" Ответ на этот вопрос находится
в следующем разделе.

Глава 5. Редактор Visual Basic к вашим услугам

93

Закрепленные и свободно перемещаемые окна
Подобно панелям инструментов, большинство окон редактора Visual Basic бывают закрепленными, т.е. вы можете привязать их к любой из четырех сторон рабочей области главного
окна, где их не перекрывают другие окна. Ясно, что закрепление окна делает рабочее пространство меньше. На рис. 5.5 показан редактор Visual Basic, в котором закреплены все допускающие закрепление окна.

Ste Edit View insert Format Qehug R1-"1 1лХ!з

ffijn*»

Це!р

В
- i С* 4a П p

VisioVBA Чо- донумент

EQVB* BuwninriTeiffioi E'aiTples UserFQrnJ^

,., j |¥ВАдлячаин и Рэ
3ackCotar
BordecColL

3 Then
ГенераторГромкогоЗвука
End I f

Параметры компилятора
Последний класс операторов представляет собой инструкции для управления поведением
компилятора VBA. К операторам, задающим параметры компилятора, относятся следующие.
Оператор

Выполняемое действие

Option Base число

Установка правила нумерации массивов переменных - начинать
нумерацию по умолчанию с 0 или 1 (подробности в главе 13)

Option Compare метод

Выбор метода, используемого VBA для сравнения строковых
переменных (текста). Вместо слова "метод" можно указать
Binary
для сравнения на основе числового кода символов, T e x t для сравнения, при котором не учитывается регистр символов,
или D a t a b a s e (только в Access) -для сравнения в
порядке, отвечающем порядку сортировки соответствующей
базы данных

Option Private Module

В результате помещения такого оператора в раздел
D e c l a r a t i o n s модуля другие проекты не смогут
получить доступ к процедурам, переменным и константам
этого модуля, даже если эти объекты объявлены как открытые
(подробно об области видимости см. выше в разделе "Обзор
области видимости")

Option Explicit

Это единственный из операторов, задающих параметры
компилятора, о котором следует знать и который стоит
использовать. В результате помещения этого оператора
в модуль VBA запрещает использовать переменные без их
предварительного явного объявления (подробности в главе 7)

130

Часть //. Курс программирования в VBA

имен
В определенных рамках вы имеете возможность совершенно произвольно выбирать имена для переменных, процедур и всего другого, что вы создаеге. Следующие правила применимы ко всем именованным элементам в VBA-программе. включая переменные, константы,
типы данных, процедуры, модули, формы ипроекты.
\ •/ Имена должны начинаться с буквы, но не с цифры. После первой буквы уже могут
\
идти и цифры, и символ подчеркивания, как, например, в имени
t S

Скоытая_ПеремекнаяЗ

\ V Кроме символа подчеркивания, все остальные знаки пунктуации для использования в
именах в VBA запрещены:
!

а

&



$ #

7

,

.

(точка)

{ } ( ) [ ] = -

А

% / - < > : ;

Не допускаются пробелы в именах.
Длина имени не должна превышать 255 символов (40 символов— для форм и элементов управления).
Имя должно не совпадать ни с каким ключевым словом, функцией или оператором VBA.
В рамках одной и той же области видимости одно и то же имя нельзя использовать
для двух разных объектов. Например, все процедуры в модуле должны иметь разные
имена. Не допускается, чтобы переменная процедуры и переменная уровня модуля
(определенная в разделе D e c l a r a t i o n s модуля) имели одинаковые имена. Однако
можно использовать одно и то же имя для разных переменных, если эти переменные
локальны и размещаются в разных процедурах.
Если вы попытаетесь ввести имя, нарушающее эти правила, редактор Visual Basic сообщит об этом, как только вы уберете текстовый курсор из соответствующей строки программного кода. Символы в строке станут красными, и на экране возникнет сообщение с так называемым объяснением ошибки (рис. 6.1). Исключение: предупреждение о дублировании имен
процедур не появится до тех пор. пока программа не начнет выполняться.

iro ПозицияВФайле A*
Mm сообщение As Str
im СтоимостьТовара

Microsoft Visuul uu

•А

а mpile eiraf.

РИС. 6.1. Редактор Visual Basic предупреждает, что введено недопустимое имя
Вот несколько примеров допустимых и недопустимых имен.
В VBA прописные и строчные буквы не различаются, но введенные вами прописные буквы любезно сохраняются. Предположим, что вы объявили переменную, имя которой состоит
только из прописных букв, например:
Dim LOUCVARIABLE As

String

Глава 6. Анатомия выдающейся VBA-программы

131

Допустимое

Недопустимое

а

ИмяБолее255СимволовНеПоместившеесяЗдесь...

Go4It

45coreAr.d7

You_Did_It

WhoDunlt?

СиниеГлаза

Черные Г л а з а

В программном коде все равно можно будет печатать имя переменной, используя как
прописные, так и строчные буквы. Например, в каждом из следующих трех операторов используется одна и та же переменная:
loudvariabie = "Ярко-красная"
lOuDvArlaBlE =Ucase(10UDvARIA3LE)
MsgBox(LoudVariable)
Конечно, слишком долго наслаждаться альтернативными версиями имени вам не удастся.
Редактор Visual Basic запоминает то имя, которое вы задаете в объявлении, и если вы напечатаете имя как-то иначе, оно будет автоматически скорректировано, как только вы перейдете
в другую строку.

Соглашения об именах в VBA
В рамках правил, обсуждавшихся в предыдущем разделе, объектам программы можно назначать любые имена. Тем не менее можно значительно облегчить себе жизнь в программировании, если придерживаться определенной логичной схемы выбора имен. По мере того как
ваши программы будут становиться длиннее, все труднее будет помнить о типе и назначении
каждой конкретной переменной. Поэтому имеет смысл научиться создавать имена, которые
смогут кое-что подсказать.
В идеале, нужно выбрать определенный метод и строго его придерживаться. Один такой
метод, используемый многими программистами, состоит в том, чтобы имя начиналось с некоторого префикса, соответствующего типу объекта, а за префиксом следовало сокращенное
описательное имя, которое начинается с прописной буквы. Например, если при создании
программы инвентаризации требуется целая переменная, в которой должен храниться инвентарный номер, то вполне подходящим именем для такой переменной будет i n t P a r t N o .
В табл. 6.1 приведены префиксы, рекомендуемые для часто используемых объектов VBA.
Вместо предложенных вы можете создать свои собственные или использовать их как суффиксы. Главное— непременно их использовать.
В главах 1-5 я не придерживался этих соглашений по той простой причине, что сначала
их нужно было объяснить. Но начиная с этой главы я постараюсь следовать тому, что здесь
проповедую.
Таблица 6 . 1 . Префиксы, рекомендуемые для имен объектов VBA
Префикс

Тип объекта

Пример

byt

Byte

bytDaysInMonth

bool

Boolean

booIClearedSta-cus

int

Integer

intWeeksOnChart

Переменные

132

Часть II. Курс программирования в VBA

Окончание табл. 8.1
Префикс

Тип объекта

Пример

Ing

Long integer

lngPopulation

sng

Single

sngRadius

dbl

Double

dblParsecs

сиг

Currency

curUnitPrice

str

String

strLastNarae

date

DateAime

dateBirthdate

var

Variant

varSerialNumber

obj

Object

obj StampCo11ection

txt

Text box (текстовое поле)

txtEnterName

Ibl

Label (надпись)

iblAnswerMessage

cmd

Command button (кнопка)

cmdCalculatelnterestRate

mnu

Menu (меню)

mnuTools

cmb

Combo box (поле со списком)

cmbioyCacegory

fra

Frame (фрейм)

fraHabitat

opt

Option button (переключатель)

optGasolineGrade

chk

Check box (флажок)

chkCaseSensiuive

bas

Module (модуль)

basTextFormatFunctions

frm

UserForm (пользовательская форма)

frmOptionsDialog

Переменные

Элементы управления

Другие

Саелашйе>чкогкаммлый tooa ккасивым
В обшем-то, программному коду совсем не обязательно выглядеть красиво — нужно, чтобы он легко читался. В этом разделе предлагается несколько простых рекомендаций по
оформлению программного кода для того, чтобы вам было легче расшифровать свой же программный код завтра, через неделю или в следующем году, если это потребуется.

Отступы в программе
Запомните: следует выработать правила использования отступов и неуклонно их придерживаться. Компилятор VBA игнорирует все пробелы в начале строк, так что вы можете смело использовать отступы для наведения порядка. Сравните следующие два фрагмента программного кода и решите, какой из них легче понять:
If i n t A = 27 Then
If t x t C h o o s e C o l o r . T e x t = "Беж" Then

Глава 6. Анатомия выдающейся VBA-программы

133

intA = 33
intB = 0
End If
For Each objCbar In CommandBars
If objCbar.Name = "Моя панель инструментов" Then
If objCbar.Visible = False Then
objCbar.Visible = True
iind If
End If
'•lext objCbar
End If
If intA = 2 7 Then
If txtChooseColor.Text = "Беж" Then
intA = 33
intB = 0
End If
For Each objCbar In CommandBars
If objCbar.Name = "Моя панель инструментов" Then
If objCbar.Visible = False Then
objCbar.Visible = True
End If
End If
Next objCbar
End If
Оба эти фрагмента дают один результат, но отступы во втором фрагменте позволяют сразу сказать для каждого из операторов E n d I f , какой из расположенных выше операторов
I f . . . T h e n будет ему парой. В результате легче отследить путь выполнения программы
в зависимости от сложившихся условий.

Правила для отступов
В каких же строках программного кода следует сделать отступ и какой по величине? Нужно установить отступы одного размера для связанных по смыслу операторов, чтобы связь между такими операторами была зрительно очевидной. Конкретнее говоря, операторы, выполняющиеся вместе при каком-то общем условии, должны иметь и одинаковые отступы.
Например, если VBA выполняет операторы внутри конструкции I f . . . T h e n . . . E l s e ,
Do . . . L o o p или F o r N e x t как одну группу, то операторы такой группы должны иметь один
и тот же отступ. Вот подходящий пример программного кода:

Do While intC 20
intA = intA + 1
If intA = intB Then
intA - 5
intB - 10
Else
intA = intB
intC = 20
End If
Loop
VBA выполняет оператор i n t A = i n t A + 1 иструктуру I f . . . T h e n . .. E l s e прикаждом
проходе структуры D o . . . Loop. По этой причине я использовал один и тот же отступ и для оператора i n t A = i n t A + 1, и для трех операторов, задающих структуру I f . . . T h e n . . . E l s e

134

Часть II. Курс программирования в VBA

( I f . . . T h e n , E l s e и End I f ) . Два оператора, следующие непосредственно за оператором
If . . . T h e n , будут выполняться, если только i n t A = i n t E , поэтому эти два оператора
получают пополнительным отступ, как и два оператора, следующие за E l s e .
Обратите внимание, что управляющие структуры типа Do . . . L o o p и I f . . . T h e n . . . E l s e
всегда состоят как минимум из двух операторов (один должен определить начало структуры,
а в т о р о м — ее конец). Дня структуры Do. . . L o o p завершающий оператор L o o p , а для
I f . . . Then . . . E l s e — это End I f . Если в рамках структуры есть другие операторы, для них
следует использовать тот же отступ. Это позволит ясно различить и саму структуру, и содержащиеся в ней подчиненные операторы. (Управляющие структуры будут подробно рассмотрены в главе 8.)

Как сделать отступ
Для добавления отступа в строке программного кода нажмите клавишу пробела или
, чтобы сдвинуть текстовый курсор вправо. Можно задать расстояние, на которое клавиша сдвигает курсор, если выбрать T o o l s ^ O p t i o n s . В диалоговом окне Options
(Параметры) на вкладке Editor (Редактор) есть поле Tab Width (Отступ табуляции), где можно впечатать число, соответствующее количеству пробелов. Поскольку пространства в окне
редактора Visual Basic не слишком много, лично я установил отступ табуляции, равный 3
пробелам, хотя можно указать любое число от 1 до 32.
Если по каким-то причинам нажимать клавишу табуляции вам не слишком удобно, всегда
можно сдвинуть начало строки вправо или влево с помощью предлагаемых VBA кнопок
Indent (Добавить отступ) и Outdent (Удалить отступ) соответственно. Эти кнопки применяются не только к отдельным строкам, но и к выделенным фрагментам текста, так что одним
щелчком можно добавить или убрать отступ целого блока. Обратите внимание на то, что при
использовании этих кнопок положение точки ввода в строке игнорируется — всегда увеличивается или уменьшается отступ сразу всей строки.

Автоматические отступы
Чтобы до минимума уменьшить объем выполняемой вами работы, редактор Visual Basic автоматически устанавливает отступ в новой строке, равный отступу в предыдущей. Если в новой
строке отступ должен быть меньше, просто нажмите клавишу удаления символа перед курсором
(клавишу •'-). Если навязанная помощь вас слишком уж раздражает, автоматическое создание отступов можно отменить на вкладке Editor в диалоговом окне Tools^Options.

Свободное пространство - это хорошо
Оставленные между группами родственных операторов пустые строки намекают
на важность выделенного таким образом фрагмента программного кода. Кроме
того, это уменьшает плотность программы и еще упрощает зрительное восприятие программного кода (рис. 6.2).

Не пользуйтесь прокруткой без необходимости!
Одна строка окна программного кода может содержать примерно 300 символов
(наверное, вы удивитесь, если я скажу, что максимальное число символов равно 308), так что
при желании можно вместить в одну строку довольно длинный оператор. Однако очевидно
и то, что удобнее иметь дело с операторами, полностью видимыми в рамках окна программного кода, когда текст в окне не приходится прокручивать туда-сюда.

Глава 6. Анатомия выдающейся VBA-программы

135

Использование символа продолжения строки
Чтобы продолжить оператор на следующую строку, поместите в конце текущей строки
символ подчеркивания ( ). Например, следующие три строки программного кода в совокупности определяют один оператор:

sngWackyNumber = Cos(12 * 57.5 / Sqr(intMyTinyNumber + _
intMyBigNuraber) •+- CustomDataMassage (sngRawInfo, 12) +
(bytFirstTuesdaylnAugust * curLastPayCheck] + 1)
He забудьте перед символом подчеркивания, который называют еще символом
продолжения строки, оставить пробел, поскольку без такого пробела вы получите
от VBA сообщение об ошибке типа "недопустимый символ" (invalid character).
И еше одно предостережение: следите, чтобы символ подчеркивания не оказался
внутри кавычек, определяющих строку текста (если, конечно, вы не собираетесь
включить символ подчеркивания в строку). Подробную информацию об использовании строк символов, включая и то, как можно продолжить их на новую строку,
вы найдете в главе 7.

Не используйте операторы в несколько строк
Хотя операторы в несколько строк и предпочтительнее длинных операторов в одну строку, не умещающихся в рамках окна программного кода, первые тоже нельзя назвать идеальными. Если VBA и не испытывает неудобств при обработке таких строк, то большинство людей воспринимают операторы в несколько строк как дополнительный источник путаницы.
Если окно программного кода не совсем уж микроскопическое, практически всегда можно разделить длинный оператор на несколько достаточно коротких, в совокупности выполняющих ту же работу, что и исходный. Возможно, для этого потребуется создать несколько
дополнительных переменных, в которых будут храниться результаты промежуточных вычислений, но это не слишком большая цена за достижение лучшей прозрачности программного
кода. Например, предыдущий пример программного кода можно переписать так:

sngTempl = Sqr(intMyTinyNumber + intMyBigNumber)
sngTemp2 = 12 * 57.5 / sngTempl
sngTemp3 = CustomDataMassage(sngRawInfo, 12)
sngTeinp4 = bytFirstTuesdaylnAugust * curLastPayCheck
sngWackyNumber = Cos(sngTemp2 + sngTemp3 + sngTemp4 + 1)
Этот фрагмент программного кода длиннее и использует несколько дополнительных переменных, но зато за представленными в этом фрагменте вычислениями легче следить. Кроме того, если
результат вычислений окажется неправильным, для локализации ошибки можно будет проследить
за каждым шагом вычисления в отдельности— ясно, что подобный пошаговый анализ невозможен, когда результат вычисления является результатом выполнения одного длинного оператора.
(Подробно приемы пошагового выполнения программного кода разбираются в главе 9.)

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

136

Часть It. Курс программирования в VBA

Ваши комментарии компилятор VBA будет полностью игнорировать. Они живут
только в текстовом файле, содержимое которого представлено в окне программного кода, но не в откомпилированной программе. Комментарии не увеличивают
откомпилированную программу ни на бит, а также никоим образом не замедляют
ее выполнение. Комментарии не будут стоить вам ничего, кроме мизерного объема дискового пространства, так что используйте их совершенно свободно.

Как создавать комментарии
Комментарий начинается с напечатанного вами апострофа. Все, что напечатано в строке
программного кода справа от апострофа, считается комментарием. Для комментария можно
выделить отдельную строку, а можно и добавить его в конец строки с активным программным кодом. Пример окна программного кода с множеством комментариев, добавленных после операторов, показан на рис. 6.2.

П р и м е р или г л а в ы B i t s - О Б у ч а п щ и й А в т о м а т (Code)
^ji'JDIsplayGueetlon
Public sub Display^uestion()
Sel e c t N e x t Q u e s t i o n
•vc



: ; . " I V , T : - т >

p

' Ь ^ Г О Е - n ; M I ",;,.•;'• д - " ^ r-,;,—•••.-.
'

':'•!'' d T h e n ' н а ч а л о вложенной с т р у к т у р ы I f . . . T h e n
d = a

End If ' конец внутренней структуры If...Then
Lcop ' конец цикла Do While...Loop
End If ' конец внешней структуры If...Then

Используйте отступы!
Правильное использование отступов служит основой создания понятного программного кода. В примере из предыдущего раздела каждая пара операторов, определяющих одну структуру, напечатана с одним и тем же отступом. При наличии отступов проще выяснить, например, какому из операторов I f . . . T h e n соответствует
данный оператор End I f . Операторы, выполняемые в рамках данной структуры,
тоже имеют один и тот же отступ, поэтому сразу видно, что все они находятся под
юрисдикцией одной структуры.

Глава 8. Управление потоком

165

на использование целебных
Несмотря на простоту концепции, управляющие структуры можно отнести к наиболее мощным средствам программирования. С одной стороны, эти структуры "только"
выбирают, какой из двух различных блоков программного кода следует выполнить.
Но, с другой — когда в результате один блок программного кода выполнен, а другой —
нет, вы имеете полное основание повторить за Фростом: "Это и явилось причиной
всех различий".
Чтобы решить, выполнять ли некоторый блок программного кода, три следующие управляющие структуры VBA оценивают предложенное вами условное выражение: Do . . . Loop,
I f . . .Then и S e l e c t Case. Весь последующий материал этого раздела посвящен использованию условных выражений в этих структурах. Две другие структуры, F o r . . . Next
и For E a c h . . . Next, условных выражений не используют.

Как работает условное выражение
Структуры I f . . . T h e n , S e l e c t C a s e и Do . . . L o o p принимают решение о последующих действиях на основе простого теста: какое значение принимает выражен и е — T r u e (Истина) или F a l s e (Ложь)? Условием здесь может быть любое выражение VBA. (Не забывайте, что в VBA 0 эквивалентен F a l s e , а все другие значения рассматриваются как True.)
Чаще всего условные выражения строятся на основе какой-нибудь операции сравнения, применяемой к двум другим выражениям, входящим в данное. Набор операций
сравнения, доступных для использования в VBA, достаточно подробно обсуждался
в главе 7. Но основные идеи видны и из примеров операторов, помещенных в следующую таблицу. Каковы эти выражения — истинные или ложные? Это только управляющим структурам известно.
Выражение

Перевод на русский язык

а < b

а меньше b

b = с

Ь равно с

colTBears ("Генри")
o b j Cur r e n t Bear

Is

s q r ( l / x * 2 9 . 3 2 3 4 ) >=
CDbl ( s t r N u m b e r ) + 12

Объект, хранящийся в коллекции c o l T B e a r s под именем
" Г е н р и " , является тем же самым объектом, что и объект,
на который ссылается переменная o b j C u r r e n t B e a r
Квадратный корень величины, равной 1, разделенной на х
и умноженной на 29,3234, не меньше числового значения
строковой переменной s t r N u m b e r плюс 12

Условные выражения без операторов сравнения
Большинство условных выражений включают операции сравнения, но ничто не мешает
создать условия, не использующие такие операции. Прежде чем привести примеры, не помешает подвести под них некоторую теоретическую базу.

166

Часть И. Курс программирования на VBA

Этот вопрос обсуждается здесь не для того, чтобы заставить вас создавать условные выражения, не использующие операций сравнения, а просто потому, что такие выражения создают многие программисты. Часто такие условные выражения
присутствуют в текстах программ, публикуемых в компьютерных журналах
и представленных в Internet. Но пока вы занимаетесь освоением VBA, я рекомендую вам включать операции сравнения в условные выражения хотя бы для ясности программного кода, даже если такие операции и не необходимы.
Теперь о деталях. Как вы знаете, значением логической переменной всегда является либо
True, либо F a l s e . Поэтому выражение
Ьоо1До13 ' это значение либо True, либо F a l s e
вполне подойдет в качестве условия в условном выражении, как, например, в случае
If Ьоо1До18 Then
ПредоставитьСкидку
End I f
Но T r u e и F a l s e имеют числовые значения, а поэтому в качестве условия можно использовать и любое числовое выражение. Все следующие выражения подходят для использования в качестве условий:
1234 ' всегда True
О ' всегда F a l s e
True ' зеегда True
F a l s e ' всегда F a l s e
intHowManyPets ' F a l s e , если intHowManyPets = 0
ingA + lngB + lngC ' F a l s e , если сумма = О
Свойства объектов часто представляют логические значения, поэтому в качестве условий
нередко используются выражения типа f rmHelpWindow. E n a b l e d и безо всяких операций сравнения.
Нельзя использовать строки и объекты в качестве условий сами по себе, хотя они
вполне годятся для использования в качестве компонентов выражений, построенных на основе подходящей операции сравнения.

Использование логических операций в условиях
Логические операции (см. главу 7) сначала оценивают значения входящих в выражение двух
выражений-компонентов как True или F a l s e , а затем, в соответствии с определенными правилами, на основе этих значений получается конечный результат— тоже True или F a l s e .
Самыми важными логическими операциями (точнее, теми из них, использование которых
проше всего объяснить) будут And, Or и Хог. Следующая таблица объясняет, что эти операции выполняют.
Операция

Возвращает T r u e

Примеры

Результат

And

Только если оба выражения
принимают значения T r u e

3 * 2 = 6
And 12 > 11

True

2 + 2 = 4
And 4 - 2 = 1

False

Глава 8. Управление потоком

167

Операция

Or

Примеры

Возвращает T r u e

Если хотя бы одно из двух выражений принимает значение T r u e

Хог

Если только одно из двух выражений принимает значение T r u e

10 > 20 Or 20

Результат

True

> 10

5 < 4 Or 6 < 5

False

5 + 5 < 9
Х о г 5 + 5 = 10
5 + 5 > 9
Хог 5 + 5 = 10

True
False

Если желаете, можете использовать две логические операции в одном условном выражении. Полюбуйтесь, например, таким выражением:
(а + b > 20 And с = 10) Or (objDoor.Open)
В переводе на русский язык этот фрагмент программного кода можно прочитать так:
"Данное выражение есть истина, когда либо
а + Ь больше, чем 20, а с равно 10,
либо

свойство Open объекта obj Door принимает значение True".
Я советовал бы не перегружать одно выражение несколькими логическими операциями, разве
что вы настолько сообразительны, что вам вообще не нужен компьютер. А чтобы гарантировать
применение операций именно к тем выражениям, к которым нужно, используйте скобки. В предыдущем примере скобки вокруг выражения o b j Door. Open гарантируют, что именно это выражение будет участвовать в операции Or первым.

Условные oneftcunoftbi Jf.. Укен
Условные операторы I f . . . T h e n , а также их вариации I f . . . T h e n . . . E l s e
и I f . . . E l s e l f используются значительно чаще любых других операторов. Довольно
часто операторы I f . . .Then встречаются и в других главах, но в этой они уж точно
в центре внимания.

Основная форма If...Then
Оператор If . . . Then выполняет некоторый блок программного кода, если условие, которое вы предложили этому оператору, принимает значение True, и не делает ничего, если
условие принимает значение F a l s e . Синтаксис оператора следующий:
If условие Then
(операторы, выполняющиеся, когда условие = True)
End If
Простой пример использования оператора I f . . .Then можно найти выше в разделе
"Анатомия управляющих структур" этой главы.
Обратите внимание на следующие моменты, касающиеся операторов I f . . . Then.
I S Здесь у с л о в и е должно быть условным выражением типа описанных выше в разделе
I
"Курс на использование условных выражений". Если у с л о в и е принимает значение
I
True, то VBA выполнит операторы, размешенные между I f . . . T h e n n E n d If.

168

Часть И. Курс программирования на VBA

IS
I
I
|^
I

Обратите внимание, ключевое слово Then размещается в одной строке с If и выражением условие. При размещении Then в следующей строке (без указания переноса с помощью символа подчеркивания в первой) VBA генерирует ошибку.
Не забывайте печатать завершающий оператор End If, При его отсутствии VBA не
поймет, какой оператор должен быть последним в блоке.

Однострочные операторы If...Then
Если структура I f . . .Then должна выполнить только один оператор, когда условие
принимает значение True, всю эту структуру можно уместить в одну строку. В таком случае
оператор End I f не требуется — точнее, его быть не должно. Оператор
If сигЦена > 20 Then MsgBox "Цена слишком в ы с о к а ! "
в результаге идентичен структуре
If сигЦена > 20 Then
MsgBox "Цена слишком в ы с о к а ! "
End I f

Операторы If...Then...Else
Если нужно, чтобы на основании одного условия программа выбирала между двумя альтернативными блоками программного кода, используйте оператор I f . . . T h e n . . . E l s e .
В том случае, если условие принимает значение T r u e , то выполняется один блок программного кода, а если условие принимает значение F a l s e , то выполняется другой. Вот формальный синтаксис этого оператора:
If условие Then
(операторы, выполняющиеся, когда условие = True)
Else
(операторы, выполняющиеся, ко^да условие = False)
End If
Если условие имеет значение True, VBA выполняет первый блок операторов и, пропустив все остальные операторы структуры, переходит к строке программного кода, следующей сразу за оператором End If. А если у с л о в и е имеет значение F a l s e , то выполняются только операторы, следующие за оператором E l s e .
В следующем примере выражение у с л о в и е проверяет, является ли элемент управления
в форме кнопкой. При положительном результате фон кнопки закрашивается красным цветом, все другие элементы управления — голубым:
If TypeOf ctlCurrentControl Is CommandButton Then
ctlCurrentControl.BackColor = &HFF& ' красный
Else
ctlCurrentControl.BackColor = &HFFFF00& ' голубой
End If
В этом примере предполагается, что переменная c t l C u r r e n t C o n t r o l уже содержит
ссылку на соответствующий объект в форме. Ключевое слово TypeOf позволяет проверить,
является ли объект, на который ссылается переменная, объектом нужного типа— в данном
случае объектом CommandButton.

ИспользованиеоператоровIf...Then
Часто, прежде чем принять решение о действиях, которые должна выполнить программа, приходится проверять два или даже больше условий. Э т о — как в жизни. Когда вы пишете книгу по

Глава 8. Управление потоком

169

VBA, то можете рассуждать примерно так: "Если я успею закончить книгу к установленному сроку
и если не закончатся деньги, а также если курс рубля к доллару не изменится, то я смогу слетать
в октябре на пару недель в Америку. Но если рубль упадет, то мне придется ехать в Тамбов11.
В зависимости от ситуации, при этом потребуется добавить в структуру I f . . .Then
ключевые слова E l s e l f или вложенные структуры If . . .Then.

Использование If... Elself
Используйте ключевое слово E l s e l f , чтобы проверить дополнительное условие, если вы
хотите выполнять определенные операторы только в случае, когда первое условие не принимает значение T r u e . Ниже представлен синтаксис такой структуры:
If условие! Then
(операторы, выполняющиеся, когда условие! = True)
E l s e l f условие2 Then
(операторы, выполняющиеся, когда условие! = F a l s e ,
а условие2 = True)
E l s e l f условиеЗ Then
(операторы, выполняющиеся, когда условие!
и условие2 = F a l s e , а условиеЗ = True)
. .. (другие операторы E l s e l f )
E l s e ' необязательное ключевое слово
(операторы, выполняющиеся, когда все условия = F a l s e )
End I f
При этом ключевое слово E l s e l f в структуре может повторяться любое число раз.
Ключевое слово E l s e необязательно, но если оно присутствует, то должно быть
в структуре последним,
Чтобы заставить работать этого монстра, представьте себе, что программа помогает вам
вести учет в магазине по продаже фотоматериалов. Пленку, срок хранения которой истек,
следует списывать и не учитывать в дальнейшем. Если же пленка еще не просрочена, ее нужно учесть в общем количестве пленок соответствующего типа.
Это делается в следующем фрагменте программного кода. Предполагается наличие объекта,
представляющего ролик с пленкой, и наличие у этого объекта свойств для даты истечения срока
хранения, типа пленки и признака цветности (как альтернативы черно-белого варианта).
If objRollOfFilm.ExpDate < Date Then
MsgBox "Эта пленка не годится."
Elself objRollOfFilm.Type = "Слайдовая" Then
int-Слайдовые = 1п!:Слайдовые + 1
Elself objRollOfFilm.Color Then
intUBeTHbieHeraTHBHHe = 1п1:ЦветныеНегативные + 1
Else
intHBHeraTMBHbie = 1п1ЧБНегативные + 1
End If
Первый оператор сравнивает значение свойства ExpDate (срок хранения) с текущей датой.
Если дата окончания срока хранения уже прошла, программа отображает окно сообщения с соответствующей информацией, и это все. Только если пленка все еще годится (т.е. если первое условие принимает значение F a l s e ) , будет выполнен первый из операторов E l s e l f . Этот оператор
проверяет свойство Туре (тип) объекта, представляющего пленку. Если значением свойства является " С л а й д о в а я " , то следующий оператор увеличивает счетчик слайдовых пленок.
Если же пленка другого типа, программа переходит к следующему оператору E l s e l f ,
в котором в качестве условия рассматривается свойство C o l o r (без операций сравнения,

170

Часть //. Курс программирования на VBA

в предположении, что это свойство может принимать только значения T r u e или F a l s e ) .
Если значением свойства будет T r u e , то пленка учитывается как цветная негативная, а если
значение F a l s e , остается только перейти к выполнению E l s e — больше некуда— и учесть
пленку как негативную черно-белую.
В структуре I f . . . E l s e l f выполняются только операторы, ассоциированные с
первым принимающим значение T r u e условием. После выполнения этих операторов все оставшиеся E l s e l f и E l s e пропускаются.

Вложение операторов if... Then
Вложенные операторы I f . . . T h e n в некотором смысле являются противоположностями операторов I f . . . E l s e l f . Используйте эти операторы, когда для принятия решения
нужно проверить дополнительное условие, но только если первое условие принимает значение T r u e . Вложение одного оператора I f . . . T h e n в другой подобно высказыванию: "Если
X есть И с т и н а и Y есть И с т и н а , то я буду делать А, В и С".
Можно вкладывать один в другой операторы I f . . . T h e n любых видов —
I f . . . T h e n . . . E l s e , I f . . . E l s e l f и разнообразные I f . . . T h e n — и в любой комбинации. Вот схематическое представление пары вложенных операторов I f . . . T h e n :
If

условие! Then
If условие2 Then
(операторы, выполняющиеся, когда условие! и условие2 = True)
Elself условиеЗ Then
(операторы, выполняющиеся, когда условие! и условиеЗ = True,
а условие2 = False)
(операторы, выполняющиеся, когда и условие1
и условие2 = False, а условиеЗ = True)
End If ' конец внутреннего блока I f . . . T h e n
(другие операторы, выполняющиеся, когда условие! = T r u e ,
независимо от т о г о , чему равно условие2)
Else
(операторы, выполняющиеся только т о г д а , когда условие! = F a l s e )
End I f
Следующий простой пример программного кода с использованием вложенных операторов I f . . . Then отображает окно с поощрительным сообщением за высокие оценки и необходимый минимум часов классной работы:
If sngGPA > 3.5 Then
If sngUnits > 10 Then

MsgBox "Вы в поощрительном списке декана!"
End If
End If

Использование логических операций в условиях
Использование логических операций в условных выражениях может быть более элегантной альтернативой использованию E l s e l f и вложенных If . . . T h e n , когда нужно выполнить лишь одну ветвь пути, определяемого множеством условий.
Взгляните снова на последний фрагмент программного кода из предыдущего раздела. Ту же задачу можно выполнить с помощью лишь одного оператора I f . . . Then, как здесь:

Глава 8. Управление потоком

171

If sngGPA > 3.5 And sngUnits > 10 Then
MsgBox "Вы в поощрительном списке декана!"
End If
Условные выражения с логическими операциями не помогут, когда необходимо использовать несколько ветвей пути решений. Попробуйте с помощью логических операций свести
к примеру, подобному приведенному выше, следующий случай:
If sngGPA > 3.5 Then
If s n g U n i t s > 10 Then
MsgBox "Вы в поощрительном списке д е к а н а ! "
Else
MsgBox "Неплохо для прогульщика!"
End If
End I f
Мне на ум приходит только одно решение, все равно требующее двух операторов
I f . . . Then, хотя и не вложенных:
If sngGPA > 3.5 And s n g U n i t s > 10 Then
MsgBox "Вы в поощрительном списке д е к а н а ! "
End I f
If sngGPA > 3.5 And sngUnits с
то з н а ч е н и е можно определить как часть выражения, находящуюся слева от знака операции сравнения (а + Ь), а все, что останется, включая знак операции, — это критерийЫ (> с).

Пример оператора Select Case
Здесь явно не помешает пример, показывающий, как в действительности может выглядеть
структура S e l e c t Case.
S e l e c t Case o b j R o l l O f F i l m . T y p e
Case "Слайдовая"
intCJiafiflOBbie = 1п1:Слайдовые + 1
Case "Цветная н е г а т и в н а я "
1п1ЦветныеНегативные = Л-Г^ЦветныеНегативные + 1
Case "ЧБ н е г а т и в н а я "
intHBHeraTHEHbie = Л-Г^ЧБНегативные + 1
Case E l s e
MgaBox "Неизвестный тип п л е н к и . "
End S e l e c t
В основном этот фрагмент программного кода делает то же, что и приведенный выше
программный код для примера из раздела об операторах I f . . . E l s e l f (опущена только
проверка срока хранения). Правда, с тех пор наш гипотетический объект, представляющий
ролик пленки, похоже, был немного модифицирован — информация о цветностибесцветности пленки теперь тоже представляется свойством Туре, а не отдельным свойством C o l o r , как раньше.
А если дело обстоит таким образом, то программе приходится работать только с одним
значением — со значением, возвращаемым свойством Туре. — но сравнивается это значение
с несколькими из допустимых. Так что S e l e c t Case — это как раз то, что для нашего случая доктор прописал.
Первое применение оператора Case в данном примере эквивалентно применению If
o b j R o l l O f F i l m . Type = " С л а й д о в а я " Then, т.е. если свойство Туре объекта равно " С л а й д о в а я " , то программа выполняет следующий оператор, в противном случае она
перейдет ко второму оператору Case.
Заметьте, что знака операции, присутствие которого кажется на первый взгляд логичным, в критериях нет. Причина в том, что в операторах S e l e c t Case равенство
в качестве операции сравнения просто подразумевается.

Оператор Case Else
Если значение свойства Туре не будет удовлетворять ни одному из критериев в операторах Case, то управление перейдет к оператору Case E l s e , который всегда находится
в самом конце структуры S e l e c t Case. В предыдущем примере результатом этого будет
сообщение об ошибке "Неизвестный тип п л е н к и " . Оператор C a s e E l s e необязателен, поскольку вполне вероятно, что вас устроит отсутствие всякой реакции на неудовлетворение всех критериев. Как и в данном примере, обычно нет никакой необходимости использовать оператор Case E l s e , разве что для того, чтобы программист проинформировал самого себя о не предусмотренных им значениях, хранящихся в программе.

Глава 8. Управление потоком

173

Дополнительные сведения об операторе Case
В предыдущем примере критерии, заданные в операторах Case, были просто цветочками, детскими вопросами типа "Равно ли свойство Туре тому-то и тому-то?" Но с помощью
оператора C a s e вы можете задавать и значительно более сложные критерии.
Это проще всего показать на примере с числами. Предположим, ваш оператор S e l e c t
Case открывается следующей строкой программного кода:
S e l e c t Case 1п^ВозрастПациента
В данном случае значением для сравнения будет переменная целого типа i n tBo3pacrnauMeHTa, представляющая возраст пациента клиники. В следующем списке
представлено несколько типов сравнения, которые можно реализовать с помощью операторов Case, и приводятся соответствующие примеры.
I S Можно сравнить тестовое значение с некоторым диапазоном значений, как в случае
1
Case 18 То 35
i
Messages("ВзрослыйМолодой").Print
I •/ Обратите внимание на ключевое слово То, размещенное между значениями, опредеI
ляющими границы диапазона. Сам диапазон включает и эти значения, и те, которые
1
находятся между ними.
1
I •/ Можно сравнивать значения и с помощью операций сравнения, отличных от операции =, как в случае
Case Is > 65
Messages("ВзрослыйПожилой").Print
Здесь предполагается использовать перед операцией сравнения ключевое слово I s .
На самом деле вы можете Is и не печатать— если вы его пропустите, VBA вставит
это ключевое слово за вас.
Можно в одном операторе C a s e указать несколько критериев для сравнения, как
в случае
Case 0 То 5, 15, Is > 55
Messages("НапоминаниеОПрививке").Print
He забудьте разделить критерии для сравнения запятыми. Кстати, оператор Case
с несколькими критериями эквивалентен выражению, построенному на основе использования операции Or, — если тестируемое значение удовлетворяет хотя бы один
из критериев, следующие за Case операторы будут выполнены.

с помещаю циклов
Управляющие структуры типа "цикл" используются тогда, когда необходимо повторить выполнение некоторого блока программного кода несколько раз. Повторение одного или нескольких операторов является главным средством выполнения многих математических вычислений, извлечения небольших порций данных из больших, применения одних и тех же действий по отношению к каждому из множества элементов
некоторой группы.
VBA предлагает три типа структур, организующих циклы.

1 74

Часть И. Курс программирования на VBA

Тип цикла

Особенности работы

Do. . .Loop
F o r . . .Next
For Each. .. Next

Пока или до тех пор, пока некоторое условие имеет значение True
Заданное число раз
Для каждого объекта из коллекции объектов

При работе с вложенными циклами помните простое правило: внутренний цикл
должен закончиться прежде, чем закончится внешний.

Циклы Do
Все возможные версии оператора Do . . . L o o p предназначены для повторения заданного
блока программного кода неопределенно долго, пока не будет выполнено некоторое условие.
Для того чтобы выяснить, продолжать цикл или нет, оператор Do . . . L o o p оценивает заданное условное выражение типа условных выражений, используемых для оператора
I f . . . T h e n и описанных выше в разделе "Курс на использование условных выражений".
Случаев, когда структуры D o . . . L o o p полезны, просто не счесть. Вот несколько примеров.
1 •/ Отображение сообщения об ошибке снова и снова, пока пользователь не введет подходящую информацию в диалоговое окно.
S Чтение данных из файла на диске, пока не будет обнаружен конец файла.
S Поиск и подсчет числа вхождений некоторой строки символов в более длинной строке.
0 писать просто Do While i n t O r i g i n a l N u m b e r — оба
варианта работают одинаково.
В самом цикле простая процедура в три строки разбирает цифры исходного числа, начиная справа налево, и использует их в обратном порядке для построения новой строки. Чтобы
понять, как работает цикл, не обязательно разбираться в программном коде внутри цикла, но,
я думаю, следующие пояснения вам не помешают.
I •/ В первой строке используется операция Mod, чтобы присвоить переменной i n |
t O n e D i g i t остаток от деления числа на 10. Поскольку число делится на 10, остатком
I
будет однозначное число, представленное последней (справа) цифрой исходного числа.
I^
|
I S
f
v
I
I
I
\S
|
|
|
;

Во втором операторе цифра, полученная в первой строке, добавляется в конец создающейся новой строковой величины.
В третьем операторе число снова делится на 10, но на этот раз результат сохраняется
в исходной переменной. При таком делении просто отбрасывается правый знак числа.
Заметим, однако, что перед тем, как результат присваивается переменной, он обрабатывается функцией I n t . Использование функции I n t здесь необходимо, поскольку
в противном случае результат был бы округлен и это изменило бы знаки числа по
сравнению с введенными изначально.
В процессе прохода цикла значение i n t O r i g i n a l N u m b e r уменьшается и наконец
становится равным 0 после того, как все цифры будут обработаны (любая цифра задает число, меньшее 10, а функция I n t отбрасывает дробную часть числа). В стране
VBA нуль означает F a l s e , поэтому цикл завершится, и программа покажет число
с обратным расположением цифр.

Другие операторы Do
Разобравшись в базовой форме оператора Do W h i l e . . .Loop, несложно понять и его
вариации В этом разделе рассмотрены три варианта циклов Do, четвертый обсуждается ниже, в разделе "Когда использовать Do без While или U n t i l " .
D o . . . Loop While
Разница между операторами Do W h i l e . , .Loop и Do. . .Loop While очень простая: Do W h i l e . . . Loop имеет условие в самом начале цикла, а в D o . . . Loop While
условие идет в самом конце.
В структуре Do While . . . Loop вход в цикл происходит вообще, только если условие
принимает значение True, когда программа впервые обращается к циклу. Если сначала условие принимает значение F a l s e , цикл не выполнится ни разу.
В структуре Do. . .Loop While, напротив, цикл всегда выполняется по крайней мере
один раз, поскольку сначала программа проходит весь блок программного кода, а лишь затем
выполняется проверка условия, чтобы повторить выполнение операторов цикла, если условие
окажется равным True. Используйте структуру Do . . . Loop While тогда, когда значение
условия для проверки устанавливается в блоке программного кода цикла.

Глава 8. Управление потоком

177

Другим случаем, когда подходящим решением оказывается структура D o . . . L o o p
W h i l e , является обработка объекта (типа строки или массива), в котором больше одного
элемента. Если вы точно знаете, что элементов не меньше одного, можно допустить выполнение операторов цикла один раз, а затем повторять выполнение столько раз, сколько нужно
для оставшихся компонентов.
Do Until...Loop
Операторы Do W h i l e . . .Loop и Do U n t i l . . .Loop функционально эквивалентны, т.е. с помощью любого из них будут выполняться одни и те же операторы, если используемые в них условные выражения представляют противоположные условия. Подобным образом дополняют один другой и операторы Do
W h i l e . . .Loop и Do U n t i l . . . Loop.
Представьте себе, что вы ведете передачу по кулинарии и рассказываете своим слушателям рецепт. Вы можете сказать: "Продолжайте вымешивать масло, пока в нем заметны неоднородности" или "Продолжайте вымешивать масло до тех пор, пока оно не станет совершенно однородным". И первое, и второе означают одно и то же.
Подобным образом взаимно дополняются операторы Do While и Do U n t i l . Если
в операторе Do While условием является А = В, то эквивалентным ему оператором будет
Do U n t i l с условием А о В.

Do или не Do
Цикл Do в своем условном выражении обеспечивает всю необходимую информацию, на
основании которой VBA может принимать решение о продолжении или завершении выполнения цикла. К сожалению, в реальности дело не всегда обстоит так идеально, и иногда изменение другого условия внутри цикла требует немедленного выхода из цикла, для чего в VBA
предусмотрен оператор E x i t Do.
Действующий только внутри цикла Do, оператор E x i t Do немедленно прекращает
выполнение цикла и передает управление оператору, следующему сразу после цикла.
В следующем примере выполняется конкатенация строковой переменной с некоторой имеющейся строкой, но если переменная содержит больше одного символа, цикл
прекращается:
Do While strA 1 Then
Exit Do
End If
strB = strB & strA
strA = GetNextCharacter
Loop
Обычно необходимость в операторе E x i t Do может возникнуть только во
вложенных в цикл операторах I f . . . T h e n и S e l e c t C a s e . В этих случаях цикл выполняется нормально до тех пор, пока не происходит что-то особое или не появляется непредусмотренное значение. Оператор E x i t Do
можно использовать также и для отладки, для временной отмены выполнения цикла, чтобы не размещать апостроф ( ' ) в начале строк целого блока
программного кода.

178

Часть II. Курс программирования на VBA

Когда использовать Do без While или Until
В стандартных операторах Do W h i l e / U n t i l . . . L o o p условие можно проверять либо
в начале, либо в конце цикла. Но что делать, если вы хотитепроверить некоторое условие
внутри цикла?
В этом случае используйте оператор D o . . . L o o p без W h i l e и U n t i l . Но при этом вам
понадобится вложить в цикл либо оператор I f , либо S e l e c t C a s e . Вложенный условный
оператор может содержать оператор E x i t Do, что позволит программе прекратить выполнение цикла, когда заданное условие окажется выполненным.
Вот схематическое представление оператора Do . . . L o o p :
Do
(операторы, выполняющиеся при каждом проходе цикла)
If условие Then
Exit Do
End If
(операторы, выполняющиеся, только если цикл продолжает выполняться)
Loop
Как видите, эта техника годится в том случае, когда нужно выполнить некоторые операторы в цикле, независимо от выполнения или невыполнения условия, а также если выполнение цикла необходимо прервать в зависимости от некоторого другого условия.
Например, часто приходится проверять правильность введенных пользователем данных
относительно целого ряда критериев. В следующем примере с помощью структуры
D o . . . Loop цикл ввода повторяется до тех пор, пока пользователь не введет правильную
букву ответа:
Sub GetAnAnswer()
Dim strAnswer As S t r i n g
strAnswer = InputBox("Enter your answer

(A-E)")

Do
If strAnswer = "" Then
strAnswer = InputBox("You d i d n ' t e n t e r a n y t h i n g . "
& " Please type a l e t t e r between A and E.")
E l s e l f Len(strAnswer] > 1 Then
strAnswer = InputBox("Your answer should be" _
& " only one l e t t e r long.

Please t r y a g a i n . " )

E l s e l f strAnswer < "A" Or strAnswer > "E" Then
strAnswer = InputBox("You typed an i n v a l i d " _
& " c h a r a c t e r . Type a l e t t e r from A to E.")
Else
Exit Do
End

If

Loop
End

Sub

Эта программа выполнит оператор E x i t Do только тогда, когда все три условия, заданные в операторах I f n E l s e l f , будут выполнены.

Глава 8. Управление потоком

179

В качестве альтернативы для достижения той же цели можно предложить использовать Do While T r u e в первой строке структуры, задающей цикл. Поскольку T r u e (константа) всегда имеет значение True, условие всегда выполняется, и, следовательно, VBA обязательно начнет и будет продолжать выполнять
цикл. Поэтому, для того чтобы завершить выполнение такого цикла, внутри него
должен присутствовать оператор E x i t Do.

Повторение под управлением циклов For...Next
Если уже перед выполнением цикла известно, сколько раз он должен выполняться, используйте
цикл F o r . . . Next. Число проходов цикла задается значениями начало и коней, которые могут быть целыми числами, переменными и даже сложными выражениями. В процессе выполнения
цикла переменная счетчик хранит информацию о числе выполненных проходов цикла. Когда
значение счетчика становится равным значению конец, выполнение цикла завершается.
Упрощенно синтаксис структуры F o r . . . Next можно представить так;
For счетчик = начало То конец
(операторы, выполняющиеся при каждом проходе цикла)
Next счетчик
В следующем примере для отображения сообщения при каждом проходе цикла в процедуре используется окно Immediate (в редакторе Visual Basic окно Immediate открывается
нажатием клавиш ):
Sub CountToTen()
Dim j As I n t e g e r
For j = 1 To 10
Debug.Print "Дубль № " & j
Next j
End Sub
В этом примере н а ч а л о и конец являются буквальными числовыми значениями. Когда
цикл начинается, j получает значение 1; другими словами, переменной с ч е т ч и к присваивается значение н а ч а л о . После каждого прохода цикла оператор Next j увеличивает значение j (на 1) и отсылает управление снова в начало цикла. Когда j достигает значения 10, выполнение цикла прекращается.

Важные замечания по поводу циклов For.. .Next
Старайтесь, чтобы ваш программный код всегда оставался понятным. Используйте 1 в качестве начального значения для цикла F o r . . . Next, если только у вас нет серьезных причин выбрать для этого другое число.
Такие серьезные причины на самом деле бывают, например, когда значение счетчика используется в самом цикле (но, уточню, не меняется в цикле). Если в цикле предпринимаются некоторые
действия по отношению к последовательно пронумерованным элементам типа номеров страниц,
то в качестве значений для величин начало и конец можно использовать реальные значения
номеров этих элементов. В частности, при работе с массивами обычно начало выбирается равным 0 (подробности -— в следующем разделе).
В операторе Next счетчик, завершающем цикл F o r . . . Next, имя переменной-счетчика указывать не обязательно — ключевое слово Next автоматически
вычислит следующее значение счетчика и отошлет VBA в начало структуры. Однако определенно стоит приучить себя включать имя счетчика в оператор Next.
Тогда даже в случае нескольких вложенных циклов F o r . . . N e x t вы всегда

180

Часть //. Курс программирования на VBA

сможете с первого взгляда сказать, какому циклу принадлежит данный оператор
N e x t . He меняйте значение счетчика внутри цикла F o r . . . N e x t . Поскольку
счетчик является обычной переменной, м о ж н о — а иногда и заманчиво— создать программный код, меняющий значение счетчика. Не поддавайтесь!
Стоит ошибиться со счетчиком и можно пропустить пару важных шагов или заставить цикл выполняться бесконечно.

Хотя и можно значение к о н е ц для цикла F o r . . . N e x t задать переменной, изменение значения такой переменной после начала выполнения цикла не повлияет на процесс выполнения. Цикл
все равно будет выполнен столько раз, сколько задано оригинальным значением к о н е ц .

Циклы For... Next и массивы
Циклы F o r . . . N e x t особенно полезны при работе с массивами, именованными хранилищами для множеств элементов данных. Подробно массивы обсуждаются в главе 13, но дискуссия о циклах F o r . . . N e x t осталась бы неполной без нескольких слов о пользе таких циклов
в совокупности с этими имеющими большое практическое значение корзинами для данных.
С помощью цикла F o r . . . N e x t несложно заполнить массив множеством вычисленных
значений, как в следующем примере:
Dim 1 г ^ М а с с и в К в а д р а т о в (14) As I n t e g e r
F o r a = 0 To 14
intMac-сивКвадратов(a) = a * a
Next a
Этот пример программного кода начинается с объявления массива из 15 целых значений
(15, а не 14, поскольку обычно VBA приписывает первому элементу' в массиве индекс 0). Затем используется цикл F o r . . . N e x t , в котором каждому элементу массива, от 0 до 14, присваивается значение. Обратите внимание на то, что переменная а используется не только как
счетчик, но и как индекс массива, указывающий на номер элемента в массиве.

Вложенные циклы For... Next
Подобно другим управляющим структурам VBA, циклы F o r . . . N e x t можно вкладывать один в другой — или в другие управляющие структуры, —- так глубоко, как это необходимо. Следующий совершенно бесполезный фрагмент программного кода иллюстрирует эту
возможность:

Dim sng~ ' наверное, С означает "случайное число"
Randomize ' инициализация генератора случайных чисел
For А = 1 То 5
sngC = Rnd()
For В = 1 То 5
Debug.Print sngC * Rnd()
Next В
Next A
Если вы достаточно наблюдательны, то без труда сможете проследить за шагами, которые
делает VBA в процессе выполнения этого программного кода.
1.

Предварительная подготовка.
Программный код начинается с объявления переменной и инициализации генератора
случайных чисел VBA.

Глава 8. Управление потоком

181

2. Начало внешнего цикла For. . .Next.
VBA вызывает функцию Rnd, чтобы присвоить переменной sngC случайное значение.
3. Начало внутреннего цикла For. . .Next.
Этот цикл вычисляет пять других чисел, повторяя вызов функции Rnd при каждом
проходе цикла. Результат отображается в окне Immediate.
4. Завершение внутреннего цикла после выполнения им всех пяти вычислений.
Теперь снова продолжится выполнение внешнего цикла. Подчиняясь оператору Next
A, VBA возвращается в начало внешнего цикла.
5. Пп. 2 и 3 повторяются еще для четырех проходов внешнего цикла.
Этот пример, вероятно, тривиален, но его можно заставить выполнять очень полезную
работу, если немного подправить. Допустим, вам нужно создать мультимедиа-программу,
случайным образом выбирающую пять компакт-дисков и проигрывающую по пять случайным образом выбранных фрагментов с каждого из дисков. В предположении, что вы знаете,
как программировать выбор компакт-дисков и воспроизведение записей, предыдущий пример
будет как раз подходящей заготовкой.
Использовать вложенные циклы F o r . . . N e x t очень удобно при обработке
многомерных массивов, если организовать циклы так, чтобы каждый из них соответствовал одному измерению массива.

Немедленный выход с помощью Exit For
Оператор E x i t For предназначен для немедленного прекращения выполнения цикла до
того, как программа доберется до его конца. Обычно этот оператор используется в условном
выражении ( I f . . . Then или S e l e c t Case), вложенном в главный цикл For . . . N e x t .
Удобно использовать E x i t For, когда проверяются массивы, есть ли в них недопустимые значения, когда неправильные данные приводят к прекращению выполнения процесса.
Скажем, вы узнали о том, что какой-то злой гений ввел неправильную информацию в ваш
прайс-лист и при этом оставлял свой "фирменный" знак. Поэтому при внесении изменений
в цены из-за инфляции вам придется проверить для каждого из массивов, не испорчены ли
в нем данные. Вот пример программного кода, который делает всю эту работу:
For р = 1 То уагДлинаМассива
If уагЦена(р) - "Здесь был В а н я ! " Then
MsgBox "Данные испорчены."
E x i t For
End I f
уагЦена(р) = varlleHa(p) * sngCOLA
Next p

Задание шага цикла
Полный синтаксис оператора F o r . . . N e x t включает необязательное ключевое слово S t e p (шаг) в первой строке структуры, как, например, в следующем фрагменте программного кода:
Sub ListOddNumbers()
Dim strOddNumbers As S t r i n g
For F = 1 To 33 Step 2
StrOddNumbers = strOddNumbers 5 F & " "

182

Часть If. Курс программирования на VBA

Next F
MsgBox "Нечетными числами между 1 и 33 являются:" &
Chr(13) & strOddNumbers
~
End Sub
В этом примере цикл создает строку, содержащую все нечетные числа из диапазона, определяемого значениями н а ч а л о и конец цикла. Значение переменной-счетчика при каждом проходе цикла увеличивается на 2 — шаг, заданный значением аргумента S t e p . Поскольку начальным значением задано 1, F всегда будет нечетным, что упрощает задачу программирования операторов внутри цикла.
В общем, аргумент S t e p сообщает VBA, как вычислять следующее значение счетчика
по достижении конца цикла. Обычно, когда аргумент S t e p явно не указан, счетчик увеличивается на 1. Указав аргумент S t e p , вы можете задать другое значение, на которое нужно будет увеличивать счетчик. При этом можно задать и отрицательное значение, тогда
счетчик будет уменьшаться.
И еще раз повторяю— не будьте слишком хитроумными. Необычные значения
аргумента S t e p могут порождать ошибки, которые трудно обнаружить просто
потому, что ошибки при этом тоже бывают необычными. Поэтому используйте
явное задание аргумента S t e p только тогда, когда этого явно требует ситуация,
да и в этих случаях лучше сначала попытаться найти другие решения, уменьшающие вероятность появления осложнений.

Убавление notnoicau с помощью Qo Jo
Если ваша программа вдруг стала неуправляемой, укажите ей, куда идти, — с помощью
передачи управления другому участку программного кода в процедуре. Оператор Go To
в совокупности со специальным оператором метки в месте назначения позволяет по желанию
перемещаться от одной точки в процедуре к другой. Метка— это оператор, просто отмечающий некоторое место в программном коде. Чтобы задать метку, напечатайте ее имя
(согласно правилам создания имен в VBA), а после него — двоеточие.

Пример использования Go To
В следующем примере оператор Go To направляет поток программы из главной части
процедуры к метке S p e c i a l V a l u e , если встречается необычное значение:
F u n c t i o n GoToExample (ItemNumber As I n t e g e r )
D_m i n t R As I n t e g e r
S e l e c t Case ItemNumber
Case 2412
Go To S p e c i a l V a l u e
Case Is < CutOffValue
DoSomething
Case >= CutOffValue
DcKardlyAr.ything
End S e l e c t
i операторы, выполняющие как/,е-то действия)
GoToExample = i n t R
Exit Function
SpeciaLvalue:

Глава 8, Управление потоком

183

DoSomethingSpecial
GoToExample = -intR
End Function
Обратите внимание на формат метки S p e c i a l V a l u e — она размещается в
своей отдельной строке и заканчивается двоеточием. Двоеточие здесь просто
обязательно — при его отсутствии VBA непременно расстроится и выведет сообщение об ошибке.

Оправдания Go To
Использование оператора Go To считается в программировании признаком низкого качества.
Дело в том, что использование этого оператора превращает программный код в "спагетти", когда путь
выполнения программы скачет туда-сюда через всю программу. "Спагетти" трудно распутывать,
а программный код по мере увеличения в нем числа операторов Go To быстро становится невозможным для чтения. Всегда, когда это возможно, используйте управляющие структуры, позволяющие
программе выполняться последовательно.
Но иногда оператор Go To оказывается самым естественным способом для того, чтобы заставить программу делать то, что вам нужно. Может быть, ваша голова уже до предела нагружена невероятным сплетением вложенных циклов и условных операторов, требующих сложного множества критериев. В таких случаях оператор Go To проложит прямую дорогу к выходу из лабиринта,
только не используйте его слишком часто.

184

Часть //. Курс программирования на VBA

Глава9

"Бронированный" программный код:
отладка и устранение ошибок
В э/ftou главе...
>

Каталог всевозможных ошибок, стремящихся "одурачить" вашу программу

> Принципы борьбы с ошибками
>

Замечательная возможность — режим паузы

>

Все средства отладки редактора Visual Basic, включая команды S t e p и окна Immediate,
Locals и Watch

> Использование редактора Visual Basic как калькулятора с помощью окон Immediate и Watch
> Изощренные приемы отладки, уменьшающие риск появления ошибок при выполнении
программы

Ш
оздание программного кода в VBA — это только полдела. Заставить этот программный
w s код работать и работать так, как нужно, — вот что требует больше всего усилий. Вылавливание и уничтожение ошибок становятся решающим моментом в создании программы,
и нам с вами пришло время выяснить, как это делается в VBA. В этой главе мы обсудим также приемы программной обработки ошибок, позволяющие программе грациозно выходить из
трудных ситуаций, которые случаются во время ее выполнения.

See возможные нен/гшиннос/ни
HftoucxoqMflобязательно
Программа, создаваемая с помощью VBA (как и любого другого языка программирования), обычно сопровождается тремя следующими типами ошибок.
•/ Ошибки компиляции. Синтаксические и другие ошибки, сразу же делающие невозможным выполнение программы.
•/ Логические ошибки. Изъяны проектирования программы, в результате которых программа делает то, что вы не планировали, или не делает того, что вы планировали.
S
1

•/ Ошибки выполнения. Приводят к остановке выполнения программы вследствие либо логических ошибок, либо возникновения ситуации, не предусмотренной в программе
(подробно об этом — ниже, в подразделе "Откуда берутся ошибки выполнения").

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

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 185

Ucnfw£ueHueсишнсиссичеашхошибок,
Если вы допустите синтаксическую ошибку, редактор Visual Basic сообщит вам об этом
почти сразу же, не дожидаясь, когда вы дадите указание выполнить программу. Если вы напечатаете что-то такое, что редактор Visual Basic не поймет, символы в строке с непонятным
программным кодом станут красными, а как только точка ввода перейдет из этой строки на
другую, вы получите сообщение, подтверждающее наличие ошибки и с некоторым разъяснением ее (при условии, что на вкладке Editor (Редактор) диалогового окна Options
(Параметры) отмечен флажок Auto Syntax Check (Автоматическая проверка синтаксиса);
чтобы открыть это диалоговое окно, выберите ToolS^Options из меню). Например, если вы
напечатаете If х = 3 и забудете напечатать T h e n , появится сообщение C o m p i l e e r r o r : E x p e c t e d : T h e n or GoTo (Ошибка компиляции: ожидалось Then или GoTo).
Некоторые синтаксические ошибки VBA не замечает до тех пор, пока программа не начнет выполняться. Например, VBA не будет поначалу возражать, если вы укажете в операторе
GoTo ссылку на несуществующую метку или вызовете несуществующую процедуру— по
этому поводу вы получите сообщение об ошибке компиляции уже после начала выполнения
программы.
Когда известно, где допущена синтаксическая ошибка, исправить ее уже несложно. Если
вы сомневаетесь в правильном написании имени, объявления или вызова процедуры или
функции, имени переменной, оператора создания нового экземпляра объекта или использования управляющей структуры, обратитесь к соответствующим главам этой книги или подходящим разделам справки по VBA.

ЭнМомолоиья qj& nftozftaMMuanoe
После того как вы выловите и уничтожите все ошибки компиляции, а ваша программа начнет выполняться, никто не осудит вас за внезапно нахлынувшее чувство гордости и удовлетворения. Но если программа вдруг сообщит, что 2 4- 2 = 22, или если весь текст в документе окажется розовым, то знайте — где-то в программном коде все же затаилась ошибка.
Причиной подобных ошибок являются ошибки в логике программы. При выполнении программа всегда делает то, что ей приказали делать вы, —- проблема заключается в том, что с помощью созданного вами программного кода вы заставши программу делать не то, что в действительности хотели заставить ее делать. Вы и должны отыскать те операторы, которые привели
к неправильным действиям. Процесс отыскания ошибок называется отладкой, и в этом разделе обсуждаются все средства и приемы, которые помогут вам в вашей отладочной кампании.
Ясно, что приемы, которые используются для выявления и исправления логических ошибок,
годятся и для предотвращения появления ошибок выполнения, вытекающих из логических. Но
поскольку ни одна программа не в состоянии предвидеть абсолютно все возможные ситуации,
в любой программе, предназначенной для использования другими людьми, необходимо предусмотреть программный код для обработки вероятных ошибок выполнения.

Тест, тест, тест
Хорошо, когда ошибки сами заявляют о себе, например, с помощью явно неправильных ответов, изменения цветов экрана на очень странные или появления сообщений об ошибках.
К сожалению, часто логические ошибки оказываются не такими "крикливыми", а многие ошибки выполнения вообще случаются только иногда, при определенном стечении обстоятельств.
Пожалуй, не стоит предполагать, что ваша программа будет работать правильно и надежно сра-

186

Часть //. Курс программирования на VBA

зу же после того, как '"вылупится", гораздо лучше запланировать достаточно времени на ее тщательное тестирование в самых разных условиях.
Вот несколько советов по тестированию программ.
•S Если профамма предназначена для работы с разными типами документов, то и попробуйте
ее в работе с разными типами документов. Попытайтесь работать с программой, когда
в VBA-приложении открыто несколько документов и когда— ни одного.
S Посмотрите, как выполняется программа, когда окно документа находится в разных
состояниях (развернуто, свернуто или восстановлено).
1 S Попробуйте выполнить программу, когда в окне документа выделены различные элеI
менты или группы элементов.
| S Если программа требует ввода информации от пользователя в специальном окне или
|
в специальной форме, опробуйте все вероятные и невероятные типы ввода и посмотI
рите на результат. Например, если вводимое значение предполагается целым, попроI
буйте ввести значение с плавающей запятой, дату и строку символов, чтобы узнать,
|
как отреагирует на это программа.
\ •/ Если программа работает со значениями дат и времени, попробуйте задать ей самые
|
разные даты (в том числе и 29 февраля) и самое разное время суток (в том числе
I
и полночь). Испробуйте не только разные значения даты и времени для переменных,
|
но и проверьте работу самой программы при условии разных дат и разного времени.
I
Для этого не нужно вставать среди ночи или ждать следующего года— просто уста|
новите для своего компьютера подходящие показания системных времени и даты.
Во время тестового запуска программы внимательно наблюдайте за ходом ее выполнения,
чтобы не пропустить даже малейших признаков ошибок. Внимательно проанализируйте документ и убедитесь в наличии всех изменений, которые должны были появиться после выполнения программы,— непредусмотренных изменений тоже быть не должно. Обращайте внимание
на точность и правильный формат каждого из результатов, выводимых профаммой на экран
или помещаемых в документ. В идеале, нужно проследить и за значениями всех переменных
в ходе выполнения программы, чтобы быть уверенным, что при этом тоже не возникает никаких
неожиданностей. (О том, как это сделать, я расскажу в следующем разделе.) И ясно, что если уж
VBA сообщит вам об ошибке выполнения, то наличие проблемы очевидно.
Если вы обнаружите ошибки, к отладке нужно отнестись со всей серьезностью.
В противном случае лучше вообще считать, что ошибок нет, потому что их не бывает
и быть не может.

Комбинации клавиш для отладки
В табл. 9.1 перечислены комбинации клавиш, которые используются при отладке. Подробно каждую из них я рассмотрю дальше в настоящей главе.
Таблица 9.1. Отладка
Действие

Комбинация клавиш

Построчное выполнение кода (пошаговое)



Построчное выполнение кода без построчного выполнения
отдельных процедур



Выполнение кода до точки вставки



Глава 9. "Бронированный" программный код: отладка и устранение ошибок

187

Окончание табл. 9.1
Действие

Комбинация клавиш

Добавление точки останова



Удаление всех точек разрыва



Определение следующей инструкции, которая будет
выполняться



Добавление контролируемого выражения



Выполнение отладочного кода или возвращение сведений об
ошибке обращения к процедуре



Пошаговое выполнение отладочного кода или возвращение
сведений об ошибке обращения к процедуре



Сделайте паузу!
Ключ к отладке программы кроется в режиме паузы VBA. Режим паузы — это временная
остановка выполнения программы на некотором операторе в программном коде. Поскольку
в этом случае программа еще ''живет", вы получаете возможность проверить текущие значения всех ее переменных. Кроме того, начиная с этого момента, вы получаете возможность
использовать команды S t e p , чтобы продолжить выполнение программы в пошаговом режиме, по одному оператору за шаг, и наблюдать за соответствующими изменениями значений
переменных,— при этом будет видно, получают переменные ожидаемые значения или нет.
Подробности такой работы с переменными и командами S t e p будут рассматриваться в этой
главе позже.
На рис. 9.1 показан вид окна редактирования VBA-процедуры в режиме паузы. Если не считать
желтой подсветки строки и стрелки на поле слева, указывающей на оператор, который должен выполняться следующим, то это окно редактора Visual Basic выглядит практически так же, как и при
обычном редактировании программного кода.

•-:; VBA lode for Wwd - tupyBo
l cko
l f lie (Code)

I
Рис. 9.1. Процедура VBA в режиме паузы

188

Часть И. Курс программирования на VBA

На самом деле, в режиме паузы вы можете редактировать свой программный код
прямо во время выполнения программы, внося изменения и добавляя совершенно
новые строки программного кода по необходимости или по своему желанию. Это
предусмотрено не для забавы — это очень удобное средство отладки, преимуществами которого нужно обязательно научиться пользоваться (подробнее об
этом — ниже, в разделе "Добавление и редактирование программного кода в режиме паузы").

Вход в режим паузы
Имеется целый ряд возможностей для перевода программы в режим паузы, который можно сравнить со стоп-кадром анимации.
Запуск программы сразу в режиме паузы с помощью команды S t e p I n t o (см. ниже
раздел "Сквозь программу по шагам").
Назначение точки останова строке программного кода. После того как программа
при выполнении дойдет до оператора, с которым связана точка останова, выполнение
прервется, и программа перейдет в режим паузы.
Помещение в программный код оператора S t o p . После выполнения этого оператора
программа переходит в режим паузы, приготовившись продолжить выполнение
с оператора, следующего за оператором S t o p .
Щелчок на кнопке Break (Пауза), выбор Rurr^Break из меню или нажатие комбинации клавиш во время выполнения программы. Используйте эту возможность для восстановления контроля над программой, которая по каким-то причинам
I
не желает останавливаться сама. Никто не сможет предугадать, где при этом проI
грамма остановится, но зато после остановки у вас появится возможность увидеть, где
I
это произошло.
| V Создание контролируемых переменных типа Break When Value Is True (стоп при
\
значении Истина) или Break When Value Changes (стоп при изменении значения).
|
Тогда программа перейдет в режим паузы, как только значение контролируемой перемен1 ной станет равным True или как только ее значение изменится.
По-другому программа может перейти в режим паузы, когда возникает ошибка выполнения. VBA отображает диалоговое окно с описанием возникшей ошибки (рис. 9.2). В этом окне щелчок на кнопке End (Закончить) останавливает выполнение программы совсем, а щелчок на кнопке Debug (Отладка) переводит выполнение программы в режим паузы. На вкладке General (Общие) диалогового окна ToolS1^1 Options вам предоставляются некоторые
возможности для выбора круга тех ошибок, появление которых должно останавливать выполнение программы.

РИС. 9.2. Диалоговое окно, сообщающее об ошибке выполнения

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 189

Размещение точек останова в программе
Если есть подозрение, что ошибка содержится в каком-то конкретном сегменте программного кода, поместите точку останова как раз перед этим сегментом. На рис. 9.3 видно,
как редактор Visual Basic представляет точку останова на экране — в виде довольно жирной
точки на полях в окне редактирования.

3

"33

II (cKecktlniffs >• 2) Ar.j
Quant I t уГОТТЕР. 3how

Er,d ;
с dec К1
ti.3

It

4 t h огйегаВЗ
. Ada ilnieiOunncltv)
Objects - .fcunc
Enii U;-_h
I* txtQuantityHidden - "Cencsl" The
ehecktimes • Ъ

Рис. 9.3. При назначении точки останова редактор
Visual Basic подсвечивает строку программного
кода, перед которой должно остановиться выполнение программы
После того как точка останова размещена, вы имеете возможность выполнить программу на
полной скорости вплоть до этой точки, пропустив отладку той части программного кода, которая
(как вы надеетесь) не содержит ошибок. Когда VBA доберется до оператора, которому назначена
точка останова, выполнение программы приостановится. В режиме паузы вы сможете проверить
значения переменных и с помощью команд S t e p проследить за тем, как эти значения меняются
при последовательном выполнении каждого из операторов в подозрительном блоке.
Чтобы разместить точку останова, просто щелкните на полях окна редактирования слева
от соответствующей строки программного кода. Можно разместить точку останова и с помощью клавиатуры — для этого поместите курсор в нужную строку и нажмите .
Можно разместить столько точек останова в разных строках программы, сколько вы сочтете необходимым. Нельзя только размещать точки останова в строках комментариев
и строках с операторами, которые VBA на самом деле не выполняет, например в строках
с объявлениями переменных.
Помните о том, что VBA останавливает программу и переключается в режим
паузы после выполнения оператора, непосредственно предшествующего оператору с точкой останова. Другими словами, оператор с точкой останова останется
пока невыполненным— с него предполагается продолжить выполнение программы после выхода из режима паузы.

Удаление точек останова
Исправив ошибки в программном коде или отказавшись на время от попыток их исправления, вы захотите удалить ненужные точки останова. Удаление точек останова даст возможность VBA при следующем запуске выполнять программу без лишних задержек. Удаляется

190

Часть П. Курс программирования на VBA

существующая точка останова точно так же, как и ставится — щелчком на полях в окне редактирования или нажатием клавиши .
Чтобы удалить все назначенные точки останова сразу, выберите из меню D e b u g ^ C l e a r All
Breakpoints или нажмите . Точки останова моментально уйдут в историю —
никакая команда Undo (Отменить) не поможет вам восстановить их.

Выяснение места остановки
Когда программа находится в режиме паузы, редактор Visual Basic подсвечивает оператор,
который предполагается выполнить следующим. Для гарантии на полях около строки с этим
оператором в окне редактирования программного кода появляется стрелка. То, что вы увидите,
показано на рис. 9.4 (но чтобы представить его в цвете, пожалуй, без фантазии не обойтись).

•orFd
«

1

i :

EEII КеуСове - VbK

'§.
:"
.,

Ел (1 К

The
+ 1

Oua ntltV
u
: f Ouanc ltliHlddr n •
chsc ttimes - 0
IK it
Er,a I I
c h e •skeines - 0
Ex ^ Sufc

•Ся

e e l " Thru



1;
S
Г,
...

fh = r d etsFtS
Ob] ееta

• .C O u [ , t

d .--L

В111

Рис. 9.4. He заметить строку с оператором, который должен будет выполняться следующим, просто
невозможно (тем более, что эта строка обязательно будет на экране)
Если строка с оператором, выполняющимся следующим, присутствует на экране, не заметить ее подсветку просто невозможно. Но что делать после того, как вы полистаете текст
программы или переключитесь в окно другого модуля? В таком случае найти этот оператор
без специальных средств будет уже сложнее.
Здесь поможет специально предусмотренная для такого случая команда Show
N e x t S t a t e m e n t (Показать следующий оператор). Выберите D e b u g ^ S h o w
Next Statement, и редактор Visual Basic быстренько доставит вас к нужному
оператору. Есть также команда, позволяющая выбрать в качестве следующего
другой оператор, но она будет обсуждаться позже, в подразделе "Назначение
другого следующего оператора".

Альтернатива точкам останова: оператор Stop
Точки останова использовать очень просто, но они имеют один недостаток: они
временны. Если отлаживаемая программа достаточно сложна, скорее всего, вам
не удастся привести ее в полный порядок за один раз. Точки останова не сохраняются в программном коде, поэтому, открыв проект в редакторе Visual Basic
в следующий раз, вы их уже не увидите.

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 191

Эта проблема решается с помощью оператора S t o p . Поместите этот оператор в программный код. и в соответствующем месте программа перейдет в режим паузы. Вместе с другими
операторами программы операторы S t o p будут сохраняться при сохранении проекта.
Желаете пример, господа? Извольте:
intflaHHbieCMapca = ПолучениеДанныхСМарса(1.5454)
Stop
MsgBox " Р е з у л ь т а т " & intflaHHbieCMapca /Z
Взглянув на этот пример, вы можете догадаться, что здесь оператор S t o p используется
для того, чтобы прозондировать подозрительные результаты, отображаемые в окне сообщения. Выполнение оператора S t o p заставит перейти программу в режим паузы сразу после
того, как процедура-функция ПолучениеДанныхСМарса присвоит свое значение переменной. Вы получите возможность проверить значения обеих переменных, используемых для
вычислений в следующей за оператором S t o p строке, чтобы выяснить, какая из переменных
стала источником проблемы.

Выход из режима паузы
Когда вы достаточно насладитесь режимом паузы (по крайней мере на этот раз), дайте указание VBA продолжить нормальное выполнение программы. Для этого используются команды, находящиеся на тех же местах, что и команды для первоначального запуска программы. В режиме паузы соответствующие пункт меню Run (Выполнить)
и кнопка панели инструментов со своих мест никуда не денутся, но изменят свои названия -— они будут теперь называться Continue (Продолжить). По-прежнему клавишным
эквивалентом для вызова соответствующей команды будет . Продолжая выполнение, программа может снова перейти в режим паузы, если доберется до следующей точки останова или возникнут иные условия, при которых активизируется режим паузы.
Чтобы совсем прекратить выполнение программы, используйте команду R e s e t
(Остановить выполнение). Для этого можно использовать кнопку Reset или пункт Reset меню
Run. Нажатие останавливает выполнение вообще любой программы в Windows, в том
числе и VBA-программ. Но прежде чем нажать , убедитесь, что вы выполняете свою
VB А-программу, потому что в противном случае закроется либо редактор Visual Basic, либо ваше
VBA-приложение, либо какая-то другая программа Windows, оказавшаяся активной в тот момент.

Сквозь программу по шагам
Как и все хорошие отладчики, редактор Visual Basic дает возможность выполнять программу по шагам, по одному оператору за шаг. Такое замедление— просто находка для тех
случаев, когда появляется подозрение на наличие логических ошибок, имеющих привычку
прятаться в укромных местах программ.
Чтобы использовать все преимущества пошагового выполнения программы, желательно видеть, как в процессе выполнения программы изменяются значения
переменных. В этом всегда готово помочь чудесное средство редактора Visual
Basic, называемое Auto Data Tips (Автоматические подсказки значений), но еще
более подробная информация предоставляется в окнах Locals (Окно локальных
переменных) и Watches (Окно контролируемых выражений), которые к тому же
позволяют при необходимости изменить значения представленных в них элементов. Все эти возможности будут обсуждаться ниже.

192

Часть II. Курс программирования на VBA

Начнем же, пожалуй, стрех команд S t e p редактора Visual Basic, а именно: S t e p I n t o ,
S t e p Over и S t e p Out. Все три доступны либо через меню Debug, либо с помощью
кнопок панели инструментов Debug, либо следующих комбинаций клавиш.

Команда

Комбинация клавиш

Step Into



Step Over



Step Out



Вход в процедуры
Команда S t e p I n t o (Войти в процедуру) используется, если нужно выполнить процедуру по шагам в порядке естественного выполнения операторов. Каждый раз, когда применяется эта команда, VBA выполняет следующий оператор программы и снова переходит в режим паузы, чтобы вы имели возможность увидеть произошедшие при этом изменения. Удобнее всего вызывать команду S t e p I n t o нажатием клавиши .
Свое название эта команда получила из-за того, что при ее использовании происходит
вход в любую из вызываемых в программе процедур: если следующим оператором оказывается вызов процедуры типа Sub или F u n c t i o n , то применение команды S t e p I n t o приведет к открытию вызванной процедуры в окне редактирования, чтобы вы могли пройти эту
процедуру по шагам и увидеть все, что происходит.
Команда S t e p I n t o доступна не только в режиме паузы. Если нужно выполнить программу по шагам с самого начала, запустите ее с помощью команды
S t e p I n t o . В таком случае команда S t e p I n t o начинает выполнение с той
процедуры, в которой оказывается текстовый курсор, причем процедура всегда
выполняется с самой первой строки.

Обход процедур и выход из них
Команда S t e p Over (Обойти процедуру) вызывается клавишами и работает подобно команде S t e p I n t o , но со следующими двумя отличиями:
•• S при вызове процедуры команда S t e p Over не приводит к пошаговому выполнению
I
вызываемой процедуры;
| S с помощью команды S t e p Over нельзя начать выполнение программы в режиме паузы.
Если оператор, который должен выполняться следующим, вызывает некоторую процедуру, команда S t e p Over выполнит эту процедуру без перерывов, целиком, сделав сразу все имеющиеся
в процедуре глупости и не дав вам проверить промежуточные результаты. Обход процедур очень
экономит время, когда вы уверены, что вызываемая процедура работает так, как нужно.
Команда S t e p Out (Выйти из процедуры) вызывается клавишами
и прекрасно дополняет команду S t e p Over. После входа в процедуру в режиме ее пошагового выполнения вы можете решить, что все в порядке или что ошибка найдена и исправлена.
Или, намереваясь щелкнуть на кнопке Step Over, вы можете случайно щелкнуть на кнопке
Step Into i лично у меня такое происходит регулярно).
В любом из таких случаев нет необходимости проходить по шагам оставшуюся часть
процедуры. Чтобы пройти остаток с полной скоростью, используйте команду S t e p Out.
VBA быстро доставит вас в ту процедуру, из которой вы пришли, подсветив оператор, следующий за оператором с вызовом процедуры.

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 193

Основные приемы отладки
В режиме паузы поток выполнения программы не рассматривается
"замороженное" только потому, что программа выполняется. VBA оказывается
сообразительным, чтобы позволить вносить коррективы прямо по ходу дела. В
в режиме паузы можно редактировать программный код и изменять порядок,
должны выполняться операторы.

как нечто
достаточно
частности,
в котором

Добавление и редактирование программного кода в режиме паузы
Все возможности окна редактирования программного кода остаются в силе и в режиме
паузы. Вы имеете возможность печатать новые операторы и редактировать или удалять уже
имеющиеся. И главное, в большинстве своем эти изменения сработают незамедлительно, став
частью выполняемой программы. Так, вы можете объявлять переменные, чтобы сразу же использовать их в вычислениях в комбинации с уже существующими переменными программы.
Но есть также изменения (например, изменение типа переменной в ее объявлении), которые
заставят VBA прекратить выполнение программы.

Назначение другого следующего оператора
Представьте, что вы, двигаясь сквозь свою программу в пошаговом режиме, вдруг обнаруживаете, что в следующем операторе содержится большая ошибка. Вместо того чтобы выполнить этот оператор и тем самым ввести свою программу в "штопор", вы можете обойти этот
оператор и не выполнять его вообще, пока когда-нибудь в будущем не исправите ошибку.
Редактор Visual Basic почти всегда позволяет с помощью клавиш'либо мыши назначить
другой оператор для выполнения следующим. При этом вы можете перемещаться в программном коде как вперед, так и назад. В дополнение к возможности пропустить неправильный программный код, вы можете повторять выполнение некоторого фрагмента программного кода до тех пор, пока не поймете, как он работает.
Только знайте, что переменные при этом будут хранить те значения, которые они имели
перед началом внесения вами изменений. Эти значения могут сильно отличаться от тех, которые переменные имели бы в соответствующей точке при естественном ходе выполнения
программы. Если необходимо, назначьте переменным значения по своему усмотрению с помощью окон Immediate, W a t c h e s или Locals, которые будут обсуждаться в этой главе ниже.
Вот как назначить другой следующий оператор.
I S С помощью клавиатуры переместите точку ввода в строку с нужным вам оператором,
(
нажмите или выберите DebugSet Next Statement из меню.
>•

Ь S С помощью мыши перетащите желтую стрелку на полях в окне редактирования проI
граммного кода к строке с новым следующим оператором (рис. 9.5).
Еще один способ пропустить программный код
Есть еще один способ пропустить часть программного кода, на который падает подозрение в содержании ошибки. Этот метод годится и для режима паузы, и для обычного режима редактирования перед запуском программы на выполнение. Как вы уже знаете, можно напечатать апострофы в начале каждой
строки того фрагмента программного кода, который нужно пропустить. Тем самым строки программного
кода превратятся в строки комментария. Единственный недостаток этого способа- на такое
"комментирование" с последующим "раскомментированием" нужно время. Правда, можно
"комментировать" сразу целый блок с помощью одного щелчка на кнопке Comment Block
(Превратить блок в комментарий) панели инструментов Edit (Правка} (см. главу 6).
194

Часть //. Курс программирования на VBA

Но часто для пропуска фрагмента программного кода самым удобным оказывается назначение метки
и временное использование ссылающегося на нее оператора GoTo. Например, при выполнении следующего фрагмента программного кода VBA пропустит все операторы между GoTo П о с л е П р о п у с к а и оператором, следующим за меткой П о с л е П р о п у с к а : . ~
GoTo П о с л е П р о п у с к а
A=В+С
'D = А + Е / F

G«В+D
ПослеПропуска:
MsgBox '"
Format(Now, "dddd"!
Когда пропущенный фрагмент понадобится снова, просто удалите строку с оператором GoTo или превратите ее в комментарий.
:

I

Salesperson. Locked

e'-

Keycodc - vbKsyRecurn The

eheclctime: • cliecluMmes + 1
QuanlltyTcim.SftOB

checktuiws • О
Exit

SUB

• 0

Sith

it
Vt
'^

ordstsBS

.*dd

(ГпсегОиапчч

obj=et=

-

.CDUOC

Рис. 9.5. Назначение другого оператора, предназначенного для выполнения следующим, дает возможность повторять выполнение фрагментов программы, чтобы разобраться в них

подсказки
Замечательная возможность автоматической подсказки значений в VBA позволяет видеть
текущее значение любой переменной в программе. Находясь в режиме паузы, задержите на секунду указатель мыши на имени нужной вам переменной, и на экране появится окно подсказки — небольшой прямоугольник с именем и текущим значением переменной в нем (рис. 9.6).
Если же прямоугольники с подсказками значений на экране не появляются, проверьте,
чтобы был установлен флажок Auto Data Tips (Автоматическая подсказка значений) на
вкладке Editor (Редактор) диалогового окна Options (Параметры).
Редактор Visual Basic позволяет также увидеть тип и область видимости переменной, хотя
соответствующая информация и не появляется автоматически. Поместите курсор между буквами или около имени переменной и нажмите , и на экране появится окно подсказки
Quick Info (Краткая справка) с этой информацией. Для этого не обязательно находиться

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 195

в режиме паузы, что особенно удобно при работе с большими программами, когда объявления переменных оказываются где-то далеко в самом начале программы. Пример того, что вы
можете увидеть в прямоугольнике краткой справки, показан на рис. 9.7,

Z1

]ll*erF rm
-1

KeyC ode - vbKeyfi: ТЬен
Sal
on.Enabled ' Ti ue
Sal
on.LoeKed - Falre
Sal
on.secFocus
E. i
sell

=

"

. Quent
KcyCade-

Focn.
vbK

Tl

";':

]eh«klir **•



Tl

ei.

S a l e : pec son. Locteed - false
Sales per son. SecFoeus
fm • Ivb
s e l l Ke y C o 0e • vOKeyRe t + n The.,

>• 2) And (cboHainlteroEntiy,Valu
Quant ir.yrorm.snov
If QuantlcyHlOden - "Cancel" TSieu
rhec-lctimes - 0

-.

s >- 2) And (cfcoHai Itemlntcy.Value - ;
Quan cicyFocn .Shoe
^

."S

eheclctin ea - •
•)H

~.
If
cheekt lines - 3

-

=UE

С lid I f

EMS

chec ifClnes EJL:

Zr.'X

eyfli

Sub

a

End I :
V: Eh o r d e r s l 3
erQu antity)
. Add
.Co „n.

It

th ocdecsPS
.Jidd (EncetQu
objects - .Co

u

A / G 5.6! 5 маленьком прямоугольнике подсказки
рядом с указателем мыши отображается значение
соответствующей переменной

Лчс. Й 7 Отображение подсказки Quick Info для
переменной

Немедленное вознаграждение в окне
Jtntnediate
Чтобы открыть окно Immediate (Окно немедленного выполнения команд, рис. 9.8), нажмите или выберите Viewolmmediate Window из меню. Окно Immediate предоставляет следующие возможности:
видеть результаты вычислений и значения переменных, вывод которых можно направить в это окно с помощью метода D e b u g . P r i n t ;
выполнять отдельные операторы сами по себе, не помещая их в процедуры: чтобы выполнить оператор в окне Immediate, просто напечатайте его там и нажмите .
"Зачем это нужно?" — спросите вы. Отвечаю.
Окно Immediate можно использовать просто как калькулятор. Напечатайте в нем выражение типа
Print

(27

*

398)

+ 1414

затем нажмите , и вы немедленно получите результат (см. рис. 14.8). При работе в окне Immediate вам нет необходимости указывать объект D e b u g .
Можно направить в окно Immediate вывод промежуточных значений переменных
и выражений при выполнении программы, разместив в подходящих строках программы операторы, вызывающие метод D e b u g . P r i n t . По завершении выполнения программы вы получите возможность просмотреть сразу все выведенные значения
(рис. 9.9), чтобы выяснить, все ли они правильны, а не рассматривать их по отдельности в разное время при пошаговом выполнении программы.

196

Часть II. Курс программирования на VBA

Рис. 9.8. Окно Immediate в действии
| S В режиме паузы в окне Immediate можно отобразить значение любой переменной
:
или свойства объекта с помощью оператора P r i n t или изменить значение с помо|
щью стандартного оператора присваивания. Можно также стандартным способом выР
зывать процедуры. При этом вы должны понимать, что в режиме паузы выполняемые
*
в окне Immediate операторы могут иметь доступ только к переменным, объектам
^
и процедурам, находящимся в области видимости той процедуры, которая выполняет|
ся в данный момент. Другими словами, результат выполнения оператора в окне
I
Immediate будет тем же, что и результат печатания этого оператора в выполняемой
|
в данный момент процедуре и работы его в ней.
Интересный факт. В окно Immediate можно перетащить текст, выделенный в окне редактирования программного кода, и тогда вам не придется печатать длинные выражения или имена
переменных снова (но знайте, если при перетаскивании вы не будете удерживать нажатой клавишу , фрагмент программного кода не скопируется в окно Immediate, а переместится
туда из окна редактирования). Клавиша в окне Immediate работает точно так же, как
и в окне редактирования программного кода, вызывая справку для ключевого слова, в котором
находится текстовый курсор. А вот автоматические подсказки значений здесь не действуют.

2Э04 3
2

Single
Osgw

53

nager

sngArayqeni
rtHmpCounto

"«OanQQDrSWng
— Веским»
— BuderColor
— Boran Style
— Ca«fc)r

-21"4вЭ«33 OLE_COLOfi
-JH? 483630 OLE_COL0fl
tmBanerSI yic ( п а и « r S l y
' A l of the Mo String

1
FIBU =1S. 2
*1S
'«J 115
~4gu tM
qu

JFornV
IFwmv
: Formv
2 FonnV

Рис. 9.9. Пример вывода программы, использующей
метод Debug. Print

See пе/геменлые noq nftucjioffifuxu € окне
Locals
Если у вас на экране еще есть место, где можно разместить окно Locals (Окно локальных
переменных), оно обязательно должно присутствовать на экране все время, пока вы занимаетесь отладкой программы в режиме паузы. Отобразить окно Locals на экране можно щелчком на соответствующей этому окну кнопке панели инструментов Debug или с помощью
View ^ L o c a l s Window из меню.
Как видно из рис. 9.10, в окне Locals автоматически отображаются имена, значения и типы данных всех переменных, доступных в выполняемой в данный момент процедуре. Эта
информация обновляется редактором Visual Basic после выполнения любого из операторов,
так что вы всегда будете видеть в окне Locals текущие значения переменных.

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 197

Другие свернутые разделы
Отдельные
переменные программы
Свернутый раздел
переменных уровня модуля

For i = 0 To 15
ArcayOIPendoi
Anniversary = Now
№«

1

FortcCount -= UsecForms.Count
Т^е^я - AcrtiveUindci'. Select ion, Coyrit
Mt-'эзаде - CSterItems) £ " otejtclj au
CusromClb^ects. Add ;proFor»a. Contrals

!1еззад= - ^ t r (Items)

* " fh

Рис. 9.10. Вид окна Locals в режиме паузы

Механика процесса
Как и ряд других окон редактора Visual Basic, окно Locals по умолчанию закреплено, но
может отображаться и в виде свободно перемещаемого окна. Основы использования окон редактора Visual Basic обсуждались в главе 5.
Если нужная вам информация не помещается в столбце, помните о том, что ширину
столбцов можно менять. Поместите указатель мыши на разделитель между заголовками
столбцов и, когда он превратится в двунаправленную стрелку, перетащите разделитель влево
или вправо, чтобы установить нужную ширину столбца.
Если снова взглянуть на рис. 9.10, вы увидите, что некоторые строки в окне Locals сообщают информацию об обычных переменных, а некоторые— о массивах, переменных пользовательских типов и объектах. Такие элементы не имеют собственных значений, а содержат
другие переменные или элементы иных типов. Изначально после запуска процедуры в окне
Locals они представлены в виде свернутых разделов, так что вы не увидите содержащихся
в них подчиненных элементов. Чтобы развернуть любой из свернутых разделов, щелкните
в прямоугольнике с плюсом слева от имени раздела (то, что можно увидеть, развернув раздел,
показано на рис. 9.11).
В развернутых уже на самом верхнем уровне иерархии окна Locals будут показаны только переменные, явно или неявно объявленные в самой выполняемой
в данный момент процедуре. Чтобы увидеть переменные уровня модуля, доступные всем процедурам данного модуля, разверните самый первый из разделов
в окне Locals. Этот раздел всегда принадлежит модулю, содержащему выполняемую процедуру. В окне Locals не появляются открытые переменные или переменные из других проектов.

198

Часть II. Курс программирования на VBA

ШШШШ
'»j*i!ftft'1. ••*"•.*•.-!•*" '
• *'/*
'Яяй^*"
^£- ~1» №
*
'

"

V

-• " ' '
* 4 f ' j i i "'» *"' • """"•• *"
:

yg.'f* * •'•
J - и J . - •"• •,"••" •
*•* • • •
• «• " ^ i
..."•

'

r

'

F

o

;

;

F

I

r

e

i

x

=

A

r

A

n

C

o

t

o

c

m

t

e

m

0

r

a

n

y

i

T

O

v

o

f

e

1

R

r

s

s

n

o

r

m

(

y

i

)

=

=

H

o

R

n

d

(

w

i

s

u

n

=

t

=

A

c

U

t

i

u

s

e

e

S

c

I

F

i

o

n

r

d

m

o

s

w

.

.

C

S

o

e

u

l

e

n

c

t

t

Message = "Выделено объекте
C u s t o m O b j e c t s . A d d (ProFocmc

ActiveWindow.SelectAll
Items = ActiveWindow.Select
Message =

"Быделено объекте

1

— !
t
я.U—)



. .

'

•"

ITroe
EtyteMsker/StyleMa
Colleclion/Colleclion
Integer
Integer
"Выделено обьеяов: i. String
ffll 12 99 12 3)'00#
Date

a
0

?„
%



5

d

a

•••

PnqWOKMJO
R SlyteMaker
X f l CustomObjects
1- FoimCourt
llemCount
Message
Anniversary
- JDefault
- SackColor
- BorderColor
- BordeiStyle
— Caption
-1 Control;
- Cycle
•i
-g

"??DDDODnDDDQOD? Slnna
•21J7483633
OLE COLOR
-2147Д8Э630
OLE_COLOR
ImBorrferStyleNone
fmS order Style
"Счзтчик выделенны! of Slrpng
Controls/Conlrols
ImCycleAIIForms
fmCycle
DrawBuffer
32000
Long
Enabled
True
Boolean
Font
Fom/Fonl
FoieColor
•21474ВЭ6Э0
OLE_COLOR
Height
103,6
Single
HelpComextlD
Long
0
InsifleHeight
85,В
Single
InsidaWidlh
236,2
Single
KeepScrollBaisVisitifmSciallBaisBoth
fmScrollBars
IblCountOIHems
Label/Label

iU
-3
z,.

li

Г,
r

-1 j

Ли;. Й / /. Вид окна Locals для той же процедуры, что и на рис. 9.10, но разделы,
там свернутые, теперь развернуты

Зачем редактировать значения переменных
Прежде чем сообщить вам, как менять значения переменных, я думаю, нужно сказать пару слов
о том, зачем их менять, Вот несколько случаев, когда это оказывается удобным.
| S Предыдущая строка программного кода содержит ошибку, в результате которой пеI
ременной присвоено неправильное значение. Вы это заметили, но хотели бы продолI
жить выполнение программы. Прежде чем продолжить, неплохо было бы исправить
|
значение переменной, чтобы ошибка не повлияла на последующие операторы.
| S Вы хотели бы проверить выполнение программы при разных значениях переменной,
I
не меняя текста самой программы. В таком случае используйте команду S e t N e x t
I
S t a t e m e n t {Назначить оператор следующим), чтобы повторить выполнение фраг\
мента программы несколько раз, задавая при этом разные значения в окне Locals.
1S
1
I
|

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

Как редактировать значения переменных
Для того чтобы изменить значение переменной в окне Locals, выполните следующее.
1. Щелкните два раза (но не делайте двойной щелчок) на текущем значении переменной так, чтобы оказалось подсвеченным только это значение.
После щелчка в любом другом месте строки выделенной окажется вся строка.
2. Напечатайте новое значение.
Если значение должно быть строковым, заключите его в кавычки, а если это значение
даты, поместите его между парой знаков #.
3. Если вы передумали менять значение переменной, нажмите , а чтобы подтвердить изменения — .

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 199

Если редактор Visual Basic сочтет предложенное вами значение недопустимым, вы
получите сообщение об ошибке с некоторыми объяснениями по поводу того, что
именно оказалось неправильным.
Можно менять значения любых переменных, в том числе значения элементов массивов
и элементов переменных пользовательских типов. Только, чтобы получить доступ к этим элементам, не забудьте развернуть раздел, соответствующий нужному массиву или переменной
пользовательского типа. В случае объектной переменной у вас нет возможности изменить ссылку на объект, но зато можно менять свойства соответствующего объекта (за исключением тех,
которые предназначены только для чтения). И опять же, можно увидеть редактируемые элементы, только развернув раздел, соответствующий объектной переменной (см. рис. 14.11).

Ключевое cfteqafWo otnuacjKu: окно Watches
Когда вы освоите работу с окном Locals, работа с окном W a t c h e s (Окно контролируемых
выражений) покажется просто забавой. Окно Watches делает, по сути, то же самое, что и окно Locals, но с одним очевидным отличием — те выражения, значения которых будут показаны в этом окне, должны выбрать вы. Примерный вид окна W a t c h e s показан на рис. 9.12.
j Ш Watches
;i
:
Expression'%•'; ' •pf'~ ' l Value'-•,.' ^lTVoe '~ "•
-" I c i r l r e
Stf sngArrayltem
2904,3
Single
Рис14 12
&rf FormCount
2
Integer
i o
52
Integer
Рис14 12
&rf intTempCounter
FouriAnO)jmion/FormAnOpinicPiic14 1^ FormvariableDerti^B
ЭД!|1ттФормз
"??DDDDaa[String
Pnc14 12.FormVariablaDem •
- _Defaurl
— BackColor
-21474B3633 OLE_COLOR
Pncl4 12.FormVariableDem
— BorderColor
-21474B363Q OLE_COLOR
Pnc14 12 FormVariableDam
fmBorderStyle fmBordeiSlyle
Рис 14 J 2. F ormVari ab I e D e m
- BorderStyle
~ Caption
"InFormAtiue" String
=ис14 12 FormVariableDem , 1

Рис. 9.12. Окно Watches редактора Visual Basic
Используйте окно Watches при отладке больших программ, в которых большое число разных процедур работает с открытыми переменными. Добавив эти переменные
в окно Watches, вы сможете контролировать их значения, независимо от того, какая
из частей программы выполняется в данный момент.
Окно W a t c h e s появится на экране автоматически, как только вы зададите контролируемое выражение. (О том, что такое контролируемое выражение, вы узнаете во врезке "Об отличиях между окнами W a t c h e s и Locals".) Если на экране не хватает места, вы всегда можете закрыть это окно, щелкнув на кнопке закрытия в его верхнем правом углу.

Об отличиях между окнами Watches и Locals
Кроме того, что появляющиеся в окне Watches объекты выбираете вы, окно Watches отличается от
окна Locals следующим.
s Каждая из строк окна Watches позволяет контролировать значение любого допустимого в VBA
выражения, а не только отдельной переменной. Например, вполне годятся выражения типа (X
- Y) >, 15, "Выбранный цвет - " & s t r C o l o r или даже просто 2 + 2.
Именно поэтому в случае окна Watches говорится о контролируемых выражениях.
200

Часть И. Курс программирования на VBA

s Из-за того что в окне Watches можно контролировать переменные из любого модуля или процедуры проекта, в этом окне добавлен еще один столбец Context (Контекст). В этом столбце
указывается область видимости, в рамках которой отображается значение данной переменной
или выражения. Если выполняемая процедура находится вне заданного контекста, вы и увидите
только пометку (Вне контекста). :.

Добавление контролируемых выражений
Если вы любите свободу выбора, вам обязательно понравится иметь дело с окном
Watches. Приготовьтесь удивиться тому, сколько есть разных способов добавления контролируемых выражений в это окно.
Правда, независимо от выбранного в конце концов способа, начать нужно с окна редактирования и выделить в нем переменную или выражение, значения которых требуется контролировать. Здесь "выделить" означает подсветить все выражение, как в любом текстовом редакторе, пользуясь мышью или клавишами со стрелками.
Если нужно контролировать значение отдельной переменной (другими словами, элемента,
не являющегося свойством объекта или частью пользовательского типа данных), то выбирать
весь элемент целиком не нужно — достаточно поместить текстовый курсор внутри имени
этой переменной.
Перечислим способы, которыми можно добавить контролируемые выражения.
| S Щелчок на выделенном тексте правой кнопкой мыши и выбор из появившегося
|
контекстного меню пункта Add Watch, открывающего диалоговое окно Add

I

Watch.

•; S Выбор Debug^Add Watch из меню, в результате чего также открывается диалоговое
|
окно Add Watch.
IV
|
{j
^

Щелчок на кнопке Quick Watch панели инструментов Debug или выбор DebugoQuick
Watch из меню. Редактор Visual Basic отобразит на экране подтверждающее сообщение
с описанием почти уже добавленного вами контролируемого выражения, но у вас не будет возможности каким-либо образом это выражение изменить.

£ •/ Перетаскивание выделенного выражения в окно Watch. При этом контролируемое
и
выражение создается без каких-либо дополнительных промежуточных шагов.
А если вы предпочитаете делать все своими руками, то можете в окне редактирования
программного кода не выбирать ничего, а сразу щелкнуть на кнопке Add Watch и просто
напечатать интересующее вас выражение вручную в соответствующем поле диалогового
окна Add Watch.

Работа с окном Add Watch
На рис. 9.13 изображено окно Add Watch (Добавление контролируемого выражения),
возникающее на экране в результате выбора Debug^Add Watch из меню или выбора пункта
Add Watch из контекстного (вызываемого щелчком правой кнопки мыши) меню в окне редактирования программного кода. В окне Add Watch уточняются детали, касающиеся добавляемых контролируемых выражений.
В поле Expression (Выражение) указывается выражение, подлежащее контролю. Если
перед открытием окна было выделено нужное выражение, менять в окне ничего не придется,
но вы всегда имеете возможность подправить выражение.

Глава 9. "Бронированный" программный код: отладка и устранение ошибок 201

В разделе Context (Контекст) можно определить процедуру, в которой редактор Visual
Basic будет вычислять и отображать значение переменной. Изначально в полях Procedure
(Процедура) и Module (Модуль) будут указаны процедура и модуль, из которых вы добавляете контролируемое выражение. Если вы хотите видеть значение при выполнении другой
процедуры, выберите ее имя. Если это процедура из другого модуля, то сначала выберите
нужный модуль, а уж затем процедуру.

|Ai)ные инструменты
Г

Пианино
Гитара

Г~ Телевизор
• т Г~ Сотовь* твпвфон

Р" (Саксофон]

Оп-разить фс^иу

Рис. 10.22. Устанавливать и сбрасывать
флажки можно независимо
Установка флажков и выбор кнопок с фиксацией
Как обычно, свойство Value содержит информацию, относящуюся к выбору параметров пользователем. Если флажок установлен, свойство Value равно True, если
флажок сброшен, свойство Value равно F a l s e . Такая же ситуация и с кнопками
с фиксацией: свойство Value равно True; если кнопка нажата. В противном случае
свойство Value равно F a l s e . Для выбора параметров можно воспользоваться следующим кодом:
If tglLightSwitch.Value = True Then
TurnLightOff
Else
TurnLightsOff
End If
236

Часть //. Курс программирования на VBA

Если вы просто хотите изменить текущее состояние флажка или кнопки с фиксацией,
лучше всего воспользоваться оператором N o t . В следующем коде флажок устанавливается,
если он был сброшен, и сбрасывается, если он был установлен:

ChkYesOrNo.Value = Not chkYesOrNo.Value

Выбор параметров из списка и комбинированных окон
Если вы предполагаете, что для
вариантов выбора, созданное вами
в нем может быть 10 -12 флажков.
сти от собственных предпочтений.
слишком тесно.

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

Что такое список
Список— это возможность, предоставляемая Windows для решения многих проблем.
В списке содержится перечень параметров, которые пользователь может выбрать (рис. 10.23).

preferred »"tad dnstoe C
o
ji n miliard irfnagrct*
lemon Кие
Thousand Illand

г г " •" •
Sl«tee(0rt«M

in
omccllnit
lorMla

Рис. 10.23. В данной форме в
верхней части располагается
список, а в нижней - комбинированное окно
С помощью списка нельзя получить доступ к элементам, которые не содержатся в нем. Кроме
того, нельзя представить список VBA в виде раскрывающегося списка в одной строке. Для того
чтобы избежать этого ограничения, необходимо воспользоваться комбинированным списком.

Комбинированные списки
Комбинированный список объединяет в себе достоинства простого списка и текстового поля.
Пользователь может выбрать необходимый элемент из списка, а если такового не окажется
в списке, ввести его. Основное отличие между списком и комбинированным списком заключается в следующем: для того чтобы раскрыть весь комбинированный список, необходимо щелкнуть на кнопке, на которой изображен треугольник. Скорее всего, вы знакомы с комбинированными списками, но посмотрите на рис. 10.24, чтобы вспомнить, как он выглядит.
С точки зрения пользователя комбинированные списки намного лучше, так как пользователь
может легко найти в них необходимый элемент. Однако программисты во многих ситуациях предпочитают офаничивать выбор пользователя, чтобы предотвратить ввод неправильных данных.

Глава 10. Создание интерактивных VBA-форм

237

Узнав, что такое список, не пользуйтесь им
Я советую использовать комбинированные списки для контроля всех параметров, которые
содержатся в списке, независимо от того, вводит или нет пользователь текст, которого нет
в данном списке. Забудьте о простых списках.
И вот почему: простой список VBA не может отображать элементы в виде раскрывающегося списка, Вместо этого вы имеете дело с списком, в котором перечислены все доступные
варианты выбора сразу. Это не всегда удобно, так как, если в списке слишком много элементов, он займет слишком большую часть формы. Если элементов в списке немного, лучше
воспользоваться переключателями или флажками.
В то же время комбинированные списки более компактные, так как они всегда занимают
только одну строку. Для того чтобы комбинированный список превратился в обычный
простой список, достаточно установить значение свойства S t y l e равным 2
( f m S t y l e D r o p D o w n L i s t ) . А теперь подумайте: стоит ли мучиться со списками?

Размещение элементов в списке или комбинированном списке
Теперь пришла очередь самого трудного. Окно Properties (Свойства) нельзя использовать для ввода вариантов выбора, которые должны находиться в списке или комбинированном списке. Вместо этого вы должны написать код для метода A d d l t e m элемента управления или связать элемент управления с источником данных (он представляет собой электронную таблицу Excel или базу данных Access).
Для того чтобы создать список прямо в коде, используется соответствующая процедура
для события A c t i v a t e данной формы. Она должна содержать несколько инструкций, которые похожи на приведенный ниже пример:
P r i v a t e Sub U s e r F o r m _ A c t i v a t e ( )
cmbOptionPoll.Addltem " O v e r p o p u l a t i o n "
cmbOptionPoll.Addltem " G l o b a l warming"
cmbOptionPoll.Addltem "No time to s m e l l t h e r o s e s "
cmbOptionPoll.Addltem "No r o s e s to s m e l l "
cmbOptionPoll.Addltem "Taxes o n t h e r i c h too h i g h "
cmbOptionPoll.Addltem "Too many s o c i a l s e r v i c e s "
cmbOptionPoll.Addltem " I n a d e q u a t e s o c i a l s e r v i c e s "
cmbOptionPoll.Addltem "HMOs"
End Sub
Технические подробности размещения элементов из базы данных в списке или
комбинированном списке выходят за пределы данной книги, однако вы должны знать, что
это возможно.

ЧТО же пользователю делать
Для того чтобы найти элемент, который пользователь выбрал или ввел в списке или
комбинированном списке, используйте свойство объекта Value в коде. Назначьте свойству
соответствующую переменную, как показано ниже:
strOption = cmbOptionFoll.Value

tpofui
Добавлять элементы управления в формы несложно, а вот, чтобы заставить их делать то, что вам
нужно, потребуется немного больше умственной работы и профаммирования. В этом разделе мы
обсудим тонкости процесса профаммирования форм.

238

Часть II. Курс программирования на VBA

Покажите то, что имеете!
Решив добавить в свою VBA-программу пользовательские формы, вы неизбежно столкнетесь с необходимостью показать эти формы на экране. Иначе зачем эти, пусть даже самые
лучшие в мире, формы нужны, если их никто не увидит?
Из-за того, что VBA-программа может при необходимости пользоваться интерфейсом содержащего ее приложения, программа не отображает никакую из ее форм автоматически. В этом отношении VBA отличается от своего собрата Visual Basic, где программа по сути является формой.
Так или иначе, чтобы отобразить форму и сделать ее доступной пользователю, в VBA-программе
вам придется добавить программный код.

Загрузка и отображение форм
Процесс отображения формы в VBA состоит из двух шагов;
I S загрузка формы в память;
I •/ отображение формы на экране.
Оба этих шага можно осуществить с помощью одного оператора VBA, Но иногда полезно разделить эти шаги и использовать для них отдельные операторы.

Отображение окон
Отображение форм осуществляется методом Show. Например, если именем формы является F o r m I C a , то нужно просто напечатать:
FormICa.Show
Заметьте, что Show — это метод объекта U s e r F o r m , поэтому метод добавляется к имени формы после точки-разделителя. Если указанная форма еще не загружена в память, метод
Show сначала загрузит форму, а потом сделает ее видимой,

Загрузка форм без отображения их на экране
Чтобы загрузить форму в память перед отображением, используйте оператор
L o a d . L o a d — это не метод, поэтому в данном случае синтаксис другой (по
сравнению с использованием Show):
Load

ФормАльДеГид

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

Внесение изменений в форму перед ее отображением
Можно загрузить форму и без оператора L o a d , выполнив оператор, в котором вызывается свойство либо метод формы или любого из помещенных в нее элементов управления. При
этом можно вносить в форму изменения перед тем, как она отображается на экране, Хотя ок-

Глава 10. Создание интерактивных VBA-форм

239

но свойств редактора Visual Basic позволяет безо всякого программирования управлять тем,
как форма будет выглядеть и вести себя на экране, здесь нужно отметить следующее: часто
вообще нельзя узнать, как должна выглядеть и что должна делать форма (или ее элементы
управления), пока программа не начнет выполняться.
Предположим, например, что в заголовке формы должны отображаться текущие дата
и время. Вы не можете предугадать, когда именно пользователь запустит вашу программу,
поэтому вам придется поручить VBA указать дату и время за вас. Это можно сделать, например, так:
Sub DisplayDateCaptionedForm()
DateCaptionedForm.Caption = Now
DateCaptionedFcrm.Show
End Sub
Аналогично можно заставить надпись или текстовое поле формы отображать информацию о том, что в данный момент выделено в VBA-приложении. На рис. 10.24 показано то,
что можно увидеть в результате выполнения следующей процедуры VBA, связанной с подходящей формой в Visio:
Sub DisplayShowSelectionForm()
Dim ItemCount As i n t e g e r , Message As String
Items = ActiveWindow.Selection.Count
Message = "Выделено объектов: " & CStr(Items) S " . "
ShowSelectionForm.lblCountOfItems.Caption = Message
ShowSelectionForm.Show
End Sub

Рис. 10.24. В этой программе содержание текста надписи выясняется непосредственно перед отображением формы
Обратите внимание на строку программного кода, в которой изменяется свойство элемента управления "'надпись" в форме:
ShowSelectionForm.lblCountOfItems.Caption = Message

240

Часть II. Курс программирования на VBA

Технически невозможно получить доступ к свойству или методу формы до тех
пор, пока форма не будет загружена, Однако вам не нужно писать для этого явный оператор. VBA автоматически загружает форму, как только потребуется выполнить оператор, ссылающийся на одно из ее свойств или на один из ее методов. Ссылка на свойство или метод любого из элементов управления в форме порождает тот же эффект.

Изменение формы с помощью событий Initialize и Activate
Пример из предыдущего раздела демонстрирует один из способов внесения изменений
в форму перед ее отображением на экране — из стандартной процедуры обычного модуля.
Но, как говорится, содрать с капусты листья можно многими способами. В нашем случае есть
варианты— события I n i t i a l i z e (Инициализация) и A c t i v a t e (Активизация) формы.
Программный код, помещенный в процедуры обработки этих событий, выполняется автоматически, когда случаются соответствующие события. Выбрать между этими событиями помогут следующие правила.
!^
1

I

Используйте событие I n i t i a l i z e для программного кода, который должен выполняться только при первой загрузке формы.
Используйте событие A c t i v a t e для программного кода, который должен выполняться при каждом отображении формы на экране (включая и первое отображение).

Создание программного кода для процедур обработки событий обсуждается ниже, в разделе "Главные события".

Как скрыть видимую форму
Используйте метод Hide (Скрыть), чтобы закрыть форму и таким образом получить возможность вернуться в документ VBA-приложения или активизировать другую форму. Это
делается следующим оператором:
FormErly.Hide
Правда, метод Hide можно использовать не в любом месте программы. Если форма модальная, метод Hide нужно поместить в процедуру обработки события, принадлежащую самой форме.
Как упоминалось раньше в настоящей главе, если открыта модальная форма, выполняться могут
только процедуры, связанные с этой формой.
И кстати, при вызове метода Hide в процедуре обработки события, принадлежащей этой форме, имя формы указывать не требуется — VBA достаточно сообразителен, чтобы понять, что в данном случае метод Hide принадлежит именно
этой форме. Поэтому в процедуре обработки события, принадлежащей форме,
можно просто напечатать
Hide
и эта форма исчезнет.
Чаше всего оператор Hide размещают в конце процедуры обработки события C l i c k
(Щелчок) для КНОПОК ОК, Отмена или Закрыть. Примеры вы найдете ниже, в разделах
"Добавление кнопок Закрыть и Отмена" и "Программирование кнопки ОК".
Скрытая форма не удаляется из памяти, вы сможете отобразить ее снова без лишних задержек с помощью метода Show в любое время.

Глава 10. Создание интерактивных VBA-форм

241

Удаление формы из памяти
Если известно, что форма больше в программе не понадобится, уничтожьте ее совсем,
удалив из памяти. В небольших VBA-программах в этом нет необходимости, но когда ваши
программы станут большими и память будет как награда, уничтожение ненужных форм приобретет очевидный смысл.
Как и для загрузки формы, для выгрузки формы из памяти используется не метод,
я оператор U n l o a d F o r m A t i o n .
Выгрузка формы удаляет ее и с экрана, если до этого форма была видима.
Если известно, что форма больше в программе не понадобится, замените метод H i d e
в процедурах обработки событий формы на оператор U n l o a d . В этом случае оператор U n l o a d Me эквивалентен оператору U n l o a d и м я _ ф о р м ы , поскольку ключевое слово Me
представляет текущую форму.
Однако, в отличие от метода H i d e , оператор U n l o a d применим и к модальным формам,
которые не присутствуют на экране. С помощью оператора U n l o a d , размещенного в главной части программы (т.е. в процедуре, не связанной с формами), можно выгружать любые
формы, в том числе и скрытые модальные формы.

Главные события
Когда выполняется процедура типа Sub, не отображающая форм, ваш программный код полностью контролирует, что и когда делает программа. Но если на экране отображается форма, программа переходит в каком-то смысле в пассивное состояние, ожидая инструкций от пользователя.
После каждого нажатия клавиши, перемещения мыши или щелчка на кнопке генерируется программное событие. Ваша программа регистрирует каждое такое событие и проверяет, не содержит
ли программный код формы процедуру, связанную с этим событием. Если подходящей процедуры
нет, событие пройдет для программы бесследно. Но если форма имеет процедуру, соответствующую событию, то программа сразу же оживет и честно выполнит эту процедуру.
Процедура обработки события может делать все, что и любая другая процедура: вычислять
значения переменных, манипулировать свойствами и методами объектов, загружать и отображать другие формы. После завершения выполнения процедуры обработки события контроль
возвращается к форме. Программа перейдет в состояние ожидания следующего события.

Типичные события
Формы VBA и элементы управления в них могут распознавать самые различные события.
(На жаргоне VBA, когда говорится, что объект "имеет" события, подразумевается, что объект
может регистрировать и распознавать эти события.) У форм и элементов управления есть
одинаковые события, но набор событий каждого объекта индивидуален. Часто встречающиеся события приведены в табл. 10.1.

Таблица 1 0 . 1 . Избранные события форм и элементов управления
Событие

Объекты, которые
распознают событие

Когда происходит событие

Activate

Формы

Каждый раз, когда форма активизируется
(получает фокус ввода)

addCont r o l

242

Формы, фреймы и формы с
множеством страниц

При добавлении в объект элемента
управления во время выполнения формы

Часть II. Курс программирования на VBA

Окончание табл. 10.1
Событие

Объекты, которые
распознают событие

Когда происходит событие

AfterUpdate

Все "действующие" элементы
управления,кроме кнопок

После установки нового значения для
элемента управления, в момент перехода
от данного элемента управления к другому

Все "действующие" элементы
управления, кроме кнопок

При изменении значения свойства
V a l u e элемента управления

;hanae
Click

Формы и все типы элементов
управления

После щелчка кнопкой мыши на объекте

DblCl:.ck

Формы и все типы элементов
управления

После двойного щелчка кнопкой мыши
на объекте

D r o p B u t t o n C l i c k Текстовые поля и поля со списком При появлении раскрывающегося списка
(после щелчка на кнопке раскрытия или
нажатия клавиши )
Enter

Все типы элементов управления

Непосредственно перед тем, как элемент
управления получит фокус ввода от другого
элемента управления в той же форме

Error

Формы и все типы элементов
управления

Когда возникает ошибка, но информация
о ней не может возвратиться программе

Exit

Все типы элементов управления

Непосредственно перед тем, как фокус
ввода перейдет от данного элемента
управления к другому в той же форме

KeyUp, KeyDown,
Keypress

Формы и все типы элементов
управления

При нажатии или отпускании кнопки

Layout

Формы, фреймы и формы с
множеством страниц

При изменении размеров объекта

RemoveControl

Формы, фреймы и формы с
множеством страниц

При удалении элемента управления из
объекта во время выполнения формы

Scroll

Формы, фреймы и формы с
множеством страниц, а также
текстовые поля, списки и поля со

При изменении положения бегунка полосы
прокрутки

СПИСКОМ

Zoom

Формы, фреймы и формы с
множеством страниц

При изменении масштаба объекта
(значения свойства Zoom)

Программирование обработки событий
Как видно из табл. 10.1, формы и элементы управления могут отвечать на многие события. Но когда форма действительно отвечает на какое-нибудь конкретное событие? Только тогда, когда она имеет соответствующую процедуру для
этого события. Процедуры обработки событий должны быть кем-то созданы —
в данном случае вами.

Глава 10, Создание интерактивных VBA-форм

243

Создание и редактирование процедур обработки событий
Создание процедуры обработки события не отличается от создания любой другой процедуры в VBA. Нужно только знать, куда поместить соответствующие операторы. Программный код для процедуры обработки события, как и весь остальной связанный с формой программный кол, в редакторе Visual Basic размешается в окне программного кода этой формы.
Следовательно, процедуры обработки событий для всех элементов управления в форме, как
и для самой формы, создаются в окне программного кода формы. Поэтому, перед тем как
программировать соответствующие событиям процедуры, выполните следующие шаги.
1. Откройте окно программного кода формы.
Двойной щелчок на форме или любом ее элементе управления — самый короткий
путь для этого. Иначе можно выделить форму и выбрать View^>Code из контекстного (вызываемого щелчком правой кнопки мыши) меню для формы или элемента
управления, с которыми вы собираетесь работать, или же нажать , когда форма
выделена в ее окне UserForm.
2. В окне программного кода формы выберите объект, для которого вы хотите создать процедуру обработки события.
Объект выбирается из раскрывающегося списка объектов вверху слева в окне программного кода формы (рис. 10.25).
3. Выберите событие, для которого нужно создать программный код.
На этот раз используйте раскрывающийся список процедур, размещенный в окне программного кода вверху справа.
! Я СДМои Я о к у м е н т м \ У | 5 . о У В А v s d - Monyconl/ols ( C o d (General)

(Genera)l
ChtckB oxl
CheckBsx?
СИескВояЭ
ComboBoHl

Activated
*
= "Щелкните в поле фор1*

авжжыш
Co m m an d В ut(o n2
Framel
Frama2
Imagei
LabeM
Label?

Click ()
стей
.
njyupOuawijjjH;_n;TH i.StantUpPosition = 3

• _*1Ш
Рис. 10.25. Выбор элемента управления в окне программного кода формы перед началом создания
процедуры обработки события
Как только из раскрывающегося списка процедур будет выбрано событие, VBA немедленно перенесет вас прямо к процедуре его обработки. Если для события еще не создано никакого программного кода, VBA создаст для вас заготовку процедуры, разместив курсор ввода в пустой строке между оператором объявления процедуры и ее завершающим оператором
(см. рис. 10.25). Если процедура обработки события уже содержит программный код, VBA
просто поместит курсор ввода в его первую строку.
Синтаксис процедур обработки событий
Вам не стоит беспокоиться об объявлении процедур, так как VBA делает это автоматически, когда вы выбираете событие в окне программного кода

244

Часть II. Курс программирования на VBA

Ш С\Мои иокумши «\Visi i V B A v n d - Mnnyconlml-j (Cud В i r a n
| CommandBultoni
Private

*rhi click

Sub Conrn n d B u t t o n l _ C l i c k (

End Sub
=•

Только что созданная заготовка процедуры обработки события в окне редактора Visual Basic
Как влдно из рис. 10.26, синтаксис процедур обработки событий не отличается от синтаксиса обычных процедур типа S u b . Единственное, что отличает процедуру обработки события, так это ее имя. Чтобы процедура обработки события вообще функционировала, ее имя должно состоять из имени объекта (формы или элемента управления), за которым следуют символ подчеркивания и официальное имя события VBA. Посмотрите на следующие примеры:
Private- Sub cmdCalcuiateSquareRoot_Click()
End Sub
Private Sub UserForm_Activate()
End Sub
Private Sub sclVolumeControl__Change ()
End Suk

Когда нужно изменить имя процедуры обработки события
Единственный случай, когда возникают проблемы с именем процедуры обработки
события, — когда имя объекта, которому соответствует процедура, изменяется после создания процедуры. VBA не меняет при этом имя процедуры автоматически,
поэтому вы должны открыть окно программного кода и привести имя процедуры
обработки события в соответствие с новым именем элемента управления.
Например, предположим, что вы создали процедуру обработки события C l i c k (Щелчок)
для кнопки, которой было автоматически присвоено имя C o m m a n d B u t t o n l . Тогда именем
процедуры будет C o m m a n d B u t t o n l ^ C l i c k . Спохватившись, вы изменили имя кнопки на
более информативное, например с т с Ш е р н у т ь И з К о р з и н ы . Но после этого, до тех пор пока вы не измените оригинальное имя процедуры на с п к 1 В е р н у т ь И з К о р з и н ы _ С 1 1 с к , соответствующая кнопка во время выполнения будет просто торчать в форме тихо и безответно, независимо от того, сколько раз вы на ней щелкнете.
Поскольку при изменении имени кнопки VBA не удаляет соответствующие этой кнопке
процедуры, вам не нужно создавать процедуру вновь, а нужно только изменить ее имя. Можно сделать и по-другому: начать новую процедуру обработки события для кнопки, а затем
с помощью команд Cut (Вырезать) и P a s t e (Вставить) перенести программный код из оригинальной процедуры в новую.

Щелкните здесь...
В Windows щелчок ( C l i c k ) является квинтэссенцией всех событий. Вам приходится щелкать на пиктограммах, чтобы выбрать их, щелкать в документах — чтобы позиционировать точку ввода, в меню — чтобы открыть их, и на кнопках — чтобы активизировать связанные с ними
функции. А раз щелчки столь часто используются в пользовательском интерфейсе Windows, вы

Глава 10. Создание интерактивных VBA-форм

245

непременно захотите, чтобы созданные вами формы отвечали на щелчки мыши. Однако для
многих элементов управления не требуется создавать программный код специально для того,
чтобы они отвечали на щелчок (почему это так, объясняется ниже, в разделе "Когда не нужно
создавать процедуры обработки события Click''). Но для самого важного изо всех элементов
управления — для кнопки — программный код создавать придется.
Очевидно, что каждая кнопка должна иметь процедуру обработки события C l i c k , если
вы хотите, чтобы кнопка делала что-нибудь полезное после щелчка на ней. Следующая процедура обработки события просто считает и отображает на экране число щелчков на кнопке:
P r i v a t e Sub cmdCountClicks__Click ( )
' Объявление переменней i n t C o u n t статической сохранит
' ее значение в промежутках между вызовами процедуры
S t a t i c intCount As I n t e g e r
intCount - intCount + 1
c m d C o u n t C l i c k s . C a p t i o n = "Вы щелкали на этой кнопке " _
& intCount & " р а з ( а ) . "
2nd Sub
Представленный здесь программный код достаточно ясен. При каждом выполнении процедуры, которое происходит только после щелчка пользователя на кнопке, знамение переменной i n t C o u n t увеличивается на 3. Это значение используется в строке, которая отображается на кнопке с помощью свойства C a p t i o n кнопки. Кстати, объявление переменной
i n t C o u n t как статической заставляет VBA сохранять значение этой переменной между вызовами этой процедуры обработки события. Если объявить переменную с помощью ключевого слова Dim, переменная будет инициализироваться при каждом вызове процедуры. Вот
процедура обработки события для кнопки с именем cmdMoveThisForm:
P r i v a t e Sub cmdMcveThisForm_Click()
Move(Left - 2 4 ) , (Top -24)
End Sub
Если вам это интересно, после щелчка пользователя на кнопке эта процедура
смещает форму на 24 единицы вверх и на 24 единицы влево. В процедуре всего
одна строка выполняемого программного кода, где метод Move используется без
прямой ссылки на объект, — VBA предполагает, что ссылка указывает на главный объект формы, т.е. на саму форму. Если нужно вместо формы переместить
содержащуюся в ней кнопку, используйте cmdMoveThisForm. Move, чтобы
указать этот объект как целевой. Точно так же, если нет явной ссылки на объект,
то подразумевается, что свойства L e f t и Тор относятся к форме.
Эти два примера довольно тривиальны, но в то же время они хорошо иллюстрируют, что процедуры обработки событий выглядят и работают точно так же, как и любые другие процедуры.
Превращение закрытых процедур в открытые
Процедуры обработки событий особые потому, что VBA выполняет их автоматически при наступлении
определенного события. Но поскольку в хтальном процедура обработки события ничем не отличается
от обычной процедуры, вы можете вызывать ее из программного кода как обычную. Просто выделив имя
процедуры в отдельный оператор, например:
стсШоказФокусов Click

246

Часть П. Курс программирования на VBA

; вы даете указание выполнить процедуру, по сути, заставляя VBA думать, что случилось соответст:
вующее событие.
• По умолчанию процедуры обработки событий локальные ( P r i v a t e ) , т.е. при создании процедуры VBA
: автоматически добавляет в начало ее объявления ключевое слово P r i v a t e . В таком случае выполнять этипроцедуры можно только из программного кода, связанного с данной формой.
Однако ничто не мешает вам удалить ключевое слово P r i v a t e и напечатать вместо него P u b l i c .
Тогда вы сможете вызывать соответствующую процедуру обработки события и из любой другой части
программы. Здесь кроется одна тонкость: прежде чем вызывать открытые ( P u b l i c ) процедуры фор\ мы, форму нужно загрузить в память (но не обязательно показывать на экране).

Когда не нужно создавать процедур обработки события Click
Большинство элементов управления VBA распознают событие C l i c k . Но, за исключением
кнопок, обычно нет необходимости и даже неразумно создавать процедуру обработки события
C l i c k , даже если нужно, чтобы объект отвечал на щелчки кнопки мыши. Причина в том, что
эти элементы управления отвечают на щелчки автоматически и обычно так, как требуется.
Предположим, вы поместили в форму VBA несколько кнопок. После запуска формы на
выполнение щелчок на кнопке выделяет эту кнопку и для этого не требуется никакого программирования. Точно так же VBA автоматически обрабатывает щелчки на кнопках выключателей и переключателей. VBA знает, что щелчок должен изменить состояние элемента
управления на противоположное, если для элемента управления предусмотрено только два
состояния (состояние включен/выключен— для выключателя, отмечен/не отмечен— для
флажка и т.д.). А после щелчка в поле текста этот элемент управления автоматически перемещает курсор ввода в то место, где вы щелкнули.
Но VBA не может передать информацию о состоянии элемента управления вашей программе— это придется делать вам, создавая программный кол. Что введет пользователь
в поле текста? Какой флажок отметит и для какого снимет отметку? Какую из кнопок переключателей выберет? Ваша программа не узнает об этом до тех пор, пока вы не создадите
программный код, позволяющий выяснить и обработать эту информацию.
Здесь нужно использовать свойство V a l u e , в котором содержится информация о текущем состоянии элемента управления, если этот элемент управления может быть в разных состояниях или содержать данные. Вы можете заставить программу считывать значение свойства V a l u e при каждом его изменении, если создадите процедуру обработки события
C h a n g e . Можно также просто прочитать значение свойства V a l u e после того, как форма
будет скрыта с экрана. Подробнее об этом — в разделе, посвященном событию C h a n g e ,
и разделе "Основные приемы программирования форм".

События Click в формах
Сама форма тоже имеет событие C l i c k . На практике, конечно, большинство форм используется просто как подложка для размещения кнопок, текстовых полей и других элементов управления. Но при желании вся форма может играть роль одной большой кнопки, и тогда щелчок в любом ее месте будет инициировать выполнение чего-нибудь очень полезного в программе.
Для этого нужно поместить программный код соответствующих действий в процедуру
обработки события C l i c k формы:
P r i v a t e Sub U s e r F o r m _ C i i c k ( )
. . . ( п р о г р а м м н ы й код, инициируемый событием)
End Sub

Глава 10. Создание интерактивных VBA-форм

247

Обратите внимание на то, что имена всех процедур обработки событий формы начинаются с U s e r Form, независимо оттого, какое имя вы назначили самой форме. Если вы действительно собираетесь создавать процедуру обработки события C l i c k формы, то должны четко
представлять себе, что VBA выполнит эту процедуру после шелчка пользователя только в той
части формы, которая не закрыта каким-нибудь элементом управления. Другие процедуры
обработки событий, связанных с манипуляциями мышью, работают аналогично.

Создание программного кода для события Change
Для элементов управления типа полос прокрутки, кнопок прокрутки переключателей и выключателей главным событием является событие C h a n g e . Эти элементы управления реагируют
на щелчки мыши и нажатия клавиш, но реагируют автоматически. VBA вместе с Windows делают всю "грязную" работу по изменению внешнего вида элемента управления и изменению его
установок в соответствии с тем, какие клавиши или какие кнопки мыши были нажаты.
Возможно, вы захотите, чтобы программа отвечала не на сами нажатия, а на те изменения, к которым они привели. В таком случае вы должны создать программный код для события C h a n g e . Событие C h a n g e происходит, когда изменяется значение элемента управления
(т.е. когда изменяется значение свойства V a l u e ) . При этом не имеет значения, почему произошло изменение значения— после шелчка кнопки мыши или печатания либо потому, что
какая-то процедура в программе в одном из своих операторов манипулировала значением
свойства V a l u e этого элемента управления.
Не исключено также, что вы захотите, чтобы программа отвечала на изменение значения
некоторого элемента управления по окончании работы с ним пользователя. В таком случае
нужно создать программный код для события Af t e r U p d a t e , которое возникает при передаче фокуса ввода другому элементу управления.
С помощью процедуры обработки события можно сделать гораздо больше, чем просто
отобразить новое значение элемента управления. Например:
проверить, удовлетворяет ли это значение заданным критериям;
сначала выполнить вычисления, основанные на этом значении, а затем определенные
действия, в зависимости от результатов вычисления;
использовать значение элемента управления для того, чтобы установить другое значение, например для громкости звука динамика вашего компьютера.

Распознавание нажатий клавиш
Используйте события K e y p r e s s , KeyDown и KeyUp, чтобы отвечать на нажатия клаииш пользователем. Событие K e y p r e s s удобно использовать для распознавания клавиш
с обычными "печатаемыми" символами (буквы, числа, знаки пунктуации), когда нужно обработать информацию, вводимую в текстовое поле или в поле со списком. С помощью этого
события распознаются также многие из комбинаций типа , а также клавиша
. Немного позже я покажу, как проверить или изменить напечатанный символ
с помощью процедуры обработки события K e y P r e s s .
События KeyDown и KeyUp, напротив, распознают практически любую посылаемую им
комбинацию клавиш, включая выкрутасы типа . С этими событиями работать труднее, чем с K e y P r e s s , но зато они позволяют использовать более широкий набор сочетаний клавиш. Например, можно создать процедуру обработки события KeyDown, которая позволяет с помощью комбинаций соответственно уменьшать или увеличивать значение полосы прокрутки, например, на 10.

248

Часть II. Курс программирования на VBA

Основные приемы программирования форм
Теперь, уяснив, как работают процедуры обработки событий, вы сможете применить свои
знания при создании диалоговых окон, которые будут работать так, как хотите вы, и так, как
ожидают пользователи. В этом разделе мы обсудим целый ряд сценариев, применяемых при
создании диалоговых окон.

Добавление кнопок Закрыть и Отмена
Большинство диалоговых окон имеют, как минимум, одну кнопку главной команды и кнопку,
убирающую диалоговое окно с экрана. В зависимости от того, что делает диалоговое окно, на этой
кнопке обычно написано либо Закрыть, либо Отмена, но вполне допустимы и другие надписи —
Выход, Готово, Пропустить, Закончить и т.п. Такая кнопка потребуется любой вашей форме.
По общепринятому соглашению кнопки Закрыть и Отмена просто прячут или выгружают форму, и ничего больше. Следующие рекомендации помогут определить, какая из этих
кнопок лучше подойдет для вашей формы.
I /
|
|

Используйте кнопку Закрыть для форм, которые только отображают информацию
или выполняют свою задачу немедленно, без изменения установок программы или
модификации переменных, которые будут использоваться в программе позже.

I S
I
|
I
|

Используйте кнопку Отмена для форм, которые изменяют переменные или установки
программы. После щелчка пользователя на кнопке Отмена диалоговое окно должно
закрыться без записи таких изменений — все должно остаться так, как было до открытия диалогового окна. Такая форма должна также иметь кнопку ОК, щелчок на
которой подтверждает изменения и вносит их.

Простые процедуры обработки событий для кнопок Закрыть и Отмена
Подобно любым другим кнопкам, для того чтобы отвечать на щелчки на них, кнопки
Закрыть и Отмена требуют создания процедур обработки события C l i c k . В большинстве
случаев эти процедуры содержат всего один оператор, как в следующих двух примерах:
P r i v a t e Sub crndClose_C±ick (}
Hide ' здесь подразумевается ссылка на форму
End Sut
P r i v a t e Sub cmdCar.cel_Click ()
Unload frmOptions
End Sut
Для любой кнопки можно использовать метод H i d e или оператор U n l o a d . Разница между этими двумя способами закрытия формы обсуждалась в разделах "Как скрыть видимую
форму" и "Удаление формы из памяти".
Конечно, процедуры, связанные с кнопками Закрыть и Отмена, могут до закрытия формы сделать что-то еще, например отобразить диалоговое окно, в котором пользователю предлагают подтвердить (или не подтвердить) желание закрыть форму.
P r i v a t e Sub c m d C l o s e _ C l i c k ( )
Message = "Вы действительно хотите закрыть " _
& "диалоговое окно и отменить все " _
5 "внесенные вами и з м е н е н и я ? "
If MsgBox(Message, vbYesNo) = vbYes Then
Hide ' закрыть, если п о л ь з о в а т е л ь ответил Да
End If ' иначе не делать ничего
End Sut

Глава 10. Создание интерактивных VBA-форм

249

Клавишная альтернатива
Не забудьте связать кнопку Закрыть и Отмена с клавишей . Пользователи
привыкли нажимать для выхода из диалоговых окон, и вы не должны обманывать их ожиданий. Тем более, что в данном случае не придется создавать
процедуру обработки события K e y P r e s s - — просто установите для свойства
C a n c e l значение T r u e в окне свойств.

Программирование кнопки О К
Представьте себе типичное диалоговое окно. Вы ожидаете, что после щелчка на кнопке
ОК программа воспримет введенные в окно данные как окончательные и соответствующим
образом изменит внешний вид, поведение или данные программы. После этого форма должна
удалить себя с экрана.
В соответствии с этими ожиданиями вы должны создать и процедуру обработки события
C l i c k для кнопки ОК. Все, что должен сделать в данном случае программный код,— это
передать значения от элементов управления переменным программы или использовать значения элементов управления в условных выражениях. Последняя строка процедуры должна содержать либо метод Hide, либо оператор Unload. В следующих примерах txtCName
и t x t C A d d r e s s представляют текстовые поля. Первых два оператора передают их значения соответствующим переменным программы. Затем программа проверяет состояние выключателя t g l S e n d и, если он включен, выполняет процедуру S e n d B i l l T o C u s t o m e r .
Наконец, она прячет форму:
P r i v a t e Sub cmdOK_Click()
strCustomerName = txtCName .Value
strCustomerAddress = txtCAddress.Value
' проверка состояния выключателя
If t g l S e n d . V a l u e = True Then
SendBillToCustomer
End I f
Hide
End Sub

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

250

Часть II. Курс программирования на VBA

л - вредит*
номер своего
удостоверения
члена кпубо:

Сьсаи-ь мажю только числе! Пожалуйста, погатодитв ввод

Рис. 10.27. Для проверки введенных данных в текстовом поле
и отображения этого сообщения об ошибке использовалась
процедура обработки события Change

Программный код проверки
Проверка значений элементов
управления
требует использования
операторов
I f . . . T h e n и S e l e c t C a s e . В следующем простом примере проверяется на допустимость значение элемента управления кнопками прокрутки:
P r i v a t e Sub spnVolumeControl_Change(>
If s p n V o l u m e C o n t r o l . V a l u e = 13 Then
MsgBox "13 не я в л я е т с я допустимым з н а ч е н и е м . "
End I f
End Sub

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

Используемая процедура

При нажатии любой клавиши

Процедура об работки события K e y P r e s s для
элемента управления (для выяснения
информации о нажатии отдельной клавиши)

При любом изменении значения элемента
управления

Процедура обработки события C h a n g e (для
оценки значения)

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

Процедура обработки события
B e f o r e U p d a t e (позволяет отменить
обновление данных и вернуть пользователя
к текущему элементу управления)

При закрытии формы пользователем

Процедура обработки события c l i c k для
кнопок О К или З а к р ы т ь в форме

Глава 10. Создание интерактивных VBA-форм

251

Как выбрать событие для проверки
Вы сами должны выбрать подходящую для проверки процедуру, ответив на следующие вопросы.
" V Насколько быстро должен выполняться программный код проверки?
•S В какой момент нужно информировать об ошибке пользователя— в момент появления неправильного значения или уже после того, как пользователь закончит формирование вводимых данных?
•S Основывается ли проверка на значениях, полученных от нескольких элементов
управления?

252

Часть II. Курс программирования на VBA

Часть III

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

В эйй>й час&и...
После того как вы познакомились с основами программирования
на VBA и решили попробовать свои силы, вам пора изучить
материал части III В главе 11 рассматриваются встроенные
функции и операторы VBA; я не рекомендую вам создавать
собственную процедуру, если встроенная функция сможет
выполнить те же действия всего в одну строку. В главе 12 мы
поговорим об использовании объектов. В главе 13 мы еще раз
затронем тему управления данными, однако на этот раз речь
будет идти о таких сложных вопросах, как использование
массивов и коллекций.

Глава 11

Инструменты встроенного оркестра VBA
гиабе...
>

Использование встроенных команд вместо нового изобретения программирования

>

Безопасное форматирование данных с помощью функции F o r m a t

>

Преобразование данных одних типов в другие

>

Работа с текстовыми строками

> Забавы с датами и временем
> Использование математических и финансовых функций

ш ж режде чем создавать свою собственную процедуру с чистого листа, убедитесь, что вы
^ Х С* не изобретаете велосипед. Каждая версия VBA приходит с небольшим арсеналом
встроенных команд, предназначенных для решения самых разнообразных часто возникающих
задач. В этой главе предлагается обзор наиболее полезных из таких готовых к бою единиц вооружения. Кое-что в этот обзор не вошло и обсуждается среди прочего в других главах.

Зяалоиюнво со валютными
Похоже, VBA немного не соответствует тому имиджу, который он себе создает. Ох, как
отчаянно VBA хочет выглядеть истинным объектно-ориентированным языком программирования (об объектно-ориентированном программировании мы поговорим в главе 12). С другой стороны, следует признать, что есть кое-что, что вы хотели бы иметь в программе, но
нельзя сказать, что это естественным образом умещается в матрицу объектноориентированного подхода.
В своем решении, достойном всех наших депутатов, VBA помещает в метод объекта как минимум одну команду, которую было бы естественнее оставить независимой, и в то же время оставляет независимыми другие действия, которые вполне подходят для связывания их с объектами.
В обшем, учитывая, что некоторые действия могут оказаться в нелогичных для них категориях, вы получаете три типа встроенных VBA-команд, способных выполнять полезную работу.
Операторы. Хотя термин оператор уже используется для обозначения целой программной директивы (см. главу 7), VBA называет операторами и отдельные ключевые
слова, выполняющие специальные задачи. Некоторые из таких ключевых слов функционируют сами по себе как целые операторы. Например, оператор В е е р заставляет
динамик компьютера издавать звук. Другие же должны использоваться как составные
части законченных операторов. Например, оператор C h D i r (перейти в каталог) бесполезен без аргумента, задающего каталог или папку, куда нужно перейти:

ChDir{"ХОтчеты о мечтаниях")

Глава 11. Инструменты встроенного оркестра VBA

255

Функции. Встроенные функции работают точно так же, как и процедуры типа
F u n c t i o n , обсуждавшиеся в главе 7,— в том смысле, что они возвращают значение. Использование функции часто заключается в присваивании ее значения переменной, как в следующем примере с функцией Tan (тангенс):
с!ЫТангенс = Tan (с!ЫЛю5ойУгол)
Функции могут также обеспечивать значения для более сложных выражений или условных операторов, например:
If Tan (дЫОстрыйУгол)

< 45 Then

Методы встроенных объектов. В этой группе курьезно выглядит метод P r i n t , единственный для объекта Debug и предназначенный для направления вывода в окно немедленного выполнения команд (окно Immediate) в редакторе Visual Basic. Для этого
используются операторы типа
Debug . P r i n t (э^ПосланиеМарсианина)
X •/ Лично я не вижу никаких преимуществ в связывании команды P r i n t с объектом, но
[
сам по себе метод P r i n t оказывается очень полезным. Подробно он обсуждается
I
в главе 14. Здесь же замечу, что, хотя VBA и не инкапсулирует файлы, как объекты,
I
можно дополнительно установить программную надстройку, которая позволит управ•
лять файлами и работать с их содержимым на основе объектно-ориентированного
I
подхода (подробности — в главе 12).
В табл. 11.1 приводятся некоторые из встроенных VBA-команд, взятые для примера и относящиеся к различным категориям (операторы, функции, методы). Дальше в главе будут рассматриваться чаще всего используемые встроенные команды.
Таблица 11.1. Примеры встроенных функций, операторов и методов
Команда

Тип

Выполняемые действия

Randomize

Оператор

Инициализирует генератор случайных чисел

Sqr (число)

Функция

Возвращает значение квадратного корня числа

Format (строка)

Функция

Форматирует строку в соответствии с заданным описанием

Date

Оператор

Устанавливает системную дату

Date

Функция

Возвращает текущую системную дату

Err . Raise

Метод объекта E r r Генерирует ошибку выполнения с заданным кодом

данных
VBA-функции F o r m a t форматируют данные любого из встроенных типов по указанному образцу для отображения их на экране или на печати. С помощью этих функций
очень просто отображать значения дат в виде короткого (19.12.99), среднего (19-дек-99)
или длинного формата даты (19 декабря 1999 г.), или любого из нескольких других
предлагаемых VBA форматов (VBA хранит значения дат в виде совершенно неудобоваримых чисел). Подобные трюки можно выполнять и с числовыми значениями, и со строками. На самом деле. F o r m a t конвертирует предложенное вами значение в новую строку, добавляя в нее символы, необходимые для представления данных в нужном виде.

256

Часть III. Практикуемся в программировании на VBA

Функция F o r m a t предлагается и в VBA 5, и в VBA 6, однако VBA 6 может похвастать
еще четырьмя новыми родственными функциями, каждая из которых предназначена для своего конкретного типа данных.

Работа с функцией Format
Функция Format, имеющаяся в VBA 5 и VBA 6,— невероятно гибкая. Она применима
практически к любым типам данных и имеет настраиваемый вывод— если ни один из встроенных форматов не подойдет, вы можете создать свой, какой пожелаете.
В упрощенной форме синтаксис функции Format выглядит так (здесь опущены два необязательных и редко используемых аргумента, относящихся к датам, — о них вы можете узнать из справки VBA):
Format(выражение,"формат")
Аргумент выражение должен содержать выражение, представляющее число, строку или
дату, которые вы хотите форматировать (т.е. отобразить в подходящей форме). Ясно, что
этот аргумент обязателен.
Аргумент формат и является тем аргументом, который выполняет реальную
работу. Как видно из следующего примера, аргумент формат нужно заключить в кавычки.
Чтобы использовать функцию Format, присвойте ее переменной либо свойствам Value
или Capt i o n элемента управления в форме. Например, оператор
l b l D a t e M e s s a g e . C a p t i o n = "Сегодня " & _
Format(Now, "Long d a t e " )
отображает текст "Сегодня 19 март 2001 г." в виде текста надписи элемента управления
l b l D a t e M e s s a g e (в предположении, что сегодня 19 марта 2001 года).

Использование встроенных форматов для функции Format
В табл. 11.2 приводятся именованные встроенные форматы для данных различных типов
в VBA. Используйте их как аргумент в функции Format. He забудьте при этом заключить в
кавычки имя выбранного вами формата (из первого столбца таблицы).
Таблица 11.2. Именованные форматы для использования с функцией F o r m a t
Имя формата

Описание вывода

Пример (соответствует
установке языка Русский
в панели управления)

Числовой
G e n e r a l N u m b e r Число без выделения разрядов тысяч

2001,5599

Currency

2 001,56р.

Fixed

Число с выделением разрядов тысяч и с двумя
знаками после десятичного разделителя,
а также с символом денежной единицы
Как минимум один знак слева и два знака
справа от десятичного разделителя (без
выделения разрядов тысяч)

Глава 11. Инструменты встроенного оркестра VBA

3390,10

257

Окончание табл. 11.2
Пример (соответствует
установке языка Русский
в панели управления)

Имя формата

Описание вывода

Standard

Число с выделением разрядов тысяч и как
минимум одним знаком слева и двумя знаками
справа от десятичного разделителя

1 323,45

Percent

Число, умноженное на 100, с двумя знаками
справа от десятичного разделителя и знаком
процентов {%) справа

12,54%

Scientific

Число в стандартном виде для научных
расчетов

1,23Е+02

Yes/No

Нет, если значение равно 0, иначе Да

Да

True/False

Ложь, если значение равно 0, иначе Истина

Истина

On/Off

Выкл, если значение равно 0, иначе Вкл

Вкл

Дата и/или время, в зависимости от значения,
представленного в соответствии с установками
в панели управления

15.03.9817:27:45

Логический

Дата/время
General Date

Long

Date

Дата в виде, заданном в панели управления
для полного формата даты

15 Март 2001 г.

Medium Date

Дата в виде, заданном в панели управления
для среднего формата даты

15-мар-01

Short Date

Дата в виде, заданном в панели управления
для краткого формата даты

15.03.01

Long

Время (часы, минуты и секунды) в виде,
заданном в панели управления для полного
формата времени

17:27:45

Medium Time

Время (часы и минуты) в 12-часовом формате
с метками до/после полудня, заданными
в панели управления

05:27

S h o r t Time

Время (часы и минуты) в 24-часовом формате

17:27

Time

Создание собственных форматов
Можно создать свои собственные форматы, собрав их из символов, имеющих специальные значения для аргумента формат. Например, чтобы отобразить строки текста символами верхнего или нижнего регистров, используйте функцию F o r m a t с аргументами
" > " или " < " соответственно. За неимением места я не могу описывать все эти специальные символы— вы найдете их самостоятельно, открыв сначала раздел Format Function
(функция F o r m a t ) в файле справки VBA, а затем щелкнув на ссылке See Also (см. также)

258

Часть III. Практикуемся в программировании на VBA

и просмотрев разделы User-defined Formats (пользовательские форматы). Но чтобы не
совсем вас разочаровывать, я привожу следующий пример с парой пользовательских форматов в действии. Кроме того, этот же пример иллюстрирует использование еще одной
встроенной функции VBA — l i f :
MsgBox "Сейчас " & Format(Now, " h : n n " ) & _
". Это время " & Ilf(Format{Now, " a / p " ) = " a " ,
"до о б е д а . " , "после о б е д а . " )
Если вы выполните этот программный код до обеда, оператор отобразит на экране строку
типа "Сейчас 9:07. Это время до обеда". После обеда вы получите нечто похожее на сообщение, показанное на рис. 11.1. (Кстати, функция MsgBox обсуждается ниже в этой же главе
в разделе "Отображение окон сообщений".)

Рис. 11.1. Окно сообщения
Теперь объяснения. В первой функции Format аргументом формат является " h : n n " .
Символ h соответствует стандарту отображения часа одной цифрой, когда имеется в виду
время до 10:00. После двоеточия пп задает отображение минут с незначащим нулем, если
прошло меньше 10 минут после начала часа.
Вторая из используемых функций F o r m a t вложена в функцию I l f . Ввиду того, что
аргументом формат в данном случае является " а / р " , возвращаемыми значениями будут просто либо " а " , либо " р " , в зависимости от того, превышает время 12 часов дня
или нет. Обычно а / р используется как компонент более длинной строки аргумента
формат, но в данном случае результат функции видеть не требуется, и он обрабатывается функцией I l f .

Использование функции Ilf
Функция I l f — это миниатюрная версия оператора I f . . . Then (обсуждаемого в деталях в главе 32). Синтаксис этой функции следующий:
I l f (выражение, результатЕслиИстина, результатЕслиЛожь)
В переводе на "человеческий" язык функция работает следующим образом: если
выражение есть истина, то функция возвращает значение р е з у л ь т а т Е с л и И с т и н а , если
же выражение есть ложь, то возвращается значение р е з у л ь т а т Е с л и Л о ж ь .
В прелыдущем примере выражением для проверки было
Format(Now, " а / р " ) = " а "
Поэтому если функция F o r m a t возвращает значение а, данное выражение есть Истина.
Если же она возвращает любое другое значение, включая р, то выражение есть Ложь. Затем
VBA вычисляет результат функции 11 f на основе того, является ли значение выражения истиной или ложью. Если это значение Истина, функция I l f возвращает до обеда, а если
Ложь, то после обеда.

Глава 11. Инструменты встроенного оркестра VBA

259

Работа с другими функциями форматирования
В VBA 6 были добавлены несколько функций, подобных функции Format, — F o r m a t Number, F o r m a t D a t e T i m e , F o r m a t C u r r e n c y и F o r m a t P e r c e n t — для работы
сданными соответствующих типов. Подобно оригинальной функции Format, каждая из
этих функций-наследниц возвращает строку с форматированным представлением исходного
значения. Ввиду того, что эти новые функции по умолчанию возвращают результаты, нужные
вам чаще всего, эти функции могут оказаться в использовании удобнее, чем сама функция
Format. Вкратце их работу можно описать следующим образом.
I S FormatNumber(число,ЧислоЗнаковПослеЗапятой,
|
ОтображатьНезначащийНуль,
|
ИспользоватьСкобкиДляОтрицательныхЧисел,
ГруппироватьРазряды). Возвращает значение числа— единственного обязательного аргумента— в виде форматированной строки. Если опустить необязательные аргументы, функция FormatNumber отформатирует число на основе установок по
умолчанию, заданных на вкладке Числа окна контрольной панели Язык и стандарты
Windows. В предположении, что языком Windows выбран русский, вы получите число
вида 132 328,55. Необязательные аргументы функции FormatNumber позволяют изменить заданные по умолчанию значения для числа знаков после запятой, отображения
незначащего нуля перед запятой для чисел, меньших 1, представления отрицательных
чисел в скобках и отделения групп разрядов одной от другой (например, пробелами).
F o r m a t D a t e T i m e ( д а т а , формат). Конвертирует значение даты в форматированную строку. Если аргумент формат не указан, строка форматируется в соответствии с системными установками для краткого формата даты и длинного формата времени, заданными на вкладках Дата и Время панели управления Язык и стандарты
Windows. Здесь аргумент формат является числом (а не строкой, как в функции
Format), но его можно задавать, используя именованные константы вида vbLongD a t e или v b S h o r t T i m e .
F o r m a t C u r r e n c y ( ч и с л о ) . Возвращает значение числа, отформатированного как
денежное, в соответствии с текущими установками в панели управления. В остальном
функция F o r m a t C u r r e n c y работает подобно функции FormatNumber и имеет те
же необязательные аргументы.
F o r m a t P e r c e n t ( ч и с л о ) . Умножает число на 100 и добавляет знак процентов
(например, 0,05 превращается в 5,00%). Функция F o r m a t P e r c e n t имеет те же необязательные аргументы, что и функция FormatNumber. Чтобы не выводить знаки дробной части, задайте аргумент Ч и с л о З н а к о в П о с л е З а п я т о й равным 0
(например, F o r m a t P e r c e n t ( . 0 5 , 0)).

уашшх
Как упоминалось в главе 9, VBA автоматически конвертирует данные одних типов в другие "на лету". Такие автоматические преобразования, конечно, удобны, да и получаемые при
этом результаты обычно соответствуют желаемым. Правда, при этом нужно обязательно
подчеркнуть слово обычно.
Когда автоматическое преобразование вас не устраивает, VBA готов предложить массу
функций для явного преобразования данных одних типов в другие. Эти функции можно использовать для того, чтобы

260

Часть III. Практикуемся в программировании на VBA

I S быть уверенным, что VBA выполняет именно то преобразование, которое нужно;
| S выполнить преобразования, которые не выполняются в VBA автоматически;
| ^ сделать свой программный код яснее.
Для конвертирования данных в VBA предусмотрена целая группа функций — CBool, CByt e,
CCur и т.д. — своих для каждого из встроенных типов данных, за исключением Ob j e c t . Например, в результате выполнения оператора boolMaybe = CBool (123) переменная b o o l Maybe будет содержать значение True (вообще любое число, не равное нулю, в результате даст
True, наверное потому, что любое такое число ассоциируется с чем-то существующим).
Замечу, однако, что, кроме превращения самой операции конвертирования в явную, эти
функции не делают ничего такого, что не может предложить VBA при автоматическом конвертировании. (Об особенностях функции С Dec см. в главе 9.)
Функции F i x и I n t отбрасывают дробную часть любого заданного им числа, возвращая
целое число. Но, в отличие от функций C I n t и CLng, они не выполняют привычного округления — например, I n t (4 . 98 9) возвращает 4, а не 5.
Результаты этих двух функций отличаются только при обработке отрицательных чисел.
Тогда I n t возвращает ближайшее к значению аргумента меньшее целое число, a F i x просто
отбрасывает дробную часть аргумента.

Работа с шестнадцатеричными и восьмеричными значениями
Функции Hex и Oct преобразуют стандартные десятичные целые числа в строки,
содержащие соответственно их шестнадцатеричные и восьмеричные эквиваленты.
Возможность явного конвертирования в обратном направлении в VBA не предусмотрена, но зато вы можете напечатать буквальные шестнадцатеричные или
восьмеричные значения и позволить редактору Visual Basic превратить их в десятичные автоматически. При этом любой шестнадцатеричный или восьмеричный
литерал должен предваряться специальным кодом: шестнадцатеричный — кодом
&Н, а восьмеричный — кодом &О (это буква О, а не цифра 0). Например, в результате выполнения оператора i n t B a s e s = 10+&О12 + &НА значением переменной i n t B a s e s будет число 30, как и должно быть (это очевидно).

Преобразование чисел в строки и наоборот
Некоторые функции VBA конвертируют числа в строки. К таким функциям относятся
следующие.
I S C S t r . Превращает данные любых типов (кроме типа O b j e c t ) , включая числовые,
\
в соответствующую им строку. Вывод форматируется в соответствии с установками,
I
заданными в панели управления Язык и стандарты Windows. Например, во Франции
I
C S t r ( 2 0 0 . 0 2 ) на выходе выдаст строку " 2 0 0 , 02". Здесь следует заметить, что
|
хотя результирующая строка и соответствует региональным установкам, подаваемые
1
на вход числовые данные должны быть представлены в формате, соответствующем
|
английскому языку США.
I •/ S t r . Конвертирует число в строку, но всегда форматирует строку в соответствии со
|
стандартом английского языка США с точкой в качестве десятичного разделителя.
I V функции конвертирования в числовые типы данных. Конвертируют строки в соI
ответствующие числовые значения, но только тогда, когда все символы в строке рас-

Глава 11. Инструменты встроенного оркестра VBA

261

познаются как допустимые для чисел. В данном случае тоже все зависит от установок
в панели управления. Например, в России CDbl ( " 2 0 0 , 0 2 р . ") в результате дает
2 0 0 , 02; в США тот же оператор порождает ошибку, но CDbl ( " $ 2 0 0 . 0 2 " ) прекрасно работает.
V a l . Конвертирует числа в строках в числовые значения, останавливаясь там, где
встречается первый символ, недопустимый для чисел. Независимо от установок панели управления, распознает только цифры и десятичную точку (а не запятую, например). Однако игнорирует пробелы, символы табуляции и переходы на новую строку.
Так, выражение Val ("28 1 9 0 . 4 3 12 by 14 ") в результате даст 28190,4312.
Chr. Конвертирует числовой ANSI-код в соответствующий символ. Используйте эту
функцию, когда в строку нужно поместить символ, который нельзя напечатать.
Asc. Примерно соответствует обратной к функции Chr —- возвращает числовой код
первого символа в строке.

со cMftOKoutu
В VBA имеется довольно богатая коллекция операторов и функций для форматирования
строк и извлечения тех их частей, которые вы сочтете особенно привлекательными. В табл. 11.3
я представил все относящиеся к строкам команды, которые мне удалось обнаружить.
Таблица 11.3. Операторы и функции для обработки строк
Не забывайте, что буквальные строковые значения (в отличие от переменных, содержащих
строковые значения) должны заключаться в кавычки.
Оператор или функция

Тип

Выполняемые действия (для операторов) или
возвращаемые значения (для функций)

Asc (строка)

Функция

Числовой код первого символа в строке

Chr ( к о д _ с и м в о л а )

функция

Символ, соответствующий значению параметра
код_символа

Filter
(массив_источник,
э т а л о н , включает,
метод сравнения)

Функция
(только в
VBA6)

Массив, состоящий только из тех строк из массиваисточника, которые содержат э т а л о н . Аргумент
м а с с и в _ и с т о ч н и к должен быть массивом
строковых значений. Если необязательный аргумент
в к л ю ч а е т равен F a l s e , то функция возвратит
только строки, которые не включают э т а л о н

Format {строка)

Функция

См. выше раздел "Форматирование данных"

Hex ( ч и с л о )

Функция

Строка, содержащая шестнадцатеричное представление
числа

InStr (старт,
строка1, строка2)

Функция

Число, соответствующее позиции строки 2 в строке 1;
поиск начинается с позиции с т а р т , этот аргумент не
обязателен

I n S t r R e v ( с т р о к а 1,
строка2, старт)

функция
(только в
VBA6)

Число, соответствующее позиции строки 2 в строке 1,
считая с правого края строки 1; поиск начинается с
позиции с т а р т , этот аргумент не обязателен

262

Часть III. Практикуемся в программировании на VBA

Продолжение табл. 11.3
Оператор или функция

Тип

J o i n (массив_строк, функция
разделитель)
(только
BVBA6)

Выполняемые действия (для операторов) или
возвращаемые значения (для функций)
Одна строка, комбинирующая все строки из
м а с с и в _ с т р о к , который должен быть массивом
строковых данных. По умолчанию J o i n вставляет
пробел между строками, взятыми из массива строк, но
можно задать и другой символ разделителя (символ
необходимо заключить в кавычки)

Функция

Строка указанной длины из символов, взятых подряд из
строки, задаваемой аргументом с т р о к а , начиная
с левого края последней

Len (строка)

Функция

Число символов в строке

LCase (строка)

Функция

Копия строки, представленная символами нижнего регистра

LSet с т р о к о в а я _
переменная =
строка

Оператор

Устанавливает значение строковой переменной, равное
заданной строке, без изменения длины этой строковой
переменной и с размещением заданной строки начиная
с левого края переменной

LTrim (строка)

Функция

Новая строка, содержащая копию данной строки без
пробелов в начале

Left (строка,
длина)

Mid(строка,
Функция
старт, длина)
Mid(строковая
Оператор
переменная, старт,
длина) = строка

Новая строка заданной длины из символов данной
строки, взятых подряд, начиная с позиции с т а р т

Oct(число)

Функция

Строка, содержащая восьмеричное представление числа

Replace(строка,
найти, заменить,
старт,
число_замен,
метод сравнения)

Функция
(только в
VBA6)

Новая строка, получаемая в результате замены в заданной
строке текста н а й т и текстом з а м е н и т ь . Аргументы
старт, число_замен иметод_сравнения
не обязательны. Используйте ч и с л о _ з а м е н , чтобы
указать, сколько замен следует сделать, если текст н а й т и
встречается несколько раз (по умолчанию заменяются все
случаи появления текста н а й т и в строке}

Right (строка,
длина)

Функция

Строка указанной длины из символов, взятых подряд из
строки, задаваемой аргументом с т р о к а , начиная
с правого края последней

RSet зтроковая_
переменная =
строка

Оператор

Устанавливает значение строковой переменной, равное
заданной строке, без изменения длины этой строковой
переменной и с размещением заданной строки
с правого края переменной

RTr im {строка)

Функция

Новая строка, содержащая копию данной строки без
пробелов в конце

Space (число)

Функция

Строка, состоящая из указанного числа пробелов

Начиная с позиции с т а р т заменяет символами данной
строки заданное аргументом д л и н а число символов
в строковой переменной

Глава 11. Инструменты встроенного оркестра VBA

263

Окончание табл. 11.3
Выполняемые действия (для операторов) или
возвращаемые значения (для функций)

Оператор или функция

Тип

Split(строка,
разделитель,
предел,
метод сравнения)

Функция (только Массив строк, полученный в результате разделения
в VBA 6)
заданной строки. По умолчанию оригинальная
с т р о к а разделяется по пробелам, но можно
задать р а з д е л и т е л ь , отличный от пробела (для
задания разделителя используйте символ,
заключенный в кавычки). Необязательный аргумент
п р е д е л задает максимальное число строк в
возвращаемом массиве

StrComp(строка!,
строка2)

Функция

О, если две строки равны; -1,если с т р о к а 1 меньше,
чем с т р о к а 2 ; 1, если с т р о к а ! больше, чем
с т р о к а 2 (о сравнении строк говорилось в главе 9)

StrConv(строка,
метод перевода)

Функция

Новая строка, созданная на основе заданной указанным
методом перевода

String(число,
символ)

Функция

Строка, состоящая из заданного числа повторяющихся
символов

StrReverse
(строка)

Функция {только Строка, содержащая символы заданной строки
BVBA6)
в обратном порядке

Trim(строка)

Функция

Новая строка, содержащая копию данной строки без
пробелов в начале и конце

UCase(строка)

Функция

Копия строки, представленная символами верхнего
регистра

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

Отбрасывание символов в конце строк с помощью Len и Left
Представим, например, что у вас есть список полных имен в виде следующих строк:
"Самодур, Иван Акакиевич, а к а д . "
"Невеселый, Степан Федорович, п р о ф . "
"Шутник, Василий Степанович, к а н д . "
(такой список должен храниться в массиве строк; массивы будут рассматриваться в главе 13).
Предположим, что кто-то заставил вас убрать звания в конце каждой из вышеприведенных строк. Имена в списке имеют разную длину, так что готовые функции задачу не решают.
Но если предположить, что оригинальное имя содержится в переменной str-Старая, то
поможет следующий трюк:
strHoeaH = L e f t ( s t r C T a p a f l , Len(strCTapan) - 7)
Если бы VBA читал книги вместо программного кода, я объяснил бы ему, что эти действия можно выполнить следующим образом.

264

Часть III. Практикуемся в программировании на VBA

1. Сначала вызывается функция Len, которая вычисляет длину оригинальной
строки.
2. Из результата, полученного в п. 1, вычитается 7, поскольку каждое из званий
занимает семь символов в конце строки (включая запятую и пробел).
В результате получится число, которому должна быть равна длина новой строки.
3. Вызывается функция L e f t , использующая вычисленную длину в качестве значения второго аргумента.
Функция L e f t читает столько символов, сколько задано вторым аргументом,
из строки, указанной первым аргументом, возвращая только эти прочитанные
символы.
4. Новая, более короткая строка, возвращенная функцией L e f t , присваивается
переменной

Извлечение символов из строк
Продолжая работать с новым списком уже без званий, предположим, что теперь вас попросили извлечь имена с отчествами и поместить их в новый список. Эту задачу можно выполнить с помощью следующего оператора:
strMMfl = Mid (strHoBafl, I n S t r (str-Новая, " , " ) + 2)
Функция Mid извлекает символы из любого места в строке, которую вы укажете в виде
аргумента. Второй же аргумент этой функции говорит, с какого места в этой строке следует
начать извлечение символов. В данном случае этот аргумент представляет собойвыражение,
состоящее из функции I n S t r плюс 2.
Функция I n S t r ищет в заданной строке (первый аргумент) другую строку (второй аргумент).
В данном случае второй аргумент — это запятая, которая в списке следует за фамилией. Значение,
которое возвращает I n S t r , соответствует номеру позиции в первой строке, где встречается вторая строка, — теперь вы знаете, где заканчивается фамилия.
К значению, возвращенному функцией I n S t r , добавляется 2, чтобы пропустить запятую
и следующий за ней пробел и найти позицию, с которой начинается имя. Теперь функция
Mid извлечет символы, начиная с этого места и до конца строки (поскольку не указан третий,
необязательный аргумент длина).

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

Глава 11. Инструменты встроенного оркестра VBA

265

Таблица 11.4. Операторы и функции для работы с датами и временем
При задании аргументов не забывайте заключать буквальные значения дат в пару символов
#, а строковые значения типа интервалов дат — в кавычки.

Имя

Тип

Выполняемые действия (для операторов) или
возвращаемые значения (для функций)

Date

Функция
Оператор

Текущая системная дата

DateAdd (интервал,
число, дата)

Функция

Новое значение даты, равное сумме исходной даты
и казенного числа заданных интервалов даты или
времени

DateDiff (интервал,
дата1, дата2)

Функция

Число указанных интервалов даты или времени, помещающихся в отрезке времени между датами 1 и 2

DatePart
дата)

Функция

Целое значение, представляющее указанный
интервал даты

DateSerial (год,
месяц, день)

функция

Значение даты, определяемое аргументами г о д ,
м е с я ц , д е н ь , которые должны быть числовыми

DateValue
(строка с датой)

Функция

Значение даты, соответствующее строке с датой

Day

Функция

Целое значение, соответствующее дню месяца,
заданного датой

Функция

Целое значение между 0 и 23 включительно,
представляющее час суток, заданный указанным
временем

Функция

Целое значение между 0 и 59 включительно, представляющее минуты, заданные указанным временем

Функция

Целое значение между 0 и 12 включительно,
представляющее месяц, заданный указанной датой

MonthName (месяц,
сократить)

Функция
(только в VBA 6)

Строка, содержащая название месяца,
соответствующего аргументу м е с я ц , который
должен быть числом от 1 до 12. Если
необязательный аргумент с о к р а т и т ь указан
и равен T r u e , то возвращаемая строка будет
содержать сокращенное название месяца

NOW

Функция

Значение, представляющее текущие системные дату
и время

Second (время)

Функция

Целое значение между 0 и 59 включительно, представляющее секунды, заданные указанным временем

Time

Функция
Оператор

Значение, представляющее текущее системное время

Time ( время)
Timer

Функция

Date

(дата)

(дата)

Hour

(время)

Minute
Month

266

(интервал,

(время)
(дата)

Устанавливает системную дату по значению
аргумента д а т а

Устанавливает системное время по значению
аргумента в р е м я
Число секунд, прошедших с полуночи

Часть ///. Практикуемся в программировании на VBA

Окончание табл. 11.4

Имя

Тип

Выполняемые действия (для операторов) или
возвращаемые значения (для функций)

T i m e S e r i a l (часы,
минуты, секунды)

Функция

Значение времени, заданное аргументами ч а с ы ,

TimeValue
(строка_с_временем)

Функция

Значение времени, соответствующее строке со
временем (вся информация о дате будет отброшена)

Weekday

Функция

Целое число, представляющее день недели,
соответствующий указанной дате

WeekdayName
(день__не дели,
сократить,
первый день недели)

Функция
(только в
VBA 6)

Строка, содержащая название дня недели, заданного
аргументом д е н ь _ н е д е л и , который должен
быть целым числом от 1 до 7. Если необязательный
аргумент с о к р а т и т ь указан и равен T r u e , то
возвращаемая строка будет содержать сокращенное
название дня недели. Нумерацию дней недели
можно менять, задавая необязательный аргумент
п е р в ы й _ д е н ь _ н е д е л и равным константам
типа vbMonday, vbTuesday и т.д.

Year(дата)

Функция

Целое число, представляющее год, соответствующий
указанной дате

(дата)

минуты, секунды

Дата со временем
В VBA есть несколько простых операторов и функций для работы с системной датой
и системным временем, т.е. со значением даты и времени, которое изменяется и хранится
встроенными часами компьютера.
Функция Now возвращает текущие системные дату и время в формате переменной типа
Data, как, например, в случае datJIoBnMoMeHT = Now.
Чтобы обеспечить работу с системным временем и системной датой по отдельности, VBA предлагает по паре отдельных команд для каждого из этих двух элементов системы. Несколько неожиданным при этом оказывается то, что в каждой из
пар и оператор, и функция имеют одинаковые имена.
Например, чтобы извлечь (т.е. получить) системное время в формате даты VBA, нужно
использовать функцию Time, а чтобы установить (т.е. задать) системное время, необходимо
использовать оператор Time. Другими словами, ключевое слово Time выполняет различные действия в зависимости от контекста:
dat3ToMoeBpeMH = Time ' функция Time возвращает значение
' системного времени
Time (113:15 АМ#) ' оператор Time у с т а н а в л и в а е т системное время
Подобным образом работают и различаются соответствующие функция D a t e и оператор D a t e .

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

Глава 11. Инструменты встроенного оркестра VBA

267

отстоят одна дата от другой или одно время от другого. А иногда бывает нужно знать, какая дата будет, скажем, через два года и три месяца. Несколько предлагаемых в VBA функций для обработки значений дат и времени превращают вычисления с датами в совсем простое дело.

Сложение и вычитание значений дат и времени
Используйте функцию DateAdd, когда нужно узнать, какая дата наступит через три года или
что было на часах один час и пятнадцать минут тому назад. Такие вычисления можно выполнить
и без компьютера вообще, но они требуют особой внимательности, поскольку операции с компонентами значений дат и времени не подчиняются правилам привычной арифметики десятичньис
чисел (дней недели — 7, секунд — 60, и т.д.), да и самих компонентов наберется немало.
Функция DateAdd имеет следующий синтаксис: DateAdd ( и н т е р в а л , ч и с л о ,
начальная_дата).
Возвращаемое функцией значение равно значению, полученному в результате добавления
к начальной дате (или начальному времени) заданного числа интервалов. Если нужна разность, а не сумма, задайте для аргумента ч и с л о отрицательное значение. В табл. 11.5 приведен набор символьных кодов, которые допустимы для аргумента и н т е р в а л (при использовании не забудьте заключить соответствующий код в кавычки).
Таблица 11.5. Значения аргументов функций D a t e A d d и D a t D i f f
Значение аргумента (заключается в кавычки)

Задаваемый интервал

уууу

Год

q

Квартал

га

Месяц

у

День года

d

День

w

День недели

ww

Неделя

h

Час

п

Минута

s

Секунда

Например, в результате выполнения оператора
datBbino = DateAdd ( " s " , -90, Now)
переменная datBbino будет содержать значение, соответствующее времени, которое было
90 секунд тому назад относительно текущего времени. Если вам нужно отобразить на экране
только ту часть этого значения, которая относится ко времени, используйте функцию Format с соответствующим времени аргументом форматирования (например, Format (datBbmo, "Medium
t i n e ")), как было описано в разделе "Форматирование данньк".
При этом функция DateAdd не возвращает недопустимых значений дат: если добавить
один месяц к дате 31 августа, то результатом будет 30 сентября. Точно так же функция
DateAdd не забудет, если нужно, изменить в результате и год.
С помощью функции DateAdd можно добавлять или вычитать некоторое число однотипных интервалов, но, например, для выяснения даты, которая была два года и три месяца
назад, ничто не мешает применить эту функцию дважды.

268

Часть III. Практикуемся в программировании на VBA

В качестве альтернативы VBA предлагает для дат и времени две другие функции, которые
позволяют смешивать интервалы,— D a t e S e r i a l и T i m e S e r i a l . Каждая из этих функций имеет по три аргумента;
D a t e S e r i a l (год, месяц, день]
T i m e S e r i a l (часы, минуты, секунды)
Все аргументы в данном случае обязательны и должны быть выражениями, дающими целые значения (а не значения типа Date). Посмотрите, можете ли вы сказать, что будет получено в результате выполнения следующего фрагмента программного кода, и обратите внимание на вычисления в третьем аргументе:
i n t r o f l = 1999
intMecHU = 12
intfleHb = 3 1
с^НовоеТысячелетие = D a t e S e r i a l ( i n t r o f l , intMecHu, intfleHb + 1)
И, конечно же, любые из этих аргументов или даже все могут быть просто числами.

Вычисление разности двух дат
Используйте функцию D a t e D i f f , чтобы выяснить, сколько определенных интервалов
времени (годы, месяцы, недели и т.п.) помещается между двумя заданными датами или моментами времени. Например:
1пдСколько = DateDiff ("m", #2/12/90#, #10/12/01*}
В результате выполнения этого оператора переменная 1пдСколько — переменная типа
Long — будет содержать число месяцев, прошедших между двумя указанными датами. Для
первого аргумента функция D a t e D i f f требует код интервала времени, и в данном случае
" т " сообщает функции о том, что нужно измерять в месяцах, а не в годах, неделях или каких-либо других единицах.

Вычисление возраста персоны
Представленная ниже процедура типа F u n c t i o n использует функции D a t e D i f f
и D a t e S e r i a l для вычисления возраста персоны в годах. Чтобы избежать появления ошибок
при выполнении программы, можете добавить в программный код проверку типа данных того
значения, которое получит аргумент, задающий дату рождения (используйте для этого функцию
I s D a t e ) , а также проверку того, что полученная дата рождения не находится в будущем.
F u n c t i o n WhatAge(dateDateOfBirth As Date)
Dim intAge As I n t e g e r
возраст > 255

' задайте Long,

intAge = D a t e D i f f ( " y y y y " ,

чтобы допустить

dateDateOfBirth,

1

Date)

п р о в е р я е т с я , день рождения в этом году был или н е т :
If D a t e S e r i a l ( Y e a r ( D a t e ) , M o n t h ( d a t e D a t e O f B i r t h ) , __
D a y ( d a t e D a t e O f B i r t h ) ) > Date Then
intAge = intAge - 1
End If
WhatAge = intAge
End F u n c t i o n

Глава 11. Инструменты встроенного оркестра VBA

Jlftoafibte конМсиаНы с внешлим иифом
Из-за, так сказать, паразитического образа жизни на больших приложениях, VBAпрограммы зачастую не требуют никаких элементов пользовательского интерфейса
(диалоговых окон, меню и т.п.)- При запуске VBA-программа может выполняться на базе активного документа приложения, сообразуя свои действия с содержимым этого документа.
Ясно, правда, и то, что существует немало ситуаций, когда требуется прямое взаимодействие с конечным пользователем VBA-программы. Прекрасные возможности для создания
интерактивных окон в программе предлагают средства создания пользовательских форм VBA
(о чем мы говорили в главе 10), но если есть возможность обойтись более простыми средствами, то чем проще, тем лучше.
Две VBA-функции, MsgBox и I n p u t B o x , обеспечивают неплохие возможности базового уровня для передачи пользователю сообщений и получения от него ответов.
Функция MsgBox отображает окно с сообщением, но не только — она позволяет определить, на какой из двух (или больше) кнопок щелкнул пользователь, чтобы закрыть окно.
Функция I n p u t B o x отображает окно с сообщением и полем, в котором пользователь имеет возможность напечатать ответ.

Отображение окон сообщений
Формально синтаксическая конструкция функции MsgBox выглядит так:
MsgBox(сообщение[,

кнопки]

[,

заголовок]

[,

файл_справки, р а з д е л ] )

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

Задание текста сообщения
В своей простейшей форме функция MsgBox действует как оператор. От вас требуется
только напечатать его в отдельной строке и добавить сообщение, которое требуется отобразить. Например:

MsgBox "Это проверка работы MsgBox."
В результате выполнения такой строки VBA отобразит на экране окно с сообщением, подобное показанному на рис. 11.2 (пример А).

Это первая строк».
Это вторая строже.

Пример А

Пример Б

Пример В

Рис. 11.2. Три простых окна сообщения
Текст сообщения можно заключить в скобки, но скобки необязательны, когда функция
используется как оператор.
Сообщение может быть также переменной или выражением. Как обычно, VBA автоматически
конвертирует за вас числовые значения и даты в отображаемые символы. Например, следующий
фрагмент программного кода вполне работоспособен, а результат показан на рис. 11.2 (пример Б):

270

Часть Ш. Практикуемся в программировании на VBA

intWishCount = 3
datWhen = Format(Now, "Short date")
strlnfol = "Ha "
s t r l n f o 2 = " осталось желаний: "
MsgBox s t r l n f o l & datWhen & s t r l n f o 2 & intWishCount
Чтобы отобразить сообщение в несколько строк, добавьте в сообщение символы
перехода на новую строку (их ASCII-код равен 13) с помощью функции Chr
(пример В на рис. 11.2).
MsgBox "Это первая строка." & Chr(13) & "Это вторая строка.'
Можно разбить текст многострочного сообщения и на столбцы, используя символы табуляции (их ASCII-код равен 9).

Создание непростых окон сообщений
Кроме сообщения, в окне сообщения может присутствовать одна из нескольких стандартных пиктограмм, а также несколько кнопок стандартного вида. Все это задается указанием
одного числового значения для необязательного аргумента к н о п к и .
С пиктограммой ваше окно сообщения будет выглядеть немного "круче", чем простенькие окна с рис. 11.2. Показанное на рис. 11.3 окно сообщения содержит пиктограмму критической ситуации (эта пиктограмма обычно вызывает у пользователя некоторое волнение).

^Нажмите»?»

Рис. 113. Непростое окно сообщения
По умолчанию окно сообщения имеет только кнопку ОК, но можно в него добавить
и кнопки с надписями Отмена, Да, Нет, Стоп, Повтор и Пропустить в различных комбинациях. На рис. 11.3 как раз показано окно с одной из таких комбинаций кнопок.
Вычисление значения для аргумента кнопок
Как и для подобных аргументов многих других функций, значение для аргумента к н о п к и
вычисляется как сумма констант, представляющих наборы кнопок и пиктограммы. Можно
подсчитать нужное значение вручную, но лучше создать подходящее выражение из именованных VBA-констант, предлагаемых как раз для этих целей. В табл. 11.6 эти константы приведены вместе с их числовыми значениями и описаниями назначения.
Таблица 11.6. Константы VBA для окон сообщений и окон ввода
Константа

Числовое значение

Соответствующее действие

vbOKCnly

О

Отображение только кнопки ОК

vbOKCancel

1

Отображение кнопок ОК и Отмена

vbAbcrtRetrylgnore

2

Отображение кнопок Стоп, Повтор
и Пропустить

Глава 11. Инструменты встроенного оркестра VBA

271

Окончание табл. 11.6
Константа

Числовое значение

Соответствующее действие

vbYesNoCancel

3

Отображение кнопок Да, Нет и Отмена

vbYesNo

4

Отображение кнопок Да и Нет

vbRetryCancel

5

Отображение кнопок Повтор и Отмена

vbCritical

16

Отображение пиктограммы Критическое
сообщение

vbQuestion

32

Отображение пиктограммы
Предупреждающий запрос

vbExclamation

48

Отображение пиктограммы
Предупреждающее сообщение

vblnformation

64

Отображение пиктограммы
Информирующее сообщение

vbDefaultButtonl

0

Выбор по умолчанию первой кнопки

vbDefaultButton2

256

Выбор по умолчанию второй кнопки

vbDefaultButton3

512

Выбор по умолчанию третьей кнопки

vbDefaultButton4

768

Выбор по умолчанию четвертой кнопки

С помощью этой таблицы несложно подсчитать, что при вызове функции, отобразившей
окно сообщения, показанное на рис. 11.3, значение аргумента кнопки было равным 531. Но
кому хочется это значение считать? Легче напечатать следующий оператор:
i n t A = MsgBox("Нажмите кнопку", vbYesNoCancel
+ v b D e f a u l t B u t t o n 3 , "VBA для ' ч а й н и к о в ' " )

vbCritical

Третья из констант, использованных в выражении для аргумента кнопки, константа
v b D e f a u l t B u t t o n 3 , назначает третью кнопку (считая слева направо) кнопкой, выбираемой по умолчанию. В данном случае это кнопка Отмена. Если внимательно рассмотреть
рис. 11.3, можно увидеть, что кнопка Отмена получила фокус ввода — надпись на ней очерчена пунктирной рамкой, и это означает, что именно эта кнопка будет активизирована, если
вы нажмете клавишу пробела или .
Какая кнопка нажата?
Смысл отображения кнопок в окне сообщения заключается в предоставлении пользователю возможности выбора действия. В данном случае пользователю не нужно ничего печатать — следует только щелкнуть на одной из кнопок. А вам нужно суметь выяснить, на какой
из кнопок щелкнул пользователь.
Это просто, поскольку функция MsgBox возвращает целое значение, как раз соответствующее той кнопке, на которой щелкнул пользователь. Чтобы не нагружать свою память,
вы можете сравнивать возвращаемое значение не с конкретными числами, а с предлагаемыми VBA именованными константами. Вот эти константы вместе с их действительными
значениями.
272

Часть III. Практикуемся в программировании на VBA

Значение

Константа
vbOK
vbCancel
vbAbort
vbRetry
vblgnore
vbYes
vbNo

Если в окне сообщения всего две кнопки, для выяснения, на какой из кнопок был щелчок,
прекрасно подходит оператор If . . . Then. Например:
If Msg3ox ("Начинать?", vbYesNo) = vbYes Then
ЧтоНибудьСделать
Else
НэДелать Ничего
End I f
Когда кнопок больше, приходится использовать оператор I f . . . T h e n . . . E l s e If.

Добавление заголовка
По умолчанию окно сообщения отображает в строке заголовка имя того VBAприложения, из которого выполняется программа (см. рис. 11.2). Этот заголовок можно изменить на любой другой, задав соответствующее значение аргумента з а г о л о в о к в операторе вызова функции MsgBox (см. рис. 11.3).

Получение информации от пользователя
Если вам нужна от пользователя более конкретная информация, не укладывающаяся
в рамки выбора из трех кнопок, используйте функцию I n p u t B o x . Вот ее формальная синтаксическая конструкция, из которой удалены некоторые необязательные аргументы, расширяющие возможности:
Input3ox(сообщение[, заголовок] [, ответ])
Как видно из рис. 11.4, эта функция отображает диалоговое окно с полем текста, куда
пользователь может впечатать некоторую, как предполагается, важную информацию. Чтобы
передать эту информацию программе, присвойте возвращенное функцией I n p u t B o x значение строковой переменной:
s t r B = InputBox("Какие места предпочитаете?", "TWA", "У прохода")

Рис. 11.4. Простое окно ввода

Глава 11. Инструменты встроенного оркестра VBA

273

Хотя с помощью окна ввода можно получить больше информации, чем с помощью
окна сообщения, с окном ввода программисту работать легче — тут нет кнопок и пиктограмм, которые можно выбирать. Аргументы сообщение и з а г о л о в о к точно такие
же, как и в случае функции MsgBox. Вы можете облегчить задачу пользователю, задав
значение аргумента о т в е т . Тем самым вы предложите ему ответ, принимаемый по
умолчанию, — если предложенный вами ответ подойдет, пользователь сможет просто
нажать клавишу .

Работа с логическими значениями
В случае переменной типа B o o l e a n изменить ее значение на противоположное
проще всего с помощью операции логического отрицания Not. При этом результат применения операции нужно просто присвоить той же самой переменной.
Например, оператор
boolBlinking = Not(boclBlinking)
делает значение переменной b o o l B l i n k i n g равным T r u e , если значением
было F a l s e , и, наоборот, равным F a l s e , если значением было T r u e .

ЗаЗабы с маЖемаЖшсой и деньгами
В VBA предлагается целый ряд функций для работы с числовыми значениями. Эти функции предназначены для решения ряда задач от совсем простых (например, возвращение абсолютного значения или знака числа) до достаточно сложных вычислений алгебраических
и тригонометрических величин. А добрая дюжина финансовых функций VBA поможет удержать на плаву любой утопающий бизнес.
Я не собираюсь останавливаться здесь на всех этих функциях, а рассмотрю лишь, как
исключение, несколько избранных из них. Да и эти последние я обсуждаю только потому,
что их непросто обнаружить в системе справки VBA и поэтому вы могли бы иначе просто
не узнать о них. Внимательно ознакомьтесь с приведенным ниже списком, чтобы знать,
что в VBA есть, а чего — нет.

Математические функции
В табл. 11.7 приведены функции VBA, которые можно назвать математическими. Перед
тем как использовать их, не забудьте снова просмотреть раздел "Конвертирование данных"
выше в этой же главе.
Таблица 11.7. Математические функции VBA
Функция

Возвращаемое значение

Abs (число)

Абсолютное значение числа

A t n (число)

Арктангенс числа

Cos ( ч и с л о )

Косинус числа

Ехр {число)
F i x (число)

274

Число е в степени, равной заданному числу
Целая часть числа (см. описание функции I n t )

Часть ///. Практикуемся в программировании на VBA

Окончание табл. 11.7
Функция

Возвращаемое значение

i n t (число)

Целая часть числа. Функции i n t и F i x по-разному действуют только
на отрицательные числа: I n t возвращает ближайшее меньшее целое,
a F i x просто отбрасывает дробную часть числа

Log (число)

Натуральный логарифм числа, значение двойной точности

Rnd ( ч и с л о )

Случайное число, значение одинарной точности

Sgn ( ч и с л о )

1, если ч и с л о положительно, 0, если равно нулю, и - 1 , если
отрицательно

S i n (число)
s qr ( ч и с л о )
Tan ( ч и с л о )

Синусчисла
Квадратный корень числа
Тангенс числа

Производные математические функции
Если вы не находите в VBA ту математическую функцию, которая вам нужна, не отчаивайтесь— можно сконструировать выражение или создать процедуру типа F u n c t i o n , которая решит нужную задачу.
Если вы знаете математику настолько, что можете сами разобраться с тригонометрическими функциями типа обратной к функции косеканса, мне, наверное, не нужно объяснять вам, как использовать тригонометрические функции. Однако вам будет не лишним знать, что в справке VBA есть нечто типа шпаргалки по таким
функциям, в которой вы найдете и выражения для их вычисления. Чтобы добраться
до этой шпаргалки, поищите раздел derived math functions (производные математические функции) в содержании справки. Этот раздел справки напомнит вам, например, что логарифм числах по основанию N вычисляется как Log (X) /Log (N).
Если вы предполагаете, что какая-то производная математическая функция понадобится в дальнейшем, сделайте ее частью своего математического арсенала, записав в виде
процедуры типа
Function,
и
сохраните
в
модуле с
названием
вроде
М о и М а т е м а т и ч е с к и е Ф у н к ц и и . Тогда вы сможете при случае воспользоваться ею, как
только в этом возникнет необходимость.

Округление чисел
Округлять десятичные числа приходится часто, особенно при работе с денежными значениями. Как ни странно, VBA не предлагает прямого решения таких задач, но обсуждаемые
ниже приемы помогут вам решить любые проблемы с округлением.
В VBA 6 есть функция Round (в VBA 5 такой функции нет), но дает она не слишком надежные результаты. Например, в результате выполнения оператора
х = R o u n d ( 2 . 5 0 5 , 2)
значением переменной х будет 2, 5, а не 2 , 5 1 , как должно быть. Поэтому не используйте Round, если, конечно, вы не намереваетесь получить заведомо неправильные ответы.

Глава 11. Инструменты встроенного оркестра VBA

275

Есть другой простой способ округления чисел в VBA, при котором используется функция
Format: просто используйте эту функцию, задав подходящее значение аргумента формат,
как показано в следующем примере (как использовать аргумент формат, см. выше в разделе
"Создание собственных форматов");
эпдОкругленное = Format(зпдНеокругленное, " # , # # 0 . 0 0 " )
В VBA 6 для получения подобного результата можно использовать функцию F o r matNumber:
sngOKpyгленное = FormatNumber(эпдНеокругленное, 2)
В обоих этих примерах значение БпдНеокругленное округляется до двух знаков после запятой. Чтобы при округлении с помощью функции F o r m a t получить иное число знаков после запятой, измените число нулей после десятичной точки в аргументе формат. Например, значение " # , # # 0 . 0 " для аргумента в результате даст округление до одного знака
после запятой. При округлении с помощью функции FormatNumber просто измените число, задающее значение второго аргумента, на нужное.
Не забывайте, что переменная, в которую вы помешаете округленное значение,
должна иметь тип S t r i n g , S i n g l e , Double, D e c i m a l , C u r r e n c y или
V a r i a n t , но никак не тип I n t e g e r или Long, поскольку тогда вы просто потеряете дробную часть числа.
Предположим теперь, что нужно округлить некоторое значение не в дробной части, а до
целых определенного порядка (например, до сотен). В этом случае выражение немного усложняется, но нельзя сказать, чтобы слишком. Вот пример округления до сотен:
sngOKpyrленное = Format(зпдНеокругленное / 100, " # , # # 0 . " ) * 100
Обратите внимание на то, что в данном случае строка для аргумента формат не
имеет нулей справа от десятичной точки. Кроме того, неокругленное значение внутри
функции F o r m a t делится на подходящую степень 10, а возвращаемый функцией результат умножается на ту же степень 10. Степень 10 должна быть равной порядку, до
которого предполагается округление. В данном примере порядок равен 2, т.е. выполняется округление до сотен.

Работа со случайными числами
Если жизненная рутина угнетает ваш бурлящий дух, оживите свои программы определенной непредсказуемостью. Генерируемые случайным образом числа бывают нужны при
создании программ, которые моделируют реальные процессы, при создании учебных программ и игр.
В VBA есть две встроенные команды для генерирования случайных чисел.
\ S Оператор Randomize. Используйте его, чтобы запустить генератор случайных чи%
сел VBA. Не требуя аргументов, оператор Randomize запускает генератор, подавая
|
ему на вход текущее системное время. Таким образом, гарантируется при каждом но;
вом запуске новая последовательность случайных чисел.
"-, •/ функция Rnd, Эта функция и поставляет случайные числа для использования в про\
грамме. Функция Rnd не имеет аргументов— вам нужно просто присвоить имя
I
функции переменной или использовать Rnd в выражении. Возвращается значение
•:
с плавающей запятой (типа S i n g l e ) .

276

Часть III. Практикуемся в программировании на VBA

Числа с плавающей запятой часто используются в статистических и научных отчетах. Однако в некоторых ситуациях нужны случайные целые значения, если, например, необходима
процедура, выбирающая случайным образом номер выигрышного билета. Чтобы преобразовать возвращаемое функцией Rnd значение в целое из определенного диапазона, используйте
следующую формулу:
случайиое_целое = Int(минимум +(Rnd() * максимум))
В этой формуле максимумы минимум залают соответственно верхнюю и нижнюю границы дли значений получаемых случайных чисел— если границы заданы правильно, эта
формула всегда будет давать число из соответствующего диапазона.

Финансовые функции
VBA предлагает ряд функций для подсчета рублей-копеечек в выплатах по ссуде или возвращениях инвестиций. Я не имею здесь возможности обсуждать все эти функции, но собираюсь все же рассмотреть функцию Pmt для расчета выплат по ссуде.

Расчет выплат по ссуде или процентов по вкладу
Используйте функцию Pmt для расчета сумм, которые предстоит выплачивать вам (или
которые должны выплачивать вам) по закладной с фиксированными процентами или какомулибо другому займу. Вот формальный синтаксис функции Pmt:
Prat(ставка, кпер, сумма[, ц е л ь [ , т и п ] ] )
Первый аргумент, с т а в к а , задает ставку процента выплат по займу за определенный период времени. Задаваемая вами ставка процента должна соответствовать периодичности выплат. Если нужно выплачивать ежемесячно по 8%-ной закладной, то не забудьте, что 8% является годовой нормой. В таком случае с т а в к а должна задаваться выражением типа
. 08/1л (8% разделенные на 12 месяцев).
Аргумент кпер должен задаваться целым значением, представляющим общее число выплат, которые предстоит сделать по займу. Для ежемесячных выплат в течение 5 лет к п е р
должно быть равно 5 * 12, или 60. Общая сумма займа задается аргументом сумма.
Остальные аргументы необязательны. Чтобы рассчитать, сколько вам нужно откладывать, чтобы накопить определенную сумму, задайте аргумент ц е л ь , чтобы передать
функции Pmt запланированную сумму в виде отрицательного числа— это сумма на
будущее. (При этом аргумент с т а в к а задает ожидаемую ставку процента. Если некоторая часть из целевой суммы уже накоплена, эта часть должна задаваться аргументом
сумма.) Аргумент тип позволяет указать, когда должны проводиться выплаты —
в конце каждого периода (задается значением 0 и подразумевается по умолчанию) или
в начале (значение 1).
Чтобы использовать функцию Pmt в программном коде, присвойте ее значение переменной типа Double. Например:
dblPay = Pmt (.08/12, 360, 300000) ' Типичная закладная
dblSav = Pmt (07/12, 120, 12500, -75000} ' Цель = 75000р.

Рог изобилия финансовых функций
Все разнообразие финансовых функций VBA представлено в табл. 11.8. Чтобы таблица
была удобной для использования, я удалил из списков аргументов необязательные. Чтобы получить дополнительную информацию о любой из этих функций, обратитесь к соответствующему раз зелу справки VBA, где вы найдете также и подходящий пример.

Глава 11. Инструменты встроенного оркестра VBA

277

Таблица 11.8. Финансовые функции VBA
Функция

Возвращаемое значение

DDB(стоимость, остаток, период)

Амортизация имущества за данный период,
используя метод двойного процента со
снижающегося остатка

FV(ставка, кпер, плата, сумма)

Будущее значение вклада на основе
периодических постоянных платежей
и постоянной процентной ставки

Impt(ставка, период, кпер, сумма) Величина выплаты за указанный период на
основе периодических постоянных платежей
и постоянной процентной ставки

IRR(значения

Внутренняя скорость оборота для ряда
последовательных операций с наличными,
представленными числовыми значениями

MIRR(значения(), фин_ставка,
реинвест_ставка)

Модифицированная внутренняя скорость
оборота средств для ряда последовательных
периодических операций с наличными

Nper(ставка, платеж, сумма)

Общее количество периодов выплаты для
данного вклада на основе периодических
постоянных выплат и постоянной
процентной ставки

NPV(ставка, значения())

Чистый текущий объем вклада, используя
учетную ставку, а также объемы будущих
платежей (отрицательные значения)
и поступлений (положительные значения)

Pmt(ставка, кпер, сумма)

Величина выплаты по ссуде на основе
постоянных выплат и постоянной процентной
ставки

PPmt ()

Платежи по процентам за данный период на
основе периодических постоянных выплат
и постоянной процентной ставки

РУ (ставка, кпер, плата)

Текущий объем вклада на основе
периодических постоянных платежей
и постоянной процентной ставки

Rate(кпер, плата, сумма)

Процентная ставка за один период при
выплате ренты

SLN(стоимость, остаток, период)

Величина непосредственной амортизации
имущества за один период

SYD(стоимость, остаток, жизнь,
период)

Годовая амортизация имущества для
указанного периода

278

Часть ///. Практикуемся в программировании на VBA

2)fttfiue вс^гоенные команды
Даже после всех приведенных выше таблиц и обсуждений, обзор встроенных команд
VBA остается далеко не полным. Некоторые из команд будут обсуждаться в следующих главах, но эту главу я завершу еще одной таблицей со множеством команд, которые вполне могут вам пригодиться.
Таблица 11.9. Различные встроенные команды VBA
При задании аргументов не забывайте заключать буквальные значения таких параметров, как
путь, в кавычки.
Имя

Функция или
оператор

Выполняемые действия
(для операторов) и возвращаемые
значения (для функций)

ChDir .путь)

Оператор

Изменяет текущий каталог (папку), но не
активный диск

ChDrive(имя диска)

Оператор

Изменяет активный диск

CurDir

Функция

Текущий путь (диск и имя каталога) в виде
строки

Dir(путь)

Функция

Имя первого файла или каталога,
соответствующего аргументу п у т ь , который
может содержать подстановочные символы

FileCopy источник,
цель

Оператор

Копирует дисковый файл и с т о ч н и к
s ц е л ь (может включать путь, имя файла
или и то, и другое)

FileDateTime(путь)

Функция

Значение типа D a t e с датой и временем
создания или последнего изменения файла,
заданного аргументом п у т ь

FileLen(путь)

Функция

Длина (в байтах) файлалзаданного
аргументом п у т ь

GetAttr(путь)

Функция

Целое значение, представляющее
атрибуты файла или папки, заданных
аргументом п у т ь

Kill

Оператор

Удаляет один или больше файлов с диска
(аргумент п у т ь может содержать
подстановочные символы)

MkDir путь

Оператор

Создает новый каталог

Name старый путь As
новый путь

Оператор

Переименовывает и/или перемещает
дисковый файл, каталог или папку

RmDir путь

Оператор

Удаляет каталог

Работа с файлами

путь

Глава 11. Инструменты встроенного оркестра VBA

279

Продолжение табл. 11.9

Имя

Функция или
оператор

Выполняемые действия
(для операторов) и возвращаемые
значения (для функций)

Оператор

Устанавливает заданные атрибуты дисковому
файлу. Аргумент а т р и б у т ы задает
числовое значение, являющееся суммой
устанавливаемых атрибутов. VBA
обеспечивает именованные константы для
каждого из атрибутов

Работа с файлами

SetAttr путь,
атрибуты

Разное
AppActivate название, Оператор

ожидание

Активизирует другое выполняемое
приложение. Если необязательный аргумент
о ж и д а н и е имеет значение T r u e , то VBA
будет ждать, пока ваша программа не получит
фокус ввода

Веер

Оператор

Извлекает звук с помощью громкоговорителя
компьютера

Choose(индекс,
вариант!, вариант2,
... варианты)

Функция

Значение объекта из списка аргументов

DoEvents

Функция

Позволяет Windows обрабатывать другие
события, пока выполняется ваша программа.
В VBA эта функция всегда возвращает О,
поэтому нет необходимости приписывать
ее значение переменной - используйте ее как
оператор

Функции

Содержимое переменной окружения,
заданной строкой с именем или числом,
определяющим позицию

RGB(красный,
зеленый, синий)

Функция

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

Randomize

Оператор

Инициализирует генератор случайных чисел

Rnd(число'

Функция

Случайное значение; аргумент ч и с л о
необязателен

Environ

(строка)

Environ

(число)

280

вариант!, вариант2,... варианты,
определяемого аргументом и н д е к с
(индекс должен задавать число)

Часть III. Практикуемся в программировании на VBA

Продолжение табл. 11.9

Имя

Функция или
оператор

Выполняемые действия
(для операторов) и возвращаемые
значения (для функций)

Оператор

Пересылает заданную строкой
последовательность символов в активное
окно, как будто эти символы введены
с клавиатуры. Если необязательный аргумент
о ж и д а н и е имеет значение T r u e ,
то выполнение программы не продолжится,
пока последовательность символов не будет
обработана

Функция

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

Разное

SendKeys с т р о к а ,
ожидание

Работа с реестром Windows
Shell(путь

DeleteSetting
Оператор
имя__приложения, р а з д е л ,
параметр

Удаляет элемент реестра

Get A l l S e t t i n g s
(имя_приложения,
раздел)

Функция

Значение типа V a r i a n t , содержащее
список всех установок для указанного раздела
приложения в реестре Windows
{в виде двумерного массива)

GetSetting

Функция

Значение параметра из указанного раздела
приложения в реестре Windows

Оператор

Сохраняет значение в реестре

Функция

Не возвращает никаких полезных значений,
используется для размещения указанного
числа пробелов в потоке вывода оператора

(имя__приложения,
раздел, параметр)
SaveSetting
имя_приложения,
раздел, параметр,
значение
Форматирование вывода

Spc{число

P r i n t # или метода Debug . P r i n t
Tab(столбец)

Функция

Не возвращает никаких полезных значений,
смещает поток вывода оператора P r i n t #
или метода D e b u g .

Глава 11. Инструменты встроенного оркестра VBA

281

Окончание табл. 11.9
Имя

Функция или
оператор

Выполняемые действия
(для операторов) и возвращаемые
значения (для функций)

IsDate (переменная)
IsNumeric(переменная)
IsObject(переменная)
IsArray(переменная)
IsNull(переменная)
IsEmpty(переменная)

Функции

T r u e , если п е р е м е н н а я имеет
соответствующий тип или содержит значение
соответствующего типа; иначе F a l s e

Len (переменная)

Функция

Число байтов, необходимое для хранения
информации, помещенной в переменную

TypeName (переменная)

Функция

Строка, представляющая тип переменной

VarType (переменная)

Функция

Целое число, представляющее подчиненный тип
переменной

Работа с переменными

282

Часть III. Практикуемся в программировании на VBA

Глава 12

Объектно-ориентированное
программирование
главе...
> Концептуализация объектов
> Понимание свойств, методов и событий — главных компонентов VBA-объектов
> Работа с объектными моделями
> Использование форм как объектов
> Выяснение и установка свойств объектов
> Вызов методов
> Использование ссылок на объект для идентификации объекта, с которым
нужно работать
> Присваивание переменным ссылок на объект
> Создание своих собственных объектов с помощью модулей классов
> Эффективное
использование
For Each . . . Next и With

объектов

с

помощью

операторов

Ш лавным преимуществом VBA является статус объектно-ориентированного средства
*J разработки приложений. Понимание объектов лежит в основе программирования
в VBA, особенно когда дело касается создания пользовательских диалоговых окон
и использования возможностей ведущего VBA-приложения. В этой главе мы сначала очертим объектное поле на уровне понятий, а затем займемся приемами программирования
с использованием объектов. Объекты стали неотъемлемыми элементами ландшафта VBA.
Именно через объекты вы получаете доступ к функциональным возможностям того VBAприложения, в котором работаете. Точно так же вы можете получить доступ к объектам других VBA-приложений и даже создать свои собственные объекты.

tnajcoe oJbetafl
Можно, конечно, привести формальное определение объекта в VBA, но, я думаю, проще
объяснить понятие объекта с помощью нескольких неформальных примеров, используя их
функциональные возможности.

Объекты как компоненты VBA-приложений
Начать изучение объектов лучше всего с рассмотрения их как частей VBAприложения и его документов. Любой элемент графики (shape) в Visio является объек-

Глава 12. Объектно-ориентированное программирование

283

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

РИС. 12. l Примеры объектов VBA
Подобным образом к объектам Excel относятся ячейки, в которых размещаются данные
и формулы, именованные диапазоны ячеек, диаграммы, украшающие многие документы, отдельные рабочие листы и целые рабочие книги. И во всех приложениях Microsoft Office —
как и во многих других VBA-приложениях— меню и панели инструментов, а также пункты
•этих меню и кнопки в этих панелях инструментов тоже являются объектами.
Объекты VBA существуют в иерархии, в которой объекты одних типов содержатся
в объектах других типов. Подобные иерархии объектов рассматриваются ниже, в разделе
"Что такое объектная модель", а пока что мы сконцентрируем внимание на обсуждении понятия индивидуального объекта.

Объекты на уровне понятий
Если вам трудно ассоциировать объекты с графическими элементами, ячейками рабочего
листа или кнопками панели инструментов, представляйте себе объекты как материальные
предметы. Вы же можете представить, как вырезаете ножницами из листа бумаги кружочек
и наклеиваете его на другой лист бумаги. А в ячейку рабочего листа вы можете впечатать
числа, на кнопке можете щелкнуть.
Правда, кроме таких конкретных объектов, VBA-приложения предлагают и более абстрактные.
• V в Microsoft Excel объект CustomView задает пользовательское представление рабочей книги (в Excel пользовательское представление определяет внешний вил рабочей
:
книги на экране и ее параметрыпечати).
^ В Microsoft Word объект F i l e S e a r c h представляет, как сказано в соответствующем
разделе справки, "функциональные возможности диалогового окна Открытие
документа (меню Файл)". Обратите внимание, этот объект представляет не само
\
диалоговое окно, а его функциональные возможности.

284

Часть III. Практикуемся в программировании на VBA

В Visio объект S t y l e представляет атрибуты линий, текста и заливки для графических элементов.
В VBA имеется несколько объектов, доступных для всех VBA-приложениЙ. Так, например, объект C o l l e c t i o n представляет контейнер для переменных или других
объектов, с которыми, независимо от типов этих объектов, предполагается работать
как с единым целым.

Практическое определение объекта
Вы можете заметить, что порой представить объект VBA в материально осязаемом виде
не так-то просто. Но это и к лучшему — чем дальше вы уходите от материализации объектов,
тем свободнее будете себя чувствовать при работе со всем диапазоном доступных объектов.
Используемое программистами-практиками определение объекта оказывается совсем простым: объектом называется любая именованная сущность, имеющая
свойства, т.е. установки, которые можно проверить и изменить;
методы, т.е. действия, которые может выполнить объект, когда программа попросит
об этом;
события, т.е. ситуации, в которых объект оказывается и на которые может ответить
заранее определенными для таких ситуаций действиями.
ВТ

Если вам не чуждо чувство прекрасного, вы можете заметить, что для таких щедро одаренных созданий термин объект не очень-то подходит, поскольку эти объекты больше похожи на братьев наших меньших, чем на инертные лампы. У тигров и китов есть отличительные особенности глаз, конечностей и хвостов, а у объектов — свойства. Лошади и собаки
умеют по команде выполнять разные трюки или убегать от опасности, а объекты имеют методы и события.
Вы все еще хотите услышать формальное определение? Вот оно: объектом в программе называется именованная единица, объединяющая в себе данные и программный код, использующий эти данные и воздействующий на них. В таком
случае говорят, что объект инкапсулирует данные и связанный с ними программный код.

Классы объектов и конкретные объекты
Есть одно формальное обстоятельство, которое следует запомнить. Существует различие
между конкретными объектами и теми образцами, на основе которых данные объекты создаются. Конкретный объект представляет отдельный документ, графический элемент, ячейку
рабочего листа или нечто другое. Например, документ, как объект, представляет текст этого
отдельного документа.
В противоположность конкретному объекту, класс объекта можно сравнить со строительным проектом. По одному проекту можно построить множество домов, в которых будут
жить люди, но в самом проекте никто не живет. Точно так же в классе планируются типы
данных, которые могут использоваться объектом, и определяются методы, свойства
и события объекта. На основе этого плана вы создаете жземпчяр данного класса-— тот объект, который будет содержать реальные данные. На основе одного класса можно создать
столько объектов, сколько вы пожелаете, чтобы использовать каждый из них для различных
целей и с различными данными.

Глава 12. Объектно-ориентированное программирование

285

Коллекции объектов
Коллекция— это VBA-объект специального назначения. Как видно из самого названия,
коллекции предназначены для упрощения работы с набором объектов, когда этот набор объектов нужно использовать как одно целое. Как правило, все объекты в коллекции имеют один
и тот же тип. Например, коллекция S h a p e s в Visio состоит из объектов Shape, а коллекция
Pages — из объектов Page.
Но есть и коллекции, которые оказываются более либеральными к типу входящих в них
объектов. Например, VBA предлагает родовой объект C o l l e c t i o n , предназначенный для
хранения в нем объектов любых типов в любой комбинации. Если возникнет необходимость
готовить самые невероятные смеси, то коллекции VBA окажутся как раз кстати.
Позже, в разделе "Работа с коллекциями объектов", мы с вами выясним, как получить
доступ к отдельным объектам в коллекциях, а в главе 13 вы узнаете, как использовать свойства и методы самих коллекций (не забывайте, что они тоже являются объектами) и как создавать свои собственные коллекции на основе родового VBA-объекта C o l l e c t i o n ,

Максе оЗьек&яая модель
Как уже упоминалось, объекты VBA существуют в иерархической зависимости один от другого. Кроме обладания своими собственными свойствами, методами и событиями, объекты
высших ступеней иерархии служат в качестве контейнеров для одного или целого множества
подчиненных объектов. Эти вложенные объекты в свою очередь содержат другие объекты и т.д.
Вся система таких иерархических отношений конкретного VBA-приложения называется
объектной моделью этого приложения. Часто представляемая в графическом виде, объектная
модель приложения описывает вложения одних объектов в другие. Пример графического
представления одной из объектных моделей показан на рис. 12.2.

The Microsoft11 Visio'
object model

РИС. 12.2. Объектная модель Visio с компакт-диска \Tisio 2000
Как видно из рис. 12.2, на вершине объектной модели VBA-приложения находится объект
Application (приложение), являющийся контейнером для всех других объектов приложения,
с которыми вы можете работать. Ваш УВА-проект тоже является объектом-контейнером,
в котором размещаются все созданные вами модули программного кода и формы, равно как
и документ проекта. (О структуре VBA-проекта и его компонентах говорилось в главе 7.)

286

Часть III. Практикуемся в программировании на VBA

Понимание важности объектной модели
Вам придется сообщать VBA о том, какой конкретный объект нужен вам для работы, поэтому хорошее понимание объектной модели VBA-приложения оказывается очень важным
для эффективной работы в нем. С помощью диаграммы объектной модели приложения, подобной показанной на рис. 12.2, очень просто проследить всю цепочку объектов, которой
принадлежит нужный вам объект. В данном случае, например, сразу видно, что объект C o n n e c t является членом коллекции C o n n e c t s , принадлежащего объекту M a s t e r , который
в свою очередь... .

Расширение объектной модели
В программах, созданных в VBA, совсем не обязательно ограничивать себя использованием
объектов только одного VBA-приложения. Не обязательно даже ограничиваться использованием только VBA-приложений как таковых. Можно использовать вообще любые приложения
и "компоненты", удовлетворяющие стандарту Component Object Model (COM) фирмы Microsoft
(Component Object Model можно перевести как объектная модель компонента).
Стандарт СОМ представляет собой набор технических спецификаций, регламентирующих правила определения объектов в приложениях и других программных
единицах, а также правила предоставления таких объектов для использования
в других приложениях. Чтобы обозначить, что удовлетворяющим стандарт СОМ
приложением можно управлять из другого приложения, используется специальный термин автоматизация. Кстати, стандарт СОМ относится не только к VBA
или Visual Basic, он понятен многим другим средствам разработки приложений
(например, компиляторам C++), которые таким образом могут использовать соответствующие объекты.
Стандарт СОМ открывает фантастические возможности для создания мощных VBAприложений, допускающих настройку пользователем. Теперь вы можете (я не сказал легко)
создавать приложения, позволяющие одновременно обрабатывать информацию, полученную
из диаграмм Visio, документов Word, рабочих листов Excel и т.п. Ваше приложение может
отображать всю эту информацию в окнах, которые разработаны вами, но которые в то же
время используют специальные функциональные возможности отображения информации
этих приложений-компонентов.
Разработка пользовательских приложений такого уровня, очевидно, относится к непростым задачам, поэтому в данной книге это будет обсуждаться весьма поверхностно (в главе 14). Но я должен по крайней мере упомянуть, что возможности VBA открывают путь к великим свершениям.

Формы € Vtfd — э/Яо тоже
Формой называют любое созданное в VBA пользовательское окно. Если в вашей программе
предусмотрен ее собственный пользовательский интерфейс, формами будут как главное окно программы, так и все другие диалоговые окна, отображаемые вашей программой (рис. 12.3).
Главное, здесь нужно понять, что формы VBA сами являются объектами, т.е. представляют собой сущности, содержащие как информацию (задающую, например, внешний вид формы на экране), так и набор средств для обработки этой информации. Официально формы
в VBA описываются в терминах объекта U s e r F o r m .

Глава 12. Объектно-ориентированное программирование

287

-L S-S.9

Лик /25. Примеры форм VBA
Как и любые другие уважающие себя объекты в VBA, формы прекрасно вписываются
в рамки парадигмы объектной модели. Каждый объект UserForra принадлежит одновременно двум коллекциям объектов — VBA-проекту, в котором хранится форма, и коллекции
UserForms, содержащей все формы, загружаемые программой. В свою очередь, объект
UserForms служит контейнером для коллекции C o n t r o l s , содержащей элементы управления, помещенные в форму.
Точно так же элементы управления в форме— кнопки, флажки, переключатели и всевозможные другие рычажки, которыми можно любоваться и играть, — тоже являются объектами.
Для каждого типа элементов управления в VBA предлагается объект соответствующего типа.
Техника, с помощью которой можно получить доступ к конкретной форме или помещенному в нее элементу управления и использовать свойства, методы и события этого объекта,
ничем не отличается от техники, используемой с другими объектами, о которых говорится
в этой главе. Подробнее о работе с формами и элементами управления (а значит, и соответствующими объектами) говорится в главах 10 и 19.

использование оЗьекрпов 6 н/юг/галсие
Теперь, когда теоретические основы пройдены, наступает время практических рекомендаций по программированию с использованием объектов VBA. Начнем, пожалуй, с использования в программном коде свойств, методов и событий объектов, а уж после этого перейдем
к более тонким вопросам идентификации объектов, которые предполагается использовать.

Основные правила программирования объектов
Хотя в самом понятии объекта и есть кое-что, над чем можно поломать голову, использовать объекты достаточно просто. Поскольку объекты имеют имена, вы всегда
можете знать, с каким из объектов работаете. Чтобы идентифицировать в программном коде метод или свойство объекта, с которыми предполагается иметь дело, нужно
просто напечатать имя объекта, за ним точку и, наконец, имя метода или свойства.
Например, My Shape . L i n e S t y l e идентифицирует свойство L i n e S t y l e объекта
с именем MyShape в Visio. Точно так же MyWorksheet. C a l c u l a t e идентифицирует
метод C a l c u l a t e объекта рабочего листа с именем MyWorksheet в Excel.
Правда, здесь вы можете задать себе вопрос: "Но как же мне узнать имя объекта, которое
необходимо поместить в начале?" Блестящий вопрос! Вот только ответ на этот вопрос требует достаточно пространных пояснений, которые я отложу до раздела ''Идентификация объекта для использования", сосредоточившись сначала на обсуждении свойств, методов и событий. А пока что примите на веру, что объект можно вызвать по его имени.
288

Часть III. Практикуемся в программировании на VBA

Использование объектных моделей
Как вам стало очевидным из раздела "Что такое объектная модель", каждое VBAприложение имеет свою неповторимую объектную модель (иерархию объектов), а каждый из
его объектов имеет свой собственный набор свойств, методов и событий. Чтобы заставить
эти объекты работать в программе, вам необходимо хорошо разобраться в деталях объектной
модели соответствующего приложения.
Во многих приложениях справка о VBA содержит специальный раздел, в котором вы найдете
фафическое представление объектной модели этого приложения (рис. 12.4). Если диаграмма объектной модели не появилась перед вами при первом же вызове справки, перейдите в окне справки
на вкладку Содержание, где она будет представлена под рубрикой типа Microsoft Excel Objects.
Используя диаграмму объектной модели в качестве гида, вы сможете открыть информацию о конкретном объекте, дважды щелкнув на его имени в диафамме. Иначе получить нужную информацию можно, отыскав в указателе справки соответствующий раздел и открыв его. Как правило,
в любом разделе, посвященном объекту, имеются ссылки на другие разделы, содержащие дополнительную информацию о свойствах, методах и событиях соответствующего объекта. (Заметьте,
здесь идет речь о справке о VBA для соответствующего приложения, а не об общей справке о приложении или VBA. О работе со справочной системой VBA см. главу 4.)

Рис. 12.4. Объектная модель Excel
Другим жизненно важным средством для изучения свойств, методов и событий объектов
и их взаимосвязей в приложении является обозреватель объектов в редакторе Visual Basic.
Полное описание обозревателя объектов см. в главе 6.

Вылснение и цопано€ка свойаНб
Вероятно, свойства — это самые простые для понимания характеристики объекта. Каждое
свойство хранит информацию о некотором аспекте внешнего вида, поведения, содержимого
объекта или, если хотите, о его генеалогии.
Например, объект D o c u m e n t может иметь свойство P a g e s , говорящее о числе страниц
в документе. Объект S h a p e может иметь свойство F i l l , задающее цвет графического эле-

Глава 12. Объектно-ориентированное программирование

289

мента. Объекты CornmandButton (представляющие кнопки в диалоговых окнах) имеют
свойство C a p t i o n , задающее текст, появляющийся на кнопке.
Как правило, VBA-программа может выяснить, какая информация хранится в том или
ином свойстве, чтобы затем принять решение о том, следует ли предпринять какие-либо действия или просто отобразить на экране текущие установки свойства. Программа может и, наоборот, изменить установки свойств с тем. чтобы соответствующий объект изменил свой
внешний вид или поведение, — но только в том случае, когда свойство допускает такое изменение (многие свойства допускают чтение своих значений, но не их изменение).
Изо всех типов свойств легче всего разобраться со свойствами, задающими различные аспекты
внешнего вида объекта. Например, объект Shape в Visio среди прочих свойств имеет следующие.
Свойство

Описание

AreaUl

Площадь графического элемента в специальных внутренних единицах

Fi 11S t у 1 е

Стиль Visio, задающий цвет графического элемента и другие характеристики заливки

Text

Текст, появляющийся на графическом элементе

Эти свойства задают внешний вид объекта в документе.
Свойства, относящиеся к поведению объекта, определяют реакцию объекта на внешние
раздражители. Например, элементы управления в формах являются объектами, среди свойств
которых свойство E n a b l e d определяет, будет ли соответствующий элемент управления вообще реагировать на такие события, как щелчок кнопки мыши на нем.
Некоторые свойства, например AreaUZ для объекта Shape в Visio, могут принимать
любое значение. Другим же допускается назначить только одно из некоторого списка заранее
определенных значений. Многие свойства могут принимать только одно т дву> возможных
значений, таких как True или Fal з е . Торячий или Холодный, Сухой или Мокрый.
В любом случае, для выяснения текущего значения свойства или его изменения можно
использовать простые операторы VBA.

Что нельзя делать с некоторыми свойствами
Знание того, как менять значение свойства, еще не означает, что его можно менять. Некоторые
свойства позволяют выяснить свои значения, но не позволяют менять их. Это свойства только для
чтения. Существуют также, хотя встречаются значительно реже, свойства только для записи — их
значения можно изменить, но прочитать их текущие значения нельзя. Однако большинство
свойств предназначено для чтения и записи — их значения можно и прочитать, и изменить.

Установки свойств — это данные
Главной задачей свойства является описание некоторой характеристики объекта,
но вы должны знать, что установки свойства — это обычные данные, в принципе
ничем не отличающиеся от тех данных, которые вы размещаете в переменных
VBA. А если так, то можно представлять себе свойства как более или менее постоянно существующие переменные, которые не требуется объявлять.
При таком представлении переменных можно говорить, что любое свойство хранит данные определенного типа точно так же, как переменная. Например, свойство, которое может
принимать только два взаимоисключающих значения (True или F a l s e . Счастливый или

290

Часть III. Практикуемся в программировании на VBA

Несчастный, Левый или Правый), имеет тип B o o l e a n . Одни свойства являются строками, другие— целочисленными значениями, третьи— десятичными числами с дробной частью или плавающей запятой и т.д. Свойства могут быть и объектами. (О допустимых в VBA
типах данных см. главу 7.)

Выяснение текущего значения свойства
Чтобы выяснить или, как говорится, получить текущее значение свойства, используйте свойство так, как будто это функция или процедура типа F u n c t i o n . А значит, присвойте это свойство
некоторой переменной в своем программном коде. Переменная при этом должна иметь тот же тип,
что и свойство, или, по крайней мере, иметь подходящий тип.
В следующем примере объект представляет собой, скажем, вопрос для вступительного экзамена. Свойство, значение которого выясняется здесь, описывает сложность вопроса по десятибалльной шкале;
Dim 1ПГ_Сложность As I n t e g e r
intСложность = оЬ]ЭкзаменационныйВопрос.УровеньСложности
Первый оператор объявляет переменную, которой будет присвоено текущее значение
свойства, что и делает второй оператор.
Но для чего выяснять текущее значение свойства? Как правило, это значение используется в условных операторах и на его основе принимается решение о выполнении или невыполнении программой определенных действий. (В данном случае, например, это может быть
"если УровеньСложности вопроса выше 8 и если ответ правильный, то количество баллов
за ответ удвоить".) Значение свойства удобно сохранить в переменной и тогда, когда нужно
присвоить это значение такому же свойству другого подобного объекта.
Правда, если значение свойства используется только однажды, совсем не обязательно
присваивать его переменной — в выражении можно использовать и само свойство. Например:
If оЬ]ЭкэаменационныйВопрос.УровеньСложности > 8 Then
1п1;0бщееЧислоБаллоБ = т ^ б щ е е Ч и с л о В а л л о в + _
Цп^ЧислоБалловЗаОтвет *2)
End I f
Такая практика удобна, но не забывайте, что частое обращение к свойствам объектов замедляет работу программы. Если значение некоторого свойства используется больше одного-двух раз, это значение лучше сохранить в переменной —
VBA извлекает значение обычной переменной значительно быстрее, чем значение свойства.

Изменение значения свойства
Не забывайте, что свойства— это просто обремененные славой переменные. Поэтому свойствам можно присваивать значения точно так же, как обычным переменным, поместив в строке имя
свойства слева, а значение — справа от знака равенства. В операторе
оЬ^МузыкаМеталл.ФакторРаздражения = 999
значение свойства Ф а к т о р Р а з д р а ж е н и я — наверное, мера искажений, резонансов и всевозможных шумов — для объекта оЬ^МузыкаМеталл устанавливается равным 999:
оЬ]МузыкаМеталл.Мелодия = F a l s e
ок^МузыкаМеталл.Название = "У меня блохи. Плохо."

Глава 12. Объектно-ориентированное программирование

291

Свойства, выбираемые по умолчанию
Многие объекты имеют свойство, выбираемое по умолчанию. Прочитать или установить
значение такого свойства можно, указывая только имя объекта и не указывая имя самого
свойства. Обратившись снова к предыдущему примеру, предположим, что для объекта o b jMyзыкaMeтaлл свойством по умолчанию является Н а з в а н и е . Тогда последний оператор в примере можно записать проще:
оЬ^МузыкаМеталл = "У меня блохи. Плохо."
Использовать свойства по умолчанию удобно, конечно, когда вы точно знаете, какое
именно свойство объекта выбирается по умолчанию. Если же вы сомневаетесь или предполагаете, что потом не удастся вспомнить, какое именно свойство выбирается по умолчанию, то
лучше в таком случае напечатать имя свойства.

Объекты в роли свойств
Как уже упоминалось в разделе "Установки свойств — это данные", свойство одного объекта может указывать на другой объект. Это дает возможность обращаться к дочерним объектам данного объекта-контейнера так, как будто дочерние объекты являются свойствами
этого контейнера. Например, в выражении
Toolbar.ToolbarItems
T o o l b a r l t e m s -— свойство объекта T o o l b a r , но значением этого свойства является объект T o o l b a r l t e m s .
На самом деле именно такое использование свойств объектов является основным средством идентификации объектов для использования в программе (подробности приведены ниже,
в разделе "Идентификация объекта для использования").

Вверх по родовому дереву
Подобно тому, как свойства объекта указывают на подчиненные объекты, с помощью
свойств можно выяснить, какому контейнеру принадлежит сам объект. Например, если в Visio в переменной хранится ссылка на объект P a g e s и вы хотели бы выяснить, к какому документ)' она относится, то выражение
Pages.Parent
возвратит ссылку как раз на нужный документ. А если вам потребуется узнать, какому пргпожению принадлежит данный объект, то, как правило, можно пропустить все промежуточные ступени
иерархии и обратиться сразу на самый верхний уровень с помощью свойства A p p l i c a t i o n :
Pages.Application

в qeuan£uu
Методы — это именованные действия, которые объект может выполнить по команде.
Ввиду того, что любой метод является неотъемлемой частью объекта, объект сам знает, что
ему делать, когда вы вызываете метод.
Например, объект, задающий графический элемент, может иметь метод R e s i z e , изменяющий размеры, и метод R o t a t e , поворачивающий графический элемент на странице документа.
Объект, представляющий ячейку рабочего листа, может иметь метод C a l c u l a t e , пересчитывающий значение в ячейке, и метод C l e a r , удаляющий ее содержимое. Объект, представляющий целый документ, скорее всего имеет методы P r i n t (Печать) и Save (Сохранить).

292

Часть III. Практикуемся в программировании на VBA

На самом деле, методы представляют собой не что иное, как процедуры, привязанные
к конкретному объекту. Чтобы вызвать метод, необходимо напечатать имя объекта, точку,
а затем имя метода. Оставив в стороне сумасшествие металла, давайте рассмотрим объект
ок^МузыкаДжаэ в предположении, что он представляет цифровую запись джазовых композиций в мультимедиа-программе. Вполне возможно, что такой объект имеет метод
В о с п р о и з в е д е н и е . Вот как его можно вызвать:
obj МуэыкаДжаз.Воспроизведение
В основном техника вызова методов вполне согласуется с техникой вызова процедур
и функций VBA, о которой шла речь в главе 7.
Чтобы вызвать метод, требующий ввода аргумента, напечатайте аргумент после имени метода. В следующем примере метод Воспроизведение получает аргумент,
говорящий о том, сколько раз нужно воспроизвести пьесу:
оЬ^МузыкаДжаз.Воспроизведение 3
Если метод имеет несколько аргументов, печатайте их через запятую (в следующем
примере предполагается, что Негромко является именованной константой, задающей невысокий уровень громкости, a intCKopocTb — переменной, определяющей
скорость воспроизведения):
оЬ^МузыкаДжаз.Воспроизведение 2, Негромко, intCKopocTb
Чтобы вызвать метод, возвращающий значение, присвойте метод переменной или используйте его в выражении как обычную процедуру типа F u n c t i o n . В этом случае
все аргументы, независимо от их числа, необходимо заключить в скобки:
о^еВремяВоспроизведения =
__оЬ]МузыкаДжаз.Воспроизведение(2, Негроко,intCKopocTb)
Как и в случае свойств, методы совершенно разных классов объектов могут
иметь одинаковые имена. Например, объекты, содержащие группы элементов
или других объектов, как правило, имеют метод Add.
Обратите внимание, что метод меняет установки одного или нескольких свойств.
Например, объект оЬ^МузыкаДжаз может иметь свойство только для чтения
ЧислоИсполнений,
допускающее
изменение
только
методом
Воспроизведение, но его значение в то же время можно выяснить оператором типа 1п1:Исполнения = оЬ^МузыкаДжаз. ЧислоИсполнений. Некоторые объекты имеют методы, единственное назначение которых — установка
значений определенных свойств.

Событие представляет собой нечто, случающееся с объектом, и на что объект может ответить заранее предусмотренным действием. К событиям можно отнести следующее.
8

•/ Физические действия пользователя программы, например щелчок кнопкой мыши, перемещение курсора, прыжки и пляски вокруг компьютера. (Ну, ладно-ладно,
прыжки и пляски вокруг компьютера, очевидно, не относятся к событиям, распознаваемым VBA.)

Глава 12. Объектно-ориентированное программирование

293

Ситуации, в которые попадает объект в ходе выполнения программы. Например,
если речь идет об объекте, представляющем документ, то к событиям можно отнести
открытие и закрытие документа, добавление и удаление страниц (такие события в Word
распознаются объектами A p p l i c a t i o n и D o c u m e n t ) . В Visio объекты P a g e s могут
отвечать надевять различных событий, среди которых E e f o r e S h a p e D e l eze (Перед
удалением графического 'элемента) и T e x t C h a n g e d (Изменение текста). Другие примеры таких не связанных с формами событий вы найдете в главе 4.
То, какие события данный объект может распознавать, определяете не вы, а ваше
VBA-приложение. К вашим задачам относится создание программного кода, определяющего, что должен делать объект в ответ на распознаваемое событие. Здесь
следует обратить внимание на такой момент: вам не нужно вызывать процедуру обработки события из программного к о д а — при наступлении соответствующего события объект автоматически предпримет запрограммированные вами действия.
Программирование процедур обработки событий для форм рассматривается в главе 10. Те
же самые приемы, в основном, применяются и в случае не связанных с формами событий, правда, тут существуют некоторые тонкости, варьирующие от приложения к приложению, а иногда
даже в рамках одного приложения. Исчерпывающая информация по этому вопросу должна содержаться в справочной документации вашего приложения или в файлах его справки.

использования
Вы должны сообщить VBA, какой именно объект нужен. Для этого используется объектное выражение— VBA-выражение специального вида, которым однозначно определяется
конкретный объект для использования. То остающееся за кулисами значение, которое VBA
вычисляет на основе объектного выражения, является ссылкой на объект (вы можете представлять себе такое значение как почтовый адрес, по которому проживает объект).
Если при работе с объектами объектное выражение составлено правильно -— цель практически достигнута. После этого можно значительно упростить себе жизнь, создав для объекта переменную и присвоив этой переменной ссылку на объект, используя построенное объектное выражение. С этого момента в программном коде можно ссылаться на объект просто
по имени переменной.

Понимание объектных выражений
Объектное выражение представляет собой фрагмент программного кода — выражение,
"указывающее" на конкретный объект. С помощью правильно построенного объектного выражения можно изменять свойства объекта, вызывать его методы или присвоить объект переменной.
Обсуждаемые здесь приемы исключительно важны для практического программирования с использованием VBA, хотя сразу понять их не очень просто. Из-за того что
в программе могут использоваться много объектов одновременно, полное объектное
выражение должно включать все объекты, содержащие нужный вам обьект. Попробую пояснить это следующим образом. Предположим, вас просят отправиться и найти "того парня". Вы сразу же спросите: "Какого еще того?"' А вот если бы вас попро-

294

Часть III. Практикуемся в программировании на VBA

сили найти самого старшего школьника, живущего в доме №3 по улице Цветочной
в городе Шепетовка, Украина, то вам не пришлось бы задавать такой вопрос. (Правда,
вы бы тогда, наверное, спросили "Зачем?'") Конечно, если вы уже находитесь в доме
№3 по улице Цветочной, и в том доме живет только один школьник, то команда типа
"покормить мальчишку" будет вполне адекватной. Точно так же, когда контекст ясен,
и VBA не требует полного списка объектов.

Работа со свойствами, являющимися объектами
Свойство одного объекта может тоже оказаться объектом. Объекты сосуществуют в иерархии, когда один объект (например, документ) служит контейнером для других, подчиненных ему объектов (страниц, рабочих листов или чего-то другого).
Связь между двумя этими идеями очевидна: если объект содержит подчиненные объекты,
то любой подчиненный объект можно идентифицировать посредством свойства первого объекта. Выражение, которое используется для указания нужного свойства, является объектным
выражением.
Например, рассмотрим следующее выражение, идентифицирующее конкретный объект
в документе Word;
ThisDocument.Sections(2).Range
В этом выражении не одна, а две точки. Посмотрите, Range является свойством объекта
S e c t i o n , который, в свою очередь, является свойством объекта ThisDocument. Возможно, чтобы понять идею, вам этого примера уже достаточно, но если нет, то в следующем разделе вы найдете более подробные объяснения.

Получение объектов
В большинстве объектных моделей VBA объект A p p l i c a t i o n (Приложение) находится
на самой вершине иерархии. Однако обычно не возникает необходимости включать этот объект в выражения — VBA соображает достаточно неплохо для того, чтобы понять, что вы работаете с объектами текущего приложения, если вы специально не указываете иного.
Объект A p p l i c a t i o n содержит объект D o c u m e n t s — коллекция, представляющая
все открытые документы. Если вам нужно работать с конкретным документом, необходимо
идентифицировать его среди членов этого объекта-коллекции Documents. Например,
Documents (5) представляет объект Document № 5 в коллекции Documents.
В примере объектного выражения вы, однако, видите ключевое слово T h i s D o c u m e n t .
Во многих VBA-приложениях ThisDocument используется для обозначения объекта
Document, ассоциированного с вашим проектом.
В Word каждый объект Document имеет свойство S e c t i o n s , которое ссылается на коллекцию S e c t i o n s , — объект, представляющий множество всех разделов документа. Поэтому
первая часть указанного выше выражения — T h i s D o c u m e n t . S e c t i o n s —идентифицирует
конкретную коллекцию S e c t i o n s , принадлежащую объекту ThisDocument. Идентифицировав объект S e c t i o n s , вы получаете возможность выбрать конкретный член этой коллекции.
Таким образом, S e c t i o n s (2 ) ссылается на второй раздел документа.
Теперь о завершающей части выражения. Тонкость здесь заключается в том, что хотя
.Range идентифицирует свойство объекта S e c t i o n , значением этого свойства является
объект Range. Таким образом, все выражение обеспечивает ссылку на этот объект Range.
Использование выражения, подобным образом прокладывающего путь к конкретному объекту сквозь дебри иерархии объектов, в профессиональной фразеологии VBA называется
"получением объекта".

Глава 12. Объектно-ориентированное программирование

295

Работа с коллекциями объектов
В рассмотренном выше примере объектного выражения
ThisDocument.Sections(2).Range
объект S e c t i o n s представляет собой коллеекцию. В VBA коллеекцией называется объект
специального типа, который может содержать любое число других объектов.
Определенные в VBA-приложениях коллекции обычно содержат объекты одного типа.
Например, коллекции S e c t i o n s в Word содержат только объекты S e c t i o n , а коллекции
P a g e s в Visio могут принадлежать только объекты Page. (Правда, VBA предлагает и родовой объект C o l l e c t i o n , в котором вы можете разместить объекты любых типов. О том,
как создавать и использовать свои собственные коллекции такого рода, говорится в главе 13.)
О коллекциях вам достаточно знать только то, как получить доступ к содержащимся в них конкретным объектам. Для этого у вас есть две возможности.

1 ю массивом
память для других пула.

Часть III. Практикуемся в программировании на VBA

Объявление динамических массивов
Объявляйте массив как динамический в следующих случаях.
I S Если вы не знаете и не можете узнать размер массива ло выполнения программы.
1 S Если знаете, что размер массива в ходе выполнения программы будет меняться.
1 S Если после завершения использования массива хотите освободить занимаемую им
1
память для других целей (большие массивы могут занимать немало памяти, которую
1
можно освободить для использования динамических массивов).
Чтобы объявить динамический массив, просто не указывайте размер массива при его объявлении. Например, оператор
Dim с ^ е Д н и Р о ж д е н и я () As Date
подготовит VBA к использованию массива элементов типа D a t e , на самом деле не создавая
пока массив.

Переопределение динамических массивов
Динамический массив не может хранить данные до тех пор, пока вы не создадите массив
реально, указав его размер. Для этого используется оператор ReDim, как в следующем примере с одномерным массивом:
ReDim с ^ е Д н и Р с ж д е н и й (1г^ЧислоДнейРождения - 1)
Обратите внимание на то, что размер создаваемого этим оператором массива задается выражением, использующим переменную, в предположении, что значение этой переменной уже
определено в программе. Значение переменной приходится уменьшать на 1, чтобы привести
число элементов массива в соответствие с предлагаемой VBA нумерацией массивов от 0, если, конечно, вы не изменили систему нумерации, принятую по умолчанию, как описывалось в
разделе "Нумерация элементов массива".
Оператор ReDim должен использоваться внутри процедур. Один и тот же массив
можно переопределять столько раз, сколько нужно, задавая совершенно новые
числа размерности и размеров. Только не забывайте, что при обычном переопределении массива его содержимое полностью уничтожается. Нельзя также изменить тип данных, назначенных массиву, разве что при определенных условиях,
объяснять которые здесь мне кажется излишне сложным.

Сохранение данных при переопределении массива
Чтобы при переопределении массива сохранить часть данных, используйте вместе с оператором ReDim ключевое слово P r e s e r v e . Такая последовательность операторов объявляет динамический массив, создает его как двумерный массив заданного размера, а затем увеличивает размеры массива по второму измерению, не разрушая уже имеющиеся данные:
Dim d b l G a l a c t i c M a s s e s () As Double
ReDim P r e s e r v e d b l G a l a c t i c M a s s e s

(1 To 30,

I To 50)

ReDim P r e s e r v e d b l G a l a c t i c M a s s e s

(1 To 30,

1 To 100)

На самом деле возможности P r e s e r v e весьма ограничены— при использовании этого
ключевого слова не допускается менять размерность массива и можно менять размер только
последнего измерения (но все равно необходимо в операторе ReDim P r e s e r v e указывать
параметры остальных измерений). При этом можно сделать размер массива меньше, но данные, хранившиеся в удаленных элементах, будут утеряны навсегда.

Глава 13. Тонкости хранения данных: массивы и коллекции

307

Обращение к элементам массива
Чтобы в программе использовать конкретный элемент массива, напечатайте имя массива,
за которым следуют скобки с указанным в них индексом этого элемента. Индекс должен задавать целые значения для каждого из измерений массива. Например, выражение s t r S a y .Lngs {4, 6 ) , очевидно, однозначно идентифицирует строковые данные из строки 4 и столбца 6 в двумерном массиве строк.
Не забывайте, что числа или значения, которые вы должны указать в индексе для
идентификации элемента массива, зависят от системы нумерации, указанной вами при объявлении массива. Если массив объявлен оператором Dim s t r S a y i n g s ( 1 0 , 2 0 ) As S t r i n g , то выражение s t r S a y i n g s ( 4 , 6) идентифицирует данные из пятой строки седьмого столбца массива. Но если массив объявлен Dim s t r S a y i n g s ( 4 To 10, б То 50) As S t r i n g , то же самое
выражение означает данные из первой строки первого столбца.

Использование элементов массива в программе
В рамках описанной системы можно использовать элементы массива как обычные переменные. Вы можете сделать следующее:
f" S присвоить элементу массива значение; в следующем примере значение присваивается
X
конкретному элементу трехмерного массива данных типа C u r r e n c y :
$
I
curBigDough(5,8,19) = 27.99
I */ присвоить значение, хранящееся в массиве, некоторой переменной, например:
I
datThatDate = datTheseDates(25,10)
j S использовать значение элемента массива в выражении, например:
|
i n t A = 35 * ( i n t B + i n t C o u n t s ( 3 , 2 ) )

Использование переменных в индексах
Конечно, в индексах можно использовать не только буквальные значения. Задание индекса
с помощью переменных позволяет выбрать в программе тот элемент массива, который нужен
в данный момент. Это демонстрирует последняя строка следующего фрагмента программы:
Sub FortuneTeller()
Dim strTodaysFortune(1 To 10)
Dim intUserChoice As Integer
strTodaysFortune{1) = _
"Вы станете богатым и знаменитым на 15 минут."
strTodaysFortune(2) = _
"Вам предстоит обед с высоким незнакомцем."
strTodaysFortune(3] = "Стоимость ваших акций удвоится!"
strTodaysFortune(4) = _
"Вы вспомните, где положили свои ключи."
strTodaysFortune(5) = __
"Вы получите огромный букет от анонимного почитателя."
strTodaysFortune(6) = "Вы опоздаете на обед."
strTodaysFortune(7) = "Все ваши мечты сбудутся."
strTodaysFortune(8) = _
"Вам вернут взятые у вас библиотечные книги."

308

Часть HI. Практикуемся в программировании на VBA

strTodaysFortune(9) = _
"Никто не заметит ваших разных н о с к о в . "
strTodaysFortune(lO) = _
"Вы встретите своего старого друга в супермаркете."
i n t U s e r C h o i c e = InputBox("Чтобы узнать свое будущее," _
& " введите число от 1 до 10")
MsgBox ( s t r T o d a y s F o r t u n e ( i n t U s e r C h o i c e ) )
Кстати, этот программный код можно существенно улучшить, если добавить в него обработку неправильного ввода, возможного при ответе пользователя на запрос функции I n p u t Box. О проблемах проверки данных при вводе говорилось в главе 10.

Выяснение размера массива
Чтобы выяснить, как много элементов может вместить некоторое измерение массива, используйте функцию Ubound, которая особенно полезна при работе с динамическими массивами, поскольку в разные моменты выполнения программы динамический массив может содержать разное число элементов. Синтаксис функции UBound следующий:
UBound 'имя_массива,измерение)
Аргумент имя_массива, очевидно, задает имя массива, к которому нужно обратиться,
а аргумент и з м е р е н и е задает целое число, которое подскажет VBA, какое измерение массива вас интересует. Если и з м е р е н и е не указано, функция UBound возвратит размер первого измерения массива.

Заполнение массива данными... навалом
При первом создании массива его элементы не содержат никакой действительной информации. В некоторый момент в программе вам необходимо будет заполнить вакантные места
массива подходящими данными. Если нужно разместить сразу много данных, лучше всего
для этого подойдут вложенные циклы For . . . Next, по одному на каждое измерение массива. Для счетчика цикла обычно выбирается временная переменная, объявляемая в процедуре,
содержащей все эти циклы.
Этот подход иллюстрируется следующей небольшой программой, в которой трехмерный массив заполняется последовательными целыми значениями начиная с 1. Вот ее
программный код:
Const S i z e As I n t e g e r = 3
(1 To S i z e , l To S i z e , l To Size) As Double
D i m dblMatrix
Sub A r r a y F i l l e r ( )
Dim I As I n t e g e r , J As I n t e g e r , К As I n t e g e r , X As I n t e g e r
X = 1
For I = 1 To S i z e
For J = 1 To S i z e
For К = 1 To S i z e
d b l M a t r i x f l , J, K) = X
X = X + 1
Next К
Next J
Next I
End Sub

Глава 13. Тонкости хранения данных: массивы и коллекции

309

•ЛИЙ.

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

Объяснять это только на словах слишком сложно, поэтому я собираюсь использовать рисунки. Снова обратимся к предыдущему примеру программного кода. Представим трехмерный массив в виде куба, сложенного из маленьких кубиков, означающих элементы массива.
Иллюстрация этого мысленного эксперимента показана на рис. 13.2.

Рис. 13.2. Этот чертеж представляет массив для хранения данных; стрелки с буквами соответствуют
измерениям массива
Обратите внимание на то, что в главной строке этого программного кода,
" i b i M a t r i x ( I , J, К) = X, переменные I, J и К представляют соответственно первое,
второе и третье измерения массива. На рис. 13.2 я произвольным образом назначил тги буквы
сторонам куба, задающим его измерения.
Теперь посмотрите, как эти переменные используются в циклах -Г'jr. . . N^xL. Счетчиком внешнего цикла является I, следующего— J и последнего, внутреннего,— К. Нужно
понять, что VBA начнет выполнение с внутреннего цикла, пройдя к нему сквозь все содержащие его циклы. Кубы на рис. 13.3 показывают два последовательных момента в самом начале заполнения массива из этого примера.
Л пока этот внутренний цикл выполняется, VBA не меняет значения переменных I и п. Когда внутренний цикл первый раз пройден полностью, первый раз получит возможность сделать
шаг следующий ц и к л — цикл J. Это увеличит значение J— и снова начнется выполнение
внугреннею цикла от начала до конца. Значение I изменится только тогда, когда цикл .Г выгюлчеи все три раза. После увеличения I начинает заполняться следующий слой массива (рис. 13.4).
Надеюсь, теперь вы поймете, как отражается изменение порядка вложения циклов на порядке заполнения массива. Предположим, что порядок вложения циклов изменен на обра г
•1ый, и счетчиком внешнего цикла теперь стало К. Вот как должен выглядеть при этом соответствующий программный код (обратите внимание, что в операторе присваивания переменчые остались на прежних местах):

310

Часть ///. Практикуемся в программировании на VBA

Рис. 13.3. Эти два чертежа иллюстрируют последовательность, в которой процедура-пример запол
массив по мере выполнения внутреннего цикла For. . .Next:
For К = 1 То Size
For J = 1 To Size
For I = 1 To Size
dblMatrix(I, u, K) = X
X = X + 1
Next I
Next J
Next К
В результате массив будет выглядеть так, как показано на рис. 13.5.

Глава 13. Тонкости хранения данных:массивы и коллекции

311

Рис. 13.4. Второй слой массива начнет заполняться только после того, как изменит значен
внешнего цикла Fo г. . . Next

I
У
1

2

3

4
5
6

^

У

Л
уГ7
8
9

\
\

\\

У

Рис. 13.5. Этот чертеж иллюстрирует порядок заполнения массива измененной процедурой
Массив будет содержать те же значения, что и в первом случае, но они хранятся иными
элементами массива.

312

Часть III. Практикуемся в программировании на VBA

Копирование одного массива в другой
В VBA 6 можно присвоить содержимое одного массива другому с помощью простого оператора наподобие
strMaccHBKonMH = str-ИсходныйМассив
Массив слева (тот, которому присваиваются значения) должен быть динамическим,
и VBA переопределит его автоматически в соответствии с размерностью и размерами массива справа. Получающий значения массив должен также допускать хранение данных того типа, который назначен данными исходного массива.
В VBA 5 вам придется копировать данные массива поэлементно, примерно так:
' выяснение размера исходного массива и
' соответствующее переопределение второго массива
intPa3MepMaccMBa = UBound(strMcxon.HbinMaccMB)
Re Dim з!:гМассивКопия (intPa3MepMaccHBa)
' выполнение копирования
For I = 0 To intPa3MepMaccMBa
э^гМассивКопия (I) = э1:гИсходныйМассив (I)
Next I

ttaJofwMU данных с помощью
Collection
Если нужно работать с наборами элементов информации, создайте для этой информации
объект C o l l e c t i o n (Коллекция). Как уже говорилось в главе 12, в VBA родовой класс
C o l l e c t i o n предназначен для хранения практически всего, что только возможно. На основе этого класса можно создать любое число объектов C o l l e c t i o n . Коллекции используются для хранения других объектов, но точно так же коллекции можно использовать и для хранения данных почти любых из допустимых в VBA типов.
Коллекция может содержать только простой список элементов, похожий на одномерный
массив. Но поскольку коллекции относятся к простейшим из массивов, за счет специализации
вы получаете выигрыш в качестве обслуживания.

Оценка преимуществ использования коллекций
Если вы чувствуете себя вполне уверенно при работе с объектами VBA, то использование
объектов C o l l e c t i o n для управления множествами элементов может оказаться для вас более
простым, чем использование массивов. Методы Add и Remove позволяют без труда изменять
размеры коллекции, и при этом вероятность возникновения ошибок будет меньше, чем при использовании оператора ReDim в разных частях программы. (Эти преимущества становятся особенно важными, если необходимо часто добавлять и удалять элементы группы.)
Кроме того, элементам коллекции можно назначить имена, по которым позже получают
доступ к элементам. При этом вы не только получите возможность выбрать описательные
имена, которые легко запомнить, но ускорите доступ к данным, особенно при числе элементов, превышающем 100,

Глава 13. Тонкости хранения данных: массивы и коллекции 313

Одним ii'j отрицательных побочных эффектов при использовании коллекций является
увеличение расхода памяти— коллекции для хранения информации используют тип V a r i a n t , а данные типа V a r i a n t занимают больше памяти, чем данные других типов. В больших коллекциях такого рода перерасход памяти весьма значителен.
Но самое главное ограничение при использовании объектов C o l l e c t i o n — запрет па хранение в них данных пользовательского типа, т.е. их нельзя непосредственно использовать с базами данных (см. ниже раздел "Определение своих собственных типов данных"). Правда, с помощью несложных приемов программирования это ограничение довольно просто обойти. И кроме того, серьезно работая
с VBA с базами данных, вы все равно, скорее всего, будете использовать готовые
объекты из ядра Microsoft Jet (DAO) и библиотек ODBC, а не объекты, созданные
кустарным способом.

Создание объектов Collection
Объекты Со; l e c t i o n создаются в программе точно так же, как и любые другие объекты, с использованием ключевого слова As для определения типа. Как и с другими объектами,
\ вас есть на выбор два варианта.
1У Можно объявить имя переменной для объекта и затем использовать оператор S e t ,
:•
чтобы создать ее. При этом в операторе S e t нужно использовать ключевое слово
New, чтобы создать новую коллекцию. Например:
Dim colMixedBag As C o l l e c t i o n
Set colMixedBag = New C o l l e c t i o n
' создание коллекции
colMixedBag.Add "Howard, E t h e l "
1
добавление элемента
Можно обязать VBA создать объект автоматически при первом использовании переменной в программном коде. Для этого нужно поместить ключевое слово New в объявление переменной;
Dim colSetOfStuff As New Collection
' следующий оператор создает коллекцию
1
при добавлении в нее целого значения
colSetOfStuff.Add intStuffing

Добавление данных в коллекцию
Для заполнения созданной коллекции данными используйте метод Add (Добавить) точно
так же, как при добавлении объектов во встроенные коллекции VBA-приложения (см, главу 12). Примеры использования метода Add вы найдете и в предыдущем разделе.
Синтаксис метода Add выглядит так:

Add (элемент[, имя] [, before индекс] [, a f t e r индекс])
При этом выражение элемент обязательное, оно может быть буквальным значением,
переменной, ссылкой на объект или более сложным выражением, составленным из этих компонентов, — в общем, всем, что возвращает значение, распознаваемое VBA. Остальные аргументы метода Add необязательны, они обсуждаются в следующих разделах.

314

Часть III. Практикуемся в программировании на VBA

Присваивание имен элементам
ii общем-то, всегда можно обратиться к элементу коллекции по его индексу в этой коллекции, ло зачастую удобнее назначить элементу информативное имя. Для этого нужно при
добаюекии элемента R коллекцию указать его имя в виде строки:
c ^ L F n : .-.ncia I s - Aoj 14 32 3 . 44,

"Продажи за ф е в р а л ь "

В этом операторе в коллекции c c l F i n a n c i a l s добавляется значение 1 4 3 2 3 . 4 4 . Одновременно для этого элемента создается имя. Вполне допустимо при задании имени использовать переменную типа S t r i n g .
Имя не только легче запомнить, чем индекс, оно, к тому же, обеспечивает единственный надежный способ доступа к конкретному элементу коллекции. При использовании методов Add и Remove позиции элементов данных
в коллекции могут меняться. Даже если элемент с №69 станет 29-м, вы
все равно сможете воспользоваться значением этого элемента, если знаете
его имя.
Имя элементу можно присвоить только е помощью метода Add. Чтобы присвоить имя
элемент), уже существующему без имени, придется удалить имеющуюся копию с помощью
R e n o v e и использовать Add для добавления элемента снова.

Добавление элемента в заданном месте
Иногда удобно разместить элементы коллекции в определенном порядке. И даже если при
этом нельзя добавлять элементы в нужном порядке последовательно, то все равно нет проблем-- мс'юд Add позволяет вставлять элементы туда, куда требуется, просто доя этого
нужно использовать аргументы b e f o r e (.перед) и a f t e r (после).
Предположим, что вам нужно вставить новый элемент перед 35-м элементом в коллекции.
Вы можете использовать для JTOTO оператор следующего вида:
г о ] Л:1! j n d i s . A d d

r,i i S p e c i e s ,

b e f L-re

35

Добавленный элемент станет 35-м элементом коллекции, подвинув все последующие,
(В отличие от- массивов, элементы коллекций нумеруются с I.) Чтобы сообщить VBA, где
вставить новый элемент, можно иеполь.ювать и имя существующего элемента, например:
со10вси;и. Add =• tstiCopT, af*:.ej. "Помидор"
В данном случае VBA найдет в коллекции существующий элемент с именем Помидор
и сразу после него вставит новый.
Ясно, что в оператор, использующий метод Add, можно включить либо b e f o r e , либо
a f t e r , но никак не оба этих аргумента.

Добавление нескольких элементов сразу
Для добавления в коллекцию множества элементов можно использовать
F o r . . . N e x t , подобно тому, как это делалось с массивами. Например:

цикл

Duu X ? s i n t e g e r , Y As I n t e g e r
У - 12
For X - I To 30
cclHcuseOfValues.Add Y * X
Next X

Глава 13. Тонкости хранения данных: массивы и коллекции

315

Удаление элементов
Говоря очевидное, сообщаю вам, что метод Remove удаляет элемент из коллекции. Объект для удаления можно задать либо с помощью индекса, либо с помощью имени, например:
со1Минералы.Remove 2123
со1Минералы.Remove "Боксит"
Не забывайте, что при удалении элемента, VBA, так сказать, "заполняет дыры" — номера
всех элементов, следующих за удаленным, уменьшатся на 1.

Подсчеты в коллекциях
Запутаться в размерах коллекции несложно, особенно после многократного использования Add и Remove. Родовой объект C o l l e c t i o n имеет только одно свойство — Count
(подсчет), — но, в силу вышесказанного, это свойство оказывается жизненно важным. Значение этого свойства можно присвоить переменной, например, так:
ол^РазмерКоллекции = со12 0Вопросов.Count
Его можно также использовать в условном выражении, как здесь:
If colPrices.Count > 1000
MsgBox "Слишком много позиций!"
End If
Кроме того, значение свойства Count можно использовать в цикле For . . . Next, чтобы
выполнить некоторые действия по отношению ко всем элементам коллекции, например:
Dim Z As I n t e g e r
For Z = 1 To c o l P r i c e s . C o u n t
MsgBox "Цена " & c o l P r i c e s ( Z )
Next Z
Но лучше для этого использовать цикл F o r E a c h . . . Next (см. главу 8).

Доступ к элементам коллекций
Чтобы идентифицировать конкретный элемент в коллекции, используется индекс элемента или его имя (если оно определено). Например, значение элемента коллекции можно присвоить переменной:
- со1ДниРождения("Василий Али-БаОаевич")
К сожалению, вам придется отслеживать имена самим — VBA не предлагает возможности прочитать имена элементов коллекции. Кроме того, нельзя изменить имя
элемента иначе, как удалив этот элемент из коллекции и затем добавив его вновь.
Точно так же нельзя в существующий элемент коллекции поместить новое значение. Следующий оператор присваивания работать не будет:
c o l l n v e n t o r y ( 1 4 6 5 ) = 119
Опять же, единственный способ изменения значения в коллекции — удаление соответствующего элемента и добавление нового с новым значением. Подобных ограничений нет для
объектов D i c t i o n a r y (словарь), которые обсуждаются в главе 14.

316

Часть ///. Практикуемся в программировании на VBA

Использование коллекций с базами данных
Как уже было сказано, применение класса C o l l e c t i o n VBA ограничивается тем,
что в нем нельзя хранить данные пользовательских типов. С этим ограничением можно
смириться, если выбрать подходящую систему создания имен элементов. В следующем
примере при каждом проходе цикла F o r . . . N e x t в коллекции создается запись базы
данных. Эта запись состоит из трех полей, каждое из которых идентифицируется именем, составленным из простого описательного признака и номера записи. Вот соответствующий программный код:
Dim I As I n t e g e r , strName As S t r i n g
Dim s t r P h o n e As S t r i n g , s t r A d d r e s s As S t r i n g
For I = 1 To T o t a l ' I идентифицирует номер записи
' получение данных для этой записи
strName = InputBox("Введите имя для этой записи")
s t r P h o n e = InputBox("Введите номер телефона для _ этой
записи")
s t r A d d r e s s = InputBox("Введите адрес для этой записи")
1
Добавление " п о л е й " для этой записи в коллекцийе
c o l D a t a b a s e . A d d strName, "Имя" & I
c o l D a t a b a s e . A d d s t r P h o n e , "Номер телефона" & I
c o l D a t a b a s e . A d d s t r A d d r e s s , "Адрес" & I
Next I
Впоследствии можно извлечь информацию, хранимую в отдельной записи по описательному признаку и номеру, как в следующем операторе:
MsgBox c o l D a t a b a s e ( " И м я 2 " )
Если вы собираетесь создавать реальные программы для управления информацией в базах данных, не используйте для этого коллекции объектов — они
имеют слишком много ограничений. Вместо этого используйте подключаемые
компоненты доступа к базам данных (соответствующие примеры вы найдете
в главе 14). Если же вы хотите выполнить всю работу самостоятельно, создайте свои собственные классы для объектов, позволяющих работать с пользовательскими типами данных. Ваши объекты должны позволять хранить в них
любые комбинации данных, которые могли бы извлекаться как свойства. Кроме того, неплохо было бы добавить программный код для проверки правильности сохраняемой в отдельных элементах информации. (Модули классов рассматриваются, хотя и не слишком подробно, в главе 14.)

Определениесвоихсобственных
данных
Если вы не математик, многомерные массивы данных одного типа вам, скорее всего, вряд
ли понадобятся. В практических задачах управления данными чаще приходится работать
с наборами элементов совершенно разных типов. В VBA-программе для управления такой
информацией лучше всего создать пользовательский тип данных.

Глава 13. ТОНКОСТИ хранения данных: массивы и коллекции

317

Обычно приводят набившую оскомину аналогию между такими структурированными данными
и карточками каталога (рис, 13.6}, хотя персональные компьютеры уже давным-давно заполонили
все вокруг, и, как мне кажется, сегодня вряд ли кто-то пользуется каталогами из карточек.

Name: Says, Fran

Name: Best, France's

Name: Smith, Francis

Name: Jones, Frances

Phone: (209) 555-3366

Phone:(612)555-9090

Position: Middle manager

Position: Database analyst

Frame of mind: Distracted

Frame of mind: Ebullient

Рис. 13.6. На этихкарточках хранится структурированная информация наподобие той,
представлена данными пользовательских типов в VBA
Огромное количество баз данных фактически представляет такого же типа организованную структуру, но в электронном виде. Ваза данных — это набор записей, каждая из которых
состоит из полей для хранения отдельных элементов информации. Разные поля могут хранить данные совершенно различных типов (строки, числа, даты или что-то другое). Содержимое одного и того же поля при переходе от записи к записи может меняться, но тип хранимых в поле данных остается во всех записях одним и тем же.

Знакомство с пользовательскими типами данных
Пользовательский тип данных VBA представляет собой, так сказать, поселившуюся под
одной крышей компанию выбранных вами типов данных. Определив пользовательский тип
данных, вы получаете возможность объявлять переменные этого типа точно так же, как переменные встроенных типов.
Переменную пользовательского типа можно сравнить с отдельной карточкой в каталоге
или одной записью в базе данных. А чтобы представить целый каталог с карточками или базу
данных с записями, объявите массив данных пользовательского типа.

Объявление пользовательского типа данных
Для объявления пользовательского типа данных используется оператор Т у р е , как в следующем типичном примере:
Туре Персона
intHov.ep As Integer ' номер работника
strФамилия As S t r i n g
strMMH As S t r i n g
strAflpec As S t r i n g
1пдТелефон As Long
сЁа^ЦатаНайма As Date
End Type
Здесь объявляется новый пользовательский тип данных П е р с о н а . Как ясно показывают
строки с отступами, этот тип состоит из целого значения, трех строковых значений, длинного
целого и даты. (Обратите внимание на то, что при объявлении типа необходимо назначить

318

Часть III. Практикуемся в программировании на VBA

каждому элементу имя — простого указания типа данных недостаточно.) Когда вы объявите
переменную типа П е р с о н а , в этой переменной автоматически будет предусмотрено место
для всех шести элементов, перечисленных в объявлении типа.
Ооратите внимание и на то, что для оператора i y p e треоуется оператор Епа
Т у р е , завершающий блок объявления. Если вы забудете об этой завершающей
С!роке, компьютер будет ругать вас.
И еще: пользовательский тип можно объявить только на уровне модуля (в разделе объявлений в самом начале модуля). Внутри процедуры объявить пользовательский тип нельзя.

Объявление переменных пользовательского типа
Как и встроенные типы данных, пользовательский тип остается абстрактным понятием до
тех пор, пока вы не объявите переменную соответствующего типа. Для этого не требуется
что-то особенное— годится стандартный синтаксис объявления обычных переменных. Точно так же в объявлениях переменных пользовательского типа можно использовать ключевые
слова P.i ' j l i с, P r i v a t e и S t a t i c . Вот пример объявления такой переменной с помощью
стандартною оператора Dim:
D Д.ГГ. i.i s г ? а б о т н v. к к в Пирсона
Как аудите, при этом не требуется объявлять элементы внутри пользовательского типа.
И хотя огератор D LIT. задает имя новой переменной, имена ее элементов фиксируются в объявлении соответствующею пользовательского типа.
Чюбь получить целую базу данных вашего пользовательскою типа, объявите массив
с помощью оператора следующего вида:
P r i v a t e П е р с о н а л ( I То 2Ъ) As Пергона

Обработка информации, представленной пользовательским
типом данных
После объявления переменной пользовательского типа ее можно "начинять" информацией. При :»гом необходимо присвоить значение каждому из элементов, составляющих тип.
А для этого нужно идентифицировать элемент с помощью имени переменной, за которым
следую п о ч к а и имя элемента. Например:
и з г Р а б о г н и к . s ^ . Ф с ш ч . ^ я •- "Ёлк.ин"
При заполнении нескольких элементов сразу оператор W i t h поможет сократить объемы
необходимого печатания. Вот пример использования этого оператора:
"With

изгРаботник

. str^^i^^y.nv^ = "Исаков"
. ?, t г Имя = " В л с л л и й "
. . ^ Д а т а Н а й ^ а - #1?/9/48#
End Wi-n
Для присвоения данных элементам в массиве пользовательского типа используйте стандартные индексы массива. В следующем примере такой индекс задается переменной:
Персона:; ( int.4or.iep; . str-Имя - "Марфа"

Глава 13. Тонкости хранения данных: массивы и коллекции

319

Работа с переменными пользовательского типа данных
Если переменная пользовательского типа хранит полный набор данных, можно присвоить
ее содержимое другой переменной того же типа— все содержимое сразу, без копания в элементах, из которых состоят эти переменные. Например, чтобы присвоить содержимое переменной и з г Р а б о т н и к второй ячейке в массиве Персонал, используйте оператор
Персонал(2) = иэгРаботник
Самое интересное, что этот трюк срабатывает также в случае чтения информации из файла и записи информации в файл на диске. Например, можно сохранить полную записей базу
данных на диске с помощью программного кода следующего вида:
Sub WriteDataf)
Open "С:\Database\CoTpyflHMKM.dat" For Binary As #1
For i = 1 To intPa3MepEa3biflaHHbix ' цикл по всем записям
Put # 1 , , Персонал(i)
Next i
Close #1 ' закрытие файла - обязательный шаг
End Sub
Чтение данных из файлов и запись данных в файлы на диске обсуждаются в главе 18.

320

Часть ///. Практикуемся в программировании на VBA

Часть IV

Профессиональная работа
cVBA

"Это не качественная или количественная
оценка твоей работы.
Это всего лишь скромный слисок пожеланий."

В atfou час&и...
sT^f'B'гяаёахс 14no 16рассматривается использование VBA \ ^\
в Microsoft Office. В главе 14ъы познакомитесь с инструментами !
, "программирования, которые рЪботают во всех Ърияожениях \
" -f ; r # % T Office, Срда.относятся приемы для настройки ~
' |
пользовательскогоинтерфейса+программироеан'юПомощника *
• -по Office, который чаще всеео появляется в лице Скрепыша, ' ^
~- а'также сохранения данных• прогр'аммы,в должном формате. *
В главах 15 и 16 мы детально остановится на программировании I
1
•." для. Word u.Excel соответственно —'наиболее широко
i~l используемых VBA-прияожетй. В каждой из глав подробно
*
*'?' г - - рассматриваются важные средства и приемы
\
_\" программирования дм работы с документами '
и их содержимым с помощью VBA.
]
Материал остальных глав настоящей части представляет
,
интерес для всех УВЛ-программистов, независимо от того, ]
в каком приложении они работают.
\
В главе 17 мы поговорим о программировании для баз данных \
на VBA. В главе 18мы рассмотрим не очень удобные, поболее \
мощные не объектно-ориентированные способы работы
!
с файлами, чем объектно-ориентированные способы, которые \
рассматриваются нами в главе 20, И наконец, в главе 19
'
я предлагаю вам расширенно рассмотреть УВА-формы.

Глава 14

VBA для Office
/3 эг&ой главе..,
>

Отображение пользовательских панелей инструментов и кнопок с помощью VBA

>

Программирование Помощника по Office

>

Сохранение значений переменных на диске

1 Х В А полезен для создания полноценных приложений не меньше, чем небольших подруч¥ ных средств. В настоящей главе я познакомлю вас с некоторыми приемами, которые позволят вам профессионально работать с приложениями Office.

/6>шЯ/ииьноупанелями
и меню
Приложения Office позволяют пользователям настраивать панели инструментов, строки
меню и контекстные меню, обходясь безо всякого программирования, поэтому для решения
подобных задач в VBA необходимости нет. Однако, если вы хотите, чтобы окно VBAпрограммы содержало определенный набор панелей инструментов или меню либо вам необходимо внести изменения в панели инструментов или меню при, например, запущенной программе, вам нужно написать программный код, который позволял бы в определенных условиях включать или отключать команды меню.
В последних версиях Office граница между панелями инструментов и меню стала исчезать: вы можете добавлять кнопки в меню или раскрывающиеся списка на любую панель инструментов. В VBA главная строка меню и остальные панели инструментов относятся к коллекции объектов C o m m a n d B a r s . Конечно же, каждая панель инструментов является отдельным объектом CommandBar.
Для работы с определенной панелью инструментов вам следует указать ее имя в коллекции C o m m a n d B a r s . Например, приведенный ниже фрагмент кода обращается к панели инструментов под названием VBA4Dummies:
Dim tbar As Toolbar
Set tbar = CommandBars("VBA4Dummies"}

Отображение и размещение панелей инструментов
Для отображения или сокрытия панели инструментов предназначено свойство V i s i b l e . Приведенный ниже фрагмент кода отображает панель инструментов под названием VBA4 Dummies.
CommandBars{"VBA4Dummies").Visible = True
Для сокрытия панели инструментов свойству V i s i b l e
значение F a l s e .

Глава 14. УВАдля Office

следует присвоить

323

Для переключения состояния отображения панели инструментов — отображения скрытой
панели инструментов, и наоборот, следует использовать оператор Not (см. главу 11).
CommandBars("ReBar").Visible = _
Not ( C o m m a n d B a r s ( " R e B a r " ) . V i s i b l e )
Если вы хотите изменить место расположения отображенной панели инструментов на экране, используйте такие ее свойства, как P o s i t i o n , Rowlndex и L e f t . При необходимости используйте свойство P r o t e c t i o n , чтобы исключить возможность перемещения панели инструментов пользователями. Подробные сведения о каждом из этих свойств приведены
в следующей таблице.
Свойство

Назначение

Доступные настройки

Position

Определение того, прикреплена ли
панель задач, и если так,
определяется сторона, к которой
она прикреплена

m s o B a r F l o a t i n g (для
неприкрепленной панели инструментов),
msoBarTop, msoBarLeft,
msoBarRight

Rowlndex

Определение порядка закрепления
панели инструментов по
отношению к другим панелям
инструментов, прикрепленным
к той же стороне

Целое число больше 0;
m s o B a r R o w F i s t или
m s o B a r R o w L a s t (длязакрепления
панели инструментов первой или последней
по порядку соответственно)

Left

Определяет расстояние от левого
края панели инструментов до
левого края экрана

Protection

Определяет способ защиты панели
инструментов от действий
пользователей

msoBarNoProtection,
msoBarNoCustoraize,
msoBarNoResize,
msoBarNoMove,
rasoBarNoChangeVisible,
msoBarNoChangeDock,
msoBarNoVerticalDock,
msoBarNoHorizonalDock

Настройка кнопок панелей инструментов
Вам не потребуется VBA для создания панели инструментов, содержащей необходимый
для вашей работы набор кнопок, — мощные средства настройки методом drag-and-drop,
представленные в любом приложении Office, с честью справляются с подобными задачами.
Но если вам необходимо изменить внешний вид панели инструментов или ее реакцию на действия пользователя буквально на лету вследствие возникновения определенных условий,
VBA — именно то, что вам нужно.
Например, предположим, что вам нужно создать кнопку, которая позволит немедленно отправлять копию открытого документа Word определенному человеку или только при работе
с документом определенного типа. Кнопка должна срабатывать только в определенных условиях.
Если вы знаете, как написать VBA-код, который сможет определять тип открытого документа, все, что вам необходимо,-— это присвоить свойству E n a b l e d значение T r u e или
F a l s e в той или иной ситуации.

324

Часть IV. Профессиональная работа с VBA

Работа с определенными кнопками
Если вам необходимо настроить параметры определенной кнопки, вам необходимо идентифицировать эту кнопку в VBA-коде.
Вы можете указать кнопку одним из следующих способов.
| S Используя индексный номер кнопке в коллекции Controls объектов панели ин|
струментов, к которой она относится. Индексный номер кнопки соответствует ее
I
расположению на панели инструментов; при этом кнопке, расположенной в крайнем
1
левом (или в крайнем верхнем) углу, соответствует индексный номер 1. Ниже приведен пример подобного обращения к объекту:
CommandBars("BarNone").Controls(3)
Проблема состоит в том, что Office позволяет пользователям перетаскивать кнопки
по панели инструментов, поэтому ничто не гарантирует, что вы обращаетесь именно
к той кнопке, которая вам необходима.
•S Использование свойства C a p t i o n кнопки. Вы можете ввести любой заголовок, используя пользовательский интерфейс Office. Выберите команду Сервис^Настройка,
перейдите на вкладку Команды появившегося диалогового окна Настройка. Щелкните на
интересующей вас кнопке правой кнопкой мыши, чтобы увидеть имя кнопки. Следующая
команда ссыпается накнопку, свойство C a p t i o n которой равно "Угадай мой в е с " .

CommandBars{"BarNone").Controls("Угадай мой вес")
Вы можете определить заголовок прямо в программном коде, но вам все равно придется указать кнопку одним из других способов.
^ Используя метод F i n d C o n t r o l коллекции CommandBars для обнаружения
кнопки. Этот метод обнаруживает кнопки по нескольким критериям. Наиболее полезным оказывается использование свойства Tag. Однако, чтобы оно сработало, вам
сначала необходимо присвоить этому свойству уник&чьное значение, используя инструкцию, подобную приведенной ниже.
CommandBars("BarNone").Controls(,,"TagOl")
После этого, когда вам необходимо обратить к кнопке из программного кода, вы можете использовать метод F i n d C o n t r o l для получения ссылки на кнопку, например,
с помощью следующей инструкции:
CommandBars.FindControl(, , "TagOl")
В этом примере запятые относятся к необязательным параметрам метода F i n d C o n t r o l ,
которые не потребуются вам при нахождении элементов управления (в нашем случае, кнопки) по свойству Tag.

Настройка кнопок на лету
В приведенной ниже таблице перечислены наиболее полезные свойства и методы, позволяющие настраивать кнопки панелей инструментов с помощью VBA,
Свойство или метод

Эффект

Доступные параметры
(только для свойств)

Свойство E n a b l e d

Определяет, включенали кнопка
и дхтупна ли она щелчком мышью либо
она отключена, а значит, затенена

T r u e или F a l s e

Глава 14. VBA для Office

325

Доступные параметры
(только для свойств)

Свойство или метод

Эффект

Свойство V i s i b l e

Определяет, видна ли кнопка

True или F a l s e

Свойство S t a t e

Определяет, кажется ли кнопка "нажатой"

msoButtonUp
(обычный вид кнопки);
msoButtoriDown (кнопка
заблокирована в нажатом
состоянии);
m s o B u t t o n M i x e d (кнопка
имеет вид "нажимаемой")

Метод CopyFace

Копирует изображение с указанной кнопки
в буфер обмена. Для кнопки, изображение
которой изменяется должным образом,
создайте панель инструментов, содержащую кнопки с нужным изображением, но не
выполняющие никаких реальных действий.
Затем скройте эту панель инструментов.
Когда придет время изменить изображение
на "настоящей" кнопке, используйте метод
C o p y F a c e для копирования необходимого изображения с соответствующей
кнопки на скрытой панели инструментов.
Затем используйте метод P a s t e F a c e
для вставки изображения на кнопку

Метод P a s t e F a c e

Размещение на кнопке изображения, уже
помещенного в буфер обмена

Отображение пользовательских экранных подсказок для кнопок
на панели инструментов
Экранные подсказки— это те небольшие сообщения желтого цвета, которые появляются
на экране после подведения указателя мыши к определенному элементу на одну-две секунды.
Экранные подсказки для панелей инструментов должны быть включены, и по умолчанию это
именно так. Если же это не так, выберите команду Сервис^Настройка, перейдите на вкладку Параметры, после чего установите флажок Отображать подсказки для кнопок.
По умолчанию экранная подсказка для кнопки содержит только ее имя. Однако, если вы
не боитесь немного попрограммировать на VBA, вы сможете добавить текст к экранной подсказке, изменив ее свойство T o o l t i p T e x t . Приведенный ниже программный код добавляет экранную подсказку для воображаемой кнопки в Excel:
Sub Этой_Кнопке_Нужна_Экранная п о д с к а з к а ! )
CommandBars("Mr. G o o d B a r " ) . C o n t r o l s ( 2 ) . T o o l T i p T e x t = _
"Форматирование ячейки: по центру, полужирный, денежный"
End Sub
Вам необходимо выполнить эту процедуру всего один раз. Поскольку Office сохраняет
новые экранные подсказки в шаблоне документа, с которым вы работаете, вы можете удалить
процедуру в любое время.

326

Часть IV. Профессиональная работа с VBA

JIftazfiaMUUifto6aHdie ТСомацника по Office
В любом приложении из состава Microsoft Office Помощник по Office позволяет быстро
находить необходимую справочную информацию или предлагает пошаговые инструкции для
выполнения повседневных задач. Как вы и могли ожидать, для манипулирования Помощником с помощью VBA достаточно использовать объект A s s i s t a n t .

Контроль над Помощником
Используйте свойства объекта A s s i s t a n t (табл. 14.1) для контроля за тем, как и когда
Помощник по Office будет появляться на экране. Пока вы не уверены в том. что Помощник
уже включен, убедитесь в том, что его свойство On имеет значение T r u e , прежде чем пытаться включить его снова.
Таблица 14.1. Свойства объекта Assistant
Свойство

Функция

Допустимые значения

On

Определяет доступность Помощника T r u e или F a l s e
no Office. Соответствует флажку
Использовать помощника
на вкладке Параметры диалогового
окна Помощник

Visible

Определяет наличие Помощника
на экране

F i l eKame

Выбирает персонаж помощника,
который будет представлен на
экране: Срепыш, Мурка и т.д.

Допустимое имя файла с расширением
. a c s , заключенное в кавычки

Animation

Заставляет Помощника выполнять
различные трюки. Вы можете
указать, какие именно действия
будет выполнять Помощник

Любая из доступных констант, определяющих
конкретные движения, такие как
m s o A n i m a t i o n G e t A r s t y . Дляпросмотра списка всех доступных констант выберите тип M s o A n i m a t i o n T y p e в библиотеке Office в окне обозревателя объектов

T r u e или F a l s e

Программирование окна Помощника
Окно Помощника— это тот желтый прямоугольник, в котором Помошник предлагает
вам возможные варианты действий. Хотя Office использует это окно практически исключительно для отображения справочной информации, вы сможете использовать VBA для создания собственных вариантов окна и заполнения его всевозможными сведениями, такими как
котировки акций, процентные ставки банков и т.д.

Создание окна
Первый шаг к отображению пользовательского варианта окна Помощника состоит в создании нового объекта. Как это ни удивительно, но NewBaloon — это свойство, а не метод
объекта A s s i s t a n t . В любом случае, используйте инструкцию S e t для создания объекта
окна с помощью такого кода, как, например, приведен ниже.

Глава 14. УВАдля Office

327

Dim blnUpUpAndAway As Baloon
Set blnUpUpAndAway = A s s i s t a n t . N e w B a l o o n
После создания объекта b a l l o o n используйте перечисленные в табл. 14.2 свойства для
определения его содержимого. В нашем случае используйте метод Show для отображения
пользователю окна Помощника.
Таблица 14.2. Свойства объекта Balloon
Свойство

Для чего предназначено

Доступные параметры; заметки

Mode

Определяет, должен ли пользователь
закрыть окно Помощника, чтобы
продолжить работу с приложением

m s o M o d e M o d e l e s s (окноостается
на экране до тех пор, пока не будет закрыто
пользователем}; m s o M o d e M o d a l
(окно должно быть закрыто пользователем);
rasoModeAutoDown
(окно закрывается
после щелчка за его пределами)

BalloonType

Определяет, должны ли заголовки
в окне быть 8 виде кнопок или же
в виде нумерованного или
маркированного списка

msoBalloonTypeButtons;
msoBalloonTypeNumbers;
msoBalloonTypeBullets

Icon

Указывает на один из доступных
значков для окна Помощника

msoIconNone; msoIconTip;
msoIconAlert

Heading

Определяет заголовок,
отображаемый полужирным
шрифтом в верхней части окна
Помощника

Любое строковое значение

Text

Определяет "обычный" текст,
который отображается после
заголовка, но над любыми
подписями, флажками или кнопками

Любое строковое значение

Labels

Указывает текст подписей в окне
Помощника
Указывает текст подписей к флажкам
в окне Помощника
Определяет количество и тип
кнопок, отображаемых в нижней
части окна Помощника

Любое строковое значение

CheckBoxes
Button

Указывает текст подписей в окне
Помощника
Любая из констант
MsoButtonSetType,
перечисленных в окне обозревателя
объектов

Добавление графических изображений
Вы можете придать окну Помощника гораздо более привлекательный внешний вид, если
добавите в него хотя бы одну картинку. Для отображения картинки вам следует присвоить
свойству I c o n значение, равное одной из констант, перечисленных в табл. 14.2. Для отображения картинки определите ее как часть текстовой строки, используемой для определения
свойств H e a d i n g или Text объекта окна Помощника, либо одной из подписей, как показано в следующем примере:
blnUpUpAndAway.Text = "VBA! {bmp c:\dummies.bmp)"
Как видно из этого примера, вы должны заключить имя файла
328

Часть IV. Профессиональная работа с VB

с изображением и путь к нему в фигурные скобки. Сначала вам
необходимо указать формат файла — bmp для формата . bmp или wmf для
формата .wmf. и только затем указывают путь к файлу и имя файла.

Закрытие окна
После того как созданное вами окно Помощника отображено на экране, вам обязательно
потребуется убрать его с экрана. Если объект окна Помощника является модельным (его
свойству Mode присвоено значение msoModeModal, что имеет место по умолчанию), окно
будет закрыто после щелчка на любой из его кнопок. Если же это не так, вам необходимо использовать в своей процедуре метод C l o s e для закрытия окна в результате наиболее вероятных действий со стороны пользователя — щелчка на кнопке ОК или на кнопке Отмена.

Работа с элементами управления окна
Точно так же как и в обычных формах VBA, элементы управления в окне Помощника предоставляют пользователю возможность взаимодействия с программой. Окно Помощника может
содержать элементы управления трех типов: флажки, надписи (могут выступать в качестве кнопок) и кнопки (это кнопки, которые располагаются в нижней части окна Помощника).
Добавление надписей и флажков
Каждое окно Помощника содержит пять надписей и пять флажков. Однако, до тех пор
пока вы не укажете текст для определенной надписи или флажка, соответствующий элемент
управления просто не отображается в окне. Для изменения значения свойства T e x t надписи
или флажка вам следует обратиться к нему по его номеру в соответствующей коллекции объектов, как показано ниже:
With blnUpUpAndAway
.Labels(2) =
"Не забудьте приобрести молоко по пути домой."
.Checkboxes(3).Text = "Я уже приобрел молоко."
End With
Надписи могут действовать в роли кнопок, реагируя на щелчки кнопкой мыши, но только
в том случае, если вы присвоите свойству B a l l o o n T y p e объекта окна Помощника значение
m s o B a l l o o n T y p e B u t t o n s . Другие значения этого свойства позволяют представлять
надписи в виде нумерованных или маркированных списков (см. табл. 14.2).
Добавление кнопок
Вы указываете количество кнопок и их тип, присваивая свойству B u t t o n объекта окна
Помощника значение, равное одной из констант типа m s o B u t t o n S e t T y p e . Например, если вы хотите, чтобы окно Помощника содержало три кнопки: Abort (Прервать), Retry
(Повтор) или Ignore (Игнорировать), ваш код должен иметь следующий вид:
blnUpUpAndAway.Button = m s o B u t t o n S e t A b o r t R e t r y l g n o r e
Считывание значений кнопок и флажков
Программисту просто необходим способ определения того, на какой кнопке щелкнул
пользователь или какой флажок он установил. Вот как это делается: для определения того, на
какой именно кнопке щелкнул пользователь, используется значение, возвращаемое методом
Show: оно предоставляет вам число, представляющее кнопку. Вы можете присвоить это значение переменной или использовать его напрямую, как показано в следующих примерах:
i n t B u t t o n = blnUpUpAndAway.Show
S e l e c t Case blnUpUpAndAway.Show
Глава 14. VBA для Office

329

Case msoBalloonButtonOK
(код, выполняемый после щелчка на кнопке ОК)
Case msoBalloonButtonCancel
(код, выполняемый после щелчка на кнопке Cancel)
Case 2
(код, выполняемый после щелчка на кнопке со другой надписью]
End S e l e c t
Как видно из двух первых инструкций Case, библиотека объектов O f f i c e содержит
именованные константы, которые соответствуют значениям каждого типа "обычных" кнопок
(т. е. кнопок, которые отображаются в нижней части окна Помощника). Вы можете использовать эти константы для определения того, на какой именно из кнопок щелкнул пользователь.
Для определения щелчка на кнопке просто используйте номер подписи к кнопке, как показано на примере третьей инструкции Case.
Для считывания сведений о текущем состоянии флажков в окне Помощника используйте
свойство Checked каждого из них после закрытия окна пользователем. В самом простейшем случае вы можете использовать последовательность операторов If ... Then, по одному оператору для каждого флажка, как показано ниже:
With blnUpUpAway
If .Checkboxes(1).Checked Then
(код, выполняемый в том случае, если флажок 1 установлен)
Else
(код, выполняемый в том случае, если флажок 1 не установлен)
End If
If .Checkboxes(2}.Checked Then
(код, выполняемый в том случае, если флажок 2 установлен)
Else
(код, выполняемый в том случае, если флажок 2 не установлен)
End If
End With
Вы можете использовать свойство C a l l b a c k объекта B a l l o o n для определения
процедуры, которая будет обрабатывать щелчки на кнопках. Этот прием оказывается
особенно полезным при использовании немодальных объектов b a l l o o n , которые
остаются на экране до тех пор, пока пользователь не щелкнет на кнопке.

Сох/гонениезначенийпе/геменнмх
на quace
В программировании очень часто возникают ситуации, когда необходимо сохранить значения переменных во время выполнения программы. Например, давайте рассмотрим простейший
случай: использование переменной-счетчика. Предположим, вам необходимо знать, сколько раз
пользователь щелкнул на определенной кнопке одной из панелей инструментов Excel на протяжении месяца. Если вы только не хотите держать программу Excel постоянно запущенной на
протяжении целого месяца, вам необходимо сохранять текущее значение переменной-счетчика
при закрытии программы и считывать его при последующем запуске Excel.
Среди всех приложений Office только Word предоставляет вам инструменты для хранения
подобных переменных (с помощью объекта V a r i a b l e ) . Однако с подобной задачей по силам справиться и многим другим приемам.

330

Часть IV. Профессиональная работа с VBA

Сохранение и получение значений переменных в Excel,
PowerPoint и Project
Пользовательские свойства документов предоставляют широкое поле для деятельности
при написании программ для большинства приложений Office. Вы можете использовать VBA
для создания пользовательских свойств документов, заполнения их данными, а также получения этих данных при первой необходимости. Раз подобные свойства стали неотъемлемой частью документа, с которым они связаны, вам не придется беспокоиться о сохранении свойств
в отдельном файле — они автоматически сохраняются вместе с документом.
Для создания нового свойства документа в Excel, PowerPoint или Project (в Word тоже при
необходимости можно воспользоваться подобным методом) выберите метод Add из коллекции свойств C u s t o m D o c u r a e n t P r o p e r t i e s этого документа. Приведенный ниже пример
срабатывает в Excel, где объект A c t i v e W o r k b o o k означает активную рабочую книгу во
время выполнения процедуры (в Word и PowerPoint это объекты A c t i v e D o c u m e n t и Act i v e P r e s e n t a t i o n соответственно):
ActiveWorkbook.CustomDocumentProperties.Add_
Name:= " B u t t o n C o u n t " , L i n k T o C o n t e n t : = F a l s e , _
Type:= msoPropertyTypeNumber, Value:=0
Параметр L i n k T o C o n t e n t должен иметь значение F a l s e , если вы сохраняете значение переменной в виде пользовательского свойства документа (вам следует присвоить этому
параметру значение True, если вы хотите, чтобы значение свойства было связано с содержимым ячейки Excel или закладкой Word). Параметр Туре определяет тип данных для свойства; в качестве значения допустимо использование таких констант, как m s o P r o p e r tyTypeNum.beг, m s o P r o p e r t y T y p e B o o l e a n , m s o P r o p e r t y T y p e D a t e , msoP r o p e r t y T y p e F l o a t или m s o P r o p e r t y T y p e S t r i n g .
Для сохранения или получения информации, хранящейся в виде свойства документа, используется свойство Value объекта P r o p e r t y . Предположим, что вы используете такое
свойство документа, как B u t t o n C o u n t , для сохранения количества щелчков мышью на
кнопке одной из форм программы. Приведенный ниже фрагмент кода считывает и обновляет
значение свойства после каждого щелчка на кнопке:
With ActiveWorkbook.__
CustomDocumentProperties("ButtonCount")
.Value = .Value + 1
End With
Приведенный ниже пример иллюстрирует выполнение небольшой практической задачи.
В этом случае пользователь видит сообщение о том, что он щелкнул на кнопке больше определенного количества раз, даже в том случае, если между щелчками документ неоднократно
закрывался и открывался заново. Предположим, что значение константы c i n t C u t O f fValue задано раньше равным минимальному количество щелчков, после достижения которого сообщение отображается на экране в первый раз.
With
ActiveWorkbook.CustomDocumentProperties("ButtonCount")
'получение сохраненного значения свойства
intCurrentCount = .Value
'отображение сообщения при выполнении условия
If intCurrentCount > cintCutOffValue Then
MsgBox "Вы щелкнули на кнопке" _
& " больше " & cintCutOffValue _
& " раз."

Глава 14. VBA для Office

331

End If
^Увеличение значения свойства
.Value == intCurrentCount + 1
End With
intCurrentCount =ActiveWorkbook
_.CustomDocumentProperties("ButtonCount").Value

Другие способы сохранения значений переменных
В Access и Excel часто удобно сохранять данные, необходимые для работы VBAпрограммы, прямо в документе — в таблицах базы данных (Access) или ячейках листа рабочей книги (Excel). Единственная проблема, связанная с подобным подходом, состоит в том,
что данные видны пользователям и их легко изменить, если только вы не предпримите предупреждающих действий.
Два остальных возможных решения для сохранения данных на диске сработают в любом
приложении, поддерживающем VBA. Вы можете сохранять значения в реестре Window
(и даже считывать их оттуда), используя инструкции S a v e S e t t i n g и G e t S e t t i n g ,
а также сохранять данные в отдельном файле. Оба эти способа рассмотрены в главе 20.

332

Часть IV. Профессиональная работа с VBA

Глава 15

Программирование на VBA в Word
В s/ftou ыа£е...
> Объектная модель Word
"> Ключевые объекты Word: окна, выделения, диапазоны и объект F i n d
> Диапазоны или выделения: что использовать при работе с текстом
> Методы и свойства для манипуляции с текстом
> Поиск и замена текста с помощью VBA в Word

м j [ ъъ всего набора приложений Office Word предлагает наиболее богатый набор
щгш? средств программирования. Знакомство с объектами Word, такими как Range
и F i n d , иногда оказывается рискованным, но это очень важно, если вы действительно хотите создавать VBA-процедуры, раскрывающие всю мощь Word. Именно об этом мы и поговорим в настоящей главе.
Объектная модель Word содержит так много объектов и их коллекций, что вам потребуется огромный лист бумаги, если вы захотите построить на нем иерархию всех этих объектов
в графическом виде. Очевидно, что я смогу рассмотреть лишь малую толику от того колоссального количества объектов, свойств и методов, которые вы сможете использовать в своих
программах. В настоящей главе освещены только наиболее важные приемы работы с Word
VBA. Если вы хотите получить более подробные сведения, вам придется неоднократно обращаться к справочной системе.

Знахоишйво с оЗъек&ом dfifilication
Как и во всех других VBA-приложениях, ключевым в объектной модели Word является
объект A p p l i c a t i o n . Другими словами, этот объект содержит все остальные объекты
Word. Поскольку объект A p p l i c a t i o n занимает центральное место в программировании
на VBA в Word, вам даже не придется явно указывать его имя при работе со многими важными объектами. Однако вам не следует забывать о роли, которую играет этот объект, поскольку он вам потребуется при работе со свойствами и методами самого приложения, а также при обращении к некоторым другим объектам. Например, приведенная ниже инструкция
использует метод L i s t Commands объекта A p p l i c a t i o n :
A p p l i c a t i o n . L i s t C o m m a n d s (True)
Между прочим, метод L i s t C o m m a n d s создает новый документ и помещает в него
таблицу, содержащую комбинации клавиш и команды меню Word. Если вы передаете
методу L i s t C o m m a n d s значение T r u e , новый документ содержит комбинации клавиш
и команды меню Word. Передайте ему значение False, чтобы в нем перечислялись только команды.

Глава 15. Программирование на VBA в Word

333

№ к qotcifMeHJiuui Word

с немощью
Если написанная вами VBA-процедура функционирует прямо в документе, вы должны
указать объект этого документа непосредственно в коде, Часто вы сможете сделать это неявным образом, используя объект S e l e c t i o n , о котором я расскажу дальше в настоящей главе. Однако в остальных ситуациях вам придется явно идентифицировать целевой объект.

Работа с активным документом
Типичная VBA-процедура в Word выполняет все свои магические действия в том
документе, который в данный момент открыт для редактирования. Для указания
активного документа используется объект A c t i v e D o c u m e n t . Например, приведенная выше инструкция просто закрывает активный документ:
ActiveDocument.Close
Как видите, вам не нужно писать код для определения того, какой же документ редактируется в данный момент: достаточно просто использовать объект A c t i v e D o c u m e n t .

Указание конкретного документа
Если вам необходимо работать с определенным документом, который сейчас не активен,
вы должны указать его как члена коллекции Documents, состоящей изо всех документов,
открытых в настоящее время в Word. Как и в случае с любой другой коллекцией объектов
в VBA, вы можете обратиться к отдельному документу в коллекции, используя его заголовок,
который в данном случае совпадает с именем файла (только именем файла, а не с полным путем к нему). Вот соответствующий пример;
Documents("Toy S t o r e N e w s l e t t e r . d o c " )
Поскольку вы не знаете точно имя файла целевого документа заранее, а пользователь может в любой момент его изменить, вам следует создать переменную, которая будет содержать
имя файла. После этого вы можете использовать эту переменную для указания объекта документа, например, так: Documents ( s t r D o c N a m e ) .
Вы также можете обратиться к документу по его индексному номеру. Следующая инструкция, например, обращается к третьему документу в коллекции Documents:
Documents(3)
Несмотря на всю простоту, этот метод достаточно ограничен, поскольку вы редко когда
знаете индексный номер документа, с которым хотите работать. При этом вам стоит узнать
имя открытого документа. Например, следующая инструкция присваивает переменной имя
файла второго открытого документа:
strDocName = Documents(2).Name

Создание, открытие, активизация и закрытие документов
Для создания нового документа используйте метод Add коллекции объектов
Documents. Используемый без каких-либо документов, метод Add создает новый документ, базирующийся на шаблоне Normal (Обычный). Для указания другого шаблона укажите
путь к нему в качестве аргумента, как показано ниже:

334

Часть IV. Профессиональная работа с VBA

Documents.Add template:= _
"C:\Windows\Application DataXMicrosoft\Hidden templates"
Дгтя открытия существующего документа используйте метод Open коллекции объектов
Documents. Конечно же, вам необходимо указать полный путь к документу, как показано ниже:
Documents.Open FileName:= __
"С:\Toys\Toys for i n f a n t s . d o c "
Для активизации уже открытого документа используйте метод A c t i v a t e коллекции
объектов Documents. Предположим, что вам необходимо, чтобы ваша VBA-программа активизировала определенный документ, который в момент запуска программы может быть
и открыт, и закрыт. Используйте код, подобный показанному ниже, для активизации открытого документа или открытия документа, если он еще не открыт:
Sub DocActivateOrOpen()
Dim docFileName As S t r i n g , docPath as S t r i n g
docFileName = "Старые игрушки.doc"
docPath - " C : \ T o y s \ "
For Each t a r g e t D o c In Documents
If targetDoc.Name = docFileName Then
targetDocIsOpen = True
End I f
Next targetDoc
If targetDocIsOpen = True Then
Documents(docFileName).Activate
Else
Documents.Open FileName := docPath & docFileName
End If
End Sub

Работа с разделами документов
Поскольку каждый документ Word состоит из одного или нескольких разделов, вы можете ожидать, что Word VBA содержит коллекцию S e c t i o n s и отдельные объекты S e c t i o n
для работы с этими элементами. Так оно и есть. Наиболее важное применение объектов
S e c t i o n — организация доступа к верхним и нижним колонтитулам (через объект Heade r F o o t e r ) . Вы можете добавлять новые разделы в документ, используя метод Add коллекции S e c t i o n s или метод I n s e r t B r e a k объекта Range или S e l e c t i o n .

О

о/сон с помощью

Каждый открытый документ содержит как минимум одно окно, а пользователь Word может открыть столько окон, сколько нужно для работы с любым документом. Каждое из подобных окон— объект с его собственными правами. В объектной модели Word объект App l i c a t i o n содержит коллекцию Windows, содержащее все окна для всех открытых документов. Кроме того, каждый объект Document содержит свою собственную коллекцию
объектов Windows.
Две основные причины работы с объектами Window в Word— контроль над внешним видом окна, а также манипулирование содержимым документа с помощью объекта S e l e c t i o n .
Объект S e l e c t i o n я подробно рассмотрю в следующем разделе настоящей главы; здесь же
я остановлюсь на приеме, позволяющем определить конкретное окно, а также познакомлю со
свойствами, которые вы сможете использовать для определения внешнего вида окна.

Глава 15. Программирование на VBA в Word

335

Обращение к окнам из программного кода
Прямо из программного кода проще всего обращаться к тому окну, в котором открыт редактируемый документ во время запуска процедуры. Для указания окна используется объект
ActiveWindow.
Для определения окна прямо в программном коде вам следует определить его как члена
одной из коллекций Windows. При работе с глобальной коллекцией объектов Windows вам
не нужно указывать собственно объект A p p l i c a t i o n . При обращении к коллекции объектов Windows определенного документа, указывать имя объекта этого документа нужно обязательно. Вы можете идентифицировать окно по его имени или индексному номеру в коллекции. Имя окна совпадает с именем документа, который в нем отображается, за исключением
того, что если для одного документа открыто несколько окон, после указания имени документа следует ставить точку с запятой, после которой указать номер окна.
Ниже приведены типичные ссылки для объектов Window.
Ссылка

Комментарии

Windows ( "Document 4" )

Действительна, если для документа
Document 4 открыто только одно окно

Windows ( " K i t e s and s k i p r o p e s . d o c : 3") Указывает на третье окно документа
Documents f "Window
d i s p l a y . d o c " ) .Windows (2)

Указывает на второе окно в коллекции
Windows данного документа

Работа с областями окон
Когда вы разделяете окно с помощью команды Окно^Разделить, верхняя и нижняя
часть окна являются отдельными областями. Окно Word содержит как минимум одну область, но может содержать и больше областей. В областях Word также отображает и такие
сведения, как верхние и нижние колонтитулы, сноски и комментарии.
Если вам необходимо получить доступ к настройкам внешнего вида выделения в отдельной области, вы должны сначала идентифицировать в программном коде целевой объект Рапе. Обращение к определенному объекту осуществляется по его номеру в коллекции объектов Panes для
данного окна. Однако вы можете опустить ссылки на области в том случае, когда вам необходимо
работать со стандартной основной частью окна (или верхней частью, если окно разделено).

Изменение внешнего вида окна
Объекты Window предлагают большое количество свойств, определяющих состояние
всех элементов, которые вы видите на экране. Основная часть этих свойств может принимать
только одно из двух возможных значений — T r u e или F a l s e . Например, чтобы включить
схему документа для активного документа, используйте следующую инструкцию:
ActiveWindow.DocumentMap = True
Используйте подобные инструкция для включения или выключения различных свойств,
таких как D i s p l a y S c r e e n T i p s или D i s p l a y V e r t i c a l S c r o l l B a r . He забывайте
о том, что ключевое слово Not обращает текущее значение логической переменной или
свойства. Вот пример изменения значения свойства:
ActiveWindow.DisplayRules = _
Not A c t i v e W i n d o w . D i s p l a y R u l e s
Свойства L e f t , Top, H e i g h t и Width позволяют вам определять размер и расположение окна, которое не развернуто на весь экран.

336

Часть IV, Профессиональная работа с VBA

Использование объекта View
Вспомогательный объект View определяет многие аспекты отображения окна или области. Объект View обладает следующими свойствами.
Свойство объекта View Для чего предназначено
Туре

Fullscreen

Соответствует выбору из меню Вид таких команд, как Обычный,
Разметка страницы, Структура и т. д. Для изменения представления
используйте в качестве значения свойства одну из следующих констант:
wdMasterView,wdNormalView,wdOutlineView,
wdPrintView, wdWebView или wdPrintPreview. Например,
инструкция ActiveWindow. View. Type = wdPrintView
переключает активное окно в режим предварительного просмотра
Контролирует отображения окна в стандартном или полноэкранном варианте

TableGridlines

Определяет отображение сетки таблицы

S h o w A l l , Show

Свойство S h o w A l l определяет отображение всех непечатаемых знаков,
что соответствует флажку Все в группе Знаки форматирования на вкладке
Вид диалогового окна Параметры. Вы можете включить или отключить
отображение отдельных непечатаемых символов, а также других элементов,
таких как выделение текста или границы, используя различные свойства,
названия которых начинаются с Show, в частности ShowBookmar ks
или S h o w H i g h l i g h t

Масштабирование документа с помощью программного кода
Для управления параметрами увеличения документа вам необходимо немного углубиться
в иерархию объектов, чтобы добраться до объекта Zoom, а затем изменить значение его
свойства P e r c e n t a g e . Соответствующий пример приведен ниже:
ActiveWindow.View.Zoom.Percentage = 135
Если вы хотите задать новый масштаб документа для представления, которое в данный
момент не используется, включите константу в качестве аргумента свойства View для этого
представления, как показано ниже:
ActiveWindow.View.Zoom.Percentage = 7 5
Когда пользователь в следующий раз выберет соответствующее представление документа,
последний сразу предстанет в указанном вами масштабе.
Кроме того, вы можете использовать свойство P a g e F i t объекта Zoom для дублирования команд По ширине страницы или Страница целиком из раскрывающегося меню Масштаб на панели инструментов. При активной любой из этих настроек Word автоматически изменяет масштаб документа при изменении размеров окна,
всегда сохраняя указанную вами пропорцию. Например, следующая инструкция эквивалентна команде По ширине страницы из раскрывающегося меню Масштаб на панели
инструментов:
ActiveWindow.View.Zoom.PageFit = w d P a g e F i t B e s t F i t
Команда Страница целиком доступна только в режиме разметки страницы, но вы можете продублировать ее с помощью приведенного ниже кода:

Глава 15. Программирование на VBA в Word

337

Windows("Documentl").View.Zoom.PageFit = _
wdPageFitFullPage
Для отключения функции автоматического масштабирования присвойте свойству P a g e F i t значение w d P a g e F i t N o n e .

использованиеодьешпаSelection
В Word VBA объект S e l e c t i o n означает любой выделенный элемент в области окна.
Да-да, объект S e l e c t i o n относится к области окна, а не документа. Документ может содержать больше одного открытого окна, а каждое окно — несколько областей, поэтому каждая из этих областей может содержать выделения. (Хотя чисто технически объект S e l e c t i o n принадлежит области окна, ничто не мешает вам считать его принадлежащим окну, если только вам не нужно работать с выделением в определенной области окна, например
в нижнем или верхнем колонтитуле).
Хотя вы можете манипулировать выделенными областями с помощью VBA-кода, используя объект S e l e c t i o n , часто гораздо удобнее оказывается использовать объект Range.
Подробно об использовании этих объектов мы поговорим в разделе "Работа с текстом в Word
VBA" дальше в настоящей главе.
Содержимое выделенной области может быть фрагментом текста, таблицей, текстовым окном, изображением или чем-нибудь другим, что можно выделить с помощью мыши и клавиатуры. Запомните: если ничего не выделено, объект S e l e c t i o n представляет текущее расположение точки вставки.
Хотя каждая область окна содержит выделение, вам необходимо только явно обратиться
к целевому окну, если интересующее вас выделение не находится в главной области активного окна. Для работы с выделенной частью в главной области активного окна вам следует использовать объект S e l e c t i o n . Например, вы можете использовать приведенную ниже инструкцию для замены выделения в области активного окна текстом, заключенным в кавычки:
S e l e c t i o n . T e x t = "У моей собаки есть блохи"
Если вам необходимо работать с выделенной областью в одном из неактивных окон, вы
.должны полностью указать имя окна:
documents("Songs.doc").Windows(2).Selection.Text = _
"Моя возлюбленная загорает на берегу океана"
Поскольку объект S e l e c t i o n может представлять содержимое различных типов, всегда лучше всего сначала проверить, данные какого вида были выделены,
прежде чем с ними что-то делать. В противном случае вы рискуете получить неожиданные результаты или даже сообщения об ошибках. Для поиска подобных
сведений используйте свойство Туре объекта S e l e c t i o n . Например, приведенный ниже фрагмент кода проверяет, является ли выделенная область обычным текстом, прежде чем вырезать ее в буфер обмена:
With S e l e c t i o n
If -Type = wdSelectionNormal Then
.Cut
End I f
Вы можете использовать при подобных проверках константы, перечисленные ниже.

338

Часть IV. Профессиональная работа с VBA

Константа

Что выделено

wdNoEelection

Ничего не выбрано

wdS е 1 е ct i o n 3 1 о с к

Вертикальный блок текста

wdSelectionColurr.n

Столбец в таблице

wdSe I e ct i on Fr arae

Рамка

wdSelectionlnlineShape

Графическое изображение в тексте

wdS e I е с t i оn IP

Только точка вставки

wdSelectionNormal

Обычное выделение фрагмента текста

wdSelectionRow

Строка таблицы

wdSelectionShape

Изображение, не помещенное в текст

Зншахиапво с оЗъешнами Лапде
Если вы редактируете документ самостоятельно, вы должны поместить указатель мыши
в нужное место либо выделить определенный фрагмент, прежде чем добавлять, удалять или
форматировать текст. Однако в Word объекты Range избавляют вас от подобной необходимости. Объект Range определяет неразрывный блок текста в документе. Объекты Range
полностью независимы от точки вставки или выделенного раздела, которые пользователь видит в окне документа. После создания объекта Range вы сможете манипулировать текстом,
используя команды VBA, полные аналоги мощных команд редактирования Word, точно так
же, как при использовании объектов S e l e c t i o n .
Вы можете определить объекты Range в программном коде одним из двух следующих способов:
\ •/ работая с диапазонами с помощью свойства Range;
% S определив диапазоны с помощью метода Range объекта Document.
й

Использование свойства Range
Открытый документ Word уже содержит объекты Range, соответствующие многим его
элементам. Каждый абзац, а также таблица, отдельная ячейка таблицы, комментарий или
нижний колонтитул (и это далеко не полный список) определяют диапазоны. Вы можете считать, что все эти диапазоны существуют в некотором виртуальном мире, пока не вы не обратитесь к ним с помощью свойства Range соответствующего объекта. Например, для определения объекта Range, соответствующего первому абзацу активного документа, вам следует
использовать объектную ссылку следующего вида.
ActiveDocumep.t. P a r a g r a p h s (1) . Range
Поскольку подобные стандартные диапазоны уже существуют в Word, вы можете использовать объектные ссылки на них напрямую, обходясь без каких-либо переменных. Это особенно хорошо подходит для тех ситуаций, когда вам необходим один конкретный диапазон
для одной операции. Например, приведенная ниже инструкция копирует вторую таблицу
в документе в буфер обмена, используя метод Сору объекта Range:
ActiveDocument.Tables[2)
.Range.Copy

Глава 15. Программирование на VBA в Word

339

Если несколько инструкций используют один и тот же диапазон, вы можете использовать
конструкцию With... для ускорения как ввода кода программы, так и ее выполнения. Ниже
приведен пример кода, который проводит сортировку абзацев в третьем разделе документа,
отображая первое предложение полужирным:
With A c t i v e D o c u m e n t . S e c t i o n ( 3 ) . R a n g e
. S o r t S o r t O r d e r := wdSortOrderAscending
. S e n t e n c e s ( 1 ) . R a n g e . B o l d = True
E'.nd With
Приведенный выше пример иллюстрирует, как объект Range содержит другие
объекты, в свою очередь содержащие диапазоны. Инструкция в третьей строке
обращается к дипазону, соответствующему первому предложению в исходном
диапазоне, после чего отображает его полужирным. Также обратите внимание на
то, что вы не можете применить форматирование непосредственно к объектам,
таким как слова, предложения или абзацы; для того чтобы это сделать, вам
следует использовать их свойства Range.
Если вы планируете использовать диапазон в нескольких инструкциях, которые не
следуют одна за другой, вам придется присвоить диапазон переменной. Это позволит вам
быстрее составить код программы, а также в конечном итроге ускорить ее выполнение.
Объекты S e l e c t i o n также обладают свойством Range. Это значительно упрощает использование свойств и методов, принадлежащих объектам Range существующих выделенных областей. Приведенный ниже пример присваивает
диапазон выделенной области переменной, перемещает выделенную область, после чего преобразует текст прописными буквами:
Set deRange = S e l e c t i o n . R a n g e
S e l e c t i o n . M o v e Unit := wdParagraph, Count := 3
deRange-Case = wdLowerCase

Определение диапазонов с помощью метода Range
Если существующие объекты не содержат текст, с которым вы хотите работать, создайте
собственный объект Range. В любом открытом документе вы сможете определить столько
объектов Range, сколько вам нужно. При этом используется метод Range документа, который требует от вас указания начальной и конечной точек диапазона в терминах расположения
символа в документе. Например, ознакомьтесь со следующим примером:
A c t i v e D o c u m e n t . R a n g e ( S t a r t : = 10, End:=2 0)
Приведенное выше выражение представляет собой объектную ссылку на диапазон, который начинается с 11-го символа и заканчивается 20-м символом. Значение расположения символа на самом деле означает место слева от данного символа. Например, значение, равное 0, соответствует первому символу в документе, а значение 10 указывает на точку между 10-м и 31-м символами. Word
считает все символы в документе, включая скрытые и непечатаемые знаки.
Для создания диапазона, который станет всего лишь местом расположения и не содержит
никакого текста, присвойте начальному и конечному значениям, определяющим диапазон, одно
и то же число. Для включения в объект Range всего документа используйте метод Range этого документа без каких-либо аргументов или же используйте свойство C o n t e n t документа.

340

Часть IV. Профессиональная работа с VBA

Объект Range создать совсем несложно (если вам известны положения начального и конечного символов, которые вы решили включить в диапазон).
Проблема возникает в том случае, когда вам необходимо работать с произвольным количеством символов в произвольном месте документа. Чаще всего вам необходимо работать с текстом в определенной части документа. Вы
можете начать диапазон с существующей закладки, с начала выделенной области или с определенного слова или фразы, о наличии которых в документе
вам точно известно.
Для определения диапазона, базирующегося на одном из подобных критериев, используйте свойства S t a r t или End объекта S e l e c t i o n , Range или Bookmark, чтобы определить месторасположение в документе интересующего вас символа. Если вам необходимо создать состоящий из десяти символов диапазон, который будет начинаться с вкладки F o r g e t MeNot, вам пригодится следующая инструкция;
With ActiveDocument
Set myEkMark = .Bookmarks{"ForgretMeNot")
Set horr.eOnTheRange = _
. F a n g e ( S t a r t := myBkMark, End := myBkMark + 10)
End With
Ниже приведен еще один пример, иллюстрирующий использование свойства Range для
поиска абзаца, определения в нем некоторого слова, а также создания нового диапазона, начинающегося с этого слова. В данном случае аргумент End опущен, поэтому диапазон начинается с указанного слова и продолжается до окончания документа:
With ActiveDocument
Set fistWord = . P a r a g r a p h s ( 1 6 0 ) . R a n g e . W o r d s ( 3 )
Set RangeTop = . R a n g e ( S t a r t := f i r s t W o r d . S t a r t )
End With
В разделе "Поиск и замена текста с помощью VBA в Word", дальше в настоящей главе,
я покажу, что использование ключевого слова F i n d совместно с диапазоном или выделенной
областью определяет объект, который будет содержать только найденный текст. После того
как инструкция F i n d найдет в диапазоне или выделенной области фразу, свойства S t a r t
и End того же диапазона или выделенной области теперь будут указывать на начало и конец
найденного текста.

€ Word
Объекты Range и S e l e c t i o n являются отправными точками для практически любых
операций, которые вы сможете выполнять с текстом с помощью Word VBA. Некоторые из
этих действий можно применять к документам в целом, но в общем случае вам необходим
диапазон или выделенная область, прежде чем вносить изменения.
У объектов Range и S e l e c t i o n достаточно много общего, но есть и несколько ключевых отличий. Оба объекта представляют непрерывные последовательности символов, над которыми вы сможете выполнять различные операции. Оба объекта имеют много общих
свойств и методов. Однако некоторые свойства и методы уникальны для выделенных областей, а другие — для диапазонов. Значительные различия состоят и в том, что объект S e l e c t i o n соответствует выделению в области окна: тексту, графическому изображению или любому другому объекту, в то время как объекты Range существуют независимо от выделенной области и всегда содержат текст.

Глава 15. Программирование на VBA в Word

341

Используйте объект S e l e c t i o n в том случае, если ваша процедура зависит от
пользователя, например, он должен указать текст, с которым будут проведены
определенные действия, или в том случае, если вам необходимо показать пользователю, какой именно текст будет изменен. В других ситуациях намного лучше
подходят объекты Range. Они обеспечивают большую скорость выполнения
программ и меньше отпугивают пользователя: Word обновляет содержимое экрана при каждом изменении содержимого выделенной области, а при изменении
диапазона содержимое экрана не обновляется. Кроме того, изменения диапазонов не отражаются на выделенных областях, созданных пользователем.

Выделение диапазонов и создание диапазонов на основе
выделенных областей
Несмотря на их различия, объекты S e l e c t i o n и Range можно создавать один из другого. Эта возможность оказывается чрезвычайно важной, так как многие функции редактирования работают только с диапазонами. В противоположность этому, единственный способ
отобразить содержимое диапазона пользователю— выделить его. Используйте следующие
простые приемы.
| S Для выделения диапазона используется его метод S e l e c t . Например, для объекта
*
RangeR команда имеет вид RangeR. S e l e c t .
i S Для получения доступа к диапазону, представляющему то же содержимое, что и выf
деленная область, используется свойство Range.
Помните: если метод, относящийся к текстовым данным, вызывается для диапазона, а вы хотите применить его к выделенной области, просто включите в свой
код инструкцию S e l e c t i o n . Range . ИмяМетода.

Повторное определение диапазонов и выделенных областей
Word VBA предлагает целый ряд методов для перемещения и изменения размеров диапазонов и выделенных областей. В настоящем разделе я рассматриваю только самые важные из
них; для знакомства с другими методами вам придется обращаться к справочной системе.

Расширение диапазонов и выделенных областей
Метод Expand увеличивает существующий диапазон или выделенную область, добавляя блок текста в их конец. Блок может представлять собой символ, слово, абзац или чтонибудь другое. Вы можете добавить только один заранее определенный блок; кроме того,
добавление подобных блоков в начале диапазона или выделенной области не допускается.
Для добавления к выделенной области слова, которое будет следовать сразу за ней, используйте такую инструкцию:
Selection.Expand(wdWord)
Вы можете использовать любую из следующих констант для расширения объекта;
w d C h a r c t e r , wdWord, w d S e n t e n c e , w d P a r a g r a p h , w d S e c t i o n , w d S t o r y ,
wdCell, wdColumn, wdRow, wdTable и (только для объектов S e l e c t i o n ) wdLine. По
умолчанию используется константа wdWord.

342

Часть IV. Профессиональная работа с VBA

Теперь нам следует остановиться на одном щекотливом моменте: объекты S e l e c t i o n
(но не диапазоны) также содержат метод Expand. Этот метод включает соответствующее
средство Word, которое позволяет расширять выделенную область при перемещении указателя мыши. Каждый раз, когда программа вызывает метод E x t e n d , выделенная область увеличивается на блок текста, который следует сразу за точкой вставки: текущее слово, предложение, абзац, выделенный фрагмент пли целый документ. Если вы указали аргумент в виде
одного символа, например, S e l e c t i o n . Expand ( " С " ). выделенная область будет расширена вплоть до первого встретившегося указанного символа.

Перемещение диапазона или выделенной области
Word VBA позволяет вам повторно определять начало и конец диапазона или выделенной
области. Только имейте в виду, что методы, в имени которых присутствует слово Move, изменяют расположение диапазона или выделенной области: они не перемещают текст, который содержится в указанном объекте.
Метод Move изменяет диапазон или выделенную область, начиная с их сжатия, отмечая
их расположение, а в них уже нет никакого текста. Расположение совпадает с началом исходного объекта. После этого метод Move перемещает "сжатый" объект в соответствии с вашими инструкциями. По окончании перемещения вы можете использовать методы Expand
и Mover,nd для наполнения объекта текстом.
Приведенный ниже пример перемещает именованный диапазон в документе на два абзаца
назад. Обратите внимание на то, что вы используете именованную константу в качестве значения аргумента U n i t (список всех допустимых именованных констант приведен в разделе
"Расширение диапазонов и выделенных областей" раньше в этой главе). Аргумент Count
представляет собой целое положительное число, если вы хотите перемешать объект вперед
по документу (т.е. к его концу), или отрицательное, если вы хотите перемещать объект назад по документу. В приведенном ниже примере аргументы не заключены в скобки, поскольку возвращенное методом значение (количество перемещенных элементов) здесь
не используется:
oTheRange .Move Unit : = waParagraph, Count, : -= -2
Методы MoveStart. и MoveEnd работают практически так же, как и метод Move,
только они изменяют начальную или конечную точку диапазона или выделенной области соответственно. Приведенная ниже инструкция перемешает начало выделенной области натри
слова ближе к концу документа:
Select-on.KoveStart Unit : = wdWord, Count := 3
Обратите внимание на то, что если вы перемещаете начальную точку объекта в конец,
Word сожмет диапазон или выделенную область и переместит их в соответствии с указанными инструкциями.
Еще одна пара методов, S t a r t O f или EndOf, перемешает или расширяет начало или
конец диапазона или выделенной области. Метод S t a r t O f перемещает начало объекта обратно к началу текущего блока, в то время как метод EndOt перемешает конец объекта вперед к концу текущего блока.
Вы можете использовать аргумент E x t e n d с любым методом для контроля над действиями Word. Если перемешаемая сторона объекта уже находится с того края, к которому вы
пытаетесь ее переместить, ничею не происходит. Используйте константу wdMove для сжимания объекта или константу wd~:-:i - не для перемещения только указанной стороны. Ниже
приведен соответствующий пример:
S e l e c t . - o n . S t a r t O f Unit :=- wdSentence, Extend := wcMove

Глава 15. Программирование на VBA в Word

343

Сжимаем диапазон или выделенную область
Очень часто вам необходимо сж-ашь диапазон или выделенную область в точку, которая
не содержит никакого текста. С технической точки зрения свернутые диапазон или выделенная область — это такие диапазон или выделенная область, начальная и конечная точки которых совпадают. Сжатие подобных объектов оказывается важным в тех ситуациях, когда вам
необходимо вставить поле, таблицу или другой элемент до или после выделенной области
или диапазона, обойдясь без замены текста. (Вы.можете вставить обычный текст, новые абзацы, а также некоторые другие элементы в "несжатые" диапазон или выделенную область).
Используйте метод C o l l a p s e для сжатия диапазона или выделенной области. Вы можете
сжать объект к его начальной или конечной точке, используя необязательный аргумент D i r e c t i o n . Приведенная ниже инструкция сжимает выделенную область к ее начальной точке:
Selection.Collapse
А этот пример сжимает выделенную область к ее конечной точке:
Selection.Collapse(Direction:=wdCollapseEnd)
Если вы сожмете диапазон, который заканчивается знаком абзаца, к его конечной
точке (используя константу wdCollapseEnd), Word разместит сжатый
диапазон после знака абзаца (это означает, что сжатый диапазон будет находиться в следующем абзаце). Если же вы хотите разместить что-то перед знаком абзаца исходного диапазона, вы должны сначала переместить диапазон обратно
с помощью метода MoveEnd, используя инструкцию, подобную этой:
Диапазон.MoveEnd Unit := wdCharacter, Count := -1

Удаление, копирование и вставка текста
Удалить весь текст в диапазоне или выделенной области совсем несложно: просто используйте метод D e l e t e соответствующего объекта. Вы можете использовать и метод Cut,
если хотите удалить текст и поместить его в буфер обмена. Конечно же, метод Сору копирует текст в буфер обмена, не оказав влияния на текст в диапазоне или выделенной области.
Вы можете вставить текст, раньше помещенный в буфер обмена, в любой диапазон или
выделенную область, воспользовавшись методом P a s t e этого объекта. Если объект назначения еше не сжат, вставленный текст просто заменит исходный текст в объекте, точно так
же как это происходит после выполнения команды Вставить в Word.
Хотя использование буфера обмена для передачи текста из одного места в другое кажется
вполне привычным, этот метод не всегда оказывается самым эффективным. Намного удобнее
использовать свойства T e x t или F o r r a a t t e d T e x t диапазона или выделенной области. Залайте эти свойства равными диапазону или выделенной области, содержащим текст, который
вы хотите передать, и все. Объект назначения должен быть сжат до тех пор, пока передаваемый текст не должен будет заменить существующий текст в объекте.
Приведенный ниже фрагмент кода передает текст из выделенной области в сжатый диапазон, привязанный к закладке (операцию передачи проделывает четвертая строка кода). В новое
место расположения попадает только сам текст; любое форматирование при этом теряется:
With ActiveDocument.Bookmarks("TheBookmark")
Set RangeY = _
ActiveDocument.Range(Start:=.Start, End=.Start)
Fnd With
RangeY. Text == Selection .Text
Для передачи вместе с текстом и его форматирования просто замените свойство T e x t
свойством F o r m a t t e d T e x t .

344

Часть IV. Профессиональная работа с VBA

Вставка нового текста
Простейшим для запоминания приемом добавления текста является задание свойства
T e x t диапазона или выделенной области равным тексту, который вы решили вставить. Это
проиллюстрировано на примере, показанном ниже:
Range2.Text = "Эй, э й ! А ведь дома-то никого н е т ! "
Просто запомните, что использование свойства T e x t приводит к замене любого существующего в объекте. Во избежание этого (если только вы действительно не хотите заменить
существующий текст), сначала сожмите объект.
Используйте методы I n s e r t B e f o r e или I n s e r t A f t e r объектов Range или S e l e c t i o n для вставки текста в определенном месте документа, не затрагивая при этом существующий
текст. Эти методы позволяют вставить новый текст непосредственно перед или после указанного
объекта соответственно. Word включает вставленный текст в вьщеленную область или диапазон.
При использовании любого из методов единственным аргументом является текст, который вы
хотите вставить. Приведенный ниже фрагмент кода вставляет новый абзац, содержащий слова
D a i r y E n t r y в начало выделенной области (обратите внимание на использование такой константы VBA, как vbCr, для добавления знака абзаца). После этого в конец добавляется новый абзац, который начинается с текущей даты. Если вы выделили целый абзац до выполнения этого кода, абзац, содержащий текущую дату, появится после знака абзаца в выделенной области.
Dim s t r l n s e r t T e x t As S t r i n g
S e l e c t i o n . I n s e r t B e f o r e " D a i r y E n t r y " & vbCr
s t r l n s e r t T e x t = "Today" & Chr(146) & "s d a t e i s "
strlnsertText =
strlnsertTex't & Format (Now, "Long date") & ". "
Selection.InsertAfter strlnsertText & vbCr
Этот пример показывает, каким образом вставленный текст может содержать строковые
переменные функции VBA, возвращающие строковые значения, а также литералы и константы VBA. Подробные сведения о форматировании и изменении строковых значений с помощью VBA изложены в главе 11.
Простейший способ добавить новый пустой абзац в документ — вставить знак
абзаца (представленный константой vbCr) с помощью свойства T e x t или
методов I n s e r t B e f o r e или I n s e r t A f t e r . Метод Add, применяемый
к коллекциям P a r a g r a p h s , работает, но не очень удобен в применении.
Используйте его в том случае, если вам необходимо разместить новый абзац
в диапазоне или выделенной области, а не в их начале или конце.

Форматирование текста
Несколько свойств диапазона или выделенной области — это ваш ключ к изменению
внешнего вида текста. Все эти свойства соответствуют командам из меню Формат программы Word и функционируют следующим образом.
Это свойство
Font

Предоставляет доступ к...
Соответствующие свойства каждого аспекта форматирования символов, такие как
Name, S i s e и B o l d . По некоторым причинам вы можете получать непосредственный доступ к самым важным свойствам форматирования объектов Range, не
обращаясь к свойству F o n t , но только не при работе с выделенными областями

Глава 15. Программирование на VBA в Word

345

Это свойство Предоставляет доступ к...
Paragrap

Соответствующие свойства каждого аспекта форматирования абзацев, такие как
LeftIndent или LineSpacing

hFormat
Style

Имя стиля символа или абзаца, примененного к диапазону или выделенной области

3orders
Tabs t o p s

Границы вокругтекста
Типы И расположения точек табуляции. Вы можете получить доступ к этим свойствам
только с помощью объектов P a r a g r a p h , а не непосредственно через диапазоны
или выделенные области

Лоиас и замена tftetcana с памацью
Хотя это звучит и несколько необычно, но F i n d — это объект Word VBA. Объекты
F i n d принадлежат диапазонам и выделенным областям. Для обнаружения или форматирования текста с помощью объекта F i n d вам потребуется выполнить следующие действия.
1. Получите доступ к объекту F i n d для определенного диапазона или выделенной
области. Если вам необходимо просмотреть нелый документ, используйте свойство C o n t e n t объекта Document для получения доступа к соответствующему
диапазону, как показано ниже:
ActiveDocument. Content:. Find
2. Определить свойства объекта F i n d в соответствии с тем, что же вы ищете и как
именно вы хотите проводить поиск.
3. Вызвать метод E x e c u t e объекта F i n d . Соответствующий пример приведен
ниже:
With OpenRange.Find
. ClearFormatting
.Text = "pogo s t i c k s "
.Execute
End With
Для свойств, значения которых явно вы задать не можете, объект F i n d выбирает
параметры, использованные последними или те, которые в настоящий момент
заданы в диалоговом окне Найти и заменить программы Word. Именно по этой
причине вам всегда следует включать метод C l e a r Format t i n g перед
началом нового поиска— он позволяет убрать все ранее определенные для
проведения поиска параметры форматирования.

Работа с найденным текстом
Основная работа метода E x e c u t e — обнаружение первого экземпляра искомого текста
или форматирования в указанном диапазоне или выделенной области. После выполнения этого метода вам прежде всего следует определить, было ли найдено то, что вы ищете. Для подобной проверки используйте свойство Found объекта F i n d совместно с инструкцией
If...Then, как показано на примере следующей заготовки программного кода:

346

Часть IV. Профессиональная работа с VBA

If .Found = True Then
(выполнение определенных действий с найденным текстом}
Else
(отображение соответствующего сообщения)
End If
Если метол E x e c u t e нашел необходимый текст, исходный диапазон или
выделенная область переопределяются таким образом, чтобы содержать
найденный текст. Это очень важный момент, поскольку это означает, что вы
можете работать с найденным текстом посредством свойств и методов исходного объекта. В следующем примере, представляющем собой расширенный вариант первого фрагмента кода из настоящего раздела, инструкция
. P a r e n t . I t a l i c = T r u e обращается к родительскому объекту по отношению к объекту F i n d , т.е. диапазону O p e n R a n g e . При выполнении
этой инструкции диапазон O p e n R a n g e теперь содержит только найденный фрагмент текста, так как только в нем предусмотрено форматирование
курсивом:

With OpenRange.Find
.С learFormatting
.Text = "pogo s t i c k s "
If .Found = True Then
. P a r e n t . I t a l i c = True
Else
MsgBox "No pogo s t i c k s found."
End If
End with

Замена текста или форматирования
Объект R e o l a c e m e n t принадлежит (а значит, является его свойством) объекту
F i n d . При написании кода для операции поиска и замены вам следует задать
свойства и выполнить методы объекта R e p l a c e m e n t .
Следующий фрагмент кода заменяет все экземпляры фразы p o g o s t i c k s словом
s k a t e b o a r d s . Выделенная область изменяется при выполнении критерия поиска, поскольку доступ к объекту F i n d осуществляется через объект S e l e c t i o n :

With ActiveDocument.Content.Find
.ClearFormatting
.Text = "pogo s t i c k s "
With .Replacement
.ClearFormatting
.Text == "skateboards"
End With
.Execute Replace := wdReplaceAll
End With
Обратите внимание на то, что метод E x e c u t e может использовать аргумент R e p l a c e ,
предназначенный для контроля за тем, будут ли заменены все обнаруженные экземпляры обнаруженного фрагмента текста, или только первый.

Глава 15, Программирование на VBA в Word

347

Поиск и замена форматирования
Для поиска текста с определенным форматированием используйте свойства объекта
Find, касающиеся форматирования. Они идентичны свойствам, используемым при работе
с форматированием диапазона или выделенной области, как я уже отмечал в разделе
"Форматирование текста", раньше в настоящей главе. Вы можете использовать те же свойства объекта R e p l a c e m e n t , если хотите указать форматирование для замещающего текста.
Для поиска любого текста с определенным форматированием задайте соответствующие
свойства объекта F i n d , а также задайте свойство T e x t равным пустой строке, используя
пару кавычек. Для изменения форматирования найденного текста без влияния на сам текст,
используйте пустую строку в качестве значения свойства T e x t объекта R e p l a c e m e n t .
Приведенный ниже код проводит поиск абзацев, которым в данный момент назначен стиль
Drab, после чего назначает им стиль F r i l l y :
With Selection.Find
.ClearFormatting
.Style = "Drab"
.Text = ""
With .Replacement
ClearFormatting
.Style •= "Drilly"
.Text = ""
End With
.Execute Replace := wdReplaceAll
.ClearFormatting
.Replacement.ClearFormatting
End With
Включение двух инструкций для "очистки формата" в вашу процедуру после метода E x e c u t e — очень неплохая идея. В противном случае, когда пользователь
в следующий раз прибегнет к диалоговому окну Найти и заменить, ему придется сбрасывать все параметры форматирования вручную.

использованиепеременных
Отличаясь от остальных приложений Office, Word позволяет определять в вашем коде
специальные переменныедокумента, которые сохраняются вместе с документом. Переменные документа позволяют сохранять используемые процедурой значения между сеансами редактирования.
Переменные документа создаются и используются как члены коллекции V a r i a b l e s
в данном документе. Как и обычные документы, переменные документа характеризуются
именами. Приведенная ниже инструкция присваивает значение переменной Henry обычной
переменной F r i e n d O f A n a i s ;
FriendOfAnais = _
ActiveDocument.Variable("Henry").Value
Для создания новой переменной документа используется метод Add коллекции V a r i a b l e s , как показано ниже:
Documents("Documentl").Variables.Add _
Name := "TimeThisMacroHasRun", Value := 0

348

Часть IV. Профессиональная работа с VBA

Вы получите сообщение об ошибке, если попытаетесь добавить уже существующую переменную документа, поэтому я рекомендую вам проверить существование соответствующего имени, прежде чем создавать новую переменную. Если это так, вы сможете получить текущее значение переменной; если нет, вы можете создать переменную и назначить ее исходное значение. Этот прием проиллюстрирован следующим примером:
For Each DocVar In A c t i v e D o c u m e n t . V a r i a b l e s
If DocVar.Name = " L a s t C a p t i o n " _
Then Doclndex = DocVar.Index
Next DocVar
If DocEndex = 0 Then
A c t i v e D o c u m e n t . V a r i a b l e s . A d d __
Name := " L a s t C a p t i o n " , Value := 1
CaptionCounter = 1
Else
CaptionCounter = _
ActiveDocument.Variables(Doclndex).Value
End I f
Несмотря на то, что объектные модели других приложений Office не позволяет
явно создавать переменные документа, вы можете создавать пользовательские
свойства документа для решения определенных задач. Подробные сведения об
использовании пользовательских свойств в качестве переменных документа изложены в главе 14.

Глава 15. Программирование на VBA в Word

349

Глава16

VBA-программирование в Excel
главе...
> Что такое объектная модель Excel
> Управление ячейками с использованием объектов диапазонов
> Создание собственных функций для использования в формулах рабочих листов
> Использование встроенных функций Excel в VBA-коле
> Работа с событиями Excel

Х ^ а ж д о г о , кто когда-либо писал формулы рабочих листов, можно считать в некотором
§ w роде программистом; поэтому не следует относиться к VBA, как к чему-то запредельному. Скорее всего, после некоторой работы с редактором Visual Basic вы обнаружите, что
писать VBA-код, на самом деле, удобнее, чем составлять формулы непосредственно в рабочем листе; VBA предоставляет больший простор для деятельности в окне редактирования кода и позволяет вносить комментарии, что бывает очень полезным.
Кроме того, VBA может служить мощным инструментом для создания настраиваемых
приложений, базирующихся на таблицах, способных выполнять вычисления и форматирования, которые без них просто не реачьны. Но прежде чем стать профессионалом в использовании кодов Excel, чему способствует представленный ниже материал, следует ознакомиться
с основами VBA, которые даются в первых трех разделах.

Знакомство с объектной моделью Excel
Прежде чем приступить к написанию VBA-кода для Excel, необходимо составить представление об иерархии объектов Excel и о том. как определять их в написанном коде. В самом
верху иерархии находится объект A p p l i c a t i o n (Приложение), отвечающий :ia функционирование всей программы Excel.
Для увеличения скорости работы многих VBA-программ следует отключить обновление
экрана. По умолчанию Excel отображает каждое изменение в рабочей книге, сделанное в ходе
выполнения VBA-кода. Это приводит к существенному снижению быстродействия. Для отключения такого режима работы Excel необходимо воспользоваться функцией S c r e e n U p d a t i n g (Обновление экрана) объекта A p p l i c a t i o n :
A p p l i c a t i o n . ScreenUpriatirig -•- F a l s e
He забудьте в конце процедуры восстановить значение True для свойства S c r e e n U p d a t i n g , в противном с.п> чае пользователь не сможет увидеть на экране полученный результат.
При использовании свойства S c r e e r . U p c a t i n g необходимо явно указывать имя объекта A p p l i c a t i o n . Однако в большинстве случаев свойства объекта A p p l i c a t i o n можно
использовать напрямую. Например, свойство Acr : v e S h e e t объекта A p p l i c a t i o n отно-

350

Часть IV. Профессиональная работа с VBA

сится к рабочему листу или диаграмме, активной в текущий момент (безусловно, в книге, активной сейчас). Для обращения в коде к такому листу вместо записи A p p l i c a t i o n . A c t i v e S h e e t можно использовать просто A c t i v e S h e e t . Коллекция Workb o o k s объекта A p p l i c a t i o n содержит все рабочие книги, открытые в данный момент.
Для идентификации определенной рабочей книги используйте ее имя, заключенное в кавычки. Вот пример активизации отдельной рабочей книги:
Workbooks("Сводная статистика п р о д а ж . x l s " ) - A c t i v a t e
Конечно же, рабочие листы также являются полноправными объектами. Они принадлежат коллекции W o r k s h e e t s , и их идентификация должна проводиться таким же образом. Выражение W o r k s h e e t s ( " Л и с т З " ) указывает на лист с именем ЛистЗ. Аналогично, отдельный объект C h a r t для диаграммы, находящейся на отдельном листе, является членом коллекции C h a r t s . Обращение к ней выполняется с помощью выражения
вроде C h a r t s ( " P a r t s C h a r t " ) . Приемы работы с диаграммами, внедренными в рабочий лист, несколько отличаются, и приемы написания кода для них являются объектом
рассмотрения данной книги.
Отображение рабочих книг можно изменить с помощью объектов Window (Окно). Объекты Window, которые иногда используются и для изменения содержимого рабочей книги, являются членами коллекции Windows объекта A p p l i c a t i o n . Ссылка на окно осуществляется
указанием в качестве индекса в коллекции Windows имени файла, содержащего рабочую книгу:
Windows("Кривая продаж и г р у ш е к . x l s " )
Если для одной рабочей книги открыто несколько окон, необходимо после имени рабочей
книги через двоеточие указать номер окна, например: Windows ("Кривая продаж
игрушек.xls:2").

использование € tcoqe оЗъеюпов Range
с ячейками
qua
Весьма неожиданно, что в Excel нет объекта C e l l (Ячейка). Поэтому при написании кода следует руководствоваться следующим подходом: для указания ячейки в VBA-коде используется объект Range. В Excel объект Range может заключать в себе одну или больше
ячеек и даже несколько не непрерывных областей листа.
Объект Range в Excel во многом подобен аналогичным объектам в Word, но вместе с тем
имеет и существенные отличия. Как и в Word, VBA-программа может ссылаться на любое
необходимое число объектов Range. Как в Excel, так и Word, действие программы не ограничивается видимым выделением пользователя, и для воздействия на какую-либо область ее
выделять не требуется.

ОпределениеобъектаRange
В Excel имеется несколько возможных методов идентификации диапазона из одной или
нескольких ячеек, на который должен воздействовать написанный код. Для достижения данной цели используются следующие.
Стандартная ссылка на ячейку. Так называемый А1-стиль ссылки на ячейку является,
пожалуй, самым простым способом работы с объектами Range. Для определения диапазона
необходимо ссылку заключить в кавычки и скобки после ключевого слова Range, как показано в следующем примере:

Глава 16. VBA-программирование в Excel

351

ActiveSheet.Range("B3")
Worksheets("Sheet2").Range("M5:S20")
Именованные диапазоны. Если рабочий лист содержит именованные диапазоны, VBAобъекты Range могут опираться на них, как показано в следующем примере:
Worksheets("Финансовый о т ч е т " ) . R a n g e ( " В ы п л а т а процентов")
Для присвоения диапазону имени непосредственно в самом коде необходимо употребить
следующее выражение с использованием функцией свойства Name (Имя):
Range("A3:В4")-Name = "Прайс-лист"
Сокращенная запись. Вследствие частого использования объектов Range, Excel позволяет
упускать ключевое слово Range при определении диапазона при записи в А1 -стиле или при записи с использованием имени. Для реализации такого приема ссылку на ячейку или имя диапазона следует заключить в квадратные скобки, как показано в приведенном ниже примере:
ActiveSheet["Al:Z26"]
["Квартальный отчет"]
Свойство Cells объекта Worksheets. Данная техника крайне необходима профессионалам, так как позволяет определять диапазон не путем указания фиксированных адресов ячейки, а на основе переменных. Основная идея состоит в составлении в цифровом виде списка
координат строк и столбцов диапазона. Читайте об этом в разделе "Использование свойства
Cells для определения диапазона" дальше в данной главе.
Свойство Selection (Выделение). Когда требуется воздействие кода на диапазон, соответствующий выделению пользователя, используется свойство S e l e c t i o n . Читайте об этом
в разделе "Работа с выделениями" дальше в данной главе.
Свойство ActiveCell (Активная ячейка). Свойство A c t i v e C e l l используется для доступа к диапазону, представляющему активную ячейку данного окна. При использовании без
спецификатора объекта (что эквивалентно использованию объекта A p p l i c a t i o n ) , свойство A c t i v e C e l l ссылается на активное окно:
ValueStorageBin = ActiveCell.Value
Свойства Rows (Строки) или Columns (Столбцы) объекта Worksheet. Доступ к диапазону, включающему весь столбец или строку, осуществляется с помощью свойств рабочего
листа Rows и Columns с использованием номера указываемого столбца или строки (нельзя
адресовать столбец через его буквенное обозначение). В следующем примере определяется
диапазон, включающий столбец Е, т.е. пятый столбец:
Workbooks("IOU.xls").Worksheets("Sheet Shootout").Column(5)
Определенные пользователем ссылки на объекты. Поскольку диапазон является объектом, можно установить именованную объектную ссылку на него, после чего доступ к диапазону осуществляется с помощью указания имени ссылки. Данную технику использовать
проще и быстрее, чем многократное указание оригинального диапазона. После установки
объектной ссылки RanGer, как показано в последующем примере, можно использовать его
свойства в таких выражениях, как RanGer . V a l u e :
Dim RanGer As Range
Set RanGer = W o r k s h e e t s ( " Л и с т 1 " ) . R a n g e ( " B 1 2 : H 1 3 " )

Использование свойств Cells для определения диапазона
При использовании без координат свойство C e l l s объекта W o r k s h e e t s указывает на
диапазон, включающий все ячейки данного рабочего листа. По аналогии, свойства C e l l s

352

Часть IV. Профессиональная работа с VBA

объекта A p p l i c a t i o n ( A p p l i c a t i o n . C e l l s ) ссылаются на все ячейки листа, активного в данный момент (свойство C e l l s может использоваться само по себе, без указания
в явном виде объекта A p p l i c a t i o n ) .
Если необходимо остановиться на более локализированном диапазоне, для свойства
C e l l s требуется числовое указание координат строки и столбца (буквенное указание столбца не допускается). В следующем примере указан диапазон, заключающий ячейку ЕЗ:
Worksheets{"Старые н о в о с т и " ) . C e l l s ( 3 , 5 )
Весьма непривычно то, что сначала указывается координата строки, а затем столбца, в противоположность записи в А1-стиле. В предшествующем примере второе значение в ссылке на
ячейку указывает на столбец Е, т.е. пятый столбец. Вследствие того, что данная система трудна
для понимания, работать с ней следует лишь в случае особой необходимости. Поскольку обе координаты являются числами, можно очень просто указывать их через переменные. Переменные
координаты позволяют программе (при работе) принимать решение о том, где находится требуемый диапазон на основе введенных пользователем данных, результатов вычислений и т.д.
В следующем примере строка выбирается в зависимости от текущего года и месяца:
intMon-h = Month (Now О)
aGoal ;= Worksheets("Monthly P r o j e c t i o n s " ) . C e l l s ( i n t M o n t h ,

8)

Способом чуть похитрее можно указать диапазон, покрывающий больше одной
ячейки:
Range(Cells(3,5), Cells(4,6))
В приведенном здесь примере указывается диапазон ячеек 2x2 на активном рабочем
листе, включающий ячейки ЕЗ (строка 3, столбец 5) в верхнем левом и ячейку F4 в левом
нижнем углах.
Для определения диапазона на неактивном листе необходимо использовать совместно
свойства Range и C e i l s для требуемого листа. Следующее выражение выполняет данную
работу, правда, имеет достаточно громоздкий вид:
Worksheets("Лист2"). _ Range(Worksheets("Лист2").Cells(3,5),
Worksheets("Лист2">.Cells(4,6))
Оператор With позволяет избежать излишних ссылок на рабочий лист. В следующем
примере к тексту всего диапазона применяется полужирное форматирование:
With Worksheets("Лист2")
. R a n g e ( . C e l l s ( 3 , 5 ) , . C e l l s ( 4 , 6 ) ) . F o n t . B o l d = True
End With
Обратите внимание, что точки перед каждым использованием свойства C e l l s необходимы для связи любой ссылки с требуемым рабочим листом. В случае отсутствия точек каждое свойство C e l l s будет относится к активному листу, что приведет к возникновению
конфликта со ссылкой свойства Range.

Выполнение совместных действий с ячейками
Используя свойства диапазона, можно одним действием изменять характеристики целого
диапазона. Следующая строка изменяет размер шрифта текста во всех ячейках диапазона:
W o r k s h e e t s ( " Л и с т 1 " ) . R a n g e ( " B 1 2 : H 1 3 " ) . F o n t . S i z e = 14
Безусловно, можно и даже предпочтительно использовать структуру With, когда необходимо работать с несколькими свойствами или методами целого диапазона, как показано здесь:

Глава 16. VBA-программирование в Excel

353

with someRange ' определенная ранее объектная ссылка
.Value = 20 ' значение всех ячеек устанавливается равным 20
.Font.Name = "Garamond"
. Font.Italic = True
.Locked = True
someRange = .Name ' сохраняется имя диапазона
ПпсЗ With

Работа с отдельными ячейками диапазона
Хотя можно с помощью одного оператора назначить одно значение всем ячейкам диапазона, как показано в предыдущем примере, в Excel нет метода, позволяющего с помощью
единственного действия изменять имеющиеся значения многоячеечного диапазона. Оператор
вроде someRange . V a l u e = someRange . Value + 10 не работает. Вместо этого необходимо осуществить циклический перебор всех ячеек диапазона с помощью цикла For
E a c h . . , Next. При использовании данной техники не требуется знание количества ячеек,
нходяших в диапазон. Вот пример работоспособного кода:
" o r Each a C e l l I n S e l e c t i o n
a C e l l . V a l u e = a C e l l . V a l u e + 10
Next
Часто перед тем, как принять решение о выполнении действия над отдельной ячейкой или
о вообще о выборе действия, требуется проверка содержимого ячейки. Основываясь на текущем значении ячейки, код может принять решение о форматировании ячейки, изменении ее
значения или же использовании данного значения для выполнения других вычислений. В таком случае также используется цикл For Each . . . Next:
For Each aCell In Worksheets("Лист2").Range("A5:BIO")
If IsNumeric(aCell) Then
Select Case aCell
Case 5 to 10
aCell.Font.Underline = xlUnderlineStyleSingle
Case 10 to 20
aCell.Font.Italic = True
Case Is > 20
aCell.Font.Bold = True
End Select}
End If
Next

Работа с выделениями
Прежде чем изменить значение или формат ячейки или нескольких ячеек, пользователь
должен их выделить. Однако в VBA выделение ячеек не требуется, так как для идентификации
ячеек, над которыми должны проводиться определенные действия, можно использовать объекты R a n g e . Но в VBA есть инструменты, связанные с выделением; они используются для реализации двух возможностей — код способен определить, какие ячейки выделены пользователем,
и код может показать пользователю место на рабочем листе, где происходит что-то важное.

Определение текущего выделения
Во многих случаях пользовательский код должен воздействовать на выбранные ячейки, как это делают встроенные команды Excel. Для доступа к выделенному пользовате-

354

Часть IV. Профессиональная работа с VBA

лем диапазону используется свойство S e l e c t i o n (Выделение) объекта A p p l i c a t i o n или Window. Свойство S e l e c t i o n объекта A p p l i c a t i o n возвращает диапазон, выделенный на рабочем листе, активном в данный момент. Следующие два оператора идентичны:
A p p l i c a t i o n . S e l e c t i o n . V a l u e = 20
Selection.Value = 2 0
Для того чтобы удостовериться в том, что ссылка всегда относится к определенному окну,
независимо оттого, какое окно активно в текущий момент, необходимо использовать свойство окна S e l e c t i o n . В следующем примере продемонстрирована данная техника; также
здесь показано, как установить объектную ссылку на диапазон, представляющий текущее выделение для повторного использования того же диапазона в дальнейшем:
Dim Se.LRange As Range
Set Se..Range = Windows("Инвентаризация игрушек.xls">.Selection
With SelRange
.CheckSpelling
.AutoFit
.Copy
End With

Выделение диапазона
Когда VBA-программа вносит изменения в рабочий лист и необходимо, чтобы пользователь их заметил, следует воспользоваться методом S e l e c t (Выделить) для перемещения
выделения на нужный диапазон, диаграмму или что-либо другое. Метод S e l e c t можно
применять фактически к любому существующему в Excel объекту, в том числе к объектам
C h a r t (Диаграмма) и всем их компонентам (каждая часть диаграммы является отдельным
VBA-объектом). к объектам Shape (Форма) и, конечно же, к объектам Range.
Для выделения диапазона необходимо сначала активизировать рабочий лист, на котором
диапазон находится, а затем использовать метод S e l e c t для объекта Range, как показано
в данном примере:
With Worksheets("Статистика любви")
.Activate
.Range("Разбитые с е р д ц а " ) . S e l e c t
End With
Кстати, метод S e l e c t для объектов W o r k s h e e t , очевидно, не выполняет ничего, кроме
активизации указанного рабочего листа, и не изменяет в нем существующее выделение. Другими словами, он эквивалентен методу рабочего листа A c t i v a t e . Подобным образом методы A c t i v a t e и S e l e c t можно использовать для активизации листа диаграммы, но ни
один из методов в действительности не выделяет диаграмму. Вот пример;
C h a r t s ( " М е с т а жительства к л и е н т о в " ) . S e l e c t
Для того чтобы выделить компонент диаграммы или внедренную диаграмму, используйте
метод S e l e c t для интересующего вас объекта.

Активизация определенной ячейки
Чтобы сделать ячейку активной для ввода, к данной ячейке используется метод A c t i v a t e (Активизировать) объекта Range. Если активизированная ячейка находится в пределах текущего выделения, весь диапазон остается выделенным. Именно таким образом работает следующий пример:

Глава 16. VBA-программирование в Excel

355

Worksheets("НичегоНеДелайДоМоегоУказания").Activate
Range("A1:E7").Select
Range("C4").Activate
Если активизированная ячейка находится за пределами выделения, оно перемещается на
активизированную ячейку.

Определение типа выделения
Код для работы с выделенными ячейками, вероятно, приведет к возникновению ошибки,
если его применить к диаграмме. Вот почему, прежде чем выполнять какие-либо операции
с выделением, обычно следует убедиться, что выделение содержит тот тип объектов, который
ожидается в коде. VBA-функция TypeName возвращает строку, содержащую тип объекта
выделения. С помощью структур I f . . .Then или C a s e . . . S e l e c t можно определить,
какое из возможных действий проводить над выделенным объектом.
В приведенном ниже примере выражение TypeName ( S e l e c t i o n ) в операторе S e . l e c t (вторая строка кода) возвращает строку, содержащую тип объекта текущего выделения. Данная строка затем проверяется рядом операторов Case, является ли выделение
диапазоном (в таком случае его значение устанавливается равным 2 001), областью диаграммы (в таком случае устанавливается красный цвет выделения), когда же выделение не
сделано, пользователь видит сообщение об отсутствии выделения. Также предусмотрен
вывод соответствующего сообщения для случая, когда выделение не принадлежит ни одному из перечисленных типов:
With Selection
Select Case TypeName(Selection)
Case "Range"
.Value = 2001
Case "ChartArea"
.Interior.Colorlndex = 3 * 3 = bright red
Case "Nothing"
MsgBox "Ничего на выделено"
Case Else
MsgBox "Невозможно определить тип выделения!"
Znd Select
End With

пользовательских
фцшщий
Даже когда кажется, что встроенные инструменты анализа данных Excel способны выполнить все необходимые действия, работа с VBA может оказаться более удобной. Использование VBA позволяет создавать пользовательские функции для рабочих листов, существенно превосходящие формулы, которые могут записываться непосредственно в ячейке.
Пользовательские функции позволяют проводить вычисления и другие операции, выполнение которых с помощью формул, основанных на встроенных функциях, просто невозможно. Даже когда написанная формула дает такой же результат, пользовательская
функция имеет существенные преимущества, например в большей простоте написания,
тестирования, понимания и т.д. Вместо тесной панели формул в распоряжение предоставляется целое окно редактирования кода, где сложную логическую конструкцию мож-

356

Часть IV. Профессиональная работа с VBA

но разбить на понятные линии. Еще одно важное преимущество состоит в возможности
вставки комментариев (и это следует максимально использовать) непосредственно рядом с кодом, к которому они относятся.

Написание пользовательских функций рабочего листа
Пользовательские функции Excel— это просто обычные процедуры VBA-функций. Детально с процедурах функций и их синтаксисе можно узнать из главы 6. Если сказать коротко, процедура функции начинается с декларации ее имени и заканчивается оператором
End F u n c t i o n . Иногда внутри может потребоваться оператор, присваивающий значение
имени функции, данное значение как раз и возвращает функция. В простейшем примере, приведенном здесь, именно это и демонстрируется:
FunctiDn MemoryAvailable ()
M-smoryAvailable = A p p l i c a t i o n .MemoryFree
End Fu.icticn
Данная функция просто возвращает количество памяти в байтах, доступных в текущее
время для Excel. Заметьте, что, поскольку функция получает данные о количестве доступной
памяти из системы, она не имеет аргументов. Ниже приведен пример немного более сложной
функции, принимающей аргументы:
F u n c t i o n CheckForvalue(aRange,Value)
For Each o b j C e l l In aRange
CheckForValue = F a l s e 'по умолчанию возвращается значение
False
If o b j C e l l . V a l u e = Value Then
CheckForValue = True
E x i t For
End If
Next o b j C e l l
EndFur.ction
Данная функция проверяет диапазон ячеек на наличие определенного значения. Если значение есть где-либо в диапазоне, функция возвращает значение T r u e , в противном случае
возвращается значение F a l s e . Перед инициированием функции необходимо обеспечить ее
двумя аргументами — диапазоном и искомым значением.

Запуск пользовательских функций
Один из способов запустить функцию, — это, конечно же, использовать стандартную
процедуру запуска в VBA, т.е. вызвать ее внутри процедуры Sub. Детально данная техника
описана в главе 6.
Для того чтобы вставить в рабочий лист возвращаемое функцией значение, следует использовать функцию таким же образом, как используется любая из встроенных функций: внести имя функции в ячейку после знака равенства. После имени печатаются круглые скобки
с любым аргументом внутри. Скобки необходимы даже в случае, когда аргументы отсутствуют, как в следующем примере:
=MemoryAvailable()
Так же как и встроенные, пользовательские функции могут быть частью более сложной
формулы ячейки, как в приведенном примере:
=MemoryAvailable() & " " с е й ч а с доступно байт"
= I F ( C h e c k F o r V a l u e ( Б 8 : В 1 8 , С 8 ) ) , " З н а ч е н и е н а й д е н о " , " З н а ч е н и е не
найденс")

Глава 16. VBA-прогрзммирование в Excel

357

Использование Панели формул с пользовательскими функциями
Действительно замечательно то, что Панель формул распознает пользовательские
функции. Если вы не помните, какие аргументы требуются для функции и принимает ли
функция вообще какие-либо аргументы, не стоит беспокоится, Панель формул показывает
рее, что необходимо для функции
Можно добавить к функции описание, которое будет появляться в диалоговом окне
Вставка функции при выборе функции. Для создания описания выберите команду
Сервис^Макрос^Макросы и затем в поле Имя макроса введите имя функции (функции
не отображаются в списке макросов). Теперь щелкните на кнопке Параметры для ввода описания функции в соответствующее поле.

Доступ к пользовательским функциям из других рабочих книг
Если нужная функция хранится в текущей книге, достаточно просто написать ее имя
г( ячейке формулы. Для того чтобы использовать функцию, хранящуюся в другой открытой
книге, имени функции должно предшествовать имя рабочей книги и восклицательный знак,
как показано в следующем примере:
•=Примитивныефункции.xls!УмнаяФункция(С4:D6,М9)
Для доступа к функциям, хранящимся в книгах, не открытых в текущий момент или закрытых при возникновении доступа к ним в дальнейшем, необходимо настроить на них ссылку VBA. Выберите команду Tools^References. Если нужная рабочая книга не представлена
в списке диалогового окна, щелкните на кнопке Browse для ее локализации и добавления
is список. Если флажок рядом с книгой не установлен, сделайте это для активизации ссылки.
Теперь любую из содержащихся в книге функций можно использовать, просто указав ее имя,
не указывая имени книги.

Тестирование пользовательских функций
Если при выполнении пользовательской функции, помещенной в формулу рабочего
листа, происходит ошибка, обычное сообщение об ошибке VBA-функции не выводится.
Все что можно увидеть вместо этого, — это неясное сообщение об ошибке вроде
£ЗНАЧ! в ячейке, содержащей формулу. При построении пользовательской функции
можно воспользоваться следующими приемами, которые помогут в тестировании и отладке функции.
Прежде чем поместить функцию в рабочий лист, протестируйте ее, вызвав через
процедуру Sub. Такой способ вызова позволяет получить сообщение об ошибке VBA и доступ к инструментарию отладки. Если функция требует ссылки на ячейки, необходимо при вызове функции использовать объект Range, как показано в данном примере:
Sub F x T e s t e r O
ReturnVal = C h e c k F o r V a l u e ( R a n g e ( " B 8 : B 1 3 " ) , R a n g e ( " C 8 " ) )
MsgBox ReturnVal
3nd Sub
В коде функции, записанной в формуле рабочего листа, в редакторе Visual Basic создайте точку разрыва. Функция будет запускаться при каждом пересчете Excel рабочего листа. Как только VBA достигнет строки, содержащей точку разрыва, вы автоматически попадете в редактор, готовый к выполнению отладки.

358

Часть IV. Профессиональная работа с VBA

Профессиональное написание функций
Не стоит отказываться от возможности написания функции таким образом, чтобы выдаваемый се результат был именно таким, как вам того хотелось бы. Зачем поручать формуле выполнять то, что можно сделать в самой функции? Приведенная модификация функции C h e c k F o r V a l u e (она приводилась в разделе "Написание пользовательских функций рабочего листа")
вместо непонятных значений T r u e и F a l s e возвращает строку поясняющего текста:
F u n c t i o n CheckForVaiue2(aRange, Value)
For Each o b j C e l l In aRange
CheckForValue2 = "искомое з н а ч е н и е " 6 Value & __ "не найдено"
I;: o b j C e l l . Value = v a l u e Then
CheckForValue2 = "искомое значение" & Value & _ "находится
в ячейке" & o b j C e l l . A d d r e s s
E x i t For
End If
Next o b j C e l l
End F u n c t i o n
Если модифицированной функции удается найти искомое значение где-либо внутри
диапазона, она возвращает строчку вроде Искомое з н а ч е н и е 3, 57 н а х о д и т с я
Б я ч е й к е SFS83; в противном случае возвращается строчка Искомое з н а ч е н и е
3,57 не найдено.

использование € scoqe вап[юешшх
функций
Независимо от того, пишете ли вы собственную функцию или процедуру Sub, не стесняйтесь
призывать на помощь широчайшие возможности встроенных функций Excel по анализу данньк
и проведению вычислений. Использовать их в своем собсгвенном коде очень просто: необходимо
вызвать их как метод объекта W o r k s h e e t F u n c t i o n s . Предположим, что нужно написать процедуру, проводящую вычисления на основе среднего значения чисел определенного диапазона.
Дня получения среднего значения можно использовать код, подобный следующему:
OnAverage = W o r k s h e e t F u n c t i o n . A v e r a g e ( R a n g e ( " В б : B 1 3 " ) )
Некоторые из встроенных функций Excel запрещены в VBA. Это касается функций, дублирующих встроенные VBA-функции, о которых шла речь в главе 11.

JlfwiftcuutuftoeciHue coJbttnuu excel
Реакция на вносимые пользователем изменения стала неотъемлемой частью функционирования электронных таблиц, поэтому написание кода для событий в Excel часто играет более значимую роль, нежели в остальных приложениях пакета Office. Изменение значения
лишь одной ячейки, использующейся в расчетах формулы или диаграммы, может привести
к существенным последствиям для всей рабочей книги. Возможность перехвата событий,
управляющих данным процессом, для улучшения и расширения функциональности встроенной системы ответов Excel, целиком находится во власти VBA-программиста.

Глава 16. VBA-программирование в Excel

359

Выбор правильного объекта
Перед написанием кода обязательно нужно решить, какой объект должен отвечать на событие. В Excel способны распознавать события четыре объекта: диаграммы, отдельные рабочие листы, рабочие книги и приложение Excel в целом. Если требуется написание кода, отвечающего на событие, связанное с диаграммой, такой код подходит к процедуре события диаграммы. Однако для событий, являющихся ответом на изменения в рабочем листе,
программист получает несколько вариантов выбора.
Хотя некоторые события Excel распознают лишь определенные объекты, большинство из них образует иерархию от объекта W o r k s h e e t до объектов Workbook и App l i c a t i o n . Например, изменения, внесенные в рабочий лист, инициируют событие
C h a n g e (Изменение) объекта W o r k s h e e t , который в свою очередь инициирует событие S h e e t C h a n g e (Изменение листа) для объектов Workbook и A p p l i c a t i o n .
Принимая во внимание сказанное выше, следует определить, подходит ли код для процедуры события рабочего листа, рабочей книги или приложения. Задача выбора не составит много труда.
IS
j;
I S
Ь

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

i S Если же код должен активизироваться в любой из открытых рабочих книг, он безусI
ловно подходит процедуре события приложения.

Испозование процедур событий
Техника написания процедуры события для любого объекта Excel в своей основе не имеет
никаких принципиальных отличий по сравнению с техникой написания кода события для
формы или элемента управления VBA. В главе 10 приведено детальное описание методики,
но основные моменты можно представить следующим образом.
1. Откройте окно редактирования кода для объекта.
2. Выберите объект, выбрав его имя из раскрывающегося списка Объект в левом
верхнем углу окна.
3. Выберите из раскрывающегося списка Процедура, в правом верхнем углу окна, событие, для которого должен быть написан код.
4. При этом в окне появляется каркас выбранной процедуры сообщения.
Кроме написания самого кода, единственным сложным моментом может быть вынос
окна редактирования кода на первое место (п. 1 в приведенном выше списке). Для объектов W o r k s h e e t , Workbook и C h a r t , занимающих отдельный лист, никаких особенностей н е т — необходимо просто выбрать объект в окне обозревателя и щелкнуть на
кнопке View Code. Объекты представляются в алфавитном порядке, а их имена можно
изменять в окне Options.
В случае диаграмм, внедренных в рабочий лист, а также объектов приложения Excel
ситуация посложнее. Для того чтобы сделать такие объекты доступными из окна, требуется написание специальных модулей классов. Объем данной книги не позволяет детально рассмотреть данный вопрос, однако информацию, касающуюся данной темы,
можно получить из справочной системы.

360

Часть IV. Профессиональная работа с VBA

Реагирование на изменения в рабочем листе
Если необходимо, чтобы код реагировал на действия, производимые пользователем с рабочим листом, потребуются такие инструменты, как свойства Change, C a l c u l a t e и Sel e c t ionChange
(для объектов Worksheet)
и
соответствующие события
SheetCnange, S h e e t C a l c u l a t e и S h e e t S e l e c t i o n C h a n g e (для объектов Workbook и A p p l i c a t i o n ) . Для запуска пользовательских процедур в то время, когда сами рабочие листы или диаграммы активизированы или не активизированы, используются события
Activate и Deactivate.

События Change и SheetChange
События C h a n g e и S h e e t C h a n g e инициируются каждый раз, когда значение любой ячейки или нескольких ячеек изменяется в результате действий пользователя или
обновления ссылки. Однако изменения в вычисляемых значениях не приводят к инициированию события. Соответствующие процедуры событий позволяют наметить ячейку,
значение которой было изменено. В следующем примере проверяются измененные значения внутри диапазона, называемого T a r g e t , на предмет их попадания в определенные пределы; такие значения выделяются с помощью шрифта с большим кеглем, полужирным начертанием и зеленым цветом.
P r i v a t e Sub Worksheet_Change(ByVal T a r g e t As Range)
Fcr Each o C e l l In T a r g e t
11 Then
If oCell > 4 And oCell

With oCe 11.Font
.Bold - True

.Size
.Color - PGE 0, 255, 0)
End With
End If
V.r
xt oCell,
End Sub
=

Зеленый

Обратите внимание, что T a r g e t может быть не одной ячейкой, а диапазоном, благодаря
тому, что операции заливки, удаления и вставки могут применяться одновременно к нескольким ячейкам. Для этого процедура сообщения Change должна включать в себя структуру
For Ea^h ... Next; в таком варианте процедура применима как отдельной ячейке, так
и к нескольким ячейкам, что и демонстрирует приведенный выше пример.
В действительности, события Change и S h e e t C h a n g e могут активизироваться даже тогда, когда значение не изменялось. Данные события готовы произойти,
когда пользователь начинает редактирование ячейки (после щелчка в панели
формул или нажатия клавиши ), даже если сразу после этого он прекратил
редактирование, не внеся никаких изменений (нажав клавишу , щелкнув
на кнопке Ввод или на рабочем листе). Событие не активизируется, если пользователь прекращает редактирование нажатием клавиши или щелчком на
кнопке Отмена.

События Calculate и SheetCalculate
Событие C a l c u l a t e распознаваемое как объектом W o r k s h e e t , так и C h a r t ,
происходит при каждом обновлении программой Excel рабочего листа или диаграммы.

Глава 16. VBA-программирование в Excel

361

Событие S h e e t C a l c u I a t e для объектов Workbook и A p p l i c a t i o n происходит в
ответ. Если средство автоматического вычисления включено, данное событие активизируется, как только изменяется значение любой ячейки, т.е. происходит в тандеме с событием C h a n g e . Когда средство пересчета включено в ручном режиме, событие C a l c u l a t e происходит лишь тогда, когда пользователь инициализирует пересчет нажатием клавиши .
Процедуры событий для событий C a l c u l a t e и S h e e t C a l c u l a г е используются
для изменения рабочего листа в соответствии с результатами вычислений. Например, если
известно, что пересчет может изменить элементы упорядоченного списка, целесообразно
использовать процедуру события W o r k s h e e t _ C a I c u l a t e для упорядочения списка после проведения вычислений. Поскольку данные процедуры не сообщают, какая из ячеек
изменялась в результате вычислений, необходимо поместить в код адреса ячеек, которые
требуется изменить.

События SelectionChange и SheetSelectionChange
При каждом перемещении активной ячейки, а также при расширении или сжатии выделения Excel вызывает событие S e l e c t i o n C h a n g e для w o r k s h e e t . Параллельно
происходит событие S h e e t S e l e c t i o n C h a n g e для объектов Workbook и A p p l i c a t i o n . Процедуры событий для данных событий можно использовать для обратной
связи с текущим выделением. В приведенном ниже примере событие S e l e c t i o n Change используется для отображения в левой верхней ячейке текущего листа адреса
активной ячейки, а также для помещения имени рабочего листа и адреса выделения в
строку состояния. Обратите внимание на то, как аргумент Sh позволяет идентифицировать и вести работу с текущим листом:
P r i v a t e Sub Workbook J 3 n e e t S e l e c t icr/ihange (ByVal Sh As O b j e c t , _ ByVal T a r q e t As E x c e l . R a n g e ;
Sh.Range{"Ai") = A c t ; v e C e I I . A d d r e s s
A p p l i c a t i o n . S t a t u s B a r - Sh . Nriire & " : " j; T a r g e t - A d d r e s s
i.'.nd Sub
Несколько усложнив код. можно добиться того, чтобы вместо простого выделения вызывался какой-нибудь ответ: например, чтобы в случае попадания определенной ячейки пли
диапазона в новое выделение отображалось пользовательское диалоговое окно:
P r i v a t e Sub Worksheet_SelectionChar.ge (ByVal T a r g e t As r'.xcel . P.ance)
If T a r g e t . A d d r e s s = "$3$2" Then
MsgBox "Вы нашли нужную я ч е й к у ! "
End If
n.nd Sub

Программирование динамических диаграмм
Поскольку объекты диаграмм Excel способны распознавать большое число событий,
многие из которых связаны с мышкой, их можно считать большим элементом управления
ActiveX, помещенным в рабочей книге. Диаграммы распознают события A c t i v a t e , Dea c t i v a t e и C a l c u l a t e . Вот еще некоторые события, для которых возможно написание кодов.
! S DragOver и D r a g P l o t . Происходят, когда ячейки перемешаются над внедренной
I
диаграммой или опускаются на нее соответственно.

362

Часть IV. Профессиональная работа с VBA

MouseDown. MouseUp и MouseMove. Происходят в ответ на действия мыши.
S e l e c t . Происходит при выделении какой-либо части диаграммы. Написанный код
может определять тип и характеристики выделенного элемента и проводить соответствуюшие действия.
S e r i e s C h a n g e . Происходит, когда пользователь изменяет значение в диаграмме
чгрез саму диаграмму (а не изменяя значения, содержащиеся в листе).

Глава 16. VBA-программирование в Excel

363

Глава17

Программирование баз данных
В э/ftou ыабе...
А Знакомство с терминологией
У Написание кода баз данных с помощью объектов данных ActiveX
У Программирование с помощью DAO
V Ускорение с помощью SQL

^•Хесмотря на то, что Access — официальное приложение для работы с базами данных,
я С" входящее в состав Office, вы не ограничены только этим приложением при создании пользовательских баз данных с помощью VBA. Действительно, любое приложение,
поддерживающее VBA, — от Word ло CorelDraw, — позволяет использовать сведения, которые хранятся в базах данных на вашем компьютере, сервере локальной сети или любом
другом компьютере в Internet. В настоящей главе мы остановимся на нескольких базовых
приемах программирования на VBA, позволяющих управлять данными прямо из ваших
собственных VBA-программ.

J[ftotftauuuifto€aHMe 100 GROUP BY Category
HAVING Count(Category) > 4
Сортировка с помощью ключевого слова ORDER BY
Используйте оператор ORDER BY для сортировки записей, полученных с помощью инструкции SELECT, в соответствии со значениями одного или нескольких полей. Оператор
ORDER BY указывается в конце инструкции, как показано ниже:
SELECT Toy,

Price,

I n S t o c k FROM T o y l n v e n t o r y ORDER BY Toy

В полученном наборе записей список игрушек будет упорядочен по именам.
Для того чтобы упорядочить этот список по иене, вам следует использовать инструкцию,
приведенную ниже. Как видите, можно проводить сортировку по значениям нескольких полей, указав эти поля в необходимом порядке сортировки:

SELECT Toy, Price FROM Toylnventory ORDER BY Price DESC, Toy
354

Часть IV. Профессиональная работа с VBA

По умолчанию сортировка всегда проводится по возрастанию. Для явного указания порядка сортировки используйте ключевое слово DESC (descending— убывание) или ASC
(ascending— возрастание), после которого необходимо указать имя соответствующего поля.
В приведенном выше примере сортировка проводилась по убыванию, поэтому товары с максимальной ценой указаны в списке первыми.

Выполнение групповых обновлений и удалений в SQL
Инструкции UPDATE и DELETE позволяют вам изменять или удалять группу записей в источнике данных с помощью всего одной команды. Эти инструкции работают непосредственно
с исходной базой данных; вам не нужно предварительно получать набор записей, изменять записи, а затем переносить в базу данных внесенные изменения. Изучите приведенный ниже пример, иллюстрирующий повышение цены на 10% для товаров определенной категории:
UPDATE T o y s SET P r i c e = P r i c e * 1.1 WHERE C a t e g o r y = ' T r a i n s '
Имя таблицы, с которой вы работаете, указывается сразу после слова UPDATE. После этого указывается оператор SET, с помощью которого вы определяете значение одного или нескольких полей в таблице. И наконец, необязательный оператор WHERE позволяет вам задать
критерии, ограничивающие записи, к которым будут применяться изменения. Оператор
WHERE работает точно так же, как и в инструкциях SELECT.
Инструкция DELETE еще проще в использовании, чем инструкция UPDATE: ее действия
сводятся к простому удалению записей. Приведенный ниже пример удаляет записи для всех
игрушек, которые отсутствуют на складе и не были заказаны:

DELETE FROM Toys WHERE InStock = 0 And OnOrder = 0
Для удаления значений отдельных полей, а не целых записей, используйте
инструкцию UPDATE вместе с оператором SET, определяющим значение поля
равным N u l l .
Инструкции UPDATE и DELETE приводят к необратимым изменениям в базе
данных; вы не сможете отменить действие этих инструкций. Поэтому, прежде
чем выполнять любую из этих инструкций, обязательно создайте резервную
копию базы данных.

Глава 17. Программирование баз данных

385

Глава18

Работа с файлами на диске
/3 эМой главе...
У Получение доступа к файлу по номеру
> Выбор режима доступа к файлу
> Чтение и запись в файлы с использованием не объектно-ориентированных методов

дополнение к объектно-ориентированным методам работы с файлами данных,
описанным в главе 12, VBA предлагает альтернативный метод для чтения и записи данных с дисковых файлов. Эта старая система по-прежнему обладает определенными достоинствами. Хоть вы и не можете работать со свойствами файла и методами, вы
получаете более полный контроль над тем, как данные организуются в файле, и над тем,
какие данные читаются и записываются. В отличие от объектно-ориентированной файловой системы операторы и функции, описанные здесь, встроены в VBA и не требуют
внешних библиотек.

Haueft — з/fio ключ,
После того как файл открыт для доступа VBA, обращение к нему осуществляется по номеру, а не по имени. Если приходится работать с несколькими файлами одновременно, отслеживать то, какой файл вам необходим в данный момент, совсем не просто. В принципе,
никто не запрещает работать таким образом. Но дальше в данной главе, в разделе "Не идите
на поводу у номеров", показан простой способ решения данного вопроса. Для работы с содержимым файла необходимо его открыть. Для этого используется оператор Open
(Открыть). Вот его синтаксис в простейшей форме:
Open " p a t h n a m e " For mode As f i l e n u m b e r
А вот пример типичного оператора Open:
Open "С:\Мои документьЛМои д а н н ы е . d a t " For B i n a r y As #1
Оператор использует три аргумента.
p a t h n a m e (путь). Полный путь (с указанием диска и каталога), определяющий
файл, который должен быть открыт как строчное выражение. При вводе строки текста необходимо заключать ее в кавычки, как это сделано в приведенном выше примере. Вместо этого можно использовать строкупеременных, а также любое выражение,
значение которого будет правильной строкой VBA.
mode (режим). Ключ VBA, определяющий то, каким образом вы планируете работать с файлом; подробности — в разделе "Выбор режима доступа к файлу".

386

Часть IV. Профессиональная работа с VBA

i S f i l e n u m b e r (номер файла). Аргумент f i l e n u m b e r принимает целочисленное
I
значение от 1 до 511, если оно не было присвоено другому файлу. Традиционно, но
I
не обязательно, в номере перед числом помешают знак #. В дальнейшем присвое|
ние номеров не обязательно, однако при желании это можно делать (можно восI
пользоваться функцией F r e e F i l e , которая возвращает следующее доступное зна1
чение f i l e n u m b e r ) .
Оператор Open может принимать еше некоторые опциональные аргументы. Все они
здесь не рассматриваются, но в следующем разделе рассмотрен один из них —
L e n = r e c l e n g t h , необходимый при работе с файлами произвольного доступа.

Выбора режима доступа к файлу
При открытии дискового файла с помощью оператора Open необходимо включить
в него аргумент mode. Данный аргумент говорит VBA об организации файла и о том, каким образом планируется осуществлять доступ к информации. Хотя в качестве аргумента
mode может быть любое из пяти возможных ключевых слов, в действительности выбор
проводится из трех основных режимов. Каждый из режимов имеет свои достоинства и недостатки, описанные ниже.
Режим доступа к
файлу в
операторе Open

Описание работы

Ключевые слова

Произвольный
доступ

Сохраняет данные в записях идентичной
длины, так что чтение или запись могут
вестись до тех пор, пока известно положение
в файле, Запись в режиме произвольного
доступа соответствует любому типу данных
V B A фиксированной длины или
определенному пользователем типу,
содержащему исключительно типы данных
фиксированной длины

Random

Последовательный

Данные сохраняются в виде серии символов.
Подходит для текстовых файлов, а также для
файлов баз данных в кодировке ASCII,
использующих разделители-запятые

I n p u t (для чтения данных из
файла); O u t p u t (для записи
данных в файл); A p p e n d (для
записи данных в конец файла)

Двоичный

Данные сохраняются в строчной форме,
в любом заданном порядке

Binary

Не идите на поводу у номеров
Хотя в VBA рекомендуется обращаться к открытым файлам по номеру, запоминать то,
с чем связаны какие-то числа, достаточно трудно и неудобно. Вместо номеров файлов
можно использовать константы или переменные с понятным названием. Если наперед известен номер, который будет использоваться для отдельного файла, объявите для него константу. Данную константу затем можно использовать в операторе, воздействующем на
файл. Вот пример:

Глава 18. Работа с файлами на диске

387

Const PetsFile = 1, BdayFile = 2
Open "C:\MiscData\PetsLog.txt" For Input As PetsFile
Open "C:\MiscData\Birthdays.txt" For Random As BdayFile
Input #PetsFile, strPetlnfo ^чтение одного элемента из файла
Close PetsFile
Put BdayFile, 45, usrBDay 'запись одного элемента в файл
CloseBdayFile
Применяйте данный прием без опасения: вместо того чтобы собственноручно присваивать файлам номера, используйте функцию F r e e F i l e , определяющую следующий
доступный номер файла. Если значение, возвращаемое функцией, присвоить переменной, необходимость в запоминании номера просто отпадет. Вот пример применения
данного приема: Dim DiaryFile As Integer DiaryFile = FreeFile () Open
«C:\MySecrets\Diary.txt» For Input As DiaryFile

Закрытие открытых файлов
Будьте аккуратными — после того как работа с файлами завершена, их следует закрыть.
Закрытие файла гарантирует, что все хранимые в памяти изменения действительно будут записаны на диск, а ресурсы, занимаемые файлами, освободятся и станут доступными для других приложений.
Для выполнения подобной задачи нужен, конечно же, оператор C l o s e . Для закрытия определенного файла используется оператор вроде C l o s e #2 (или C l o s e P e t s F i l e , как в
предыдущем примере). Для закрытия всех открытых файлов оператор C l o s e используется
сам по себе.

Чтение и запись данных
Есть несколько VBA-команд для записи и извлечения данных из файла. В приведенной
ниже таблице описана их работа.
Пример
команды

Использование

Пояснение

Оператор P u t

Предназначен для записи
переменных в файл

P u t # 1 , 1 8 0 0 , S t r Q u o t e (записывает
переменную S t r Q u o t e в двоичный файл,
начиная с позиции 1800);
Put # 1 , 15, u s r C u s t o m D a t a
(записывает переменную u s r C u s t ornDa t a
в файле с произвольным доступом в запись 15}

Оператор Get

Предназначен для чтения из
файла переменной,
сохраненной с помощью
оператора P u t

G e t t # 1 , 1 8 0 0 , S t r Q u o t e (читает
строку данных из двоичного файла с позиции
1800 в переменную S t r Q u o t e ) ; G e t # 1 ,
1 5 , u s r C u s t o m D a t a (читает
определенные пользователем данные, хранимые
в 15-й записи переменной u s r C u s t o m D a t a )

Функция I n p u t

Предназначена для чтения из
файла данных, сохраненных
с помощью оператора P u t

StrBigText = Input (400,#1)
(читает 4000 символов в переменную
StrBigText)

388

Часть IV. Профессиональная работа с VB

Пример
команды

Использование

Пояснение

Oneparopwrite # Предназначен для записи списка перемены в последовательный файл, с созданием новой
строки после каждого прохода

W r i t e #3, s t r S h o r t S t r i n g ,
strLongString,
i n t L i t t l e N u m b e r (записывает три
переменные в строку последовательного файла)

Оператор i n p u t # Предназначен для чтения
списка из последовательного
файла переменных,
сохраненных с помощью
onepaTopaWrite #

I n p u t #3, s t r S h o r t S t r i n g ,
strLongString,
i n t L i t t l e N u m b e r (читает данные для трех
переменных из последовательного файла)

Глава 18. Работа с файлами на диске

389

Глава 19

Еще о VBA-формах
/3 э*ной главе..,
> Выбор цвета и добавление изображений к формам и элементам управления
> Настройка указателя мыши
У Использование дополнительных параметров элементов управления
У Проверка правильности вводимых данных и другие приемы

jm м атериал настоящей главы дополняет сведения, изложенные в главе 10, предлагая
^/vb вам советы о проектировании и программировании VBA-форм.

О внешнем 6uqe фо/гм и эиемешпов
управления
Хотя вы можете изменить параметры, относящиеся к внешнему виду форм и элементов управления, с помощью программного кода, чаше всего делать это не имеет смысла. Лучше воспользоваться диалоговым окном Properties для выбора всех необходимых настроек (подробности об использовании диалогового окна свойства редактора Visual Basic изложены в главе 10).

Выбор цветов
Значения свойств F o r e C o I o r и B a c k C o l o r задают соответственно цвет переднего плана и цвет фона для форм и элементов управления. Для элементов
управления значение свойства F o r e C o I o r задает цвет текста, размещаемого на
элементе управления. Это свойство недоступно для тех элементов управления, на
которых текст разместить нельзя. В случае форм значение свойства F o r e C o I o r
задает цвет, который будет использоваться по умолчанию для всех новых размещаемых на форме элементов управления, а также для сетки на форме (эта сетка
видна только в режиме проектирования формы).
Все относящиеся к выбору цветов свойства используются одинаково. После щелчка на
кнопке со стрелкой в поле свойства, относящегося к цвету, появляется приятное на вид небольшое окно, в котором, несмотря на его небольшой размер, будет целые две вкладки (рис. 19.1).
На вкладке System (Системные) (рис. 19.1, слева) можно выбрать цвет из системной палитры Windows, т.е. из цветов, заданных в панели управления Windows для элементов интерфейса Windows. Если из списка выбрать пункт типа Desktop (Рабочий стол) или Button Face
(Поверхность кнопки), VBA будет автоматически корректировать хранящееся в свойстве значение цвета при изменении соответствующих параметров в панели управления Windows.

550

Часть IV. Профессиональная работа с VBA

;

106 юрВозмо ж пост ей UserForm

Взять01пуск Checkbox

Capton
СОГАЭСИТЬСЯ взять отпуск
ContolTipTgid Бесппаткый фуиз вокруг ев
IHffjMuMMfl

SpeoaEffect 2 - frreuttan
False
visible
True
В Behavio

False

Locked
False
TeiKIgn 1 - fmTeiiia
Tripl^staie False
wordwrap True

I] Button Face
Button Shadow
Disabled Te*l
Inactive Title Bar
I] Button Highlight _
•utton Dark Shad

В Data
ContrclSource
a Font
Font
HaettBnichwBile

El Appearance
BsckColor
eordercotor
EorOerStyte
Cap! ic
Spec a Effect
В Behavior
Cycle
Enabled
a Font
Font
В Mlsc
(Ma me)
DrawBuffer
HelpCcntEiUD
Mouse Icon

t J SHS0O000OFS
• 8H80000012B
0 - frrecrderStyleNone
Розовые фантазии
O-frr
0 - frr
Тгчв
Наем
Обэо
Э200С
0
(Нота

Рис. 19.1. Здесь показаны обе вкладки диалогового окна выбора цвета в VBA
На вкладке Palette (Палитра) (рис. 19.1, справа) можно выбрать цвет из предлагаемой палитры. VBA автоматически назначит свойству числовое значение выбранного цвета. В общем, довольно просто.

Выбор шрифтов
Хотя текст, который вы размешаете в форме и элементах управления, используя параметры,
предлагаемые VBA по умолчанию, выглядит вполне сносно, можно выбрать гарнитуры шрифтов
по своему вкусу. С помощью свойства F o n t (Шрифт), которое есть у форм и большинства элементов управления, вы можете выбрать для текста любой из шрифтов, установленных в системе.
Свойство F o n t формы на самом деле ничего не меняет в самой форме. Шрифт для заголовка формы, видимый в ее строке заголовка, задается системными установками в панели
управления Windows. Свойство F o n t задает шрифт, который будет использоваться по умолчанию для текста тех элементов управления, которые добавляются в форму.
Из этого можно извлечь такой вывод: если вы собираетесь использовать какой-то
нестандартный шрифт для всех элементов управления в форме, установите подходящее значение свойства F o n t для формы. Тогда вам не придется менять
свойства F o n t для каждого из элементов управления по отдельности.
Чтобы выбрать шрифт для формы или элемента управления, найдите свойство F o n t в окне
свойств, щелкните в соответствующем поле, а затем на появившейся в этом поле кнопке с многоточием. В результате на экране появится стандартное диалоговое окно Шрифт (рис. 19.2).
Если вы подумываете об использовании нестандартных шрифтов, имейте в виду
два связанных с этим потенциально неприятных момента. Первый момент практический; если вы собираетесь распространять свою программу, то пользователям
вашей программы нужно будет установить все использованные вами особые
шрифты, поскольку в случае отсутствия каких-либо шрифтов Windows использует
подстановки, и кто знает, как будут выглядеть шрифты, подставленные вместо ваших? Другой момент чисто эстетический: непривычные шрифты, как и комбинации различных гарнитур шрифтов, отвлекают внимание на себя, вместо того чтобы
подчеркивать функциональное назначение формы.

Глава 19. Еще о УВА-формах

391

ни*-"-

Обочны и
Comci Sens MS
ЯИИ1Н
ИГ""
1 Bookman Od
l Syle
i
Наклон
Полу*1
1
C
e
n
t
u
y
i
G
o
h
l
c
i
r
T Cenu
lyi SchoolbookИ i Погожи рныи
)ньи наклонно и
T
Cuood
uud
*C
E
ireireirr New
Ь1И

гый

АаВЬБбЯя
НоЦ символов
рТфйтлица

^ 1 .

Рис. 19.2. В таком диалоговом окне выбирается шрифт, который будет использоваться по умолчанию для формы или текста
на элементе управления

Простые фокусы с мышью
В VBA есть несколько свойств, которые позволяют управлять тем, что увидят пользователи программы при разглядывании формы, двигая указатель мыши туда-сюда по экрану.
Самое главное, что никакого программирования событий при этом не требуется!

Изменение вида указателя мыши
В любом профессионально изготовленном приложении вид указателя мыши зависит от
того, над каким сегментом экрана он находится. И вы, как настоящий профессионал, непременно должны добавить такую эффектную возможность в свои VBA-программы. Тем более,
для этого вам придется изменить значения лишь одного-двух свойств. Вот что нужно сделать.
1. Выделите форму или элемент управления, для которого потребуется изменить
вид указателя мыши.
2. Найдите в списке окна свойств свойство M o u s e P o i n t e r и щелкните в поле
этого свойства.
3. Выберите подходящий пункт из раскрывающегося списка этого поля.
Все пункты раскрывающегося списка, кроме одного, соответствуют указателям мыши, задаваемым с помощью панели управления Windows (конкретно, на вкладке Указатели панели
управления Мышь). Так что при выборе этих пунктов вид указателя в выполняемой программе будет на самом деле зависеть от той графики, которая назначена соответствующему типу
указателя в панели управления Windows.
Если назначить специальный указатель мыши форме, то он получит соответствующий вид в рамках формы, включая все ее элементы управления (кроме тех,
которым приписаны указатели иного вида).

Выбор изображения для указателя мыши
Не исключено, что вам понравится идея появления изображения черепа со скрещенными костями, когда указатель мыши будет пересекать недоступный элемент управле392

Часть IV. Профессиональная работа с VB

ния, — неважно, какой, и независимо от установок в панели управления Windows.
Или, может быть, вы захотите видеть более приятное изображение, например золотую
рыбку (рис. 19.3).

Рис. 19.3. Пользовательский указатель мыши на форме VBA
Превратить имеющееся графическое изображение в пользовательский указатель мыши
несложно. Вот соответствующие инструкции.
1. Создайте новую пиктограмму или возьмите готовую из коллекции рисунков.
Изображение нужно сохранить в стандартном формате Windows для пиктограмм,
в файле с расширением . i c o .
2. Выполнив инструкцию, предложенную в предыдущем разделе "Изменение
вида указателя мыши", установите для свойства M o u s e P o i n t e r формы
значение 99.
3. Щелкните в поле свойства Mouselcon.
4. Щелкните на кнопке, вызывающей диалоговое окно (на кнопке с многоточием).
VBA откроет диалоговое окно Load Picture (Загрузка рисунка), с помощью которого
можно найти и открыть файл с картинкой для вашего указателя мыши.

Добавление всплывающих подсказок для элементов управления
Вы можете даже связать со своими формами всплывающие подсказки — небольшие текстовые сообщения, которые появляются рядом с указателем мыши при задержке последнего
на секунду-другую на элементе управления. Всплывающие подсказки являются прекрасным
средством ненавязчивого информирования пользователя о назначении элемента управления.
И еще, всплывающие подсказки предусмотрены только для элементов управления, но не для
содержащей их формы.
Чтобы назначить элементу управления всплывающую подсказку, просто напечатайте
подходящий текст в поле свойства T o o l T i p . Пример того, что вы можете получить, показан на рис. 19.4.

Добавление изображений
Нельзя навсегда подавить свои художественные порывы, поэтому придет время, когда вы
захотите украсить форму или ее элементы управления рисунками. В дополнение к возможности выбирать цвет для тривиальных текстовых окон, вы можете размещать изображения на
кнопках, флажках, переключателях, фреймах и других элементах управления. Результат подобного творчества показан на рис. 19.5.

Глава 19. Еще о VBA-формах

393

* Щ. (ft •*?«•'
JElil

ЗНа*'-1пте чтооыузнат&свое будущее вес и размер обуви [

g

Рис. 19.4. ЧТО же делает эта кнопка? Указания на этот счет дает всплывающая подсказка
Добавление рисунков в формы и элементы управления
Элемент управления I m a g e (Изображение)— тот элемент управления в панели
Toolbox, пиктограмма которого напоминает картину,— можно использовать не
только для того, чтобы размещать в нем изображения. Элемент управления I m a g e —
это, по сути, просто надпись без заголовка. Поэтому вы можете для размещения изображений использовать элемент управления надписью ( L a b e l ) , очистив поле свойства C a p t i o n (Заголовок), если текст на элементе управления не нужен.

Рис. 19.5. В эту форму и ее элементы управления добавлены изображения
394

Часть IV. Профессиональная работа с VB

Не волнуйтесь, хотя работа с графикой не считается простой для начинающего программиста, но VBA превращает процесс в почти тривиальный. Вот инструкции, которым вам
нужно следовать в данном случае.
1. Щелкните на форме или элементе управления, куда нужно поместить прекрасный рисунок.
2. В окне свойств для выделенного объекта щелкните в поле свойства P i c t u r e .
3. Щелкните на открывающей диалоговое окно кнопке с многоточием, которая
теперь появилась в поле свойства P i c t u r e .
4. В открывшемся диалоговом окне Load Picture (Загрузка рисунка) найдите файл
с нужным изображением и щелкните на кнопке Открыть, чтобы добавить изображение в объект.
В форме (или элементе управления) появится рисунок.
5. Используйте свойства P i c t u r e A l i g n m e n t , P i c t u r e S i z e M o d e и P i c t u r e T i l i n g (если они есть у того объекта, с которым вы работаете), чтобы
разместить рисунок так, как вам нравится. Вот некоторые подробности об этих
свойствах.
Выбрав подходящее значение свойства P i c t u r e A l i g n m e n t , можно разместить изображение либо по центру, либо в углу объекта.
Выбрав подходящее значение свойства P i c t u r e S i z e M o d e , можно либо
растянуть изображение так, чтобы оно заняло всю поверхность объекта
(соответствующее значение— f m P i c t u r e S i z e M o d e S t r e t c h ) , либо пропорционально сжать изображение, чтобы оно поместилось в объекте
(fmPictureSizeModeZccm). либо оставить размер изображения как есть,
обрезав лишнее ( f m P i c t u r e S i z e M o d e C l i p ) .
Для свойства P i c t u r e T i l i n g допускаются всего два значения— True
(т.е. VBA нужно размножить изображение и заполнить копиями весь объект)
и False.

Удаление рисунков с помощью окна свойств
Поиграв некоторое время с рисунками в формах, не исключено, что вы придете к выводу,
что "спартанский" вид для форм предпочтительнее. Чтобы удалить изображение из элемента
управления или формы, щелкните в поле свойства P i c t u r e в окне свойств, а затем нажмите
клавишу . Другие методы не работают — ни нажатие , ни нажатие клавиши
пробела или печатание и даже нажатие клавиши .

Другие возможности форматирования
По большей части, другие опции меню Format применимы и к отдельным элементам
управления, и к их группам. Выделив один или несколько элементов управления, вы можете
использовать следующие опции.
| S Center in Form (Центрировать в форме) — чтобы центрировать объекты по вертика1 ли или по горизонтали. Если выделено несколько элементов управления, эта команда
1
выставляет все элементы управления по средней линии, а не центрирует набор как
|
одно целое (чтобы получить последнее, сначала нужно сгруппировать элементы
|
управления).

Глава 19. Еще о VBA-формах

395

Arrange Buttons (Выстроить кнопки) — чтобы разместить одну или несколько выделенных кнопок у нижнего или у правого края формы. Команда Arrange Buttons работает и тогда, когда выделены не только кнопки, но перемещаются в результате выполнения этой команды только кнопки.
Size to Fit (Задать размеры в соответствии с содержимым) — чтобы заставить VBA
привести размеры элемента(ов) управления в точное соответствие с размерами содержащегося в нем текста. Эта команда действует одноразово — она не устанавливает для свойства A u t o S i z e значение T r u e , так что при изменении текста в элементе
управления размеры последнего не изменятся.
Size to Grid (Задать размеры по сетке) — чтобы сдвинуть все стороны элемента(ов)
управления к ближайшим линиям сетки.
В редакторе Visual Basic нет команды, позволяющей равномерно распределить элементы управления в форме по горизонтали или вертикали. Однако
приблизительно то же самое можно сделать достаточно просто с помощью
такой последовательности действий {все упомянутые здесь команды находятся в меню Format).
1. Разместите элементы управления с помощью мыши примерно так, как вам
нужно.
2. Выделите эти элементы управления и активизируйте команду AlignoTops
(ВыровнятьПо верху) или любую другую команду выравнивания по горизонтали.
3. Оставив все элементы управления выделенными, активизируйте команду
Horizontal Spaclng^Make Equal (Расстояние по гор изо италик Сделать одинаковым).
4. Сгруппируйте выделенные элементы управления (т.е. активизируйте команду
Group (Сгруппировать)).
5. Активизируйте команду Center in Form Horizontally (Центрировать в форме по
горизонтали).
В вышеприведенной инструкции предполагалось равномерно распределить элементы
управления по горизонтали. Чтобы распределить их равномерно по вертикали, выберите
в пп. 2, 3 и 5 версии команд, соответствующие действиям по вертикали.

Зополншйельно о ftaSopfie с элементами
управления
В главе 10 вы познакомились с наиболее важными элементами управления и их использованием. В настоящем разделе я дам вам дополнительные советы о работе с отдельными типами элементами управления, а также расскажу об элементах управления, которым не нашлось места в главе 10.

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

396

Часть IV. Профессиональная работа с VBA

Использование текстовых полей в качестве надписей
Как и надписи, текстовые поля могут содержать сообщения, которые вы адресуете пользователям. Однако обычно пользователь может изменять текст, отображаемый в текстовом
поле. Если вы не хотите, чтобы пользователь изменял текст ваших сообщений, обязательно
присвойте свойству Locked текстового поля значение T r u e . Только имейте в виду, что
пользователи все равно могут скопировать текст в буфер обмена, чего они не в состоянии
сделать с текстом надписей. Вы можете предотвратить это, присвоив свойству E n a b l e d
значение F a l s e , однако в этом случае текст будет отображаться затененным.
Вы можете даже придать текстовому полю вид стандартной надписи, придав его свойству
BackCo^or значение, соответствующее цвету форму, а свойству S p e c i a l E f f e c t — значение 0, чтобы сделать его "плоским".

Что такое секретный пароль?
Пароли используются для защиты важных данных от неавторизированного копирования, а
также для того, чтобы создать у людей впечатление, что они действительно получат какие-то чрезвычайно важные сведения, если уж им предлагают ввести пароль. Какая бы из этих причин вам ни
понравилась, создать текстовое поле VBA, предназначенное для ввода пароля, совсем несложно.
При выбранном текстовом поле в редакторе Visual Basic найдите свойство P a s s w o r d C h a r в диалоговом окне свойств, после чего введите подстановочный символ, который будет
отображаться в текстовом поле (например, !) вместо символов, действительно вводимых
пользователем. Текстовое поле все равно позволяет считывать введенные данные, но делать
это может только программа (рис. 19.6).

Рис. 19.6. В этом текстовом поле
вместо вводимых символов отображаются только восклицательные знаки
Конечно же, само по себе требование пароля не позволит защитить ваши данные. Сами
данные и список паролей доступа должны быть зашифрованы, а ваша программа должна
расшифровать данные в том случае, если пользователь ввел правильный пароль.

Использование многострочных текстовых полей
Для того чтобы данные в текстовом поле отображались корректно, текст понадобится
разбить на несколько строк, поэтому вы должны присвоить свойству M u l t i L i n e значение
True. В противном случае, даже если значение свойства WrapText равно T r u e , весь текст
будет размещен в одной строке, выходя за границы текстового поля.
Текст, который VBA для вашего удобства разделяет на несколько строк, на самом деле
сохраняется в виде одной строки. Однако многострочные текстовые поля также позволяют
пользователю начать "настоящую" новую строку с помошью, либо комбинации клавиш
, либо присвоения свойству E n t e r K e y B e h a v i o r значения T r u e и нажатия
клавиши . Это позволит вам создать разрыв строки раньше, чем это автоматически
сделает за вас VBA.

Глава 19. Еще о VBA-формах

397

Если вы программист (а не пользователь программы), разместите текст в текстовом поле,
после чего вы решайте, где ставить точки разрыва строк, Используйте любой из следующих
двух методов.
I S Если вы проектируете форму, щелкните на элементе управления два раза (но не дважI
ды!), чтобы отобразить точку вставки. После этого воспользуйтесь комбинацией клаI
виш для начала новой строки.
В программном коде присвоите текст свойству V a l u e элемента управления, используя строковые значения, объединенные с помощью символа возврата каретки.
На рис. 19.7 приведено несколько примеров использования свойств Wordwrap и MultiLirte.

I can t sec y

H
Q
i iuS5JtiK
• j'Timetoeet 1

FBft

~

I

*i"

4 Ъ*
*•«-t
• -я

L ^
ft

-%c. /£