Автор: Кузьменко В.Г.
Теги: языки программирования компьютерные технологии программирование
ISBN: 5-9518-0039-0
Год: 2003
Текст
ПРОГРАММИРОВАНИЕ НА VBA 2002 В.Г. Кузьменко ПРОГРАММИРОВАНИЕ НА VBA 2002 Москва ЗАО «Издательство БИНОМ» 2003 УДК 004.43 ББК 32.973.26-018.1 К89 Кузьменко В.Г. Программирование на VBA 2002. — М.: ООО «Бином-Пресс», 2003 г. — 880 с.: ил. В книге содержится курс по программированию на Visual Basic for Applications (VBA), являющимся базовым языком в приложениях Microsoft Office (Word, Excel, Access, PowerPoint, FrontPage, Visio и др.). Книга предназначена для начинающих программировать в среде Windows с применением Word-, Excel-, PowerPoint-объектов. Часть книги посвящена вопросам разработки Office-приложений, использующих базы данных, хранимых как в отдельных файлах, так и на удаленных серверах. Материала книги достаточно для изучения основ языка Visual Basic и создания простых макросов, помогающих автоматизировать рутинную повторяющуюся работу с документами, электронными таблицами, диаграммами, презентациями и т.д., а также для разработки довольно сложных приложений обработки баз данных с использованием диалоговых окон, обеспечивающих пользователя самыми современными интерфейсными средствами. Большинство примеров в книге посвящены актуальным в настоящее время вопросам коммерческой деятельности, поэтому книга будет очень полезной менеджерам различных уровней, которым, по-видимому, и предназначен как Microsoft Office, так и встроенный язык программирования VBA. Приложения в конце книги могут послужить удобным справочником при работе как с VBA, так и с обычным VB. ISBN 5-9518-0039-0 © Кузьменко В.Г., 2003 © Издательство БИНОМ, 2003 Содержание Введение.................*...............................................21 Часть I. Язык программирования Visual Basic..............................23 Глава 1. Макросы и языки программирования................................24 Макрос и макрорекордер.................................................24 Из истории VBA........................................................25 Зачем изучать язык программирования VBA...............................27 Создание макросов.....................................................28 Создание макроса в Word..............................................28 Создание макроса в PowerPoint........................................30 Запись новых макросов.................................................32 Задание стартовых условий для макроса................................33 Запуск макрорекордера и присваивание имени макросу...................33 Запись макроса в Word 2002.......................................... 35 Задание стартовых условий..........................................35 Присваивание имени макросу и выбор места для его сохранения........36 Использование панели инструментов и клавиатуры для запуска макроса .... 36 Запись ваших действий..............................................37 Остановка макрорекордера...........................................38 Запись макроса в Excel 2002......................................... 38 Задание стартовых условий..........................................39 Назначение имени и выбор места для сохранения макроса..............39 Запись действий....................................................40 Остановка макрорекордера...........................................42 Код макроса...........................................................42 Выполнение макросов...................................................45 Примеры записи более полезных макросов................................46 Оформление замечаний.................................................47 Подписи к рисункам...................................................47 Подчеркивание листинга...............................................49 Макрос-шутка..........................................................49 Глава 2. Среда Редактора Visual Basic....................................52 Модули................................................................52 Модули в Word 2002 ................................................. 52 Модули в Excel 2002 ................................................ 52 Модули в PowerPoint 2002............................................ 53 Редактор Visual Basic.................................................53 Запуск Редактора VB................................................ 53 Окна Редактора VB....................................................54 Меню Редактора VB....................................................56 Меню Файл (File)...................................................56 Меню Edit (правка).................................................57 - Меню View (Вид)...................................................58 Меню Insert (Вставка)..............................................59 Меню Format (Формат)...............................................60 Меню Debug (Отладка)...............................................61 Меню Run (Запуск)..................................................62 Меню Tools (Сервис)................................................63 Меню Add-Ins.......................................................63 Другие меню........................................................63 6 Программирование на VBA 2002 Знакомство с панелями инструментов Редактора VB........................64 Панель инструментов Standard.........................................65 Панель инструментов Edit (правка)....................................66 Глава 3. Редактирование простых макросов.................................68 Редактирование макросов.................................................68 Отображение модуля.....................................................68 Как найти записанный макрос............................................69 Использование инструмента Object Browser...............................69 Просмотр модулей проекта с помощью Object Browser....................70 Составные части записанного макроса..................................72 z Редактирование текста макроса...........................................74 Символ продолжения строки VBA.......................................76 Перемещение или копирование макроса из одного модуля в другой.......77 Сохранение и перенос модулей как текстовых файлов......................78 Экспортирование модулей..............................................78 Импортирование модулей...............................................79 Удаление модулей из проекта............................................80 Написание новых макросов и процедур....................................81 Вставка и переименование модуля.......................................81 Выделение существующего модуля........................................82 Написание текста процедуры.............................................82 Свойство Auto-Indent (автоотступ)...................................84 Запуск процедуры во время редактирования...............................85 Отображение сообщений для пользователя процедуры......................85 Сообщения об ошибках во время написания, редактирования или выполнения процедуры................................86 Ошибки синтаксиса......................................................87 Ошибки времени исполнения.............................................88 Печать исходного кода.................................................90 Глава 4. Типы данных, переменные и константы.............................91 Обзор типов данных Visual Basic.........................................91 Экспоненциальное представление........................................93 Тип Date...............................................................93 Числа.................................................................94 Типы данных Byte, Integer и Long.....................................94 Числа с плавающей точкой............................................95 Тип данных Currency..................................................96 Текстовые строки......................................................96 Логические значения..................................................96 Тип данных Variant....................................................97 Переменные..............................................................97 Что такое переменная?.................................................97 Выбор имен для переменных.............................................98 Идентификаторы......................................................98 Создание переменных....................................................99 Задание типа данных переменной.......................................101 Использование Dim для объявления типизированных переменных.........102 Использование символов определения типа для объявления типизированных переменных..........................................103 Использование Dim для объявления строковых переменных фиксированной длины................................................104 Область действия: доступность переменных.............................104 Область действия процедурного уровня...............................104 Область действия модульного уровня.................................105 Использование переменных с одним и тем же именем в различных уровнях области действия...............................106 Содержание 7 Персистенция: Определение того, как долго переменные удерживают свое значение...........................................107 Требование явного объявления переменных............................108 Константы ........................1.................................110 Создание именованных констант......................................110 Область действия констант..........................................111 Написание литеральных констант.....................................112 Константы String. 112 Численные константы..............................................112 Константы Date...................................................113 Константы Boolean................................................113 Задание типа константы.............................................113 Внутренние константы...............................................114 Поиск имеющихся внутренних констант с помощью Object Browser.....115 Получение данных от пользователя....................................116 Глава 5. Выражения в Visual Basic.................................118 Совместимость типов данных..........................................119 Автоматическое преобразование данных Visual Basic..................120 Преобразования численных типов.....................................121 Преобразования строк и чисел.......................................121 Преобразования значений типа Boolean...............................122 Преобразования значений типа Date..................................122 Оператор присваивания (=)...........................................122 Арифметические операции.............................................124 Сложение (+).......................................................124 Вычитание (-)......................................................126 Умножение (*)......................................................128 Деление (/)........................................................128 Целочисленное деление (\)..........................................129 Деление по модулю (Mod)............................................129 Возведение в степень (~)...........................................129 Операции сравнения.................................................130 Сравнение строк....................................................131 Двоичное и текстовое сравнение строк.............................132 Выбор метода сравнения строк.....................................132 Сравнение строки с шаблоном........................................132 Сравнение объектов.................................................135 Логические операторы................................................135 Таблицы истинности...............................................136 And..............................................................136 Or...............................................................137 Not..............................................................137 Xor..............................................................138 Eqv..............................................................138 Imp..............................................................139 Конкатенация строк.................................................139 Использование конкатенации строк.................................140 Операторы конкатенации строк.....................................141 Приоритеты выполнения операций при вычислении сложных выражений . . 142 Глава 6. Использование функций Visual Basic...........................144 Функции.............................................................144 Использование функций в выражениях.................................144 Аргументы и возвращаемое значение функции..........................145 Игнорирование результата функции...................................146 Использование именованных аргументов функции........................147 Использование других функций VBA....................................152 8 Программирование на VBA 2002 Математические функции.............................................152 Функции преобразования данных......................................153 Функции даты и времени.............................................154 Строковые функции..................................................156 Использование функций для манипулирования строками.................158 Удаление ненужных символов.........................................158 Определение длины строки...........................................160 Сравнение и поиск строк............................................160 Использование функции StrComp....................................160 Использование функции InStr......................................161 Разбиение строки на меньшие части..................................162 Функция Left.....................................................162 Функция Right....................................................163 Функция Mid......................................................163 Использование символов, которые нельзя ввести с клавиатуры.........164 Форматирование значений данных.....................................166 Использование функций host-приложений..............................174 Глава 7. Создание и использование функций и функций-процедур . . 177 Функции-процедуры и определенные пользователем функции..............177 Создание функций-процедур...........................................178 Написание функции-процедуры........................................178 Создание определенных пользователем функций для Excel..............180 Объявление типов данных для аргументов функции.....................181 Использование функций-процедур в VBA................................182 Использование инструмента Object Browser для нахождения функций-процедур....................................183 Ввод описания функции-процедуры с помощью инструмента Object Browser . . 184 Использование функций пользователя в рабочих листах Excel...........185 Создание функций для Excel.........................................186 Глава 8. Изменение порядка выполнения операторов в VBA . . . 190 Простой выбор......................................................191 Использование необязательных аргументов............................194 Выбор ветви с помощью If...Then...Else.............................195 Сложный выбор......................................................197 Вложенные операторы If...Then....................................197 Использование If...Then...ElseIf...................................199 Оператор Select...Case...........................................201 Безусловный переход................................................204 Использование MsgBox для обеспечения возможности выбора.............205 Глава 9. Дополнительные свойства процедур и функций...................209 Раннее окончание процедур, функций и целых программ.................209 Использование оператора Exit.......................................209 Использование оператора End........................................212 Дополнительные свойства необязательных аргументов...................214 Управление передачей аргументов.....................................215 Передача аргументов по ссылке и по значению........................215 Определение способа передачи аргумента.............................216 Рекурсия............................................................217 Примеры рекурсивных функций........................................218 Как избежать случайной рекурсии и других проблем...................220 Глава 10. Объекты и коллекции, введение...............................221 Объекты.............................................................221 Свойства объекта...................................................222 Методы объекта.................................................... 222 Содержание 9 Классы объекта....................................................223 Использование объектов............................................223 Использование свойств объектов..................................225 Использование методов объекта...................................231 Объявление объектных переменных...................................236 Объект в выражениях...............................................237 Ссылка на объекты с помощью With...End With.......................240 Работа с коллекциями объектов и контейнерами объектов.............241 Добавление к коллекциям...........................................246 Ссылка на конкретные объекты в коллекции или контейнере...........247 Фигуры в слое векторной графики....................................248 Добавление к коллекции Shapes ♦ автофигур»........................248 Добавление к коллекции Shapes специальных фигур...................251 Использование Object Browser с объектами, методами и свойствами. . . . 258 Глава 11. Повторение действий в Visual Basic: циклы..................260 Команды организации циклов.........................................260 Повторение цикла фиксированное число раз: циклы For...............261 Использование цикла For...Next..................................261 Использование For...Next с возрастающим счетчиком...............262 Использование For...Next с убывающим счетчиком..................264 Цикл For Each...Next............................................267 Циклы Do..........................................................270 Как прервать выполнение макроса или процедуры.....................272 Использование циклов, тестирующих условия до выполнения тела цикла. . . 273 Циклы Do While..................................................273 Циклы Do Until................................................ 275 Использование циклов, тестирующих условия после выполнения тела цикла. . 277 Циклы Do...Loop While...........................................277 Циклы Do...Loop Until...........................................278 Вложенные циклы....................................................279 Вложение циклов For...............................................280 Вложенные циклы Do..............................................281 Глава 12. Массивы....................................................284 Размерность массива................................................284 Одномерные массивы................................................284 Многомерные массивы...............................................285 Статические и динамические массивы................................285 Оператор Option Base................................................286 Объявление массивов.................................................287 Использование массивов..............................................288 Использование ReDim с динамическими массивами......................291 Функции LBound и UBound............................................295 Использование Erase для очистки или удаления массивов..............296 Использование массивов в качестве аргументов процедур и функций . . . 298 Часть II. Разработка приложений......................................301 Глава 13 Управление файлами с помощью VBA............................302 Управление файлами.................................................302 Что такое управление файлами......................................302 Возможности VBA по управлению файлами.............................302 Атрибуты файла......................................................303 Получение атрибутов файла.........................................305 Изменение атрибутов файла.........................................307 Как находить файлы..................................................309 Использование функции Dir для нахождения файлов....................309 10 Программирование на VBA 2002 Использование встроенных диалоговых окон Excel > для получения имен файлов............................................313 Использование метода GetOpenFilename................................313 Использование метода GetSaveAsFilename..............................317 Использование встроенных диалоговых окон Word для получения имен файлов............................................319 Использование Word-диалогового окна Открытие документа..............320 Использование Word-диалогового окна Сохранение документа............321 Работа с дисками и папками...........................................323 Получение пути текущей папки и буквенной метки диска................323 Изменение текущей папки.............................................324 Изменение текущего диска..........................................325 Создание дисковых папок.............................................326 Удаление дисковых папок...........................................327 Копирование и удаление файлов........................................327 Копирование файлов..................................................327 Удаление файла......................................................329 Переименование или перемещение файлов................................330 Получение информации о файлах........................................331 Получение времени и даты создания/модификации файла.................331 Получение длины файла...............................................332 Глава 14. Элементы диалоговых окон.....................................334 Формы пользователя...................................................334 Свойства объекта UserForm...........................................335 Методы объекта UserForm.............................................336 События и событийные процедуры......................................338 Синтаксис Load/Unload.............................................339 Примеры программ модуля класса формы................................339 Элементы управления..................................................343 Использование Toolbox (панели элементов).............................350 Добавление к форме элементов управления.............................350 Редактирование элементов управления на форме........................358 Выбор элементов управления..........................................359 Перемещение элементов управления....................................359 Изменение размеров элементов управления.............................359 Копирование, вставка и удаление элементов управления................359 Редактирование или форматирование заголовков элементов управления . . . 360 Управление последовательностью перехода............................ 360 Задание свойств формы и элементов управления в режиме разработки. ... 361 Пример разработки приложения с диалоговой формой.....................363 Интерфейс...........................................................363 Что должен уметь пользователь?....................................363 Что поместить в диалоговое окно?..................................364 Данные для макроса................................................364 Разработка приложения...............................................364 t Разработка диалогового окна..........................................364 Глава 15. Отладка VB-кода. Поиск и устранение ошибок...................372 Типы ошибок.........................................................372 Средства отладки....................................................374 Режимы отладки......................................................376 Режим останова......................................................376 Переход в режим останова из окна сообщения об ошибке..............376 Точки останова......................................................377 Использование оператора Stop......................................378 Переход в режим останова с помощью команды Step Into..............379 Переход в режим останова прерыванием исполнения кода..............379 Содержание 11 Выход из режима останова...........................................379 Использование команды Step Into.......................................380 Наблюдение за значениями выражений....................................380 Редактирование наблюдаемого выражения...............................383 Удаление наблюдаемого выражения....................................383 Использование команды Step Over.......................................384 Использование окна Locals............................................. 384 ' Трассировка вызовов процедур..........................................384 Использование окна Immediate..........................................386 Оператор Debug.Print..................................................387 Оператор Debug. Assert................................................387 Обработчик ошибок.....................................................387 Выход из блока обработки прерывания по ошибке......................389 Программная обработка ошибок при помощи оператора On Error............392 Часть Ш. Управление другими приложениями................................395 Глава 16. Управление host-приложениями VBA..............................396 Работа с Excel.........................................................396 Возвращение объекта книга.............................................396 Как открыть книгу.....................................................397 Как создать новую книгу........................................... . 398 Как сделать книгу активной............................................399 Как сохранить книгу...................................................400 Как закрыть книгу.....................................................404 Работа с объектами Worksheet..........................................406 Возвращение значения объекта Worksheet.............................406 Как сделать лист активным..........................................408 Как создать новый лист.............................................408 Как переименовать лист.............................................409 Копирование и перемещение листа....................................409 Как удалить лист...................................................410 Методы, возвращающие объекты Range....................................411 Использование Range метода.........................................411 Использование метода Cells............................................412 Использование метода Offset........................................415 Другие методы и свойства, возвращающие диапазоны ячеек.............416 Работа с Cells и Ranges...............................................417 Выделение ячейки или диапазона ячеек...............................417 Свойства Value и Formula...........................................418 Определение имени диапазона ячеек..................................419 Как вырезать, скопировать и очистить данные........................420 Работа с объектами Word...............................................422 Работа с объектами Document...........................................422 Доступ к объекту Document..........................................422 Как открыть документ...............................................423 Как создать новый документ.........................................424 Как сделать документ активным......................................425 Как сохранить документ.............................................426 Как закрыть документ...............................................428 Работа с объектами Template...........................................429 Как создать шаблон.................................................429 Как загружать и выгружать общие шаблоны............................429 Как присоединить шаблон............................................431 Компоненты объекта Document...........................................431 Как задать диапазон..................................................432 Как получить ссылку на объект......................................433 Как выполнить ссылку на диапазон...................................434 Работа с объектом Selection...........................................436 Как переместить или «свернуть» объекты Selection и Range..............437 12 Программирование на VBA 2002 Добавление текста..................................................439 Как вырезать, скопировать, вставить и удалить текст................441 Глава 17. Работа с другими приложениями: Automation...................444 Что такое OLE?......................................................444 Краткая история OLE................................................444 Работа Visual Basic for Applications с технологией OLE ............446 Поиск типа класса объекта..........................................447 Использование реестра Windows......................................447 Поиск объектного класса в реестре................................448 Использование программы System Information.......................450 Добавление связанных и внедренных объектов.........................451 Объекты Shape и OLEFormat..........................................452 Использование метода AddOLEObject коллекции Shapes.................462 Примеры использования метода AddOLEObject коллекции Shapes.........455 Вставка нового внедряемого объекта...............................455 Вставка существующего файла как внедренного объекта................456 Вставка существующего файла как связанного объекта.................457 Коллекция Excel OLEObjects.........................................458 Коллекция InLineShapes в Word......................................460 Работа со связанными и внедренными объектами........................461 Доступ к OLE-объектам..............................................461 Использование свойств OLE-объектов.................................462 Методы OLE-объектов................................................465 Метод Update.......................................................465 Методы Verb и DoVerb...............................................468 Технология Automation...............................................472 Доступ к объектам Automation.......................................472 Создание нового Automation-объекта..................................475 Функция CreateObject...............................................475 Использование ссылок на библиотеки объектов........................478 Доступ к существующим объектам Automation..........................479 Глава 18. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш»..................................482 Запуск приложения-сервера...........................................483 Инициализация и завершение связи с DDE-сервером.....................484 Инициализация и завершение связи с DDE-сервером.................. 485 Управление приложением-сервером....................................487 Обмен данными с приложением-сервером DDE............................489 Получение данных от DDE-сервера....................................489 Передача данных DDE-серверу........................................493 Передача «нажатий клавиш» другому приложению........................494 Доступ к DLL из Visual Basic for Applications.......................496 Объявление DLL-процедур............................................497 Примеры DLL........................................................498 Глава 19. Использование обработчиков событий..........................503 События и обработчики событий.......................................503 Где хранится обработчик события....................................504 Имена и объявление обработчиков событий......................... . 505 Аргументы обработчика события......................................506 Работа с событиями объекта Application..............................506 Работа с событиями объектов Excel...................................508 Событие Open.......................................................510 Событие BeforeClose................................................512 Событие Activate...................................................513 Содержание 13 Событие Deactivate..................................................513 Событие BeforeDoubleClick...........................................514 События Change и SelectionChange....................................515 Событие Calculate...................................................518 Другие события......................................................519 Печать............................................................519 Сохранение рабочих книг...........................................519 Создание новых объектов...........................................520 Изменение выделенного фрагмента...................................520 Работа со свойствами и методами Excel, связанными с событиями .... 520 Свойство OnWindow Excel.............................................521 Метод OnKey Excel...................................................522 Метод OnTime Excel...................................................525 Работа с событиями объектов Word.....................................526 Событие Open........................................................527 Событие Close.......................................................528 Событие New.........................................................529 Событие Documentchange..............................................529 Событие Quit........................................................530 Работа с коллекциями и методами, связанными с событиями Word .... 532 Коллекция KeyBindings................................................532 Метод OnTime Word....................................................534 Часть IV. Доступ к базам данных из приложений Microsoft Office. . 537 Глава 20. Введение в базы данных..................................... 538 Что такое «базы данных»?..............................................538 Типы баз данных......................................................539 Функции систем управления базами данных..............................540 Модель данных........................................................541 Реляционная модель данных............................................541 Операции над отношениями..........................................542 Объединение.......................................................542 Пересечение..........................................................543 Вычитание.........................................................543 Декартово произведение............................................544 Деление...........................................................544 Проекция..........................................................545 Соединение........................................................546 Выбор.............................................................546 Связи между отношениями...........................................548 Ограничения реляционной модели....................................550 Нормализация отношений............................................550 Базы данных в Excel..................................................552 Импорт данных в Excel из баз данных..................................554 Создание базы данных в Access........................................561 Бизнес-задача: разработка базы данных для учета движения товаров на складе . . 562 Создание таблицы в Access..........................................565 Другие способы создания базы данных..................................569 Занесение данных в таблицы баз данных...............................570 Глава 21. Основы языка SQL.............................................572 Типы команд SQL......................................................573 SQL в Visual Basic...................................................574 Инструкция SELECT....................................................574 Выбор в SQL-запросе определенных полей.............................578 Выбор в SQL-запросе определенных записей...........................579 Использование в SQL-запросе функций для вывода определенных записей . . . 580 Форматирование выводимых в запросе данных..........................582 14 Программирование на VBA 2002 Выбор данных из более чем одной таблицы...........................583 Вывод выбранных данных в определенном порядке.....................584 Агрегирующие функции в инструкции SELECT..........................585 Группировка данных в инструкции SELECT............................587 Подзапросы в инструкции SELECT....................................588 Глава 22. Доступ к базам данных из VBA-кода............................593 Microsoft DAO.........................................*..............593 Рабочие пространства DAO............................................594 Использование DAO-модели для Microsoft Jet..........................597 Объект Database...................................................597 Объект Recordset..................................................599 Пример работы подключения VBA-кода к базе данных..................602 Пример создания базы данных из кода VBA...........................608 Доступ к источникам данных ODBC......................................610 Использование DAO-модели для ODBCDirect.............................612 Microsoft ADO........................................................615 Объект Connection.................................................617 Объект Recordset..................................................621 Коллекция Field как свойство объекта Recordset....................623 Глава 23. Работа с SQL Server..........................................634 Установить SQL Server на компьютер очень просто......................636 Базы данных в SQL Server.............................................637 Основные этапы работы с SQL Server...................................639 Создание базы данных при помощи Server Enterprise Manager...........639 Создание базы данных посредством кода...............................647 Представления и хранимые процедуры..................................651 Приложения.............................................................657 Приложение А. Справочные таблицы книги.................................658 Приложение Б. Приоритеты операций в Visual Basic.......................701 Приложение В. Операторы в VBA..........................................702 AppActivate..........................................................702 Веер.................................................................702 Call.................................................................703 ChDir................................................................704 ChDrive..............................................................704 Close................................................................704 Const................................................................705 Date.................................................................705 Declare..............................................................706 Deftype..............................................................708 DeleteSetting........................................................709 Dim..................................................................709 Do...Loop............................................................710 End..................................................................711 Enum.................................................................712 Erase................................................................713 Error................................................................714 Event................................................................714 Exit.................................................................715 FileCopy.............................................................716 For Each...Next......................................................717 Содержание 15 For...Next............................................................717 Function..............................................................718 Get...................................................................721 GoSub...Return........................................................723 GoTo..................................................................724 If...Then...Else......................................................724 Implements..............*.............................................725 Input #...............................................................725 Kill..................................................................726 Let...................................................................726 Line Input #..........................................................727 Load..................................................................728 Lock, Unlock..........................................................728 LSet..................................................................729 Mid...................................................................730 MkDir.................................................................730 Name..................................................................730 On Error..............................................................731 On...GoSub, On...GoTo.................................................733 Open..................................................................734 Option Base...........................................................735 Option Compare........................................................735 Option Explicit.......................................................736 Option Private........................................................736 Print #...............................................................736 Private...............................................................737 Property Get..........................................................738 Property Let..........................................................741 Property Set..........................................................743 Public................................................................745 Put...................................................................746 RaiseEvent............................................................748 Randomize.............................................................749 ReDim.................................................................749 Rem...................................................................750 Reset.................................................................750 Resume................................................................750 RmDir.................................................................753 RSet..................................................................753 SaveSetting...........................................................753 Seek..................................................................754 Select Case...........................................................755 SendKeys..............................................................756 Set...................................................................758 SetAttr...............................................................759 Static................................................................759 Stop..................................................................760 Sub...................................................................760 Time..................................................................762 Type..................................................................762 Unload................................................................763 While... Wend.........................................................763 Width #...............................................................764 16 Программирование на VBA 2002 With.................................................................764 Write#.............................................................. 765 Приложение Г. Функции в VBA...........................................767 АЪз..................................................................767 Array................................................................767 Asc.................................................*...............767 Atn..................................................................768 CallByName...........................................................768 Функции преобразования типов.........................................769 Возвращаемые типы..................................................769 Choose...............................................................769 Chr..................................................................770 Cos..................................................................770 CreateObject.........................................................770 CurDir.............................................................. 771 CVErr................................................................771 Date.................................................................772 DateAdd..............................................................772 DateDiff.............................................................773 DatePart.............................................................774 DateSerial...........................................................774 DateValue............................................................775 Day..................................................................775 DDB..................................................................775 Dir..................................................................776 Environ..............................................................777 EOF..................................................................777 Error................................................................778 Exp..................................................................778 FileAttr.............................................................778 FileDateTime........................................................779 FileLen..............................................................779 Filter...............................................................779 Fix..................................................................780 Format...............................................................781 Formatcurrency.......................................................782 FormatDateTime.......................................................783 FormatNumber........................................................783 FormatPercent........................................................784 FreeFile.............................................................785 FV...................................................................785 GetAllSettings.......................................................786 GetAttr..............................................................786 GetObject............................................................787 GetSetting...........................................................788 Hex..................................................................788 Hour.................................................................789 Ш....................................................................789 Input................................................................790 InputBox.............................................................790 InStr................................................................791 InStrRev.............................................................792 Int..................................................................793 Содержание 17 IPmt...............................................................793 IRR................................................................794 IsArray............................................................795 IsDate.............................................................795 IsEmpty............................................................795 IsError.......................................................... 796 IsMissing..........................................................796 IsNull.............................................................796 IsNumeric..........................................................797 IsObject...........................................................797 Join...............................................................798 LBound.............................................................798 LCase..............................................................799 Left...............................................................799 Len................................................................799 Loc................................................................800 LOF................................................................800 Log................................................................801 LTrim..............................................................801 Mid................................................................801 Minute.............................................................802 MIRR...............................................................802 Month..............................................................802 MonthName..........................................................803 MsgBox.............................................................803 Now................................................................805 NPer...............................................................805 Функция NPV...................................................... 806 Oct................................................................806 Partition..........................................................807 Pmt................................................................807 PPmt...............................................................808 PV.................................................................809 QBColor............................................................810 Rate...............................................................811 Replace............................................................812 RGB................................................................813 Right..............................................................814 Rnd................................................................815 Round..............................................................816 Rtrim..............................................................816 Second.............................................................816 Seek...............................................................816 Sgn................................................................817 Shell..............................................................817 Sin................................................................818 SLN................................................................819 Space..............................................................819 Spc................................................................819 Split..............................................................820 Sqr................................................................821 Str................................................................821 StrComp............................................................821 18 Программирование на VBA 2002 StrConv............................................................822 Str Reverse........................................................823 String.............................................................823 Switch.............................................................824 SYD................................................................824 Tab.............................................................. 824 Tan................................................................825 Time...............................................................825 Timer..............................................................825 TimeSerial.........................................................825 TimeValue..........................................................826 Trim...............................................................826 TypeName...........................................................826 UBound.............................................................827 UCase..............................................................828 Vai................................................................828 VarType............................................................828 Weekday.......................................................... 829 WeekdayName........................................................830 Year...............................................................831 Приложение Д. Константы в VBA........................................832 Календарные (Calendar) константы...................................832 Константы типов вызова (CallType)..................................832 Константы цветовые (Color).........................................832 Константы типов сравнений (Comparison).............................833 Константы компиляции (Compiler)....................................833 Константы дат (Date)...............................................833 Константы формата дат (Date Format)................................834 Константы функций Dir, GetAttr и SetAttr...........................835 Константы типов драйверов (DriveType)..............................835 Константы атрибутов файлов (File Attribute)........................835 Константы файлового ввода/вывода (File Input/Output)...............836 Константы форм (Form)...............................................836 Константы Dir, GetAttr и SetAttr....................................836 Константы ключевых кодов (Keycode)..................................837 Смешанные константы (Miscellaneous Constants)......................839 Константы функции MsgBox...........................................840 Аргументы-константы функции MsgBox.................................840 Возвращаемые значения функции MsgBox..............................841 QueryClose-константы...............................................841 Константы Shell....................................................841 Константы специальных папок (SpecialFolder)........................841 Константы преобразования строк (StrConv)...........................842 Константы системных цветов (System Color)..........................842 Tristate-константы.................................................843 VarType-константы........................................... . . . 844 Приложение Е. События объектов User Form.............................845 Activate...........................................................845 Initialize.........................................................845 QueryClose.........................................................846 Возвращаемые значения...........................................846 Resize.............................................................847 Содержание 19 Terminate............................................................847 События объектов управления.............................................848 AddControl...........................................................848 AfterUpdate...........................................................849 BeforeDragOver.......................................................849 BeforeDropOrPaste.....................................................851 BeforeUpdate........................................................ 852 Change...............................................................852 Click................................................................853 DblClick.............................................................853 Enter................................................................854 Error.................................................................855 Exit.................................................................856 KeyDow, KeyUp........................................................856 KeyPress.............................................................857 Layout...............................................................858 MouseDown, MouseUp...................................................858 MouseMove............................................................859 RemoveControl........................................................861 Scroll...............................................................861 SpinDown, SpinUp.....................................................863 Zoom.................................................................865 Предметный указатель.................................................... 867 Введение Без преувеличения можно сказать, Microsoft Office любых версий является самым полезным и самым используемым продуктом Microsoft. И современный руководитель, и менеджер, и преподаватель, и студент, и школьник — все, кто имеет в своем распоряжении компьютер, в той или иной степени используют эту систему. Часто встречаются такие пользователи, которые не умеют включить и выключить компьютер, но большую часть своей профессиональной деятельности работают с приложениями типа Word, Excel, Outlook и т.д. Это связано с большой универсальностью Microsoft Office, набор приложений предназначен для решения очень широкого круга задач: от создания простых документов и отчетов до полной автоматизации документооборота с использованием систем управления базами данных. При этом каждый пользователь имеет возможность, с одной стороны, расширить этот диапазон, с другой — настроить любое приложение Microsoft Office для оптимального выполнения своих специфических задач. Одним из наиболее важных и полезных аспектов подготовки Microsoft Office к выполнению определенных задач является автоматизация процессов взаимодействия пользователя с приложениями Microsoft Office. Эти приложения не являются законченными продуктами, настроенными на выполнение всех возможных задач, а представляют собой системы, которые нуждаются в определенной настройке, что обеспечивается разнообразными средствами, как интерактивными, так и программными. Все приложения Microsoft Office поддерживают язык программирования Visual Basic for Applications (VBA). VBA позволяет работать c Microsoft Office, как с некоторым конструктором: в распоряжении разработчика VBA-приложения не только большое количество объектов и коллекций, но и возможности настроек, позволяющие до такой степени программно настроить любое приложение, что пользователь такого приложения может и не понять, с каким приложением происходит «общение». Важнейшим достоинством VBA является возможность объединять любые приложения Microsoft Office для решения, практически, любых задач по обработке информации. В этом смысле Microsoft Office можно считать системой программирования, подобной C++, Delphi и т.д., но с более мощными и разнообразными функциями, поскольку здесь имеется неизмеримо большее количество управляемых системой объектов и готовых решений для конечных пользователей. Привлекательная особенность VBA в том, что он очень удобен для первого знакомства с программированием в среде Windows. Этому способствует широкое распространение приложений Microsoft Office, беконечное разнообразие возможных практических задач, интуитивно понятная интегрированная среда редактора Visual Basic, возможность обучения программированию посредством анализа кода, записанного при помощи макрорекордера, наличие огромного количества объектов, которыми можно управлять из VB-кода. Многие программные структуры VB-кода, работу с объектами, принципы программирования в Windows намного легче изучать в среде редактора Visual Basic какого-либо приложения Microsoft Office, чем в интегрированной среде любой другой системы программирования, например, C++ или Delphi. При этом очень быстро гарантируется результат: даже небольшие навыки по созданию макросов (основных единиц кода на языке VBA), помогающих автоматизировать рутинную повторяющуюся работу над документами, электронными таблицами, почтовыми сообщениями и т.д., коренным образом изменят процесс создания необходимых документов и отчетов, а более глубокие знания VBA-программирования позволят решать, практически, любые задачи: от автоматизации создания простых документов до обработки баз данных с использованием как настольных, так и сетевых СУБД. Возможности VBA совсем не уступают другим системам программирования в Windows и постоянно растут. К тому же многие системы программирования в Windows и VBA используют общие библиотеки объектов, среди которых — объекты Word, Excel и т.д. ЧАСТЬ I Язык программирования Visual Basic I Глава 1 Макросы и языки программирования Удивительно, но многие пользователи Word и Excel не знают самых простых дополнительных возможностей этих продуктов, которые реализуются посредством макросов. Конечно, и Word, и Excel предоставляют достаточно широкий набор функций для выполнения самых разнообразных офисных задач, но все же знание и использование макросов VBA дает такие преимущества, которые невозможно переоценить. Перед тем как вы начнете писать собственные макросы, вам следует хорошо понять, что такое макросы и чем отличается VBA-программируемый макрос от записанного макрорекордером. Макрос и макрорекордер Независимо от используемых вами операционной системы и программных приложений вы часто выполняете одни и те же последовательности команд для многих рутинных задач. Вместо повторения последовательности команд каждый раз, когда вам необходимо выполнить какую-либо задачу, вы можете создать мак рос (macro), который вместо вас будет выполнять эту последовательность. Макросы позволяют вводить одиночную команду, выполняющую ту же задачу, для реализации которой вам было бы необходимо вводить несколько команд вручную. Записанные макрорекордером последовательности команд первоначально назывались макрокомандами (macro commands).Сейчас этот термин сократился до более простого слова макрос. (Термин macro используется как префикс в нескольких словах в английском языке; он произошел от греческого слова, означающего расширенный или растянутый). Применительно к информатике и программным приложениям под словом макрос всегда подразумевается макрокоманда. Макросы, кроме удобства, имеют и другие преимущества. Поскольку компьютеры больше приспособлены для выполнения повторяющихся задач, чем люди, запись макрорекордером неоднократно выполняемых команд повышает точность и скорость работы. Другим преимуществом использования макросов является то, что при их выполнении обычно нет необходимости в присутствии человека-оператора. В случае, если макрос очень длинный или выполняет операции, требующие значительного времени (например, поиск в базе данных и сортировка), вы можете оставить работающий компьютер и делать что-нибудь другое, а также переключиться на другое приложение. Макрорекордер (или просто «рекордер») записывает все действия пользователя, включая ошибки и неправильные запуски. Когда программа воспроизводит макрос, она выполняет каждую записанную рекордером команду точно в такой последовательности, в которой вы их выполняли во время записи. Первые макрорекордеры имели серьезный недостаток. Если вы записывали длинную серию действий, содержащую маленькую ошибку, единственной возможностью удалить эту ошибку являлась повторная запись макроса. Кроме того, если вам было необходимо внести небольшое изменение в длинный макрос, то также приходилось перезаписывать весь макрос. Перезапись длинного макроса часто приводила к дополнительным ошибкам в новой записи. По этим причинам разработчики программного Макросы и языки программирования 25 обеспечения добавили макрорекордерам возможность редактирования макросов, чтобы вы могли легко исправлять небольшие ошибки или вносить другие изменения в макрос без его полной перезаписи. Из истории VBA Несмотря на то что Visual Basic for Applications (VBA) — это относительно новый продукт, предпосылки его появления имеют историю, почти столь же долгую, что и вся компьютерная индустрия. Язык VBA является современным диалектом языка программирования BASIC, который был создан в начале 60-х годов. (BASIC — это сокращение от Beginner’s All-Purpose Symbolic Instruction Code.) Хотя по сегодняшним стандартам первоначальный язык BASIC имел значительные ограничения, изучать и понимать его было легко, что способствовало его быстрому распространению. Версии языка BASIC создавались (и все еще создаются) для использования на всех типах компьютеров. Версия Microsoft GWBASIC (GW означает Graphics Workshop) была одним из первых языков программирования, доступных для компьютеров, которые эволюционировали в современные персональные компьютеры. GWBASIC поставлялся с версиями MS-DOS до Version 5.0. Ранние ПК, выпускаемые IBM, имели даже версию BASIC, встроенную в микросхемы ROM (Read Only Memory) компьютера. С годами первоначальная структура и спецификации BASIC были улучшены. По мере усовершенствования и изменения технологии для языков программирования различные создатели программного обеспечения добавляли некоторые возможности к первоначальному BASIC. Современные диалекты BASIC обычно имеют многие или все свойства, существующие в других более поздних языках программирования, таких как Pascal или С. В конце 80-х годов Microsoft опубликовала значительно улучшенную версию языка BASIC, названную QuickBASIC. QuickBASIC включал почти все возможности современных систем разработки программного обеспечения. Microsoft поставляет теперь версию QuickBASIC с DOS Version 6.0 и более поздними версиями (но не в Windows 95). После нескольких версий QuickBASIC в 1992 году Microsoft представила Visual Basic for Windows. Как и в случае с QuickBASIC, Visual Basic for Windows был дополнен современными возможностями и тесно интегрирован в среду Windows. Visual Basic предоставляет команды для создания и управления необходимыми элементами программы в Windows: диалоговыми окнами, линейками меню, раскрывающимися списками, командными кнопками, флажками, панелями инструментов и так далее. В частности, Visual Basic включает необходимые команды для использования Object Linking and Embedding (OLE) и Dynamic Data Exchange (DDE) для связи или совместного использования данных с другими приложениями Windows. Visual Basic является существенно новым языком программирования для Windows со своими корнями в BASIC. В то время как BASIC развивался и улучшался, изменялись макрорекордеры, используемые в программных приложениях. С годами макросы приложений постепенно становились все сложнее в ответ на пожелания пользователей сделать макросы более гибкими в действии и более легкими для сопровождения. Многие макроязыки начали включать возможности, подобные тем, которые обычно имеются только в законченных языках программирования. Макроязыки многих приложений значительно изменяются от продукта к продукту. Это означает, что вам может понадобиться изучить несколько различных макроязыков; в результате эффективность вашей работы может снизиться во время изучения нового макроязыка. Чтобы избежать необходимости изучения нового макроязыка для каждого продукта, Microsoft начала включать элементы языка 26 Глава 1 BASIC в макроязыки своих продуктов. Примером может служить макроязык для Word for Windows фирмы Microsoft (до Word 97), известный как WordBASIC, тогда как язык программирования для Access фирмы Microsoft был известен как Access Basic. Для унификации макроязыков в своих приложениях Windows и для интеграции приложений на этих макроязыках с DDE и OLE Microsoft создала специальную версию языка Visual Basic, названную Visual Basic for Applications (сокращенно VBA). Excel 5 был первым продуктом, включающим Visual Basic for Applications (VBA). С появлением Microsoft Office 97 и 2000/2002 VBA реализуется теперь в Microsoft Word 97 и 2000/2002, Access 97 и 2000/2002, Excel 97 и 2000/2002, Microsoft PowerPoint 2000/2002, Microsoft FrontPage 2000/2002 и Microsoft Vi-sio 2000. В основные приложения Office (Word, Excel, PowerPoint), начиная с версии 2000, включен редактор сценариев — Microsoft Visual Basic Script Editor, который позволяет редактировать Web-страницы (например, в Word) и придать им динамику. Язык VBScript (Visual Basic Scripting Edition) входит в семейство языков Visual Basic и, являясь упрощенной версией языка Visual Basic, позволяет программировать документы, отображаемые браузерами World Wide Web. Visual Basic for Applications в основном является тем же, что и Visual Basic for Windows, с некоторыми небольшими различиями. Макропрограммы VBA сохраняются в файловом формате, используемом приложением, в котором вы написали макрос Visual Basic for Applications, а не в отдельных текстовых файлах1. Например, макропрограммы VBA, созданные в Excel 2002, сохраняются в файле рабочей книги Excel, программы VBA в Word 2002 сохраняются в файле документа, а программы VBA в Access 2002 — в файле данных Access. Для выполнения макропрограммы VBA вы должны сначала запустить ее, используя приложение, в котором написали этот макрос. Например, вы не можете запустить макрос Excel VBA из любой другой программы, кроме Excel. Несмотря на то, что основные возможности VBA остаются теми же в приложениях, каждое приложение добавляет специальные команды и объекты (в зависимости от конкретного приложения) в Visual Basic for Applications. Например, VBA в Excel 2002 содержит много команд, которые относятся только к рабочим листам и задачам, которые вы можете выполнить с рабочим листом. Аналогично, VBA в Word 2002 содержит команды, относящиеся только к операциям над текстом в документе, тогда как VBA в Access 2002 содержит команды, относящиеся только к операциям с базой данных, и так далее. Если до появления MS Office 97 средства программирования в офисных пакетах предназначались в основном для создания макрокоманд, расширяющих возможности конкретных приложений, то с выходом MS Office 97 специалисты получили универсальную систему программирования для прикладных программ на базе Visual Basic. Впервые MS Office был представлен как единая платформа для создания бизнес-приложений, предназначенных решать специализированные задачи пользователей. Это новое качество MS Office обуславливалось специальным выпуском для разработчиков — Developer Edition. По сведениям Microsoft, в настоящее время MS Office в качестве платформы создания бизнес-приложений используют более двух миллионов профессиональных разработчиков. Кроме выпуска Developer Edition, MS Office выпускается как Standard, Small Business, Professional и Premium. Эти выпуски отличаются только составом приложений, хотя от дельные приложения одинаковы во всех выпусках. Поскольку книга предназначена в основном тем, кто только начинает про граммировать в среде Windows, здесь подробно рассмотрено VBA-программирова ние только для двух наиболее используемых приложений — Word и Excel. Основ 1 Пакет MS Office Developer (MOD), предназначенный для разработчиков профессиональны: приложений, позволяет создавать автономные VBA-проекты, которые хранят исходный ко, файлов в виде двоичных файлов отдельно от таких приложений как Word, Excel и т.д. Макросы и языки программирования 27 ной целью, которую преследует автор книги, является изучение основ языка VBA, который, как утверждает Microsoft, начиная с версии MS Office 2000, не отличается от обычного VB. VBA-программирование (разработка макросов) рассматривается для самого распространенного (по крайней мере, в России) пакета MS Office ХР Professional, в состав которого входят такие приложения, как Microsoft Access for Windows, Microsoft Excel for Windows, Microsoft FrontPage for Windows, Microsoft Outlook for Windows, Microsoft PowerPoint for Windows, Word for Windows. Зачем изучать язык программирования VBA Поскольку вы можете использовать макрорекордер в Word или Excel для записи ваших действий в макрос (а в Access для этой цели использовать своего рода конструктор) и затем воспроизводить их, сначала может показаться, что изучать VBA необязательно. Однако одни записанные макросы не могут удовлетворить все ваши потребности. Записанный макрорекордером макрос может только воспроизводить без отклонений каждое действие в той же последовательности, в которой вы первоначально выполняли эти действия. VBA можно использовать для улучшения макросов, записанных макрорекордером, значительно повышая их мощь и возможности. Записанные макрорекордером макросы лишены гибкости, поэтому они не могут реагировать на изменившиеся или меняющиеся условия. На языке VBA вы можете написать макрос, который проверяет соответствие различным предопределенным условиям и выбирает соответствующую последовательность действий на основе этих условий. Если вы, например, выполняете какой-либо Excel-макрос, который пытается выбрать рабочий лист с именем "Продажи", в то время, когда в книге нет такого рабочего листа, записанный вами макрос будет выполняться неправильно и Excel выведет на экран сообщение об ошибке. Добавив VBA-команды к этому записанному макросу, вы могли бы с его помощью выполнить проверку наличия этого определенного рабочего листа перед его выбором или даже вставить новый рабочий лист и дать ему соответствующее имя, если нужный рабочий лист не существует. Что касается повторяющихся действий в самом макросе, записанные рекордером макросы имеют значительные ограничения. Если вам необходимо, чтобы записанный макрос повторял какое-либо действие несколько раз, вы должны вручную повторять это действие нужное количество раз, когда записываете макрос. Такой макрос всегда повторяет это действие одинаковое количество раз, всякий раз, когда вы его запускаете, до тех пор, пока вы не отредактируете или не перезапишете его. Напротив, макрос, написанный на языке VBA, может использовать предопределенные условия или вводимые пользователем данные для повторения действия различное количество раз или для принятия решения о необходимости выполнения этого действия. В качестве примера вы можете записать рекордером макрос для изменения ширины нескольких смежных столбцов в рабочем листе Excel. Если вам необходимо, чтобы макрос изменял ширину первых трех столбцов в рабочем листе, вы должны вручную повторить операцию изменения размера для каждого из трех столбцов при записи макроса. Записанный макрос будет только (и всегда) изменять ширину первых трех столбцов в рабочем листе. Вы не можете использовать тот же макрос для изменения ширины двух или четырех столбцов. Кроме того, если вы изменили ширину первых трех столбцов, записанный макрос будет выполнять действие только над тремя первыми столбцами. Вы не сможете использовать тот же макрос для изменения ширины столбцов со второго по четвертый. Добавив команды VBA к этому записанному рекордером макросу, вы можете создать макрос, который запрашивает, размер скольких и каких столбцов необходимо изменить, и даже позволяет задавать новую ширину столбцов. 28 Глава 1 Эти два примера представляют пару простейших задач, которые вы можете выполнить с командами VBA в макросах. Существует много обстоятельств, при которых вам может понадобиться добавлять команды принятия решений и эффективное повторение команд к макросам, записанным макрорекордером. Единственный способ получить такие возможности — это вручную добавить операторы VBA к записанному макросу. Конструктор макросов в Access также не «всесилен» и не позволяет создавать приложения со сложной обработкой данных. Рано или поздно наступает время, когда самый искушенный в Access пользователь приходит к тому, что ему не хватает только конструктора для решения новых задач по обработке баз данных. Кроме улучшения определенных макросов, записанных макрорекордером, вы можете использовать VBA для соединения, организации и управления несколькими записанными макросами, с помощью которых вы выполняете сложную общую задачу, состоящую из нескольких меньших задач. Например, вы можете регулярно импортировать данные из базы данных в рабочий лист Excel, форматировать эти данные для вывода на экран, генерировать диаграмму из этих данных и затем распечатывать эту диаграмму и отформатированный отчет. Для того чтобы объединить эти отдельные задачи для создания единственной задачи, выполняемой одним макросом, вы можете сначала написать отдельный макрос для каждой из отдельных задач: для импортирования данных, форматирования этих данных для последующего отображения, создания диаграммы и печати данных. Далее вы могли бы организовать записанные макросы так, чтобы они выполнялись в нужной последовательности одним макросом, который вы напишете посредством команд VBA. С помощью макросов можно создавать пользовательские меню, диалоговые окна и панели инструментов, которые могут до неузнаваемости изменить интерфейс всем известных продуктов Word и Excel. Уместно здесь отметить также и возможность создания разнообразной системы проверки данных, вводимых пользователем в диалоговых окнах. Когда вы научитесь писать программы на языке VBA, вы, скорее всего, уже никогда не станете начинать создание макроса с использования рекордера. Создание макросов Существует мнение, что изучение языка VBA легче всего начать с записи нового макроса при помощи рекордера. Поэтому большая часть литературы по VBA следует схеме, по которой читателю предлагается сначала посмотреть, как макросы создаются самими продуктами, такими как Word и Excel, а затем, осторожно внедряя свои инструкции в работающие макросы, изучить новый для них язык. Мне же представляется более продуктивным другой подход, при котором вы начнете писать макросы (с использованием Visual Basic Editor — Редактора), как обычные программы на новом для вас языке программирования и каждый свой шаг будете проверять контрольными запусками кода. В следующей главе будут очень подробно приведены все детали построения макросов, а сейчас создадим первый простой макрос, точнее — процедуру, в Word и в Access. Да, в Access, это — не опечатка. Access 2002 позволяет писать процедуры так, как это позволяет Word 97/2002 и Excel 97/2002. Далее мы не будем рассматривать макросы Access: в виду особого места этого приложения в Office 2002 вам следует обратиться к другим источникам, если вы хотите освоить VBA для Access. Создание макроса в Word Запустите Word, выберите Tools | Macro | Visual Basic Editor (Сервис | Макрос | Редактор Visual Basic) или нажмите комбинацию клавиш Alt+Fll. Ваш экран будет выглядеть подобно приведенному на рис. 1.1. Не вникая в маловажные для перво Макросы и языки программирования 29 го раза детали, поместите курсор в самое большое окно (Code) и введите следующий текст (без нумерации строк!): Листинг 1.1. Первый макрос в Word 1 Sub MyFirstMacro() 2 MsgBox ("Макрос в Word1") 3 End Sub Рис. 1.1 Ваш экран будет выглядеть подобно, хотя возможны некоторые несовпадения Первая и третья строки этого макроса-процедуры являются заголовком и окончанием процедуры, соответственно. Причем MyFirstMacro — это имя макроса, под которым он будет узнаваем системой. Вторая строка макроса содержит функцию вывода диалогового окна с текстом "Макрос в Word!". Если учесть, что в Windows по-другому вывести информацию из любой (!) программы довольно трудно и чаще всего не нужно, то можно считать, что вторая строка содержит обычный оператор вывода на экран. Не всегда при запуске Редактора Visual Basic вам сразу будет предоставлено окно Code, в котором можно сразу начать писать операторы на языке Visual Basic Чтобы вывести это окно для вашего первого макроса, щелкните на значке Project(ChapterOI) в окне Project, а затем на кнопке с вертикальной стрелкой рядом с кнопкой Insert Module (вторая кнопка вверху слева) и в появившемся меню выберите Module После ввода инструкций (иногда так называют операторы языка программирования, чтобы не путать их с математическими и другими операторами) в окно Code ваш экран должен иметь вид, как на рис. 1.2. Подобным образом можно вы Рис. 1.2 Макрос в окне Code редактора Visual Basic 30 Глава 1 вести предварительно вычисленные или введенные (в диалоговом окне) данные. Таким образом, вы уже на полпути к написанию простейших макросов. Теперь можно выполнить контрольный запуск макроса, не выходя из Редактора. Выберите Run | Run Sub/UserForm. Результатом работы макроса будет выдача на экран диалогового окна. Сравните его с рис. 1.3. Рис. 1.3 Результат работы вашего первого макроса (программы на языке Visual Basic) Если у вас имеется опыт работы с какой-нибудь другой системой программирования, то вас, видимо, никак не впечатлит подобное достижение, но задержитесь немного в Word, прежде чем повторить этот результат в Access, и запустите созданный макрос непосредственно из Word (все-таки Редактор VB в Word — это не совсем Word). Для этого покиньте Visual Basic Editor либо при помощи комбинации клавиш Alt+Q, либо — меню File | Close and Return to Microsoft Word. После того как вы окажитесь в привычном для всех окне Word, выберите Tools | Macro | Macros (Сервис | Макрос | Макросы). В появившемся диалоговом окне Macros выберите (видимо, единственный) уже знакомый вам макрос MyFirstMacro и щелкните на кнопке Run. Создание макроса в PowerPoint Совсем несложно создать макрос в приложении PowerPoint. Запустите PowerPoint. На рис. 1.4 представлено диалоговое окно, которое может появиться в вашей системе (состояние этого окна зависит от «истории» работы с PowerPoint этой или предыдущей версии). Рис. 1.4 По крайней мере, система PowerPoint не позволит вам «потеряться» в начале работы с ней !*] Файл фавка Вид &стдэ^ Форцат сейме Показ слайдов Окно Сграека • 18 » ж К у A z Конструктор -Создать слайд Создание презентацив ▼ * Заголовок слайда Подзаголовок слайда Открытие презентации и#" f -резан ли» Создание '' новая pSs<-fl г » К2 Ит oat офс$*< и- кя **1 Из НеКЛвра Создание из ююгащейся презентации V бьйир 'ра«в~ <*|ии Создание с помощью шаблона j Ххцие иибта-ы jfj цйПлонь- кзмсяч веб ifj шлблпнь. н* Мм слаб сот 51% ’ * • ДМ Заметки к <_л «щу 33 ? Дейсрия • U | Автофисуры • *1 / • «X ’ 88 ~~ & С' ysns 3) Стрзйьаьчг'язДНтиигГо t __ * Пекаммть при эапуов Оформление по умолчанию русский (Россия) Поскольку нашей целью является создание самого простого макроса, щелкните на надписи Новая презентация (Blank Presentation) в правом окне в разделе Создание (New) для выбора пустой презентации. Далее вам снова будет предложено сделать некоторый выбор (рис. 1.5). Впрочем, выбор уже сделан (первый тип слай Макросы и языки программирования 31 да выделен синим прямоугольником), вы можете не согласиться с ним и выбрать другой, но пока нас устроит и выбор по умолчанию. Рис. 1.5 «Пообщайтесь» с PowerPoint или продолжайте свой путь к созданию макроса В данный момент нас интересует вопрос написания макроса. Поэтому выберите Сервис | Макрос | Редактор Visual Basic (Tools | Macro | Visual Basic Editor), в появи-шемся на экране окне редактора щелкните на кнопке со стрелкой с именем Insert UserForm (в верхней правой части окна) и выберите из раскрывающегося меню опцию Module. Редактор Visual Basic создаст новый модуль и откроет соответствующее ему окно, как показано на рис. 1.6. Рис. 1.6 Совсем не трудно в PowerPoint подготовить место для написания макросов В этом окне следует набрать код из листинга 1.1, только вместо слова "Word” наберите "PowerPoint", как показано на рис. 1.7. Если вы запустите этот макрос (Run | Run Sub/UserForm), то увидите на экране результат, подобный приведенному на рис. 1.8. Теперь после того, как вы изучите следующий раздел, у вас будет свое мнение о том, с чего легче начать изучение языка VBA. 32 Глава 1 Рис. 1.7 Так может выглядеть ваш первый макрос в PowerPoint tie Microsoft Visual Basic • Презентация! - (Module! (Code)l Eife Edit View Insert Format Debug bun Tools &dd-lns JMndow tjelp @ Д * Ы 53> Д *••"> Col 33 I jrJ jMyFiisfMiKio MyFirstMacro () MsgBox ("Макрос в PowerPoint!") Sub }r(Generaii - VBAProject (Презентация!) - Modules 42 Module! Sub End ‘ МосКШ Module 1 Module Alphabetic <Categorized^ Рис. 1.8 Так может выглядеть диалоговое окно, созданное посредством написания кода в Редакторе Visual Basic в системе PowerPoint Макрос в PowerPort! Запись новых макросов В этом разделе рассказывается о том, что вам необходимо знать для записи кг кого-либо макроса. Затем вы выполните необходимые шаги для записи определе! ного макроса как в Word 2002 и Excel 2002, так и в PowerPoint 2002. Обычно запись макроса включает четыре основных шага: 1. Задание стартовых условий для макроса. Это означает задание тех услови вашей рабочей среды, которые должны быть соблюдены во время воспроизв дения записанного макроса. 2. Запуск макрорекордера и присвоение имени макросу. Одновременно с запу ком макрорекордера вы должны дать имя макросу и выбрать место, где < должен быть сохранен. При запуске макрорекордера вы можете выбирать м жду назначением команды запуска макроса с помощью так называемой «гор чей клавиши» или связыванием макроса с каким-либо меню или панелью и струментов (в зависимости от того, записываете ли вы макрос в Excel ш в Word). 3. Выполнение действий, которые вам необходимо записать для использован позже. Вы можете записать в макрос любое действие, которое можно выпс нить, используя клавиатуру или кнопки мыши, включая выполнение рав записанных макросов. Конкретные выполняемые вами действия зависят от ; дачи, которую вам необходимо записать. 4. Остановка макрорекордера. Когда вы останавливаете макрорекордер, ваг действия больше не записываются и не сохраняются в макросе. Как только останавливаете рекордер, новый записанный макрос сразу же готов к испо. зованию. В последующих двух разделах описываются более подробно два первых обш шага при записи макроса. Затем вам будут представлены конкретные пошагов инструкции для записи макроса в Word, Excel и PowerPoint. Макросы и языки программирования 33 Задание стартовых условий для макроса Перед записью какого-либо макроса вы должны задать условия, при которых вы будете запускать его позже. Выполнение (running или executing) макроса означает воспроизведение записанных в этом макросе инструкций. Предположим, например, что вам необходимо создать макрос, который будет применять определенный шрифт, размер и цвет шрифта в любом выбранном тексте документа в Word. Стартовыми условиями для этого макроса будут открытый документ с выделенным блоком текста. Если вы хотите создать подобный макрос форматирования текста в Excel, стартовыми условиями будут открытая рабочая книга, выбранный рабочий лист и выделенная ячейка или диапазон ячеек. Вам необходимо задать стартовые условия для макроса перед тем, как запускать макрорекордер, потому что макрорекордер будет записывать все действия, которые вы выполняете. Если вы запустите макрорекордер, а затем откроете некоторый документ и выделите текст, эти действия станут частью полученного в результате записи макроса. Ваш законченный макрос будет слишком специфическим: он будет всегда открывать один и тот же документ и форматировать один и тот же блок текста. Для создания общего макроса, который вы можете использовать для форматирования любого выбранного текста, вам следует запускать макрорекордер после открытия документа и выбора текста. Запуск макрорекордера и присваивание имени макросу Независимо от того, работаете ли вы в Word, Excel или PowerPoint, запись нового макроса осуществляется одним и тем же способом. Выберите команду Сервис | Макрос | Начать запись (Tools | Macro | Record New Macro). И в Word, и в Excel, и в PowerPoint отображается диалоговое окно Запись макроса (Record Macro), которое используется для того, чтобы вы могли дать имя новому макросу, выбрать место его сохранения и другое. Диалоговое окно Запись макроса может немного отличаться в зависимости от того, записываете ли вы макрос в Word, Excel или PowerPoint. Диалоговое окно Запись макроса в Word 2002 позволяет по выбору назначать «горячую клавишу» для запуска нового макроса или добавлять новый макрос как кнопку на панели инструментов. В Excel 2002 диалоговое окно Запись макроса дает возможность назначать только «горячую клавишу» для запуска нового макроса. В PowerPoint 2002 подобное диалоговое окно позволяет указать имя макроса, презентацию, в которую следует записать макрос. Во всех этих приложениях окно Запись макроса позволяет внести описание макроса. Больше о специфических опциях Excel, Word и PowerPoint, имеющихся в диалоговом окне Запись макроса, вы узнаете из конкретных пошаговых инструкций немного позже в этой главе. Имена макросов должны начинаться с буквы, хотя они могут содержать числа. Имена макросов не могут включать пробелы или знаки препинания. В Excel вы можете вводить имя макроса длиной до 64 символов; Word позволяет вводить имя макроса длиной до 80 символов. Диалоговые окна Запись макроса в Word и в Excel имеют следующие три общих элемента (на рис. 1.10 приведено окно для Word, а на рис. 1.15 — для Excel): 1. Текстовое окно Имя макроса (Macro Name). Первой опцией диалогового окна Запись макроса является Имя макроса. По умолчанию VBA выбирает имя макроса, состоящее из слова «Макрос» («Macros»), за которым следует номер, соответствующий числу макросов, уже созданных в этом сеансе работы. Вам следует вводить макросам имена, которые несут определенную информацию о том, что выполняют макросы. 2 Программирование на VBA 2002 34 Глава 1 2. Текстовое окно Описание (Description). Информация в текстовом окне Описание макросом непосредственно не используется. Текстовое окно Описание предназначено для ввода некоторых замечаний и комментариев о том, что выполняет данный макрос. Когда вы записываете макрос, VBA заполняет по умолчанию окно Описание информацией, начиная с даты записи этого макроса и имени пользователя. [VBA получает имя пользователя из текстового окна Имя и фамилия (Name) на вкладке в диалоговом окне Параметры (Options) на вкладке Пользователь (User Information) в Word (рис. 1.9) и текстового окна Имя пользователя (User name) вкладки Общие (General) диалогового окна Параметры (Options) в Excel (рис. 1.10).] 3. Раскрывающийся список Макрос доступен для: (Store macro in:). Этот раскрывающийся список позволяет выбрать, где следует сохранить записанный макрос. Макросы, записываемые в Word, всегда сохраняются в файле документа (.doc) или в файле шаблона документа (.dot). Макросы, записываемые в Excel, всегда сохраняются в файле рабочей книги (.xls). Рис. 1.9 Вкладка Пользователь диалогового окна Параметры в Word Рис. 1.10 Вкладка Общие диалогового окна Параметры в Excel Макросы и языки программирования 35 Запись макроса в Word 2002 Предположим, что вы часто форматируете слова или фразы, к которым хотите привлечь внимание в вашей документации, с помощью полужирного шрифта Arial 12-го размера. Поскольку вы форматируете только одиночные слова или короткие фразы, использовать какой-либо именованный стиль невозможно, так как стили Word применимы только к целым параграфам. Поэтому вам приходится применять форматирование шрифта вручную. Выбор шрифта Arial, изменение его размера и применение атрибута полужирного шрифта к тексту включают несколько операций с мышью или клавиатурой. Если вы часто выполняете эту задачу, можете сберечь время и усилия, записав макрорекордером макрос для выполнения нужного форматирования любого выделенного блока текста. Задание стартовых условий Поскольку вам необходимо, чтобы макрос выполнял действие над любым выделенным блоком текста в любом открытом документе, стартовыми условиями для этого макроса являются открытый документ и выделенный блок текста. Для задания стартовых условий в этом упражнении выполните следующие шаги: 1. Запустите Word 2002. 2. Откройте какой-либо документ. 3. Выделите любое слово или фразу в документе. На рис. 1.11 показан пример открытого документа с единственным выделенным словом. 3l Chapter©! -Microsoft Word файл Правка Вид Вставка Формат Сервис Таблица Qn-ю Справка Н RX «о т 5] 115% ▼ ” Listing - Times New Roman Исправления в измененном документе - Показать * । J - ЭД , 0. - 10 2 1 t' 2 t 3 ' l_4 1 5l 1 6 и 7 1 U 8 'I? ' 10u ' 11 il 12 ' L13 ' Щ 1 15 L ' 16 L £ Предположим что вы часто форматируете слова или фразы к которым хотите привлечь внимание в вашей документации с помощью полужирного шрифта Anal 12-го размера Поскольку вы формалисте только одиночные слова или короткие фра гы использовать какой-либо именованный стиль невошпжно гак как стили Woid применимы только к целым параграфам Поэтому вам приходится применять форматирование шрифта вручную Выбор шрифта Anal изменение его размера и применение атрибута полужирного шрифта к тексту включают несколько операций с мышью пли клавиатурой Если вы часто выполняете чу тадач\ можете сберечь время и усилия, записав макрорекордером макрос для выполнения нужного форматирования любого выделенного блока текста 3 Я Задание стартовых* условий Поскольку вам необходимо чтобы макрос выполнял действие над любым выделенным блоком текста в любом открытом документе стартовыми условиями для этого макроса являются открытым докчмент и выделенный блок текста Для задания стартовых у словил в пом упражнении выполните следующие шаги 1 Запустите Woicl 2(»О2 2 Откройте какой-либо документ 3 Выделите любое слово или фразу в документе На рис 1 11 показан пример открытого документа с единственным ловом <ыд елейным Выделив текст в открытом документе вы спздапп необходимые стартовые х словил дат записи общего макроса i цепью применения форматирования символов к любомч выбранноьа теылх Стр 13 Разд 1 13/25 На 23 5см Ст 20 Кол 14 русачий (Ро В Рис. 1.11. Задавайте стартовые условия для макроса форматирования текста в Word перед запуском макрорекордера Выделив текст в открытом документе, вы создали необходимые стартовые условия для записи общего макроса с целью применения форматирования символов к любому выбранному тексту. 2» 36 Глава 1 Присваивание имени макросу и выбор места для его сохранения Теперь вы готовы запустить макрорекордер в Word, дать имя макросу, выбрать место для сохранения нового макроса и выбрать дополнительные опции. Выполните следующие шаги: 1. Выберите команду Сервис | Макрос | Начать запись (Tools | Macro | Record New Macro). В Word отображается диалоговое окно Запись макроса (Record Macro), показанное на рис. 1.12. Заполненное диалоговое окно Запись макроса для макроса-примера ВыделитьТекст Запись макроса Р>Ж| ДОя ма»<роса |ВыделитьТекст Назначить макрос Макрос доступен для jbcex документов (Normal dot) ▼ Описание IМакрос записан И 01 2003 Владимир Кузьменко Устанавливает Arial, Bold 12 для выделенного фрагмента текста OK J Отмена 2. В текстовом поле Имя макроса (Macro name) введите ВыделитьТекст (или Вы-делить_Текст) в качестве имени макроса. Это имя помогает запомнить, что выполняет макрос. 3. Оставьте описание по умолчанию, в текстовом поле Описание (Description), но в добавление к существующему описанию введите следующий текст: Устанавливает Arial, Bold, 12 для выделенного текста. Этот дополнительный комментарий поможет вам (и другим) определить назначение этого макроса. 4. Используйте раскрывающийся список Макрос доступен для: (Store Macro in:) для выбора места, в котором будет сохранен записанный макрос. Вы можете сохранить макрос в любом загруженном в данный момент глобальном шаблоне или в текущем документе. Так как вам необходимо, чтобы макрос мог использоваться в любом документе, над которым вы будете работать, выберите Всех документов (All Documents) (Normal.dot). 5. Щелкните на кнопке ОК для начала записи макроса, если только вы не хотите добавить ваш макрос в панель инструментов или назначить для него «горячую клавишу». Для выбора любой из этих опций выполняйте инструкции, описанные в следующем разделе этой главы. Итак, вы теперь готовы выполнять действия, которые хотите записать. Конкретные места хранения, доступные в Word в диалоговом окне Запись макроса, зависят от того, какие глобальные шаблоны у вас загружены в данный момент. Доступные варианты всегда включают шаблон Normal.dot и текущий активный документ. На рис. 1.12 показано диалоговое окно Запись макроса, заполненное для макроса-примера ВыделитьТекст. Использование панели инструментов и клавиатуры для запуска макроса Существуют две дополнительные опции, которые вы можете выбрать в диалоговом окне Запись макроса в Word: либо назначить «горячую клавишу» для нового макроса, либо связать его с командной кнопкой на панели инструментов. Если вы Макросы и языки программирования 37 назначаете «горячую клавишу» для макроса, вы можете позже запускать этот макрос нажатием сочетания клавиш. Если вы связываете макрос с командной кнопкой на панели инструментов, то можете запускать его, щелкая эту кнопку на панели инструментов. Используйте опции «горячей клавиши» и клавиатуры только в случае, если уверены, что будете очень чдсто использовать макрос, который собираетесь записывать макрорекордером. Если вы будете назначать «горячие клавиши» всем вашим макросам, у вас скоро не останется неназначенных сочетаний «горячих клавиш». Если вы будете связывать все ваши макросы с панелью инструментов, вам ее не хватит, хотя она достаточно большая. Щелчок мышью на кнопке панели (Toolbars) или клавишам (Keyboard) для помещения вашего нового макроса на панель инструментов или назначения ему «горячей клавиши» приводит к запуску макрорекордера. Поэтому, если вы собираетесь использовать обе опции, выберите сначала кнопку панели, а затем нажмите кнопку клавишам для вывода на экран диалогового окна Настройка клавиатуры (Customize Keyboard). Для того чтобы назначить макросу «горячую клавишу», щелкните на кнопке клавишам в диалоговом окне Запись макроса в Word. Открывается окно Настройка клавиатуры, показанное на рис. 1.13. Так как вы назначаете «горячую клавишу» новому макросу (который еще не был записан), список Категории (Categories) отключен. Имя записываемого вами нового макроса выбирается по умолчанию в списке Команды (Commands). Нажмите сочетание клавиш, которое Хотите использовать для запуска этого макроса; клавиши, которые вы нажимаете, появляются в текстовом окне Новое сочетание клавиш (Press new shortcut key). Щелкните на кнопке Назначить (Assign), чтобы назначить сочетание клавиш новому макросу. Щелкните на кнопке Закрыть (Close) для выхода из диалогового окна Настройка клавиатуры и переходите к записи макроса. Как только вы закрываете диалоговое окно Настройка клавиатуры, Word активизирует макрорекордер и начинает запись ваших действий. Рис. 1.13 Диалоговое окно Настройка клавиатуры позволяет назначить сочетание «горячих клавиш» для макроса Запись ваших действий Независимо от того, запускаете ли вы макрорекордер щелчком на кнопке ОК или, выбирая опцию панели (Toolbars) или клавишам (Keyboard), Word отображает панель Остановка записи (Stop Recorder). Когда макрорекордер начинает записывать ваши действия, на экране появляется значок магнитофонной кассеты как 38 Глава 1 часть указателя мыши. Макрорекордер сохраняет каждое действие, которое вы • выполняете, в новом макросе до тех пор, пока вы не остановите рекордер или не сделаете паузу. Обратите внимание, что в строке состояния в нижней правой части окна Word появляется аббревиатура REC (ЗАП), чтобы напоминать вам о том, что Word записывает все ваши действия. В качестве примера выполните следующие действия: 1. Используйте список Шрифт (Font) на панели Шрифт для выбора шрифта Arial. 2. Используйте список Размер (Size) для выбора 12 в качестве нового размера шрифта. 3. Выберите Полужирный (Bold) из списка Начертание (Font Style) для включения атрибута полужирного шрифта для текста (рис. 1.14). Это были действия, необходимые вам для этого отдельного макроса, и теперь вы готовы к остановке макрорекордера. Рис. 1.14 Диалоговое окно Шрифт позволяет задать характеристики текста Шрифт Шрифт Интервал Анимация Шрифт Начертание Размер |^.al ........................... IBSS& ~ [Д~~ Цвет текста Авто Подчеркивание V] [(нет) Г [ Видоизменение Г“ зачеркнутый двойное зачеркивание Г надстрочный ~~ подстрочный Г~ с тенью Г Контур Г приподнятый Г~ утопленный Г малые прописные j gee прописные Г~ скрытьм Образец выделенным Шрифт TrueType Он используется для вывода как на экран, так и на Остановка макрорекордера Как было упомянуто в предыдущем разделе, Word начинает запись макроса и отображает панель Stop Recorder сразу после того, как вы щелкните на кнопке ОК в диалоговом окне Запись макроса. Завершив последовательности действий, которые вам необходимо записать, немедленно остановите макрорекордер. Для остановки макрорекордера щелкните на кнопке Остановить запись (Stop Macro) на панели Остановка записи или выберите Сервис | Макрос | Остановить запись (Tools | Macro | Stop Recording). Для макроса-примера ВыделитьТекст вам следует остановить макрорекордер немедленно после выполнения шагов, указанных в предыдущем разделе. Ваш новый Word-макрос является теперь законченным и готовым к запуску. Далее в этой главе вы узнаете, как запускать этот новый макрос. Запись макроса в Excel 2002 Для этого примера предположим, что вам также часто приходится применять полужирный шрифт Arial 12-го размера в качестве стиля форматирования симво Макросы и языки программирования 39 лов ячеек рабочих листов, к которым вы хотите привлечь особое внимание. В этом случае вы не можете использовать именованный стиль Excel [доступный с помощью команды меню Формат | Стиль (Format | Style)] для применения необходимого форматирования символов, поскольку это повлияло бы на все атрибуты ячеек, а не только на формат символов. Вместо этого вы должны каждый раз задавать атрибуты шрифта вручную. С целью сокращения времени, необходимого для форматирования текста, вам необходимо записать макрос, который выбирает полужирный шрифт Arial 12-го размера и применяет это форматирование к любой ячейке или диапазону ячеек текущего выделенного фрагмента. Задание стартовых условий Так как вам необходимо, чтобы макрос работал с любой выделенной ячейкой или диапазоном ячеек, стартовыми условиями для этого макроса являются открытая рабочая книга с выделенным диапазоном ячеек в активном рабочем листе. Чтобы'задать стартовые условия для данного конкретного примера в Excel, выполните следующие шаги: 1. Запустите Excel 2002, если он еще не запущен. 2. Откройте какую-либо рабочую книгу. 3. Выберите какой-либо рабочий лист. 4. Выделите любую ячейку в рабочем листе. Вы только что создали необходимые стартовые условия, чтобы записать общий макрос для форматирования символов любой выделенной ячейки или диапазона ячеек в рабочем листе Excel. Назначение имени и выбор места для сохранения макроса Для запуска макрорекордера в Excel, назначения имени макросу, выбора места для сохранения нового макроса и выбора дополнительных опций выполните следующие шаги: 1. Выберите команду Сервис | Макрос | Начать запись (Tools | Macro | Record New Macro). В Excel отображается диалоговое окно Запись макроса (Record Macro), показанное на рис. 1.15. 3 длись макро Рис. 1.15 Заполненное диалоговое окно Запись макроса для макроса-примера FormatArialBold12 ймя макроса |FcrmatAriaBoldl2 —— Сочетание клавиш Сохранить g CtrM-| [личная книга макросов т । ^писание [Макрос записан 1/11/2003 (Владимир Кузьменко) [форматирует ячейку Arial Вой, 12| ОК < Отмена [ 2. В текстовом окне Имя макроса (Macro Name) введите FormatArialBoldl2 в качестве имени макроса. Это имя помогает запомнить, что выполняет макрос. 3. Оставьте описание по умолчанию, введенное в текстовом окне Описание (Description), но введите следующий текст дополнительно к существующему описанию: Форматирует текст диапазона: Arial, Bold, 12. Этот дополнительный комментарий поможет вам (и другим) определить назначение данного макроса. 4. Используйте список Сохранить в (Store macro in) для выбора места, в котором будет сохранен записанный макрос. Доступными вариантами являются Личная книга макросов (Personal Macro Workbook), Новая книга (New Workbook) 40 Глава 1 и Эта книга (This Workbook). Поскольку вам необходимо, чтобы этот макрос был доступен во всех ваших рабочих книгах, выберите Личная книга макросов. Выбор Эта книга приведет к тому, что Excel сохранит новый макрос в текущей активной рабочей книге. Выбор Новая книга приведет к созданию в Excel новой рабочей книги, в которой будет сохранен этот макрос, — рабочая книга, которая была активной при запуске вами макрорекордера, остается активной рабочей книгой; любые действия, которые вы записываете, выполняются в этой книге, а не в новой рабочей книге, созданной для сохранения макроса. 5. Если вы уверены в том, что будете часто использовать макрос, который собираетесь записывать, можете назначить для его запуска горячую клавишу. Если — да, введите горячую клавишу в текстовое окно Сочетание клавиш (Shortcut Key) окна Запись макроса. 6. Щелкните на кнопке ОК для начала записи макроса. На рис. 1.15 показано диалоговое окно Запись макроса, заполненное для макроса-примера FormatArialBoldl2. Запись действий Как только вы щелкните на кнопке ОК в диалоговом окне Запись макроса, Excel запустит макрорекордер, отобразит панель Остановить запись (Stop Recorder) и начнет запись ваших действий. Макрорекордер сохранит каждое ваше действие в новом макросе. На рис. 1.16 показана панель Остановить запись в Excel, выведенная на экран во время сеанса записи макроса. (На рис. 1.16 записываемым макросом является макрос-пример FormatArialBoldl2). Заметьте, что в строке состояния в нижней левой части окна Excel появляется слово Запись (Recording) как напоминание о том, что Excel записывает все ваши действия. Не всегда при запуске макрорекордера вы можете увидеть на экране панель Оста-новить запись Поскольку это — обычная панель, ее можно отображать или не ото-бражать Этим, как и другими панелями, управляет команда Панели инструментов (Toolbars) меню Вид (View) В любом случае (при наличии на экране панели Остановить запись или ее отсутствиии) вы можете остановить макрорекордер, выбрав Сервис | Макрос | Остановить запись В Microsoft Excel-PRESK2 Рис. 1.16 Excel отображает панель Остановить запись и слово Запись (в строке состояния) во время записи макроса файл Правка Вид Вставка фодат Сервис Да-ные окно Справка ~ - в х И & & & 120% ” СУ ? Arid * 12 - [ж К ч g, S » gi «в t» • •й” • Д, - ” А7 ▼ д Группа товара Аксессуары 7 июл 2001 j Общество с — 7 ограниченной ч ответственностью , 125047, Россия. Москва. ул.Красноармеиская. д.4 4 Л’ « , ГТр| ВЭ С Тел.(095) 212-38-01. 212-64-23 Факс (095) 212-39-14 E-mail:symbas@orc.ru 6 ~~ " [Группа товара: Аксессуары 7 июл 20» 8 9 Наименование Цена Наименование 10 1 (A) 64-bit "DOCTOR V 64" 0 44 (A) Gun PSX Jolt 11 2 (A) Automatic RF SWITCH SPS 0 45 (Al Gun PSX Judge Dredd EL-' 12 3 (A) AV Multi Box 9,5 46 (Al Joystick PSX Arcade Rex Н 4 (A) CD LensCleaner n 47 (A) Joystick PSX Sakkara 602 и И 4 Я н (Д) rioaninn Krt МП \ Прейскурант / Sheetl / Dialog 1 / /Д) Invctirk Готово Эагмсь Макросы и языки программирования 41 По умолчанию панель Остановить запись в Excel содержит две командные кнопки (см. рис. 1.16). Левая кнопка — это кнопка Остановить запись (Stop); щелкните на этой кнопке для остановки макрорекордера. Правая кнопка — это кнопка Относительная ссылка (Relative Reference). По умолчанию Excel записывает абсолютные ссылки на ячейки в ваши макросы. Если вы, например, начнете запись с выделенной ячейки А7, а затем выделите ячейку справа От А7, то есть В7, то ваш записанный макрос также будет выделять ячейку В7, и так каждый раз, когда он будет запускаться. Если вы щелкаете на кнопке Относительная ссылка, Excel записывает относительную ссылку на ячейку каждый раз, когда вы выделяете какую-либо ячейку. Если выделенной в данный момент является ячейка А7 и вы выбираете ячейку справа от нее во время записи с относительными ссылками, то Excel записывает, что вы выделили ячейку, находящуюся на 1 столбец и 0 строк правее от текущей выбранной ячейки. Когда вы запустите записанный макрос, он выделит ячейку, находящуюся непосредственно справа от активной ячейки. Кнопка Относительная ссылка является кнопкой-переключатпелел» (toggle). Когда запись с относительными ссылками отключена, кнопка Относительная ссылка выглядит плоской; при помещении курсора мыши на кнопку вид кнопки изменяется и она выглядит отжатой. Когда запись с относительной ссылкой включена, кнопка Относительная ссылка на панели Остановить запись нажата (находится в «утопленном» положении). Щелкая на кнопке Относительная ссылка, можно включать и выключать запись с относительными ссылками во время записи по вашему желанию. Для выполнения записи макроса FormatArialBoldl2 действуйте следующим образом: 1. Выберите команду Формат | Ячейки (Format | Cells) для отображения диалогового окна Формат ячеек (Format Cells). 2. Щелкните на ярлычке Шрифт (Font) для отображения опций шрифта. (На рис. 1.17 показано диалоговое окно Формат ячеек с отображенными опциями шрифта). 3. Выберите Arial в списке Шрифт (Font). (Выполните этот шаг, даже если шрифт Arial уже выбран). Рис. 1.17 Диалоговое окно Формат ячеек в Excel с опциями шрифта, заполненное для макроса FormatArialBold12 Формат ячеек Число | Вьравнивание j Шрифт p граница < Вид | Защита J Размер: Шрифт; | Arial & Abertis Extra Bold fi Abertis Medium Начертание: | полужирный обычный курсив Подчеркивание: |нет полужирный курсив Цвет: I Авто I Обычный - видоизменение Г~ зачеркнутый Г верхний индекс Г нижний индекс Образец АаВЬБбЯя Шрифт типа TrueType. Шрифт будет использован как для вывода на экран, так и для печати. ОК Отмена 42 Глава 1 4. Выберите Полужирный (Bold) в списке Начертание (Font Style). 5. Выберите 12 в списке Размер (Size). 6. Щелкните на кнопке ОК, чтобы закрыть диалоговое окно Формат ячеек и изменить выделенную ячейку в рабочем листе. Остановка макрорекордера После того как вы закончите выполнение последовательности действий для записи, вам следует немедленно остановить макрорекордер Excel. Для этого щелкните на кнопке Остановить запись (Stop Macro) на панели Остановить запись (Stop Recorder) или выберите команду Сервис | Макрос | Остановить запись (Tools | Macro | Stop Recording). Для макроса-примера FormatArialBoldl2 вам необходимо остановить макрорекордер сразу же после того, как вы щелкните на кнопке ОК, чтобы закрыть диалоговое окно Формат ячеек. Ваш новый макрос в Excel теперь закончен и готов к выполнению. Вы узнаете о том, как выполнить новый макрос, позже в этой главе. Код макроса При записи макроса в Word, Excel или PowerPoint рекордер сохраняет последовательность текстовых инструкций, которые описывают на языке программирования Visual Basic for Applications различные действия, выполняемые вами в то время, когда рекордер включен. Это текстовое описание ваших команд называется исходным кодом (source code) для этого макроса. Позже, когда вы запускаете макрос, VBA считывает записанные в исходном коде инструкции и выполняет каждую последовательно, дублируя таким образом действия, которые вы выполняли, когда записывали макрос. В следующих строках приведен исходный код, полученный при записи вами макроса ВыделитьТекст в Word 2002. Обратите внимание, имя и описание макроса, которые вы ввели в диалоговое окно Запись макроса, включены в начало исходного кода записанного макроса. Листинг 1.2. Макрос, записанный в Word 1 Sub ВыделитьТекст() 2 ’ 3 ' ВыделитьТекст Макрос 4 1 11 Макрос записан 11.01.2003 Владимир Кузьменко 5 ' "&chr (10)&"Устанавливает Arial, Bold, 12 для выделенного б ' фрагмента текста 7 With Selection.Font I 8 .Name = "Arial" 9 .Size = 12 10 .Bold = True 11 .Italic = False 12 .Underline = wdUnderlineNone 13 .Underlinecolor = wdColorAutomatic 14 .StrikeThrough = False 15 .DoubleStrikeThrough = False 16 .Outline = False 17 .Emboss = False 18 .Shadow = False 19 .Hidden = False 20 .SmallCaps = False 21 .AllCaps = False 22 .Color = wdColorAutomatic Макросы и языки программирования 43 23 .Engrave = False 24 .Superscript = False 25 .Subscript = False 26 .Spacing = -0.1 27 .Scaling = 100 28 .Position = 0 29 .Kerning = 10 30 .Animation = wdAnimationNone 31 End With 32 End Sub Подобный код производится макрорекордером Excel. Следующие строки представляют собой исходный код, полученный при записи макроса FormatArial-Boldl2 в Excel. Заметьте, что имя и описание макроса, которые вы ввели в диалоговое окно Запись макроса, также включены в начало исходного кода записанного макроса. Листинг 1.3. Макрос, записанный в Excel 1 Sub FormatArialBoldl2() 2 ' 3 ' FormatArialBoldl2 Макрос 4 ' Макрос записан 1/11/2003 (Владимир Кузьменко) Форматирует 5 ' ячейку: Arial, Bold, 12 6 7 8 With Selection.Font 9 .Name = "Arial" 10 .Fontstyle = "полужирный" 11 .Size = 12 12 .Strikethrough = False 13 .Superscript = False 14 .Subscript = False 15 .OutlineFont = False 16 .Shadow = False 17 .Underline = xlUnderlineStyleNone 18 .Colorindex = xlAutomatic 19 End With 20 End Sub Так же просто записать макрос и в PowerPoint. Если вы перед редактированием слайда выполните команды (как и в Word, и в Excel) Сервис | Макрос | Начать запись, то после редактирования и форматирования строк Заголовок слайда и Подзаголовок слайда и отключения макрорекордера вы можете получить следующий код макроса. Листинг 1.4. Макрос, записанный в PowerPoint 1 Sub Макрос1() 2 ' 3 ' Макрос записан 1/11/2003. Автор: Владимир Кузьменко 4 ' 5 6 ActiveWindow.Selection.SlideRange.Shapes("Rectangle 2").Select 7 ActiveWindow.Selection.ShapeRange.TextFrame.TextRange.Select 8 ActiveWindow.Selection.ShapeRange.TextFrame.TextRange._ Characters(Start:=1, Length:=0).Select 9 With ActiveWindow.Selection.TextRange 10 .Text = "Новый слайд" 44 Глава 1 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 With .Font .Name = "Arial" < i .Size = 44 .Bold = msoFalse .Italic = msoFalse । .Underline = msoFalse .Shadow = msoFalse .Emboss = msoFalse » .BaselineOffset = 0 •AutoRotateNumbers = msoFalse .Color.SchemeColor = ppTitle End With End With ActiveWindow.Selection.ShapeRange.TextFrame.TextRange._ Characters(Start:=l, Length:=ll).Select With ActiveWindow.Selection.TextRange.Font •Name = "Times New Roman" •Size = 36 •Bold = msoTrue .Italic = msoFalse .Underline = msoFalse .Shadow = msoFalse .Emboss = msoFalse .BaselineOffset = 0 .AutoRotateNumbers = msoFalse .Color.SchemeColor = ppTitle End With ActiveWindow.Selection.SlideRange.Shapes("Rectangle 3").Select ActiveWindow.Selection.ShapeRange.TextFrame.TextRange.Select ActiveWindow.Selection.ShapeRange.TextFrame.TextRange._ Characters(Start:=1, Length:=0).Select With ActiveWindow.Selection.TextRange .Text = "Первый подзаголовок" With .Font .Name = "Arial" .Size = 32 .Bold = msoFalse •Italic = msoFalse .Underline = msoFalse .Shadow = msoFalse .Emboss = msoFalse •BaselineOffset = 0 .AutoRotateNumbers = msoFalse .Color.SchemeColor - ppForeground End With End With ActiveWindow.Selection.ShapeRange.TextFrame.TextRange._ Characters(Start:=1, Length:=19).Select With ActiveWindow.Selection.TextRange.Font .Name = "Arial" .Size = 32 .Bold = msoFalse .Italic = msoTrue .Underline = msoFalse .Shadow = msoFalse .Emboss = msoFalse » •BaselineOffset = 0 .AutoRotateNumbers = msoFalse .Color.SchemeColor = ppForeground End With End Sub Макросы и языки программирования 45 На данном этапе работы с книгой еще рано изучать приведенные листинги. Вы можете записывать и выполнять макросы, даже не заглядывая в исходный код или не зная, что данный макрос выполняет. В следующей главе описываются разные составляющие макроса и объясняется, как находить исходный код для определенного макроса и выводить его на экран для редактирования и проверки. Выполнение макросов После того как вы записали рекордером макрос, этот макрос можно выполнить. При выполнении макроса Word, Excel или PowerPoint следуют всем инструкциям, записанным в макросе. И в Word, и в Excel макрос запускается выбором команд Сервис | Макрос | Макросы (Tools | Macro | Macros). Word отображает диалоговое окно Макрос (Macros), приведенное на рис. 1.18, a Excel — на рис. 1.19. Эти диалоговые окна идентичны1 — выберите необходимый вам макрос в списке Имя (Macro name) и щелкните кнопку Выполнить (Run) для запуска макроса (другие кнопки в диалоговом окне Макрос обсуждаются далее). Рис. 1.18 Используйте в Word диалоговое окно Макрос для выбора макроса, который необходимо выполнить (приводятся только макросы, доступные в текущем документе или в общих шаблонах) Рис. 1.19 Используйте в Excel диалоговое окно Макрос для выбора макроса, который необходимо выполнить Макрос Имд макроса Описание Макрос записан 1/11/2003 (Владимир Кузьменко) Форматирует ячейку Aral, Вой, 12 1 В Word Список с именами макросов называется Имя, а в Excel — Имя макроса. 46 Глава 1 Например, для выполнения макроса ВыделитьТекст, который вы записали ранее в этой главе, сначала выделите некоторый текст в документе. Затем выберите Сервис | Макрос | Макросы для отображения диалогового окна Макрос. Выберите макрос ВыделитьТекст в списке Имя и затем щелкните на кнопке Выполнить, чтобы выполнить макрос ВыделитьТекст. Выделенный перед выполнением макроса текст в вашем документе будет отформатирован с использованием полужирного шрифта Arial 12-го размера. Для выполнения записанного вами в Excel макроса FormatArialBoldl2 выберите сначала ячейку в рабочем листе (предпочтительнее ячейку, содержащую некоторый текст, чтобы вы могли видеть изменения). Выберите команду Сервис | Макрос | Макросы для отображения диалогового окна Макрос и затем выберите макрос PERSONAL. XLS!FormatArialBoldl2 в списке Имя макроса. Наконец, щелкните на кнопке Выполнить для запуска макроса FormatArialBoldl2. Текст в любой ячейке, которая была выделена до запуска вами этого макроса, будет теперь иметь формат полужирного шрифта Arial 12-го размера. В Word диалоговое окно Макрос перечисляет макросы, сохраненные в текущем документе или в любых общих шаблонах (см. рис. 1.18). Используйте список Находится в: для выбора определенного документа или шаблона, если затрудняетесь найти нужный вам макрос в полном списке доступных макросов. Диалоговое окно Макрос в Excel перечисляет макросы, сохраненные в любых рабочих книгах, открытых в данный момент. Имя рабочей книги, содержащей макрос, помещено перед именем макроса в списке Имя макроса, если макрос не находится в текущей рабочей книге (как в случае с макросом PERSONAL.XLS! For-matArialBoldl2). Если необходимый вам макрос не находится в списке, откройте рабочую книгу, в которой был сохранен этот макрос, чтобы сделать макрос доступным перед тем, как вы откроете диалоговое окно Макрос. Если вы использовали опции диалогового окна Запись макроса (Record Macro) в Word для назначения вашему макросу горячей клавиши или кнопки на панели инструментов, вы можете также запускать этот конкретный макрос, щелкая на соответствующей кнопке панели инструментов или нажимая соответствующее сочетание клавиш. Как и в случае с макросами, перечисленными в диалоговом окне Макрос в Word, только макросы, сохраненные в текущем документе или в общем шаблоне, добавляются к панели инструментов или могут иметь активизированные горячие клавиши. Аналогично, если вы назначили горячую клавишу в диалоговом окне Запись макроса в Excel, вы можете запускать этот конкретный макрос, нажимая сочетание назначенных клавиш. Как и в случае с макросами, перечисленными в диалоговом окне Макрос в Excel, только макросы, сохраненные в текущей отрытой рабочей книге (это не должна быть обязательно активная рабочая книга), могут иметь активизированные горячие клавиши. Как вы уже знаете, вы можете также запускать макросы в Word и Excel, назначая им кнопки на панели инструментов или создавая для их вызова пункты меню. Вы можете также назначить макросу кнопку или графический объект, помещенный непосредственно в рабочий лист Excel или в документ Word. Для получения более полной информации об использовании интерактивных возможностей для назначения макросов кнопкам панели и графическим объектам в документах и рабочих листах обращайтесь к разделам справочной системы Excel и Word. Примеры записи более полезных макросов Закрепим первые успехи в изучении записи макросов, чтобы после прочтения этой главы вы уже могли уверенно записывать и использовать макросы, например, в Word 2002. Макросы и языки программирования 47 Оформление замечаний Начнем с постановки задачи. Пусть вам при написании некоторого отчета или статьи необходимо выделять каким-либо особенным способом части текста, в которых вы хотите высказать свое мнение, дать совет или предупредить читателя о чем-либо. В таких случаях неплохо было бы поместить в текст заголовок и выделить абзац или более, например, рамкой и отличным от остального текста стилем. Итак, решено, что нужен макрос, который будет выполнять следующие действия: 1) выводить заголовок Замечание стилем Замечание_заголовок, 2) устанавливать стиль последующего абзаца Замечание_текст. Понятно, что эти стили необходимо создать заранее и при этом нужно при создании стиля Замечание_заголовок следующим за ним стилем указать стиль Замечание_текст. Перед тем как начать запись макроса рекордером, всегда планируйте свои дей-/дгх. ствия до мельчайших деталей, пока не научились редактировать записанные макросы. Выполните следующие шаги: 1. Перейдите на новую строку текста. 2. Выберите Сервис | Макрос | Начать запись (Tools | Macro | Record New Macro). 3. В окне Запись макроса (Record Macro) в поле Имя макроса (Macro name) введите имя нового макроса «Замечание». 4. В поле Описание (Description) добавьте «Подготавливает текст-замечание». 5. Нажмите на кнопку клавишам (Keyboard). При появлении окна Настройка клавиатуры (Customize Keyboard) нажмите комбинацию клавиш, например, Alt+Ctrl+З, а затем — кнопки Назначить (Assign) и Закрыть (Close). 6. После появления на экране панели Остановить запись выберите на панели инструментов Word стиль Замечание_заголовок, введите слово Замечание (этим стилем) и нажмите клавишу Enter. 7. Остановите запись, щелкнув на кнопке Остановить запись (Stop Macro) на одноименной панели или выбрав команду Сервис | Макрос | Остановить запись (Tools | Macro | Stop Recording). Теперь у вас имеется макрос, который всегда при нажатии вами комбинации клавиш Atl+Ctrl+З будет производить подготовительные действия для ввода текста замечания. Чтобы проверить это, перейдите на новую строку текста и нажмите вышеуказанную комбинацию клавиш. Если вы сделаете все правильно, то на экране появится заголовок «Замечание», а следующий за ним абзац будет иметь стиль Замечание_текст. Подписи к рисункам Подпись к рисункам — это тоже одна из частых операций при написании различного рода документов. Поэтому запишем еще один макрос, который будет выполнять следующее: 1) автоматически задавать номер рисунка; 2) устанавливать стиль Рис_номер для номера рисунка; 3) устанавливать стиль Рис_текст. После выполнения такого макроса остается только ввести текст подписи. Выполните следующие шаги: 1. Перейдите на новую строку текста. 2. Выберите Сервис | Макрос | Начать запись. 3. В окне Запись макроса в поле Имя макроса введите имя нового макроса Номерурисунка. 48 Глава 1 4. В поле Описание добавьте Автоматически нумерует рисунок, устанавливает стиль подписи рисунка. 5. Нажмите на кнопку клавишам. При появлении окна Настройка клавиатуры нажмите комбинацию клавиш, например, Alt+Ctrl+N, а затем — кнопки Назначить и Закрыть. 6. После появления на экране панели Остановить запись выберите Вставка | Ссылка | Название (Insert | Reference | Caption) для вывода окна Название (рис. 1.20). В этом окне щелкните кнопку Создать (New Label), а в окне Новое название (New Label) (рис. 1.21) введите, например, Рис. и щелкните кнопку ОК. Рис. 1.20 Используйте диалоговое окно Назаание для создания нового заголовка к подрисуночной подписи и задания свойств заголовка Название Название. |Рмсуток 1 Параметры подпись: (Рисунок 1 J Создать... | | Нумерация... j Ав1оназвание... [ | ОК | Отмена j Рис. 1.21 Введите, например, "Рис." и щелкните кнопку ОК 7. В окне Название (рис. 1.22) щелкните кнопку Нумерация. В появившемся окне Нумерация названий (рис. 1.23) установите флажок Включить номер главы и выберите в окне комбинированного списка начинается со стиля стиль заголовка главы (который должен быть нумерованным). Щелкните на кнопке ОК в этом окне, а затем и в окне Название. »ис. 1.22 J окне Название щелкните кнопку Нумерация Установите стиль текущей строки Рис_номер, нажмите клавишу Enter. Остановите запись, щелкнув на кнопке Остановить запись (Stop Macro) на одноименной панели или выбрав команду Сервис | Макрос | Остановить запись (Tools | Macro | Stop Recording). Макросы и языки программирования 49 Рис. 1.23 Установите флажок Включить номер главы и выберите в окне комбинированного списка начинается со стиля стиль заголовка главы (который должен быть нумерованным) Формат: включить номер главы начинается со стиля I Заголовок 1 разделитель: р(точка) Образец: Рисунок П-1, Таблица 1-А ОК I Отмена После этого вы можете использовать макрос Номер_рисунка для автоматической нумерации рисунков, а после выполнения макроса — вводить текст подписи. Именно так были подготовлены подписи к рисункам этой главы. В окне Caption можно указать редактору использовать в нумерации рисунка номер текущей главы документа, но эта возможность не применена в данном макросе Подчеркивание листинга Если вы уже успели заметить, листинги отделяются в этой книге от обычного текста строкой из символов . Вы тоже можете использовать подобное оформление для своих текстовых документов. Чтобы записать макрос с подчеркивающей строкой, необходимо сначала создать стиль, которым вы хотите выводить подчеркивающие символы, а затем выполнить обычные действия, связанные с включением рекордера, выбором созданного стиля, вводом строки символов и остановкой рекордера. 1. Создайте новый стиль для строки с подчеркивающими символами. В данном случае в окне Шрифт (Font) были отмечены флажки верхний индекс (Superscript) и малые прописные (Small caps). 2. Выберите Сервис | Макрос | Начать запись (Tools | Macro | Record New Macro). 3. В окне Запись макроса в поле Имя макроса введите имя нового макроса «Line- Under». 4. После появления на экране панели Остановить запись выберите на Word-панели инструментов Форматирование (Formatting) стиль Подчеркнутый (Underline), введите строку символов (этим стилем) и нажмите клавишу Enter. 5. Остановите запись, щелкнув на кнопке Остановить запись на одноименной панели или выбрав команду Сервис | Макрос | Остановить запись. В отличие от предыдущих случаев при записи последнего макроса не была выбрана «горячая клавиша». Вы можете указать ее, хотя делать это необязательно. Макрос-шутка В качестве шутки вы можете написать очень простой макрос, который будет запускаться при каждой загрузке, например, Excel-рабочей книги. Вы можете подшутить над своим сослуживцем-менеджером, который 1-го апреля (в день смеха и шуток) оставил свой компьютер без присмотра, уходя’ покурить (встречаются у нас люди, желающие на своем примере убедиться во вреде курения). Представьте себе такую ситуацию: загружает объект вашей шутки рабочую книгу, над которой он трудился не один день, а ему на экран вместо знакомых колонок цифр и прочего выдается сообщение о том, что в результате разрушительного действия неизвестного вируса 50 Глава 1 (на компьютере же была установлена совершенно новая антивирусная программа!) рабочая книга полностью уничтожена. Эта первая шутка будет очень непродолжительной: после щелчка на кнопке ОК все будет работать по-прежнему. Далее в книге мы вернемся к этому макросу-шутке для добавления более «умного» кода. Итак, «пробираемся» тайком на компьютер, загружаем файл, например, с именем Важные_данные. Рабочий лист этого файла может иметь, например, вид, как представлено на рис. 1.24. Рис. 1.24 Главное при создании макроса-шутки, чтобы файл, котором будет размещен макрос, был хоть как-то «дорог» тому, кто его создал Выберите Сервис | Макрос | Редактор Visual Basic (Tools | Macro | Visual Basic Editor). В окне редактора щелкните на стрелке кнопки Insert UserForm и выберите Module в появившееся окно кода введите следующий код: Sub Auto_open() MsgBox "Ой1 Мамочки родные1 Самый страшный вирус " & "разрушил этот файл1" End Sub Рис. 1.25 L.tlX Шутка закончится, bfe'l <£айл Правка Вид Встарка Формат и -.j -.правка «• . 9 X как только кто-либо В й 120% - 7 Arial ’12 -г ж К Н SS. & 4Й Ж .F щелкнет кнопку ОК ▼ ft ($) ОТЧ (м+р)книжка 16 бит бол A ] В С D Е Т 7 ($) ОТЧ (м+р) комп Simba МР2 0 0 8 ($) ОТЧ (м+р) кор 16бит 0 0 9 ($) ОТЧ (м+р) кор 8бит 0 0 10 ($) ОТЧ (м+р) короб ВЗЛОМ КОД 0 0 11 |($) ОТЧ (м«р)книжка 16 бит бол 1 0 0 12 ($) ОТЧ печать SM4 0 0 13 ($) ОТЧ шнур DC ft. 14 ($) отчие книжкЖИЕИЯИИ 15 ($) ОТЧИС КНИЖК 16 ($) ОТЧИС КНОПКА Ои1 Мамочки родные' Самый страшный вирус разрушил этот файл 17 ($) ОТЧИС КОР KAJ 18 ($) ОТЧИС КОР KAI 1 О* 1 19 ($) отчие корпус 20 ($) ОТЧИС КОРПУС ДЖ КА S А-168 0 0 21 ($) ОТЧиЬ Корпус Дж ка Sega 0 0 22 ($) ОТЧИС Корпус комп Simba s 0 0 23 ($) ОТЧИС КРЕСТ ДЖ A SEGA 0 0 24 ($) ОТЧИС ПРИСТАВ 8 бит SIMBAS 0 о 26 ($) ОТЧИГ ОРОРКА ДЖОЙСТИКА П, Л ’ И 1 ► Н \Sbeetl / Sheet2 / Sheets / !>' ! >1Г, 3 Макросы и языки программирования 51 Обратите внимание на имя Sub-программы. Эта программа запускается при открытии рабочей книги. Далее мы будем этим пользоваться не только для шуток. Пока никто не видит, щелкните кнопку Save Важные_данные.х1а, затем выберите File | Close and Return to Microsoft Excel. Теперь остается срочно закрыть рабочую книгу и принять «смиренную позу». Как только ваш коллега вернется и загрузит этот файл, на экране он увидит что-то похожее на рис. 1.25. и . -s.> Гл«в« 2 Среда Редактора Visual Basic » В первой главе вы узнали, как записывать и выполнять макросы в Word и Excel. Перед редактированием и написанием макросов вам следует узнать больше о том, где сохраняются макросы. Необходимо также иметь общее представление о компоненте VBA Editor, его командах меню и кнопках панелей инструментов и о том, как они включаются в Word и Excel. Модули Вы уже знаете из первой главы, что макросы Visual Basic for Applications сохраняются как часть файлов, в которых Word, Excel и Access обычно содержат свои данные, — макросы сохраняются в файлах документов в Word и в файлах рабочих книг в Excel. Макросы сохраняются в специальной части файла данных, называемой Modules (модули). Модуль VBA содержит исходный код (source code) макроса — текстовое представление инструкций. Каждый документ Word (или шаблон документа) может содержать один или несколько модулей или не содержать никакого модуля; аналогично, каждый файл рабочей книги Excel может не содержать модулей или содержать один или несколько модулей. Модули, сохраняемые в одном документе Word или рабочей книге Excel, имеют общее название Project (проект). Знание того, как Word и Excel именуют создаваемые в них модули, поможет вам находить ваши записанные рекордером макросы, когда вам потребуется просмотреть или редактировать их. В следующих нескольких параграфах описывается, как Word и Excel выбирают имена модулей при записи макроса рекордером. Модули в Word 2002 При записи макроса в Word вы можете определять только документ или шаблон, в котором Word сохраняет записанный макрос. В Word все записанные макросы сохраняются в модуле с именем NewMacros. Например, если вы хотите сохранить новый записанный макрос в шаблоне Normal.dot, Word сохраняет исходный код этого макроса в модуле NewMacros шаблона Normal.dot. Другой пример — если вы открываете документ с именем Ch02.doc, а затем записываете макрос в этот документ, Word сохранит записанный макрос в модуле NewMacros документа Ch02.doc. Если модуль NewMacros не существует, Word создаст его. Word продолжает сохранять записанные макросы в модуле NewMacros документа или шаблоне документа, который вы выбираете, независимо от того, записываете ли вы дополнительные макросы в текущем или каком-либо другом сеансе работы. Модули в Excel 2002 Как и в Word, при записи макроса в Excel вы можете определять только рабочую книгу, в которой Excel сохраняет записанный макрос, — текущую рабочую книгу, новую рабочую книгу или рабочую книгу Personal.xls. Excel выбирает модуль, в котором сохраняется записанный макрос, и при необходимости создает этот модуль. Правила выбора модуля, в котором сохраняется ваш записанный макрос, в Excel являются более сложными, чем в Word. Среда Редактора Visual Basic 53 Когда Excel создает модуль, в котором сохраняется записанный макрос, модулю присваивается имя ModuleN, где N — это количество модулей, созданных для определенной рабочей книги во время текущего сеанса работы. Например, в первый раз, когда вы сохраняете записанный макрос в Personal.xls (личной книге макросов), Excel создает модуль с именем Modulel. Если вы продолжаете записывать макросы в том же сеансе работы и сохранять их в Personal.xls, Excel продолжает сохранять записанные макросы в том же модуле Modulel до тех пор, пока вы не выберете другую рабочую книгу. Если позже в том же сеансе работы вы опять захотите сохранить записанные макросы в Personal.xls, Excel добавляет другой модуль с именем Module2 в эту книгу. Если какая-либо рабочая книга уже содержит модуль с тем же именем, что выбран в Excel для нового модуля, Excel увеличивает число в имени модуля до тех пор, пока имя нового модуля не будет отличаться от имен существующих модулей. Например, если вы начнете новый сеанс работы в Excel и затем захотите сохранить записанный рекордером макрос в книге Personal.xls, Excel сначала выбирает имя Modulel для нового модуля. Если же книга Personal.xls уже содержит модули с именами Modulel и Module2, Excel увеличивает число в имени модуля, чтобы оно не совпадало с существующими именами; новый модуль получает имя Module3. Модули в PowerPoint 2002 При записи нового макроса макрорекордером в PowerPoint имя макроса, предлагаемое приложением по умолчанию, состоит из слова "Macro" и номера очередного макроса. Если в момент записи нового макроса вы имеете открытыми несколько файлов с презентациями, то вам в окне Record Macro будет предложен список открытых презентаций, для указания того, в какой презентации сохранить записываемый макрос. Приложения Microsoft Visio и Microsoft FrontPage не имеют макрорекордера. Все «офисные» приложения позволяют содавать новые модули, в которых вы можете хранить свои собственные макросы. Редактор Visual Basic Для просмотра модулей, сохраненных в определенном документе, шаблоне или рабочей книге (и исходного кода макроса, который они содержат), вам необходимо использовать компонент Visual Basic Editor (Редактор Visual Basic). Этот компонент предоставляет инструментальные средства, которые используются для создания новых модулей, просмотра содержимого существующих модулей, создания и редактирования исходного кода макроса, создания пользовательских диалоговых окон и выполнения других задач, относящихся к написанию и обслуживанию программ на VBA. Как вы уже могли заметить, в этой книге компонент Редактор Visual Basic называется просто «Редактор VB». Редактор VB содержит одни и те же возможности в Word, Excel и Access. Когда вы используете Редактор VB в Word, вы, фактически, используете тот же Редактор VB, который имеется в вашем распоряжении в Excel. В последующих нескольких параграфах рассказывается о том, как запускать Редактор VB, объясняется назначение различных окон, отображаемых компонентом Редактор VB, и описывается меню Редактора VB и команды панели инструментов. Запуск Редактора VB Как указывалось в предыдущих разделах, чтобы просмотреть модули или исходный код VBA, который они содержат, вам необходимо сначала запустить Ре 54 Глава 2 дактор VB. Независимо от того, работаете ли вы в Word или в Excel (а также и Access), Редактор VB запускается одним и тем же способом. Используйте для этого один из следующих приемов: Выберите Tools | Macro | Visual Basic Editor (Сервис | Макрос | Редактор Visual Basic). Нажмите сочетание клавиш AH+F11. Каким бы приемом вы не воспользовались, Word (Excel или PowerPoint), запустит Редактор Visual Basic. На рис. 2.1 показано типичное окно Редактора Visual Basic, отображенное в Word. Окно Редактора VB, отображаемое в Excel (рис. 2.2), в основном подобно окну Редактора VB, показанному на рис. 2.1. Рис. 2.1 Типичное окно Редактора VB в Microsoft Word 'Ji Microsoft Visual Basic - Normal - [NewMacros (Code)) 0e Edt yiew Insert Format Qetxjg Bin Tools idd-Ins ^ndow tHp ia-в > « ем ‘ • ► и x ra ini,con - A Modules «££ Modulel •41 Module? «4£ NewMacros - Protect (Chapter02) - "*< Microsoft Word Objects pGenerah yj [ВыделитьТекст Sub ВыделитьТекст() ’ ВыделитьТекст Ма«р ~ ’ Уекр z •залига-i 11.01.zjCL Lr uvwc T — J" f > j. With Selection.Font .Name = "Arial" NewMacros Module Alphabetic j Categorized j .Size = 12 .Bold - True .Italic = False .Underline = wdUnderlineNone .UnderlineColor = wdColorAutomatic .StrikeThrough = False .DoubleStrikeThrough = False □ ~ ез Рис. 2.2 Типичное окно Редактора VB в Microsoft Excel Microsoft Visual Sasic - Книга! - {Modulel (Code)} Bte Edit yiew Insert Format Qebug Bin Tools idd-Ins Window ИФ Я-H J‘fUI > H titfW’'' S Ini.an Sf ▼j [(Declaiations) ♦ л Microsoft Excel Object a - Modules •% Modulel ~ VBAProject (Книга!) - Microsoft Excel Object С ЛИСТ1 (JVCTl) Sub FormatArialBoldl2 () 1*1 [Лист! Worksheet Alphabetic j categorized j jlVCTl DisplayPageBre. False DIsplayRightToL False Enable AutoFiteiFalse With Selection.Font .Name = "Arial" .Fontstyle = "полужирный .Size = 12 .Strikethrough « False .Superscript = False .Subscript - False gfopartie? - ЛИС.Н Окна Редактора VB В окне Редактора VB имеются три дочерних окна, каждое из которых отображает важную информацию о VBA-проекте. [Project (Проект) — это группа модулей и других объектов, сохраняемых в определенном документе, шаблоне документа, рабочей книге или шаблоне рабочей книги.] Каждое из окон Редактора VB отображается по умолчанию в прикрепленных (docked) положениях, показанных на рис. 2.1. Среда Редактора Visual Basic 55 Если необходимо, вы можете переместить любое из дочерних окон Редактора VB в любое место на экране, перетаскивая строку заголовка {title bar) этого окна таким же образом, каким бы вы перемещали любое окно на рабочем столе Windows. Перетаскивание одного из дочерних окон из его прикрепленного положения приводит к тому, что оно становится плавающим окном. Плавающие {floating) окна всегда остаются видимыми поверх других окон.) Вы можете также изменять размер любого из дочерних окон Редактора VB, расширяя или уменьшая рамку окна для увеличения или уменьшения его размера, что подобно изменению размера любого окна на рабочем столе Windows. Далее описываются три окна Редактора VB и их назначение. Project Explorer (Окно проекта) содержит дерево-диаграмму открытых в данный момент файлов (документы, шаблоны или рабочие книги) и объектов, содержащихся в этих файлах (объекты host-приложения, модули, ссылки, формы и так далее). Project Explorer можно использовать для перехода к различным модулям и другим объектам в проекте VB при помощи кнопок (панели инструментов этого окна) View Code (Программа), View Object (Объект) и Toggle Folders (Папки). Properties Window (Окно свойств) содержит все свойства объекта текущего выбора. В некоторых случаях, как в окне, показанном на рис. 2.1, свойства объекта состоят только из его имени. (Подробнее об объектах и свойствах объектов вы узнаете из следующих глав.) Вкладка Alphabetic (по алфавиту) этого окна предоставляет список свойств выделенного объекта, составленный из имен свойств в алфавитном порядке. Вкладка Categorized (по категориям) отображает свойства объекта, отсортированные по категориям. Code Window — это окно, в котором вы можете просматривать, редактировать нли создавать исходный код VBA. В режиме Full Module View весь исходный код макроса в модуле отображается сразу в прокручивающемся текстовом окне, а макрос отделяется от другого макроса серой линией. Редактор VB позволяет также просматривать содержимое модуля в режиме Procedure View (представление процедуры). Чтобы выбрать режим просмотра, щелкайте кнопки в нижнем левом углу Code Window (см. рис. 2.3). .Name = "Arial" .Size = 12 .Bold = True .Italic = False .Underline = wdUnderlineNone .Underlinecolor = wdColorAutomatic .StrikeThrough = False .DoubleStrikeThrough = False Procedure View Full Module View Рис. 2.3. Чтобы выбрать режим просмотра, щелкайте кнопки в нижнем левом углу Code Когда Code Window находится в режиме Procedure View, видимым является исходный код только одного макроса. Используйте раскрывающийся список Procedure (процедура) для просмотра другого макроса. В режиме Full Module View вы можете также использовать раскрывающийся список Procedure для быстрого перехода к отдельному макросу. Используйте список Object List (объект) для выбора объекта, процедуры которого хотите просмотреть или редактировать. В случае стандартных модулей, таких как модули, в которых сохраняются записанные вами макросы, единственным выбором в списке Object List является General (общая область). 56 Глава 2 Теперь, ознакомившись с окнами Редактора VB, вы можете перейти к изучению панелей инструментов и меню Редактора VB, которые содержат команды, помогающие управлять окнами Project Explorer, Properties Window, Code Window и их содержимым. Меню Редактора VB В этом и последующих разделах рассказывается о меню и панелях инструментов Редактора VB. Сейчас вам необходимо лишь познакомиться с имеющимися командами. Можете попробовать использовать некоторые из этих команд, только убедитесь сначала, что вы экспериментируете с документом (или рабочей книгой), не содержащим незаменимых данных. Далее в тексте значки "О” с находящимся внутри них текстом означают, что в зависимости от ситуации на это место подставляется имя файла, модуля, макроса, проекта и т д Меню Файл (File) Меню File, как и во всех приложениях Windows, содержит команды, относящиеся к сохранению и открытию файлов. В Редакторе VB меню File предоставляет команды, необходимые для сохранения изменений в проекте VBA и вывода на экран исходного кода вашего макроса VBA. В табл. 2.1 приведены команды меню File, их горячие клавиши и назначение каждой команды. Таблица 2.1. Команды меню File Команда Горячая клавиша Действие Save <project> (сохранить <про-ект>) Ctrl+S Сохраняет текущий проект (презентацию, рисунок и т.д. в зависимости от приложения, в котором открыт Редактор VB) VBA на диске, включая все модули и формы. Import File (импорт файла) Ctrl+M Добавляет существующий модуль, форму или класс в текущий проект (презентацию). Вы можете импортировать только модули, формы или классы, сохраненные ранее командой Export File из другого проекта (презентации). Export File (экспорт файла) Ctrl+E Сохраняет текущий модуль, форму или класс в формате текстового файла для импортирования в другой проект или в целях архивирования. Remove <item> (удалить <...>) Перманентно удаляет модуль или форму текущего выбора из проекта (презентации) VBA. Эта команда не доступна, если в Project Explorer не выбран никакой элемент. Print (печать) Ctrl+P Печатает модуль или форму для документирования или с целью архивирования. Close and Return to ... (закрыть и вернуться в ... ) Alt+Q Закрывает Редактор VB и возвращает вас в host-приложение и документ/рабочую кни-гу/презентацию, из которых был открыт Редактор VB. Среда Редактора Visual Basic 57 Меню Edit (правка) Меню Edit содержит команды, относящиеся к управлению исходным кодом макроса в Code Window и объектами в формах. В табл. 2.2 приведены имеющиеся команды меню Edit, их горячие клавиши и описывается действие, выполняемое каждой командой. Таблица. 2.2. Команды меню Edit Команда Горячая клавиша Действие Undo (отменить) Ctrl+Z Отменяет самую последнюю команду. Не все команды могут быть отменены. Меню доступно только в случае, если есть, что отменять. Redo (вернуть) Возвращает самую последнюю команду, которую вы отменили. Cut (вырезать) Ctrl+X Вырезает выделенный текст или объект и помещает его в Windows Clipboard. Выделенный текст или объект удаляется из модуля или формы. Сору (копировать) Ctrl+C Копирует выделенный текст или объект и помещает его в Windows Clipboard. Выделенный текст или объект остается неизменным. Paste (вставить) Ctrl+V Вставляет текст или объект из Windows Clipboard в текущий модуль или форму. Clear (очистить) Del Удаляет выделенный текст или объект из модуля или формы. Select АП (выделить все) Ctrl+A Выделяет весь текст в модуле или все объекты в форме. Find (найти) Ctrl+F Подобно команде Find в Word или Excel, позволяет находить указанный текст в модуле. Find Next (найти далее) F3 Повторяет последнюю операцию Find. Replace (заменить) Ctrl+H Подобно команде Replace в Word или Excel, позволяет находить указанный текст в модуле и заменять его другим текстом. Indent (увеличить отступ) Tab Смещает весь выделенный текст вправо на интервал табуляции. Outdent (уменьшить отступ) Shift+Tab Смещает весь выделенный текст влево на интервал табуляции. List Properties/ Methods (список свойств/методов) Ctrl+J Открывает список в List Properties/ Methods, отображая свойства и методы объекта, имя которого вы только что ввели. Когда курсор вставки находится на пустом месте в List Properties/ Methods эта команда открывает список глобально доступных свойств и методов. List Constants (список констант) Ctrl+ Shift+J Открывает список в Code Window, отображающий допустимые константы для свойства, которое вы только что ввели с предшествующим знаком ". 58 Глава 2 Команда Горячая клавиша Действие Quick Info (сведения) Ctrl+I Открывает всплывающее окно подсказки, отображающее правильный синтаксис для процедуры, функции или метода, который вы только что ввели в Code Window. Parameter Info (параметры) Ctrl+ Shift+I Открывает всплывающее окно подсказки, отображающее параметры (называемые также аргументами) процедуры, функции или оператора, который вы только что ввели в Code Window. Complete Word (завершить слово) Ctrl+ Space Редактор VB заканчивает слово, которое вы вводите, как только вы введете достаточно символов для того, чтобы VBA распознал ключевое слово. Bookmarks (закладки) Открывает подменю с пунктами для помещения, удаления или перехода к закладкам, которые вы ранее поместили в ваш модуль. В отличие от закладок в Word, закладки Редактора VB не имеют имен. Меню View (Вид) Меню View содержит команды, позволяющие выбирать элементы Редактора VB для просмотра и способ просмотра. В табл. 2.3 приведены команды меню View, их горячие клавиши и действие, производимое каждой командой. Таблица 2.3. Команды меню View Команда Горячая клавиша Действие Code (программа) F7 Активизирует Code Window для отображения исходного кода VBA, ассоциированного с выбранным модулем или формой. Object (объект) Shift+F7 Отображает объект текущего выбора в Project Explorer. Definition (описание) Shift+F2 Отображает исходный код VBA для процедуры или функции, на которую указывает курсор; отображает Object Browser для объектов в справке VBA. Last Position (вернуться к последней позиции) Ctrl+ Shift+F2 Переходит в последнюю позицию в модуле после использования команды меню Definition или после редактирования кода. Object Browser (просмотр объектов) F2 Открывает Object Browser, позволяющий определять, какие макросы доступны в данный момент. Immediate Window (окно отладки) Ctrl+G Отображает окно отладчика Immediate Window VBA. Среда Редактора Visual Basic 59 Команда Горячая клавиша Действие Locals Window (окно локальных переменных) Отображает окно отладчика Locals Window. Watch Window (окно контрольного значения) Отображает окно отладчика Watch Window (контрольные значения). Call Stack (стек вызова) Ctrl+L Отображает список последовательности вызовов для текущей функции или процедуры VBA. Project Explorer (окно проекта) Ctrl+R Отображает Project Explorer. Properties Window (окно свойств) F4 Отображает Properties Window. Toolbox (панель элементов) Отображает Toolbox. Toolbox используется для добавления элементов управления в пользовательские диалоговые окна. Tab Order (последовательность перехода) Отображает диалоговое окно Tab Order, которое используется при создании пользовательских диалоговых окон. Toolbars (панели инструментов) Отображает подменю, позволяющее показывать или скрывать различные панели инструментов Редактора VB или открывать диалоговое окно для настройки одной из панелей инструментов Редактора VB. <Host applications (host-приложение) Alt+Fll Возвращает вас в host-приложение, из которого был запущен Редактор VB, но оставляет Редактор VB открытым. Конкретное имя этого пункта меню зависит от того, из какого host-приложения VBA вы запустили Редактор VB. Меню Insert (Вставка) Команды меню Insert позволяют добавлять различные объекты, такие как модули и формы, в ваш проект. В меню Insert никакие команды не имеют «горячих клавиш». В табл. 2.4 приведены действия, выполняемые каждой командой этого меню. Таблица 2.4. Команды меню Insert Команда Действие Procedure (процедура) Вставляет новую процедуру (Sub, Function или Property) в текущий модуль. (Процедура — это еще одно название макроса). UseForm Добавляет новую форму (используется для создания пользовательских диалоговых окон) в проект. Module (модуль) Добавляет новый модуль в проект. Редактор VB дает этому модулю имя в соответствии с правилами, описанными ранее в этой главе. 60 Глава 2 Команда Действие Class Module (модуль класса) Добавляет в проект class module (модуль класса). Модули класса используются для создания пользовательских объектов в вашем проекте. File (файл) Позволяет вставлять текстовый файл, содержащий исходный код VBA, в модуль. Меню Format (Формат) Команды меню Format используются при создании пользовательских диалоговых окон и других форм. Команды меню Format позволяют выравнивать объекты в форме по отношению друг к другу, настраивать размер элемента управления в соответствии с его содержимым и выполнять многие другие полезные задачи. Команды меню Format представлены здесь для полноты изложения материала, хотя вы не будете их применять до тех пор, пока не начнете создавать собственные пользовательские диалоговые окна. В табл. 2.5 приведены команды меню Format и их действия. Заметьте, что эти команды не имеют «горячих клавиш». Таблица 2.5. Команды меню Format Команда Действие Align (выровнять) Открывает подменю команд, которые позволяют выравнивать выбранные объекты в форме по отношению друг к другу. Здесь можно выравнивать объекты по верхней/нижней, правой/левой границам, по центру или середине создаваемого объекта. Make Same Size (выровнять размер) Открывает подменю команд, позволяющих изменять размер выделенных объектов до размера указанного объекта. Size to Fit (подогнать размер) Одновременно изменяет ширину и высоту объекта до соответствия размеру его содержимого. Size to Grid (выровнять размер по сетке) Одновременно изменяет ширину и высоту объекта до ближайших меток сетки. При разработке форм Редактор VB отображает в форме сетку, чтобы было легче располагать и изменять размеры объектов в форме. Horizontal Spacing (интервал по горизонтали) Открывает подменю команд, позволяющих устанавливать горизонтальный интервал для выбранных объектов. Здесь можно устанавливать равномерный горизонтальный интервал, уменьшать или увеличивать его или удалять всякий горизонтальный интервал между объектами. Vertical Spacing (интервал по вертикали) Открывает подменю команд, позволяющих устанавливать вертикальный интервал для выбранных объектов. Здесь можно устанавливать равномерный вертикальный интервал, уменьшать или увеличивать его или удалять всякий вертикальный интервал между объектами. Center in Form (разместить по центру в форме) Открывает подменю команд, позволяющих изменять положение выбранных объектов, чтобы они были центрированы в форме горизонтально или вертикально. Среда Редактора Visual Basic 61 Команда Действие Arrange Buttons (разместить кнопки) Открывает подменю команд, позволяющих автоматически располагать командные кнопки в форме в ряд с равным интервалом по нижнему или правому краю формы. Group (группировать) Связывает несколько выбранных объектов вместе в одну группу, чтобы вы могли перемещать, изменять размер, вырезать или копировать объекты, обращаясь с ними, как с одним целым. Ungroup (разделить) Отменяет группировку объектов, которые перед этим были связаны вместе с помощью команды Group. Order (порядок) Открывает подменю команд, позволяющих изменять упорядочение сверху вниз (называемое z-order) перекрывающихся объектов в форме. Цспользуйте команду Order, чтобы обеспечить, например, появление текстового окна всегда поверх графического объекта в форме. Меню Debug (Отладка) Команды меню Debug используются при выполнении тестирования или отладки макросов. (Debugging — так называется процесс нахождения и исправления ошибок в программе.) В табл. 2.6 приведены команды меню Debug, их «горячие клавиши» и выполняемые действия. Таблица 2.6. Команды меню Debug Команда Горячая клавиша Действие Compile <project> (компилировать <проект>) Компилирует проект, выбранный в данный момент в Project Explorer. Step Into (шаг с заходом) F8 Выполняет исходный код вашего макроса по одному оператору каждый раз. Step Over (шаг с обходом) Shift+F8 Подобно команде Step Into команда Step Over позволяет выполнять все инструкции в макросе без паузы на каждой отдельной инструкции. Step Out (шаг с выходом) Ctrl+ Shift+F8 Выполняет все остающиеся операторы в макросе без паузы на каждом отдельном операторе. Run to Cursor (выполнить до текущей позиции) Ctrl+F8 Выполняет операторы исходного кода макроса от оператора, выполняющегося в данный момент, до текущей позиции курсора. Add Watch (добавить контрольное значение) Позволяет указывать переменные или выражения, значения которых можно наблюдать во время выполнения исходного кода VBA. Edit Watch (изменить контрольное значение) Ctrl+W Позволяет редактировать спецификации для наблюдаемых переменных и выражений, которые были созданы ранее с помощью команды Add Watch. 62 Глава 2 Команда Горячая клавиша Действие Quick Watch (контрольное значение) Shift+F9 Отображает текущее значение выбранного выражения. Toggle Breakpoint (точка останова) F9 Отмечает место (или отменяет отметку) в исходном коде VBA, где вы хотите остановить выполнение макроса. Clear АП Breakpoints (снять все точки останова) Ctrl+ Shift+F9 Удаляет все точки останова в модуле. Set Next Statement (задать следующую инструкцию) Ctrl+F9 Позволяет менять обычное выполнение кода путем указания вручную следующей строки исходного кода, которая должна выполняться. Show Next Statement (показать следующую инструкцию) Приводит к подсветке Редактором VB следующей строки кода, которая будет выполняться. Команды меню Debug позволяют непосредственно контролировать выполнение макроса, останавливать и запускать макрос в заданных точках и отслеживать выполнение макроса по шагам. Меню Run (Запуск) Команды меню Run позволяют начать выполнение макроса, прерывать или возобновлять его выполнение или возвращать прерванный макрос в состояние до выполнения. Таблица 2.7. Команды меню Run Команда Горячая клавиша Действие Run Sub/User Form (запуск подпро-граммы/User Form) F5 Приводит к тому, что VBA запускает макрос, который редактируется в данный момент, то есть VBA запускает макрос, на тексте которого находится курсор вставки. Если какая-либо форма активна, VBA запускает эту форму. Break (прервать) Ctrl+Break Прерывает выполнение вашего кода VBA и приводит к тому, что Редактор VB переходит в режим прерывания (Break mode). (Break mode используется при отладке кода VBA.) Resert <project> (сброс) Устанавливает все переменные модульного уровня и Call Stack (список последовательности вызовов) в исходное состояние. Design Mode (конструктор) Включает и выключает Design mode (режим проектирования или разработки) для проекта. В этом режиме никакой код в вашем проекте не выполняется, и события от элементов управления не обрабатываются. Среда Редактора Visual Basic 63 Меню Tools (Сервис) Команды меню Tools не только позволяют выбрать макрос для выполнения, но и получить доступ к внешним библиотекам макросов и дополнительным элементам управления форм (кроме встроенных в VBA). Команды меню Tools обеспечивают также доступ к диалоговому окну Options (параметры) Редактора VB и свойствам проекта VBA текущего выбора в Project Explorer. В табл. 2.8 приведены команды меню Tools и их действия. Команды меню Tools не имеют «горячих клавиш». Таблица 2.8. Команды меню Tools Команда Действие References (ссылки) Отображает диалоговое окно References, позволяющее устанавливать ссылки на библиотеки объектов, библиотеки типов или другой проект VBA. После установления ссылки объекты, методы, свойства, процедуры и функции в этой ссылке появляются в диалоговом окне Object Browser. Additional Controls (дополнительные элементы) Отображает диалоговое окно Additional Controls, позволяющее настраивать Toolbox (панель элементов) так, чтобы вы могли добавлять элементы управления в формы помимо встроенных в VBA. Диалоговое окно Additional Controls предназначено для добавления к панели элементов кнопок, которые позволяют добавлять к форме объекты, такие как рабочий лист Excel или документ Word. Macros (макросы) Отображает диалоговое окно Macros, позволяющее создавать, редактировать, выполнять или удалять макросы. Options (параметры) Отображает диалоговое окно Options, позволяющее выбирать различные опции для Редактора VB, такие как число пробелов в интервале табуляции (tab stop), когда VBA проверяет синтаксис ваших операторов, и так далее. <project> Properties (свойства проекта) Отображает диалоговое окно Project Properties, позволяющее устанавливать различные свойства вашего проекта VBA, такие как имя проекта, описание и файл контекстной справки. Это диалоговое окно позволяет также защищать проект, чтобы никто не мог его редактировать без указания пароля. Digital Signature (цифровая подпись) Отображает диалоговое окно Digital Signature, в котором можно задать для проекта сертификат цифровой подписи. Меню Add-Ins В этом меню находится всего одна команда, Add-In Manager, которая приводит к отображению диалогового окна Add-In Manager. Это окно позволяет регистрировать, загружать или выгружать и определять поведение дополнений. Другие меню В Редакторе VB имеются два дополнительных меню: Window (окно) и Help (помощь). Оба этих меню содержат команды, идентичные меню Window и Help, имеющимся в других приложениях Microsoft Windows. Команды в меню Window позволяют выбирать активное окно, разбивать текущее окно, размещать дочерние окна вертикально и горизонтально, организовывать дочерние окна VB в виде каскада или выравнивать значки минимизированных дочерних окон. 64 Глава 2 Команды меню Help также идентичны командам меню Help в Word, Excel и других приложениях Microsoft Windows. Меню Help Редактора VB позволяет получать контекстно-зависимую подсказку посредством справочной системы Microsoft Office и просматривать файлы справочной системы VBA для host-приложения, из которого вы запустили Редактор VB. Если у вас имеется модем или доступ к Internet, вы можете использовать Help | MSDN on the Web для соединения с разнообразными страницами Web, содержащими информацию о продуктах Microsoft и VBA. Последняя команда в меню Help — это команда About Microsoft Visual Basic. Она отображает диалоговое окно, содержащее сведения об авторских правах на Microsoft Visual Basic. Диалоговое окно About Microsoft Visual Basic содержит также командную кнопку System Info, которая отображает информацию о вашей вычислительной системе: какие драйверы видеосистемы, звуковой системы и принтера установлены, какие программы загружены в память в данное время, какие программы зарегистрированы в системном реестре (Windows System Registry) и другую техническую информацию. Знакомство с панелями инструментов Редактора VB Для многих пользователей выбрать командную кнопку с помощью мыши легче, чем выбрать команду в меню. Поэтому Редактор VB предоставляет важнейшие и наиболее часто используемые команды в виде кнопок на панели инструментов. Если вы часто работаете с Редактором VB, можете заметить, что использование командных кнопок на различных панелях Редактора VB ускоряет вашу работу. По умолчанию Редактор VB отображает только панель инструментов Standard, показанную на рис. 2.4. В конце панели, справа, находится кнопка (со стрелкой) More Buttons. Если вы хотите удалить с панели или добавить некоторые кнопки на панель Standard, нажмите на эту кнопку, а затем укажите соответствующую кнопку в появляющемся меню (рис. 2.5). . . 1 3 5 7 9 11 13 15 17 19 ® 3’@ ! а 2 4 6 8 10 12 14 16 18 Рис. 2.4. Панель Standard Редактора VB содержит кнопки для важнейших и наиболее часто используемых команд: 1 - View host-приложение; 2 - Insert UserForm; 3 - Save module; 4 - Cut; 5 - Copy; 6 - Paste; 7 - Find; 8 - Undo; 9 — Redo; 10 — Run Sub/UserForm; 11 - Break; 12 — Reset; 13 - Design Mode; 14 - Project Explorer; 15 - Properties Window; 16 - Object Browser; 17 - Toolbox; 18 — Microsoft Visual Basic Help; 19 - More Buttons Кроме панели Standard Редактор VB предлагает еще три панели: Edit (правка), Debug (отладка) и UseForm. Панель Edit Редактора VB содержит несколько командных кнопок, полезных при редактировании текста в Code Window (окне кода). Эта панель предлагает даже пару команд, которых нет на панели Standard (стандарт). Панели Standard и Edit описываются далее в этом разделе. Вы можете управлять тем, какие панели инструментов отображает Редактор VB с помощью команды View | Toolbars (вид | панели инструментов). Поскольку Редактор VB по умолчанию не отображает панель Edit, вам нужно будет выводить ее на экран вручную. В следующих нескольких параграфах описываются сначала команды, имеющиеся на панели Standard, а затем — дополнительные команды, находящиеся на панели Edit. Среда Редактора Visual Basic 65 Рис. 2.5 Кнопка More Buttons панели Standard Редактора VB позволяет добавлять и удалять любые кнопки Microsoft Visual Basic - Normal - [NtwMacros (Cod»}} Зе Edft tfew insert Format Debug Bid loots Add-ins window Дор й ЗГ s E п т pr______________________ - Normal * .... Merceoft word Object nt «С Modulel NewMacroe Module Alphabetic jcaisgoreedl |§^|NewMacros ► 11 & 4 I# Ln 1,Col20 в Sub выделитьТекс Я ’ *. В ' гдхделит- Гекс» ~7' £ ’ млгрог '»н'кса/'^ йк • *. ®> With Selecti5’' Л .Name = -/ .Bold «= ™ . Italic I— * .underlie ’* .underli * .Strikelff. .Doubles.^ cm Alt+Fll Mcrosoftword Insert Object gave Normal cuj СРРУ Baste Epd. Cant undo Cant Redo Rid Sub/JserForm Break Beset Design Mode Eroject Explorer Properties y^ndow Object Browser Toobox Оправка Mcrosoft Visual Basic Fl Standard C«*S CM+x Ctri*C Ctrl+v Cfrl+F ctrt+z Ctri+R M F2 FS ctrt+Break tjacTpoCka Сброс панели Панель инструментов Standard Панель инструментов Standard содержит 19 кнопок. Каждая кнопка является быстрой командой меню. При изучении таблицы 2.9 обращайтесь к рис. 2.4 для сопоставления имени каждой командной кнопки со значком на передней стороне кнопки. Таблица 2.9. Кнопки панели инструментов Standard Кнопка Действие View <host application> (вид <ко81-приложе-ние>) Переключает на host-приложение VBA, из которого вы запустили Редактор VB. Значок этой кнопки изменяется в зависимости от конкретного приложения, из которого вы запускали редактор VB. Insert UserForm (вставить UserForm) Щелкните на кнопке со стрелкой вниз справа от этой кнопки, чтобы отобразить список объектов, которые вы можете вставить в текущий проект: UserForm, Module, Class Module или Procedure. Это можно выполнить и при использовании одноименных команд меню Insert (вставка). Save (сохранить) Сохраняет текущий проект так же, как File | gave. Cut (вырезать) Вырезает выделенный текст или объект и помещает его в Clipboard; так же, как команда Edit | Cut. Copy (копировать) Копирует выделенный текст или объект в Clipboard; так же, как команда Edit | Сору (правка | копировать). Paste (вставить) Вставляет текст или объект из Clipboard в Code Window или форму пользователя в позицию курсора так же, как команда Edit | Paste (правка | вставить). Find (найти) Открывает диалоговое окно Find для нахождения определенного слова или фразы в модуле; так же, как команда Edit | Find (правка | найти). 3 Программирование на VBA 2002 66 Глава 2 • Кнопка Действие Undo (отменить набор) Отменяет самую последнюю команду, если это возможно (не все действия могут быть отменены); так же, как команда Edit | Undo (правка | отменить набор). Redo (вернуть набор) Возобновляет самую последнюю отмененную команду; так же, как команда Edit | Redo. Run Macro 1 (запуск подпрограм-। мы/UserForm) Запускает текущую процедуру или форму так же, как команда Run | Sub/UserForm. Break (прервать) Прерывает выполнение кода VBA; так же, как команда Run | Break (запуск | прервать). Reset (сброс) Перезапускает код VBA, как команда Run | Reset (запуск | сброс). Design Mode (конструктор) При нажатии этой кнопки Редактор VB переходит в режим Design (конструктора) так же, как командой Run | Design Mode (запуск | конструктор). Project Explorer (окно проекта) Отображает Окно проекта (Project Explorer) так же, как команда View | Project Explorer) (вид ] окно проекта). Properties Window (окно свойств) Отображает Properties Window (окно свойств) так же, как команда View | Properties Window (вид | окно свойств). Object Browser (просмотр объектов) Отображает диалоговое окно Object Browser (просмотр объектов) так же, как команда View | Object Browser (вид | просмотр объектов). Toolbox (панель элементов) Отображает Toolbox (панель элементов) так же, как команда View | Toolbox (вид | панели элементов). Office Assistant (помощник по Office) Отображает окно Справочной системы Microsoft Office для контекстно-зависимой подсказки по текущей задаче. Cursor position (положение курсора) Эта область панели инструментов Standard фактически не является командной кнопкой и появляется только тогда, когда курсор находится в Code Window. Эта область показывает, в какой строке модуля и в каком столбце строки находится курсор вставки. More Buttons Позволяет добавить или удалить кнопки панели. Панель инструментов Edit (правка) По мере того как вы узнаете о написании кода VBA и все больше работаете в окне Code Window (программа), вы можете заметить, что использование панели Edit с целью получения «горячих клавиш» для различных команд редактирования экономит ваше время и усилия. Редактор VB не отображает автоматически панель Edit, если только вы сначала не вывели эту панель на экран, выполнив два шага, указанные в начале этого раздела. В табл. 2.10 приведены командные кнопки по умолчанию на панели инструментов Edit и описывается действие каждой кнопки. При изучении табл. 2.10 обращайтесь к рис. 2.6 для сопоставления имени каждой кнопки со значком на передней стороне кнопки на панели инструментов. Среда Редактора Visual Basic 67 Таблица 2.10. Команды панели инструментов Edit Кнопка Действие List Properties/Methods (список свойств/мето-дов) Отображает раскрывающийся список свойств и методов, принадлежащих объекту, который вы только что ввелр; так же, как Edit | List Properties/Methods (правка | список свойств/методов). List Constants (список констант) Отображает раскрывающийся список предопределенных констант; так же, как Edit | List Constants (правка | список констант). Quick Info (сведения) Отображает всплывающее окно, показывающее правильный синтаксис для объектного метода; так же, как Edit | Quick Info (правка | сведения). Parameter Info (параметры) Отображает всплывающее окно, показывающее параметры (называемые также аргументами [arguments]) функции или оператора VBA; так же, как Edit | Parameter Info (правка | параметры). Complete Word (завершить слово) Завершает текущее ключевое слово VBA, как только вы введете достаточно символов, чтобы VBA идентифицировал слово, которое вы вводите; так же, как Edit | Complete Word) (правка | завершить слово). Indent (увеличить отступ) Сдвигает выделенный текст вправо на одну позицию табуляции; так же, как Edit | Indent (правка | увеличить отступ). Outdent (уменьшить отступ) Сдвигает выбранный текст влево на одну позицию табуляции; так же, как Edit | Outdent (правка | уменьшить отступ). Toggle Breakpoint (точка останова) Устанавливает или отменяет точку прерывания в исходном коде VBA; так же, как Debug | Toggle Breakpoint (отладка | точка останова). Comment Block (закомментировать блок) Превращает выделенный блок текста в Code Window в комментарии, добавляя символ комментария в начало каждой выделенной строки. Эквивалентной команды меню не имеется. Uncomment Block (раскомментировать блок) Удаляет символ комментария из блока выделенного текста в Code Window. Эквивалентной команды меню нет. Toggle Bookmark (закладка) Устанавливает или отменяет закладку в вашем исходном коде VBA; так же, как Edit | Bookmarks | Toggle Bookmark (правка | закладки | закладка). Next Bookmark (следующая закладка) Перемещает курсор вставки в Code Window к следующей закладке; так же, как Edit | Bookmarks | Next Bookmark (правка | закладки | следующая закладка). Previous Bookmark (предыдущая закладка) Перемещает курсор вставки в Code Window к предыдущей закладке; так же, как Edit | Bookmarks | Previous Bookmark (правка | закладки | предыдущая закладка). Clear All Bookmarks (снять все закладки) Удаляет все закладки в модуле; так же, как Edit | Bookmarks | Clear All Bookmarks (правка | закладки | снять все закладки). 3* fi t. Глава 3 Редактирование простых макросов После того как вы немного ознакомились со средой Редактора VB или, по крайней мере, с терминологией, связанной с компонентами редактора, пора рассмотреть более детально те макросы, которые вы должны были записать при помощи макрорекордера, и те, которые были написаны без рекордера и содержали только вывод краткого сообщения. Редактирование макросов Начнем с редактирования ранее записанных макросов, так как по мнению многих авторов книг в этой области такой подход быстро приносит определенную пользу. Многие опытные программисты предпочитают книги по программированию с большим количеством кода (конечно, код должен быть хорошего качества). Перед тем как вы сможете редактировать макрос, необходимо отобразить модуль, содержащий этот макрос. Например, чтобы редактировать макрос ВыделитьТекст в Word, который вы могли записать при чтении первой главы, вы должны сначала отобразить модуль в Normal.dot (где было предложено сохранить записываемый макрос), содержащий исходный код макроса ВыделитьТекст. Аналогично, для редактирования макроса FormatArialBoldl2 в Excel, который вы также записали в главе 1, вы должны сначала отобразить модуль в рабочей книге Personal.xls (где был сохранен записанный макрос), содержащей исходный код макроса Format-ArialBoldl2. Отображение модуля Как найти модуль, содержащий необходимый макрос? Для этого в Редакторе VB для Excel 2002 выполните следующую процедуру: 1. Нажмите Alt+Fll, чтобы активизировать Редактор VB, если он еще не открыт. 2. Выберите команду View | Project Explorer (Вид | Окно проекта), чтобы отобразить Project Explorer. 3. Просмотрите дерево-список в Project Explorer, чтобы найти модуль, который вам необходимо отобразить. Если опция просмотра папок в Project Explorer включена, вы найдете все модули проекта в папке Modules вашего проекта (рис. 3.1). 4. Дважды щелкните на модуле, который вам необходим. Редактор VB отображает этот модуль в Code Window (Окно программы). После того как вы отобразите модуль, можете использовать список Procedure (процедура) в Code Window для получения определенного макроса в этом модуле. Вы можете также использовать метод, описанный в следующем разделе, для нахождения макроса без предварительного открытия модуля, содержащего этот макрос. Редактирование простых макросов 69 Рис. 3.1 Все модули проекта вы найдете в папке Modules Как найти записанный макрос Поскольку Word всегда сохраняет записанные макросы в модуле NewMacros документа или шаблонного файла, найти исходный код макроса в Word просто. Найти исходный код макроса в Excel может быть немного сложнее. Когда вы записывали макрос FormatArialBoldl2 в Excel 2002 во время изучения первой главы, вы сохранили его в рабочей книге Personal.xls. Если это был первый макрос, какой вы когда-либо записали и сохранили в Personal.xls, Excel сохранил макрос FormatArialBoldl2 в модульном листе с именем Modulel. Если бы вы затем записали другой макрос в том же самом сеансе работы, Excel также сохранил бы его в том же самом модуле (Modulel). Если вы выходили из Excel между временем записи вами макроса FormatArialBoldl2 и временем записи другого макроса, Excel сохранил последний макрос в другом модуле (скорее всего, в Module2). Использование инструмента Object Browser Вместо поиска по всему тексту во всех модулях определенного макроса вы можете использовать инструмент, называемый Object Browser, чтобы найти этот макрос, вывести на экран или редактировать, независимо от того, где он находится — в Word, Excel или других приложениях. Для использования инструмента Object Browser в Excel выполняйте следующие шаги: 1. Нажмите Alt+Fll, чтобы открыть Редактор VB. 2. Выберите View | Project Explorer (Вид | Окно проекта) для отображения Project Explorer (рис. 3.2). Рис. 3.2 Выделите проект в Project Explorer перед поиском макроса в окне Object Browser Project - VBAProject ® Г '• [б] IVHAPrnjert (PERSONAEJCESj! (+ Microsoft Excel Objects Cj Modules * Й VBAProject (Важные_данные.х1$) 70 Глава 3 3. В Project Explorer выделите проект VBA, в котором вам необходимо найти макрос. Например, на рис. 3.2 показана книга Personal.xls, выделенная в Project Explorer. 4. Выберите команду View | Object Browser (Вид | Просмотр объектов). Редактор VB отобразит диалоговое окно Object Browser, показанное на рис. 3.3. Project Library Search Text Search '<AII Ubiaile«> , Object Browser Classes View Definition Show Search Results Members of <globals> * Abs Й1 ActiveCell eS1 ActiveChart eS* ActivePnnter .............’ й? ActiveWmdow tS? ActiveWorkbook eS* Addins AppActivate Й? Application о Asc о AcrR globais> Ш Addin *51 Addins Л Adjustments AllowEditRange AllowEditRanges Answerwizard oS AnswerWizardFiles Application Areas 6$ Assistant <S*A AntnOnrrprt Property ActlvaSheet As Object read only Member of [jod Рис. 3.3. Используйте диалоговое окно Object Browser для более легкого поиска макросов и модулей, в которых они сохраняются 5. Убедитесь, что в раскрывающемся списке Project/Library (Проект/Библиотека) выделен элемент <AII Libraries> (<Все библиотеки;»). Окно Object Browser отображает все имеющиеся модули и объекты в списке Classes (Классы). 6. Введите имя макроса, который вам необходимо найти, в текстовом окне Search (поиск). Например, чтобы найти исходный код для макроса FormatArialBoldl2 в Excel, введите FormatArialBoldl2 в поле Search Text (Образец поиска). 7. Щелкните на кнопке Search (Поиск) в окне Object Browser (см. рис. 3.3). Object Browser выполняет поиск текста, который вы ввели в окно Search Text, в вашем • проекте VBA (а также в других открытых в данный момент библиотеках). После выполнения поиска меняется вид окна Object Browser: оно отображает список Search Results, показанный на рис. 3.4. Если Object Browser обнаружил макросы, совпадающие с текстом в окне Search Text (образец поиска), они отображаются в списке Search Results (результаты поиска). В противном случае, в этом списке отображается сообщение No items found (элементы не найдены). 8. Щелкните на макросе в списке Search Results, затем — на кнопке View Definition (описания) в окне Object Browser (см. рис. 3.4). Редактор VB открывает Code Window (программы) для модуля, содержащего этот макрос, и отображает исходный код макроса (см. рис. 3.5). Просмотр модулей проекта с помощью Object Browser Если ваш проект не содержит большого количества различных модулей, то легче находить макрос, выполняя следующую альтернативную процедуру: 1. Нажмите Alt+Fll, чтобы открыть Редактор VB. 2. Выберите View | Project Explorer (Вид | Окно проекта), чтобы отобразить Project Explorer. Редактирование простых макросов 71 Рис. 3.4 Окно Object Browser после выполнения поиска макроса FofmatArialBold12 ши All Uhrailes> j ? I Jt! FoimatAi’ialBo’idli ftfT Search Results I iffy л Ipiasp Classes Math Л Modulel ' MsoAiertButtonType « MsoAlertCancelType J1 MsoAlertDefaultType v Members of 'Modulel' FormatArlalBold12 Public Sub FormatArlalBold120 Member of k1<><kibi1 Макрос записан 1/11/2003 (Владимир Кузьменко) Форматирует ячейку Arial Bold, 12 Рис. 3.5 Код макроса FofmatArialBold12 в Code Window 3. В Project Explorer выделите проект VBA, в котором вам необходимо найти макрос. 4. Выберите команду View | Object Browser (Вид | Просмотр объектов). Редактор VB отображает диалоговое окно Object Browser. 5. Выделите имя вашего проекта в раскрывающемся списке окна Object Browser. Если только вы не изменили имени вашего проекта, он называется VBAProject в Excel (Project — в Word). Вы узнаете о том, как переименовать проект, позже в этой книге. 6. Выделите модуль в списке Classes (Классы). Окно Object Browser отображает теперь все макросы в выделенном модуле в списке Members of <object> (компонент <объект>). (Точный заголовок этого списка изменяется в зависимости от объекта, выделенного в списке Classes.) 7. Выделите макрос, исходный код которого вам необходимо увидеть, в списке Members of <object>. 72 Глава 3 8. Щелкните на кнопке View Definition (Описания) в окне Object Browser. Редактор VB открывает Code Window для модуля, содержащего этот макрос, и отображает исходный код макроса. Когда вы выделяете отдельный проект в списке Project/Library (Проект/Библио-тека) окна Object Browser, список Classes (Классы) будет содержать только те объекты, которые являются частью вашего проекта, — обычно один или больше модулей, сам документ Word или рабочую книгу Excel и (если ваш проект является рабочей книгой Excel) один или больше рабочих листов. После того как вы отобразите макрос в Code Window (Окно программы), используя любой из методов, описанных в предыдущем разделе, можете просмотреть или отредактировать исходный код этого макроса. На рис. 3.5 показано Code Window, отображающее исходный код макроса FormatArialBoldl2, записанного в главе 1. Здесь Project Explorer и Properties Window были закрыты, чтобы размер Code Window был настолько большим, насколько это возможно. Теперь вы можете использовать горизонтальную и вертикальную линейки прокрутки для изменения позиции макроса в окне. Можно также использовать команду Edit | Find (Правка | Найти) для поиска имени макроса в модульном листе. Использование команды Edit | Find для поиска текста в модульном листе сходно с поиском текста в рабочем листе Excel, документе Word, презентации PowerPoint и т.д. (Подробнее о команде Edit | Find можно узнать из справочной системы Редактора VB.) Составные части записанного макроса Если вы рассмотрите несколько записанных макросов, то заметите, что все они имеют общие элементы. Листинг 3.1 показывает исходный код для макроса FormatArialBoldl2 в Excel, который вы записали при изучении главы 1. Листинг 3.2 показывает исходный код макроса ВыделитьТекст в Word, также записанный вами во время работы с главой 1. Исходный код макроса в реальных модулях не включает номер каждой строки; Лргх. в этой книге во всех листингах приведены номера строк, чтобы было легче обозна-xSrL-/ чать и обсуждать отдельные строки в различных листингах-примерах. Листинг 3.1. Макрос FormatArialBold12, записанный в Excel 1 Sub FormatArialBoldl2() 2 ' 3 ' FormatArialBoldl2 Macro 4 ' Макрос записан 11.02.2003 (Владимир Кузьменко) 5 ' Форматирует текст ячейки: Arial, Bold, 12 б ' 7 ' 8 With Selection.Font 9 .Name = "Arial" 10 .Fontstyle = "Полужирный" 11 .Size = 12 12 .Strikethrough = False 13 .Superscript = False 14 .Subscript = False 15 .OutlineFont = False 16 .Shadow = False 17 .Underline = xlUnderlineStyleNone 18 .Colorindex = xlAutomatic 19 End With 20 End Sub Редактирование простых макросов 73 Листинг 3.2. Макрос, записанный в Word 1 Sub ВыделитьТекст() 2 ' 3 ' ВыделитьТекст Macro 4 ' Macro recorded 07.02.03 by Владимир 5 ' "Schr(10)^"Устанавливает Arial, Bold, 12 для выделенного текста 6 ' 7 With Selection.Font 8 .Name = "Arial" 9 .Size = 12 10 .Bold - True 11 .Italic = False 12 .Underline = wdUnderlineNone 13 .Underlinecolor = wdColorAutomatic 14 .StrikeThrough = False 15 .DoubleStrikeThrough = False 16 .Outline = False 17 .Emboss = False 18 .Shadow = False 19 .Hidden = False 20 .Smallcaps = False 21 .AllCaps = False 22 .Color = wdColorAutomatic 23 .Engrave = False 24 .Superscript = False 25 .Subscript = False 26 .Spacing = 0 27 .Scaling = 100 28 .Position = 0 29 .Kerning = 0 30 .Animation = wdAnimationNone 31 End With 32 End Sub В листинге 3.1 строка 1 является началом записанного макроса. Каждый макрос VBA начинается с ключевого слова Sub, за которым следует имя макроса. Строку, содержащую ключевое слово Sub и имя макроса, называют строкой объявления (declaration) макроса. За именем макроса всегда следуют пустые круглые скобки; назначение и использование этих скобок подробно описывается в следующих главах". Сейчас же вам необходимо знать только то, что круглые скобки всегда следуют за именем. В листинге 3.1 строки 2-7 являются комментариями. Комментарий (comment) — это строка в макросе VBA, которая, действительно, не содержит инструкции, являющиеся частью этого макроса. Следует всегда помещать комментарии в исходный код макроса с информацией о его назначении. Обратите внимание на то, что каждая строка комментария начинается с апострофа ('). Для VBA любой текст, который следует за апострофом, представляет собой комментарий, начинающийся с апострофа и заканчивающийся в конце этой строки. В языках программирования, в которых допускаются многострочные комментарии, такие комментарии называют конечными. Записанный макрос всегда начинается со строк комментариев, формулирующих имя макроса и содержащих текст, который вы ввели в текстовое окно Description (Описание) диалогового окна Record Macro (Запись макроса) в момент записи этого макроса. Конкретное количество и содержимое строк комментариев в записанном макросе зависит от длины вводимого вами описания. Сразу за объявлением макроса следует тело (body) макроса (которое может включать или не включать строки комментариев). В листинге 3.1 строки 8-19 составляют тело макроса FormatArialBodyl2; в листинге 3.2 строки 7-31 составля 74 Глава 3 ют тело макроса ВыделитьТекст. Каждая строка в теле макроса состоит из одного или более операторов VBA. Оператор (statement) VBA — это последовательность ключевых слов и других символов, которые вместе составляют одну полную инструкцию для VBA. Макрос VBA состоит из одного или нескольких операторов. Операторы VBA в записанном макросе содержат инструкции, соответствующие действиям, которые вы выполняли, когда записывали этот макрос. Например, строка 9 в листинге 3.1 устанавливает шрифт Arial, -строка 10 — размер шрифта и так далее. В листинге 3.2 строка 8 устанавливает шрифт Arial, а строка 9 устанавливает размер шрифта. Каждый из этих операторов соответствует действию, выполняемому при записи макроса. За телом макроса следует строка, содержащая ключевые слова End Sub, которые сообщают VBA о том, что достигнут конец макроса. Макрос в листинге 3.1 заканчивается в строке 20, а в листинге 3.2 — в строке 10. Когда вы запускаете макрос, VBA начинает выполнение кода с первой строки в теле этого макроса (первая строка после объявления макроса) и выполняет инструкции в этой строке последовательно слева направо. Затем VBA переходит к следующей строке и выполняет инструкции в ней и так далее, пока он не достигнет конца макроса, обозначенного оператором End Sub. VBA игнорирует любые строки комментариев, которые могут появиться в теле макроса. Как вы могли уже заметить, многие строки в обоих записанных макросах имеют отступ от левого края. Каждый уровень отступа помогает отделять одну часть макроса от другой. Заметьте, что все тело каждого макроса смещено вправо между ключевыми словами Sub...End Sub для наглядного выделения тела макроса. В других местах (в строках 9-18 в листинге 3.1) операторы расположены с еще большим отступом. Этот второй, больший уровень отступа помогает определить все операторы, заключенные между ключевыми словами With...End With. В следующих главах оператор With...End With будет обсуждаться подробнее. Макрорекордер при создании макроса автоматически делает отступы в коде, чтобы пользователю было легче читать записанный макрос. Когда вы будете писать собственные макросы, следует всегда делать отступы в коде для выделения различных секций макроса. Смещать строки не обязательно; макросы в листингах 3.1 и 3.2 будут так же выполняться, если все строки будут выровнены по левому краю модуля. Размещение строк с отступом выполняется хорошими программистами лишь для более легкого чтения и сопровождения их программ. При использовании цветного монитора, когда вы будете просматривать записанный макрос на экране (используя редактор VB), то заметите, что различные части текста макроса отображаются различными цветами. Комментарии отображаются зеленым цветом, тогда как Sub, End Sub и другие ключевые слова VBA •— синим. Остальной текст в макросе отображается черным цветом для указания на то, что он содержит данные и программные операторы, созданные пользователем. VBA выполняет цветовое кодирование текста на экране, чтобы можно было легко определить, какую часть макроса или оператор вы просматриваете. Редактирование текста макроса При редактировании кода макроса в модуле вы можете использовать команды и методы, известные вам как пользователю Windows, Word или Excel. Редактирование текста в модуле, отображенном в Code Window, похоже на редактирование текста в Windows Notepad или в WordPad. Вы используете ту же клавиатуру, мышь или команды меню Edit (для добавления, удаления, выделения, вырезания, копирования или вставки текста в модуле), которые применяются в Windows Notepad, WordPad. Для сохранения изменений, которые вы вносите в модуль, используйте команду File | Save (Файл | Сохранить) Редактора VB или щелкайте на кнопке Save (Сохранить) на панели инструментов. Любые изменения, которые вы выполняете в моду Редактирование простых макросов 75 ле, также сохраняются всякий раз, когда вы сохраняете документ или файл рабочей книги, содержащий этот модуль. (Word автоматически сохраняет любые изменения в шаблоне Normal.dot, когда вы выходите из Word; Excel выдает запрос на сохранение любых изменений, выполненных в Personal.xls, при выходе.) В качестве примера редактирования макроса сначала запишите новый макрос в Excel следующим образом: 1. Запустите макрорекордер, устанавливая параметры в диалоговом окне Record Macro (запись макроса) так, чтобы макрос сохранялся в книге Personal.xls. 2. Дайте макросу имя NewBook. 3. Запишите следующие действия: выберите из меню File | New и Blank Workbook — в появляющемся в правой части экрана окне New Workbook для создания новой рабочей книги, выберите File | Save As для сохранения этой рабочей книги (используйте имя NewWorkbook). Сразу же после сохранения файла выберите File | Close, чтобы закрыть файл. 4. Остановите макрорекордер. Макрос, который будет записан в результате вышеприведенных действий,, имеет вид, представленный в листинге 3.3. Листинг 3.3. Нередактированный макрос NewBook 1 Sub NewBook() 2 ’ 3 ' NewBook Macro 4 ' Macro recorded 13.02.2003 by Владимир 5 ' 6 7 ' 8 Workbooks.Add 9 ActiveWorkbook.SaveAs Filename:= _ 10 "С:\Мои flOKyMeHTbi\NewWorkbook.xls", _ 11 FileFormat:=xlNormal, Password, WriteResPassword:="", _ 12 ReadOnlyRecommended:=False, CreateBackup:“False 13 End Sub Листинг 3.4 показывает, как может выглядеть макрос NewBook после «косметического» редактирования. Исходный код этого макроса был переформатирован так, чтобы он был более читабельным. Листинг 3.4. Отредактированный макрос NewBook 1 Sub NewBook() 2 ' 3 ' NewBook Macro 4 ' Macro recorded 13.02.2003 by Владимир 5 ' 6 7 ’ 8 Workbooks.Add 9 ActiveWorkbook.SaveAs Filename:= _ 10 "С:\Мои AOKyMeHTbi\NewWorkbook.xls", 11 FileFormat:=xlNormal, _ 12 Password:_ 13 WriteResPassword:_ 14 ReadOnlyRecommended:=False, _ 15 CreateBackup:“False 16 End Sub 76 Глава 3 Символ продолжения строки VBA Посмотрите еще раз на строки 8-13 в листинге 3.4. Обратите внимание на символ подчеркивания (_) в конце каждой из этих строк. Заметьте также, что символу подчеркивания предшествует пробел, отделяя его от другого текста в строке. Эта особая комбинация символа пробела, за которым следует символ подчеркивания в конце строки, называется символом продолжения строки (line-continuation character) и сообщает VBA о том, что следующая строка макроса должна быть присоединена к текущей строке для образования единого оператора. В листинге 3.4 строки 8-13 являются одним оператором, в данном случае — командой, которая сохраняет рабочую книгу и устанавливает несколько опций для нее. Для того чтобы макрос был более читабельным, макрорекордер разделил эту единую логическую строку на несколько физических строк, используя символ продолжения строки, но это разделение (см. листинг 3.3) не намного улучшило читабельность кода. Поэтому код пришлось еще подправить (см. листинг 3.4). Заметьте также, что операторы, разделенные (уместнее было бы говорить «объединенные») символом продолжения строки, размещаются с еще большим отступом, чтобы их было легче обнаружить при чтении кода. Для того чтобы добавить комментарии к макросу NewBook, выполните следующие шаги: 1. Переместите курсор вставки в конец строки 7 (см. листинг 3.4). 2. Нажмите Enter, чтобы вставить пустую строку. 3. Напечатайте апостроф (') — все комментарии начинаются с апострофа. 4. Теперь введите комментарий, в данном случае, введите предложение: «Следующая строка создает новую рабочую книгу». 5. Повторите шаги 1 и 2 для вставки пустой строки перед строкой 10 (см. листинг 3.4). 6. Напечатайте апостроф, чтобы пометить строку как комментарий, а затем введите это предложение: «Следующая строка сохраняет рабочую книгу». Листинг 3.5 содержит модифицированный макрос NewBook; добавленные комментарии являются теперь строками 8 и 10. На рис. 3.6 представлен этот макрос в Code Window. Листинг 3.5. Макрос NewBook с добавленными комментариями 1 Sub NewBook () 2 ’ 3 ' NewBook Macro 4 ’ Macro recorded 13.02.2003 by Владимир ,. .5 ' ’ 6 7 8 ' Следующая строка создает новую рабочую книгу 9 Workbooks.Add 10 ' Следующая строка сохраняет рабочую книгу 11 ActiveWorkbook . SaveAs Filenames "С : \Мои flOKyMeHTbi\NewWorkbook. xls" , 12 FileFormat:=xlNormal, _ 13 Password:="", _ 14 WriteResPassword:_ 15 ReadOnlyReconunended:=False, _ 16 CreateBackup:=False 17 End Sub Редактирование простых макросов 77 Рис. 3.6 Отредактированный макрос NewBook в Code Window -ji Microsoft Visual Basic - Ьажные^данные.хЬ - [Module! (Code)] * Эе < yiew Insert Format Qebug Run Xoofc 4dd-In$ i^bdow tjelp - в * а я-В, см ► и - hg за су w ~ ua mi6,coi9 pGene< al| save Важные „данные xts| Vj plewBoak Sub NewBook() ж ’ h-*wFook ' Mat Г'» г*>.Л v 0/ ' Ь/ **амм») ‘' иедсцлка яс»уь р-лЧочую - Workbooks.Add 1 "лецующая с^сока сохраняя'-’ рабочую кни' , ActiveWorkbook.SaveAs Е11епагое:="С:\Мои flOKyMeHTbi\NewWorkbook.xls", FileFormat.=xlNormal, Password:»”", _ WriteResPassword*»"", __ J ReadOniyRecommended.=False, _ JcreateBackup: «False End Sub ▼ ! ?_<J_ 1 Jt." При добавлении комментариев в макрос NewBook заметьте, что, когда вы вставляете новую строку и начинаете вводить текст, он отображается черным цветом. Когда вы перемещаете курсор вставки в любую другую строку, — либо нажимая на Enter, используя клавиши со стрелками, либо щелкая кнопкой мыши, — новая строка комментария становится зеленой. Это происходит из-за того, что VBA проверяет каждую новую строку, которую вы вводите (или существующую строку, которую вы изменяете) всякий раз, когда курсор вставки покидает эту строку. VBA проверяет каждую новую или измененную строку в макросе для определения того, является ли эта строка правильной с точки зрения синтаксиса. Если новая или измененная строка имеет правильный синтаксис, VBA выполняет цветовое кодирование частей строки, используя схему цветового кодирования, описанную ранее. Если в строке имеется ошибка синтаксиса, VBA отображает всю строку красным цветом и может вывести одно или несколько возможных сообщений об ошибке синтаксиса. Сообщения о синтаксических ошибках описываются более подробно далее в этой главе. Перемещение или копирование макроса из одного модуля в другой Для копирования одного макроса используйте Clipboard, выполняя следующие шаги: 1. Отобразите макрос, который вам необходимо копировать. 2. Выделите весь текст исходного кода макроса. Убедитесь, что вы выделили весь макрос, включая строки Sub, End Sub и все строки между ними. 3. Используйте команду Edit | Сору (Правка | Копировать) для копирования текста макроса в Clipboard. 4. Отобразите модуль, в который вам необходимо копировать этот макрос. 5. Используйте команду Edit | Paste (Правка | Вставить) для вставки текста макроса в модуль. Вы можете пользоваться описанным выше методом для копирования макроса в тот же модуль, в другой модуль одного и того же проекта или в модуль другого проекта. Можно также использовать этот метод для вставки текста макроса в другие приложения Windows, такие как Notepad. 78 Глава 3 Сохранение и перенос модулей как текстовых файлов Если вам необходимо сделать резервную копию всего модуля, вы можете сохранить его как текстовый файл. Сохранение целого модуля как текстового файла полезно, если вы хотите импортировать модуль в другой проект VBA, создать архивные копии вашей работы или перенести модули VBA в Visual Basic 6 Такое сохранение модуля называется экспортированием модуля. После тогр как вы экспортируете модуль, вы можете импортировать его в любой проект VBA или Visual Basic. Экспортирование модулей Для экспортирования модуля как текстового файла выполните следующее: 1. Выделите в Project Explorer модуль, который хотите экспортировать. 2. Выберите команду File | Export File (Файл | Экспорт файла). Редактор VB отображает диалоговое окно Export File (экспорт файла), показанное на рис. 3.7. Диалоговое окно Export File работает в основном так же, как любое диалоговое окно File Save (сохранение документа) Windows. Рис. 3.7 Используйте диалоговое окно Export File для сохранения всего модуля в виде текстового файла 3. Убедитесь, что в списке Тип файла (Save as type) выделен пункт Basic Files (A.bas). Расширение .bas определяет этот файл как файл исходного кода VBA или Visual Basic. Информация, сохраняемая в этом файле, — это читаемый текст. 4. Введите имя экспортируемого файла в текстовое окно Имя файла (File Name). Редактор VB вводит имя модуля по умолчанию. 5. Щелкните на кнопке Сохранить (Save), чтобы экспортировать файл. Редактор VB экспортирует выделенный модуль и закрывает диалоговое окно Export File. Когда вы экспортируете модуль, Редактор VB создает файл читаемого текста, содержащий все макросы в этом модуле. Если необходимо, вы можете просматривать или редактировать файлы .bas, созданные Редактором VBA, с помощью Windows Notepad или Visual Basic. На рис. 3.8 и 3.9 показан экспортированный в файл .bas модуль, содержащий макрос Newbook листинга 3.5, отображенный в Windows Notepad и Visual Basic 6, соответственно. Обратите внимание на то, что текст в файле .bas, отображенный приложением Notepad (на рис. 3.8), содержит строки, начинающиеся со слова Attribute и отсутствующие в модуле в Code Window на рис. 3.6. Редактор VB добавляет эти дополнительные строки к экспортированному файлу .bas, поскольку они содержат информацию, которая потребуется VBA или Visual Basic, если вы в дальнейшем будете импортировать файл .bas в другой проект. Редактирование простых макросов 79 Рис. 3.8 Экспортированный модульный файл, отображенный Записной книжкой (Windows Notepad) Modulel,bas - Notepad tie Format Mew йФ Attribute VB_Name = "Modulel" Sub NewBookО ' NewBook Macro ' Macro recorded 13 02.2003 by Владимир 'Следующая строка создает новую рабочую книгу workbooks.Add 'Следующая строка сохраняет рабочую книгу Activeworkbook.SaveAs Filename:="C.\Mon документы\ме*№огкЬоок xls", _ FileFomat =xlNormal, _ Password_ WriteResPassword.="", _ ReadOnlyRecommended:=False, _ CreateBackup:=False End Sub , Microwfl Visual |des<n] - |Modu(e1 (Code)] x Й?’ Q’ й M ► & ES* Й W & Ln 1, Col 1 File Edit View Project Format 2ebug Run Query Diagram look ftdd-Ins Window Help Xj General j llGenetal) Sub NewBook () ' Na* St uk taunt ‘ reru’-let □ (proje(:tYj I - M Modules I <42 Modulel (Module! ba ' i UtewBook Ca P 6 □ <6> ifln Workbooks.Add * ‘ ж " $ mu ы crppku сохрани *ч гни > ActiveWorkbook.SaveAs FileNaroe:_"C:\HoM докумем'гы\Ме®ЫогкЬоок.х1в"1 FileFormat:"xlNormal, _ Password:"’”’, _ WriteResPassword:"'”’, ReadOn 1 yRecorttnended: "False, __ CreateBackup:«False End Sub ^Module! Module Alphabetic j Categorized j (Name) Returns the name used In code to Рис. 3.9. Экспортированный модульный файл, отображенный при помощи Visual Basic 6 Импортирование модулей Вы можете добавлять любой модуль, экспортированный вами как файл .bas, в любой из проектов VBA. Модуль добавляется в проект импортированием текстового файла .bas. Для того чтобы импортировать файл .bas, выполните следующее: 1. Выделите проект в Project Explorer, в который необходимо импортировать файл .bas. 2. Выберите команду File | Import File (Файл | Импорт файла). Редактор VB отображает диалоговое окно Import File (Импорт Файла), отображенное на рис. 3.10. Диалоговое окно Import File работает в основном так же, как любое диалоговое окно открытия файла Windows. 3. Используйте элемент Папка (Look In) для перемещения на диск и в папку, где содержится файл, который вам необходимо импортировать в ваш проект. Это должен быть файл, который вы создали, используя Редактор VB для экспортирования модуля. 4. Убедитесь, что в списке Тип файлов (Files Of Туре) выделен пункт VB Files (*.frm, *.bas, *.cls). 80 Глава 3 Рис. 3.10 Используйте диалоговое окно Import File для добавления к любому проекту модуля, экспортированного ранее в виде текстового файла 5. Щелкните мышью дважды на имени файла, который вам необходимо импортировать. Редактор VB читает файл и добавляет модуль в ваш проект. Если проект уже содержит модуль с тем же именем, что и модуль, импортируемый вами, Редактор VB добавляет число в конец имени модуля (1, 2, 3 и так далее) для создания уникального имени модуля. Удаление модулей из проекта Возможно, вы решите, что вам больше не нужны макросы, содержащиеся в определенном модуле. Вам может понадобиться удалить модуль из проекта, потому что макросы, которые он содержит, были заменены новыми версиями или потому, что этот модуль содержит экспериментальные макросы, ненужные вам более. Модуль можно удалить из проекта VBA, выполнив следующее: 1. Выделите модуль, который хотите удалить из проекта, в Project Explorer Редактора VB. 2. Выберите команду File | Remove <object> (Файл | Удалить <объект>). Редактор VB отображает окно сообщения, запрашивающее у вас, хотите ли вы экспортировать модуль перед тем, как удалить его (рис. 3.11). Рис. 3.11 Редактор VB не сразу удалит указанный вами модуль Microsoft Visual Basic Do you want to export Module? before removing It? Cancel 3. Щелкните на кнопке Yes (Да), если хотите экспортировать модуль перед его удалением. (Настоятельно рекомендуется экспортировать модуль как файл .bas, если только вы не уверены абсолютно, что вам никогда не понадобятся макросы, содержащиеся в этом модуле). Иначе можно щелкнуть на кнопке No (Нет) для удаления модуля без его экспортирования. 4. Если вы выберите экспортирование модуля перед его удалением, Редактор VB отображает диалоговое окно Export File, описанное ранее в этом разделе. Заполните диалоговое окно Export File, как было описано ранее, и щелкните на кнопке Сохранить. В любом случае Редактор VB удаляет модуль из проекта. Редактирование простых макросов 81 Написание новых макросов и процедур ’ Чтобы записать макрос без использования макрорекордера, вы можете ввести этот макрос в существующий модуль или создать новый модуль, который будет содержать этот макрос. До сих пор в этой книге использовался термин макрос {macro) как для макросов, которые вы записываете рекордером, так и для макросов, которые пишите сами. Существует другой термин, помогающий различать эти макросы. Строго говоря, термин макрос применим только для инструкций, которые вы записываете с помощью макрорекордера (или создаете при помощи, например, Access Macro Builder). Иногда в литературе макросами называют программы, которые не имеют аргументов (вы, наверное, уже поняли, что записываемые рекордером макросы не могут иметь аргументов). Макросы, которые вы пишете заново более точно называются подпроцедурами (subprocedures) или просто процедурами (procedures). Далее в этой книге термин макрос относится к коду, записываемому с помощью макрорекордера, а термин процедура — к коду VBA, который вы пишете сами. Вставка и переименование модуля Если документ (шаблон, рабочая книга, презентация, рисунок) в котором вы хотите сохранить процедуру, еще не содержит модуль, вы должны вставить модуль перед тем, как сможете написать процедуру VBA в этом проекте. Вы можете также вставить новый модуль, если существующие модули заполнены (модуль может содержать не более 4000 строк) или если вы просто хотите создать новую процедуру VBA в ее собственном модуле. Если вы решили написать процедуру VBA в новом модуле, выполните следующие шаги для добавления модуля в проект: 1. Убедитесь, что в host-приложении VBA (Word, Excel, Outlook, PowerPoint, Visio или FrontPage) открыт тот документ, шаблон или рабочая книга, в котором вы хотите сохранить процедуру. 2. Нажмите Alt+Fll для активизации Редактора VB. 3. В Project Explorer выделите проект, в который хотите добавить модуль (скорее всего, в этот момент он там будет один). 4. Выберите команду Insert | Module (Вставка | Модуль) или на панели Standard с помощью кнопки Insert <object> (вторая кнопка слева) выберите в раскрывающемся меню Module. Редактор VB добавляет новый модуль в проект и открывает Code Window для нового модуля. Когда Редактор VB вставляет новый модуль, он дает ему имя в соответствии с правилами, изложенными ранее в этой главе; ваш новый модуль будет иметь имя по умолчанию Module (Модуль) с последующим номером. Всякий раз при вставке модуля следует переименовывать его, чтобы этот модуль имел описательное имя. Для переименования модуля выполните следующие шаги: 1. Выделите в Редакторе VB модуль, который будете переименовывать. 2. Если Properties Window (Окно свойств) еще не выведено на экран, выберите команду View | Properties Window (Вид | Окно свойств) (или щелкните на кнопке Properties на панели инструментов), чтобы отобразить его. На рис. 3.12 показано Properties Window для модуля; модули имеют только одно свойство — имя. 3. В текстовое поле Name (Имя) в Properties Window введите новое имя для модуля. Как только вы уберете курсор вставки из текстового поля Name, Редактор VB переименует модуль. 82 Глава 3 Рис. 3.12 Изменяйте имя модуля, изменяя его свойство Name Properties Module 1 Module 1 Module 3J Alphabetic | categorized | Выделение существующего модуля Для написания новой процедуры в существующем модуле необходимо сначала открыть Code Window (Окно программы) для модуля, в котором вы хотите написать процедуру. Чтобы открыть Code Window для модуля, либо щелкните дважды на этом модуле в Project Explorer, либо выделите этот модуль в Project Explorer и затем выберите команду View | Code (Вид | Программа). Написание текста процедуры Чтобы написать исходный код для процедуры, независимо от того, добавляете ли вы процедуру в новый или в уже существующий модуль, поместите курсор вставки в Code Window в то место в модуле, куда вы хотите ввести новую процедуру- Вы можете ввести исходный код новой процедуры VBA в любом месте в модуле, следя за тем, чтобы новая процедура начиналась после оператора End Sub, который заканчивает предыдущую процедуру, и перед оператором Sub, который начинает следующую процедуру в модуле. Для многих пользователей самым простым является добавление новых процедур в конец модуля. Когда вы пишете новую процедуру, вы должны указать имя процедуры и включить ключевое слово Sub в начале процедуры и ключевые слова End Sub — в конце. Если вы опустите любой из этих трех элементов, синтаксис процедуры не будет верным и VBA отобразит сообщение об ошибке, когда вы попытаетесь запустить эту процедуру. Первой классической программой в любом описании языка программирования является программа, отображающая на экране сообщение «Hello, World!»1. Листинг 3.6 показывает такую программу VBA, состоящую из единственной процедуры. Листинг 3.6. Процедура HelioWorld 1 Sub HelioWorld() 2 MsgBox "Hello, World!" 3 End Sub Для самостоятельного ввода этой программы VBA выполните следующие шаги: 1. Откройте любой документ Word или рабочую книгу Excel или создайте новый документ или рабочую книгу. 2. Нажмите Alt+Fll для активизации Редактора VB. 3. В Project Explorer выделите документ или рабочую книгу, в которой хотите сохранить эту программу. В первой главе эта традиция была нарушена, но там макрос создавался только в «рекламных» целях и деталям его создания внимания не уделялось. Редактирование простых макросов 83 4. Выберите Insert | Module (Вставка | Модуль), чтобы добавить новый модуль к вашему проекту. Редактор VB добавляет новый модуль и открывает для него Code Window. 5. Переименуйте новый модуль, дав ему имя FirstProgram. 6. Убедитесь, что курсор вставки находится в начале пустой строки в Code Window, и введите текст, показанный в листинге 3.6, нажимая на Enter в конце каждой строки для начала новой строки. Вводите исходный код из листинга 3.6 в модуль точно так, как он выглядит в листинге, но без номеров строк. Редактор VB содержит несколько возможностей, помогающих в написании процедур. Во-первых, как только вы нажмете на Enter после ввода ключевого слова Sub и имени процедуры, Редактор VB автоматически добавляет ключевые слова End Sub. Таким образом, вам не приходится беспокоиться о том, что вы можете случайно забыть об этом важном элементе процедуры. Во-вторых, Редактор VB включает возможность, известную как Auto Quick Info (краткие сведения). Как только вы вводите MsgBox и нажимаете на клавишу пробела (строка 2 листинга 3.6), появляется всплывающее окно, показывая полный список аргументов для встроенной процедуры VBA или функции, которую вы только что ввели (MsgBox — в данном случае). На рис. 3.13 показано всплывающее окно с информацией об аргументах встроенной VBA-процедуры MsgBox. Аргумент, значение которого, как ожидается, вы теперь должны ввести, выделен полужирным шрифтом во всплывающем окне Auto Quick Info. [Аргумент (argument) — это информация, которая необходима процедуре для выполнения ее задачи; подробнее об аргументах вы узнаете далее]. Всплывающее окно Auto Quick Info закрывается, если вы нажимаете на Enter для начала новой строки в Code Window или используете клавиши со стрелками или мышь для перемещения курсора вставки с текущей строки на другую. Вы можете также закрыть окно Auto Quick Info, нажимая на клавишу Esc. Рис. 3.13 Всплывающее окно Auto Quick Info для MsgBox •S Microsoft Visual Basic - ChapterOS - (Modulel (Code)] nx EHe Edit yew insert Format Debug bun Tools Add-Ins ^hdow help .ex й jit ’ hi £5* > 11 • ’ pGenetaif" '""’“'Vj [HeHWoid — —.... Sub HellWord () MsgBox | End MsgBox(Prompr, [Sutfons As VbMsgBoxStyle = vbOKOnly] [Trffe], [HelpFile], [Context]) As ' VbMsgBoxResult Если вас интересует возможность Auto Quick Info, вы можете включать и выключать ее с помощью команды Tools | Options (Сервис | Параметры) в Редакторе VB. Более подробно о диалоговом окне Options (Параметры) можно узнать из справочной системы Редактора VB. Каждое объявление процедуры должно начинаться с ключевого слова Sub, за которым следует пробел и затем — имя процедуры. В листинге 3.6 именем процедуры является HelloWorld. Финальная часть объявления процедуры — это пара пустых круглых скобок. Эти скобки обязательны. (Вы узнаете о их назначении в следующих главах). Если вы не включаете эти скобки, VBA добавляет их в объявление процедуры, когда курсор вставки убирается вами из строки объявления. 84 Глава 3 Вторая строка в листинге 3.6 образует тело процедуры и является единственным оператором, выполняющим «полезную» работу. Тело процедуры может состоять из одного или многих операторов или не состоять ни из одного оператора. Оператор MsgBox отображает сообщение в диалоговом окне на экране и описывается более подробно далее в этой главе. Третья и последняя строка процедуры HelloWorld — End Sub — завершает процедуру. Эта строка сообщает VBA о том, что это — конец процедуры; VBA прекращает выполнение процедуры при достижении им этой строки. Подобно объявлению процедуры, оператор End Sub должен быть первыми двумя словами в строке и должен быть один в строке, хотя вы можете добавлять конечный комментарий после него. Как было упомянуто ранее, Редактор VB автоматически добавляет эту строку, после того, как вы введете объявление процедуры. После того как вы введете исходный код для процедуры HelloWorld, выполните ее, используя метод, о котором вы узнали в главе 1: 1. Выберите команду Tools | Macros (Сервис | Макрос) для отображения диалогового окна Macros (макрос). 2. Выберите процедуру HelloWorld в списке Macro Name (Имя макроса). 3. Щелкните на кнопке Run (Запуск). Когда VBA выполняет процедуру HelloWorld из листинга 3.6, он отображает диалоговое окно, показанное на рис. 3.14. Точный заголовок этого диалогового окна зависит от того, в каком host-приложении (Word, Excel и т.д.) вы создали процедуру. Щелкните на кнопке ОК для установки диалогового окна в исходное состояние и завершения процедуры. Рис. 3.14 Это окно отображает процедура HelloWorld, приведенная в листинге 3 6 Hello, World1 Microsoft Word OK Заметьте, что даже в этой короткой процедуре тело процедуры расположено с отступом для отделения его от объявления и конца процедуры. Следует всегда размещать код с отступом, чтобы его было легче читать. Сравните листинг 3.6 со следующими далее строками кода; вы видите, что даже короткие процедуры легче читать, если строки в них расположены с отступом. 1 2 3 1: Sub HelloMacroQ 2: MsgBox "Hello, World1" 3: End Sub Свойство Auto-Indent (автоотступ) Текстовый редактор VBA содержит свойство, называемое автоматический отступ {auto indenting), позволяющее форматировать исходный код с различными уровнями отступа. Если свойство автоматического отступа включено, то всякий раз, когда вы нажимаете на Enter, чтобы начать новую строку, курсор вставки на новой строке автоматически перемещается в положение, совпадающее с уровнем отступа строки, расположенной выше. (Нажмите на Backspace, чтобы вернуться к предыдущему уровню отступа). Для включения и выключения автоматического отступа устанавливайте или отключайте флажок Auto Indent (автоотступ) на вкладке Editor (редактор) диалогового окна Options (параметры). Свойство автоматического отступа является включенным по умолчанию. Редактирование простых макросов 85 Запуск процедуры во время редактирования Независимо от того, пишете ли вы новую процедуру или редактируете записанный макрос, вам потребуется запускать эту процедуру для проверки результатов ваших усилий. Вы уже знаете, как использовать диалоговое окно Macros для запуска макроса или процедуры; вы можете их также запускать непосредственно из модуля во время редактирования (как это было показано в первой главе). Отображение сообщений для пользователя процедуры Листинг 3.6 включает VBA-оператор MsgBox, который можно использовать для отображения процедурами сообщения на экране. Сообщения или другая информация, которую процедура отображает на экране, пересылает на принтер или записывает в дисковом файле, называется выходом (output). Оператор MsgBox является простейшей формой экранного выхода, которую вы можете включать в процедуры VBA. Оператор MsgBox подобен встроенной в VBA процедуре. Строка в процедуре HelloWorld, содержащая оператор MsgBox, сообщает VBA, что необходимо вызвать эту встроенную процедуру. Оператор MsgBox из листинга 3.6 приводится ниже еще раз: MsgBox "Hello, World!" Текст, заключенный в кавычки, в этой строке после имени процедуры MsgBox — это текст сообщения, которое должно отображаться с помощью MsgBox. VBA передает эту дополнительную информацию процедуре MsgBox. Дополнительная информация, передаваемая процедуре, которую вызывает исходный код, называется аргументом (argument) для этой процедуры. Текст "Hello, World!" является аргументом для процедуры MsgBox. Двойные кавычки (") в аргументе "Hello, World!" указывают на то, что текст, заключенный в них, является данными для процедуры, а не инструкциями, которые должен выполнить VBA. Обратимся еще раз к рис. 3.14 и заметим, что строка заголовка в диалоговом окне, отображаемом оператором MsgBox, содержит слова «Microsoft Word». По умолчанию диалоговое окно, отображаемое оператором MsgBox, имеет заголовок, указывающий на host-приложение, выполняющее процедуру VBA (в данном случае — Microsoft Word). Вы можете изменить заголовок диалогового окна, которое отображает MsgBox. Листинг 3.7 показывает процедуру HelloWorld из листинга 3.6 с оператором MsgBox, измененным таким образом, что он отображает диалоговое окно, показанное на рис. 3.15. Сравните рис. 3.14 и 3.15 и обратите внимание, что теперь заголовком диалогового окна MsgBox является текст «Окно приветствия». Листинг 3.7. Отображение настраиваемой строки заголовка с помощью MsgBox 1 Sub HelloMacroO 2 MsgBox "Hello, World!", , "Окно приветствия" 3 End Sub Рис. 3.15 Заметьте, что заголовок диалогового окна отлтчается от показанного на рис. 3.14 Окно приветствия НеИо, World1 ОК 86 Глава 3 Оператор MsgBox (строка 2 листинга 3.7) теперь отличается от используемого в предыдущем листинге, хотя все еще выполняет ту же самую задачу в процедуре — отображать сообщение для пользователя. В листинге 3.7 оператор MsgBox имеет три аргумента (которые следуют после него); каждый аргумент отделяется от других запятой. Первый аргумент оператора MsgBox такой же, как в листинге 3.6, и является текстом, который должен быть отображен посредством MsgBox (показанный во всплывающем окне Quick Info как аргумент Prompt). Поскольку этот вариант оператора MsgBox имеет более одного аргумента, за первым аргументом следует запятая; списки аргументов {argument lists) в процедурах VBA отделяются запятыми, точно так, как элементы в каком-либо списке. Как только вы ввели запятую, отделяющую первый аргумент от второго, вы, вероятно, заметили, что всплывающее окно Quick Info изменяется: аргумент Buttons в окне Quick Info выделяется полужирным шрифтом, тогда как аргумент Prompt отображается опять обычным шрифтом. В то же время, в модуле появляется раскрывающийся список; этот список содержит все возможные значения для аргумента Buttons. Появляющийся список является результатом свойства Auto Data Tips (подсказка значений данных) Редактора VB. Это свойство работает подобно свойству Auto Quick Info, но отображает списки допустимых значений для аргументов процедуры и других элементов в коде VBA. Второй аргумент оператора MsgBox является необязательным; в данном примере необязательный второй аргумент опущен. Поскольку необязательный аргумент опускается, в списке аргументов имеется один символ пробела. Этот пробел указывает VBA на то, что в этом списке пропущен необязательный аргумент. За символом пробела следует запятая, чтобы отделить его от следующего аргумента в списке. Если вы не введете символ пробела между двумя запятыми, VBA добавляет его. Необязательный второй аргумент в операторе MsgBox — это аргумент Buttons. Он появляется во всплывающем окне Auto Quick Info, заключенный в квадратные скобки для указания того, что это — необязательный аргумент. Аргумент Buttons определяет, сколько и какого типа командные кнопки появляются в диалоговом окне, отображаемом посредством MsgBox. Когда вы опускаете необязательный второй аргумент (как в этом примере), диалоговое окно, которое отображает MsgBox, содержит только одну кнопку — кнопку ОК. (Подробнее о необязательном аргументе Buttons описывается в следующих главах). Третий и последний аргумент в операторе MsgBox определяет заголовок диалогового окна (см. рис. 3.15). Как только вы вводите запятую, отделяющую второй и третий аргументы в списке аргументов оператора MsgBox, всплывающее окно Auto Quick Info указывает, что вы теперь должны ввести значение аргумента для аргумента Title. Подобно первому аргументу текст для строки заголовка диалогового окна заключается в кавычки (""). VBA всегда воспринимает заключенный в кавычки текст как данные, а не как текст, содержащий программные инструкции. Если вы опустите кавычки для текста сообщения MsgBox или для текста строки заголовка диалогового окна, VBA отобразит сообщение об ошибке. Поскольку третий аргумент является также и последним, никакой запятой после третьего аргумента не требуется. Сообщения об ошибках во время написания, редактирования или выполнения процедуры При написании или редактировании процедуры, вы можете сделать ошибки в операторах. VBA определяет многие из этих ошибок во время написания и редактирования вами исходного кода и может обнаружить некоторые ошибки при выполнении процедуры. Редактирование простых макросов 87 Ошибки синтаксиса Синтаксисом (syntax) — называется определенный порядок слов и символов, который образует правильный оператор VBA. Некоторые из наиболее общих ошибок, с которыми вы сталкиваетесь во время написания или редактирования процедур VBA, — это ошибки синтаксиса (syntax errors), например, пропущенные запятые, кавычки, аргументы и так далее. Всякий раз, когда вы пишете новую строку кода или изменяете существующую, VBA анализирует (parses) строку, как только курсор вставки перемещается из новой или измененной строки. [Синтаксический анализ (parsing) — так называется процесс разбивки оператора VBA на составляющие части и определение того, какие части строки являются ключевыми словами, переменными или данными; этот процесс подобен анализу предложения в каком-либо языке для определения его составляющих частей — существительных, глаголов, прилагательных и так далее]. После выполнения анализа строки кода VBA компилирует эту строку кода. Компиляция (compiling) в VBA означает составление исходного кода в форме, которую VBA может непосредственно выполнять без необходимости снова анализировать код. После того как VBA успешно завершит анализ и компиляцию строки кода в процедуре и не будет обнаружено никаких ошибок, выполнится цветовое кодирование различных частей строки. (Помните, ключевые слова в Редакторе VB отображаются синим цветом, комментарии — зеленым, а данные или другие операторы отображаются в виде черного текста.) Если, однако, VBA обнаруживает ошибку синтаксиса в строке в процессе анализа или компиляции, VBA отображает всю строку красным цветом и выводит на экран диалоговое окно с сообщением об ошибке. Рассмотрим следующий фрагмент кода, представляющий неправильно написанный оператор MsgBox: MsgBox "Hello, World1", , Окно приветствия В этом примере кавычки, необходимые вокруг текста, определяющего заголовок диалогового окна, были случайно пропущены. В результате VBA не может определить, что два слова в последнем аргументе являются данными; вместо этого VBA воспринимает слово Окно как имя переменной. [Переменной (variable) называют место в памяти, используемое для сохранения данных. Переменные описываются в следующей главе.] Поскольку третий аргумент воспринимается как переменная с именем приветствия, VBA «ожидает» запятую или конец списка аргументов для процедуры MsgBox. Вместо этого, VBA находит символ пробела, за которым следует, как это кажется, имя другой переменной. VBA отображает всю строку красным цветом, чтобы указать, что она содержит ошибку, выделяет слово или символ в том месте строки, где, по определению VBA, находится ошибка, и затем отображает диалоговое окно, показанное на рис. 3.16. Если вы получаете подобное сообщение об ошибке синтаксиса или компилирования, щелкните на кнопке Help для доступа к справочной системе VBA и получения более подробной информации о конкретной встретившейся ошибке синтаксиса1. Чтобы удалить диалоговое окно, щелкните на кнопке ОК. После удаления с экрана диалогового окна с сообщением об ошибке попробуйте устранить ошибку. Вы можете переместить курсор вставки со строки после удаления диалогового окна, но строка остается отображенной красным цветом для указания на то, что в ней содержится ошибка. VBA не анализирует и не компилирует строку, содержащую ошибку синтаксиса снова, пока вы не запустите проце- 1 К сожалению, в окне справочной системы появляется не описание конкретной синтаксической ошибки, а описание самого понятия синтаксической ошибки под заголовком Syntax error. 88 Глава 3 дуру или не отредактируете эту строку. VBA анализирует строки в процедуре только тогда, когда вы убираете курсор вставки со строки непосредственно после внесения изменений или когда запускаете процедуру. Если при выполнении процедуры встречается строка с синтаксической ошибкой, выполнение кода прекращается, отображается модуль, содержащий процедуру, в которой имеется ошибка синтаксиса, выделяется конкретная строка в модуле, где обнаружена ошибка и отображается диалоговое окно с сообщением об ошибке. Рис. 3.16 VBA отображает сообщения об ошибках ситаксиса, анализируя каждую строку, которую вы вводите или изменяете Ble Edit kiew insert Fyi mat bebug Bun Tools Add Ins Window yelp « в1 > й Д • U X I» » > II К gy и [iGeneial) ж] jHellWoKl Sub HellWord () End MggEox SorMi”, , Огне' Sub Microsoft Visual Basic К error Syntax error Help Диалоговое окно, которое VBA отображает для ошибки синтаксиса, обнаруженной при выполнении процедуры, обычно содержит гораздо меньше деталей о конкретной ошибке, чем диалоговое окно, которое VBA отображает, когда обнаруживает ошибку синтаксиса после того, как вы напишете или измените строку. По этой причине (и для того, чтобы избежать проблем, вызванных неожиданным прерыванием выполнения процедуры) следует всегда стараться исправлять ошибки синтаксиса, когда VBA их обнаруживает впервые. VBA обнаруживает многие ошибки синтаксиса, информируя о пропущенных запятых, кавычках и так далее. Однако не всякое сообщение об ошибке такое понятное, как хотелось бы. В некого-, рых случаях VBA не может определить, что именно неверно в синтаксисе конкретного оператора, а только сообщает об имеющейся ошибке. Ошибки времени исполнения Вы можете создать синтаксически правильный оператор VBA, который все же не выполняется правильно. Ошибки, которые выявляются только при фактическом выполнении процедуры, называются ошибками времени исполнения (runtime errors) или runtime ошибками. Существуют различные типы таких ошибок. Они обычно вызваны пропуском аргументов процедуры, аргументами неверного типа данных, пропуском ключевых слов, попытками доступа к несуществующим драйверам диска и папкам каталога или ошибками в логике. Рассмотрим следующий оператор VBA, который снова содержит неправильный оператор MsgBox: MsgBox "Hello, World1", "Окно приветствия" В этом примере VBA не находит ничего неверного в синтаксисе оператора MsgBox: текст данных правильно заключен в кавычки и список аргументов правильно разделен запятыми. (Поскольку все аргументы, кроме первого для MsgBox являются необязательными, VBA принимает два аргумента для MsgBox в качестве пра Редактирование простых макросов 89 вильного синтаксиса.) Однако когда VBA пытается выполнить оператор в этой строке, он отображает диалоговое окно с сообщением об ошибке, показанное на рис. 3.17. Это диалоговое окно информирует о том, что возникла ошибка при выполнении процедуры, и отображает сообщение, описывающее эту ошибку. В данном случае ошибкой является ошибка несоответствия типа (type mismatch). Если вы еще раз посмотрите на вышеприведенный оператор MsgBox, то можете заметить, что отсутствует запятая, отмечающая место для необязательного MsgBox-аргумента Buttons. Рис. 3.17 VBA обнаруживает некоторые ошибки только во время выполнения процедуры и отображает диалоговое окно с сообщением об ошибке времени исполнения File Edit View Insert Format Qeoug Kun Tools Addins vvndow Help -вх йд-н в* » - > ii «иjMi-уч' g__________ ((General) " V] (HellWoiil Sub HellWordO MsgBox ’Hello, florid!'', "окно приветствия” Microsoft Visual Basic Run time error 13' Type mismatch Когда VBA анализирует этот оператор, заключенный в кавычки текст «Окно приветствия» компилируется как второй аргумент MsgBox, а не как третий аргумент из-за пропущенной запятой. Поскольку аргумент командной кнопки должен быть числом, а не текстом, VBA сообщает о том, что тип данных, передаваемый процедуре MsgBox, не совпадает с типом данных, ожидаемых для этого аргумента. (Более подробно о типах данных рассказывается в следующей главе.) Диалоговое окно для сообщений об ошибках времени исполнения содержит несколько командных кнопок. Далее описывается каждая из этих кнопок: Continue (продолжить) — Выбирайте эту командную кнопку для продолжения процедуры. Некоторые ошибки времени исполнения позволяют продолжать выполнение процедуры; однако для большинства таких ошибок эта кнопка отключена. End (завершить) — Выбирайте эту кнопку, чтобы закончить процедуру. Debug (отладка) — Выбирайте эту кнопку для перехода в режим прерывания и используйте возможности отладки Редактора VB для отслеживания и решения любой проблемы, вызванной ошибкой времени исполнения. Help (справка) — Эта команда предоставляет доступ к справочной системе VBA и отображает текст подсказки, описывающий конкретную ошибку времени исполнения, которая возникла. Используйте эту кнопку, чтобы получить больше информации, если вам не понятно, что означает данная ошибка времени исполнения. Если вы не понимаете, почему использование определенного ключевого слова VBA или процедуры приводит к ошибке времени исполнения, вы можете получить справку по этому конкретному ключевому слову или процедуре, поместив курсор на этом слове и нажав на клавишу F1. VBA отображает раздел справочной системы для этого ключевого слова или процедуры, если таковой имеется. 90 Глава 3 Печать исходного кода В некоторый момент времени вам может понадобиться распечатать какой-либо исходный код VBA. Может появиться необходимость печати в целях архивирования или документирования, демонстрации или изучения. При печати исходного кода VBA можно печатать все модули в проекте или только модуль текущего выбора. Нельзя выделять для печати отдельные процедуры. Чтобы напечатать исходный код, выполняйте следующие шаги: 1. В Project Explorer выделите модуль или проект, который вам необходимо печатать. Если вы хотите печатать только выделенный текст в модуле, выведите модуль на экран и выделите текст, который необходимо печатать. 2. Выберите команду File | Print (Файл | Печать). Редактор VB отображает диалоговое окно Print (см. рис. 3.18). Рис. 3.18 Вы можете задать различные параметры печати в диалоговом окне Print Print - Project Я Prrter HP LaserJet 5L I °* I Range C Print What ; Cancel ’ Current Module Г Current Projec |> Qode Setup. j Print Quality jHigh Т-Д Print to File Help 1 3. В группе элементов управления Range (Диапазон печати) укажите, будет ли печататься текст текущего выбора, выделенный модуль или весь проект. 4. В группе элементов управления Print What (Печатать) должен быть установлен флажок Code (Программу) (чтобы печатать исходный код); если ваш проект содержит формы, установите флажок Form Image (рисунок формы) для печати рисунка формы. 5. Установите любые другие параметры печати, какие необходимо, так же, как вы это делаете в любом приложении Microsoft Office. 6. Щелкните на кнопке ОК, чтобы напечатать исходный код. Когда вы печатаете проект или модуль, вы не можете предварительно просматривать печатаемый модуль. Отпечатанный листинг из модуля всегда форматируется одним и тем же образом [за исключением ориентации страниц, которую вы можете регулировать, щелкнув на кнопке Setup (настройка) в диалоговом окне Print]. Глава 4 Типы данных, переменные и константы Из этой главы вы узнаете о типах данных, которыми может управлять VBA, и о том, как в VBA хранятся временные данные. Информация, изложенная в этой главе, применима к VBA в любом host-приложении, реализующем VBA, — Word, Excel, PowerPoint, FrontPage, Visio, Outlook и даже Access. В действительности, информация в этой главе также применима к Visual Basic, и все, что вы узнаете о типах данных, переменных и константах, справедливо в любой из реализаций Visual Basic, в которых вы будете программировать. Обзор типов данных Visual Basic Перед изучением переменных, следует понять, как VBA сохраняет различные виды информации. VBA, как и большинство других систем программирования, разделяет обрабатываемые данные на числа, даты, текст и другие типы. Тип данных (data type) — это термин, относящийся к определенным видам данных, которые VBA сохраняет и которыми может манипулировать. В табл. 4.1 обобщены типы данных VBA, показано, какой объем памяти занимает каждый тип, кратко описаны типы данных и дан диапазон значений, которые данный тип может сохранять. •••• (byte) — это единица измерения компьютерной и дисковой памяти Байтсосто-/дгх. ит из восьми......(bits) или двоичных разрядов Обычно один алфавитный сим- вол требует для хранения одного байта памяти Таблица 4.1. Типы данных VBA Название типа Размер в байтах Описание и диапазон значения Byte 1 Для хранения положительного числа от 0 до 255. Boolean 2 Для хранения логическиих значений; может содержать только значения True или False. Currency 8 От -922337203685477.5808 до 922337203685477.5807. Date 8 Для хранения комбинации информации о дате и времени. Диапазон дат может быть от 1 января 100 года до 31 декабря 9999 года. Диапазон времени от 00:00:00 до 23:59:59. 92 Глава 4 Название типа Размер в байтах Описание и диапазон значения Decimal 12 Переменные типа Decimal сохраняются как 96-битовые знаковые целые, масштабируемые значением некоторой степени числа 10. Степень десяти определяет число десятичных знаков справа от десятичной точки и может быть в диапазоне от 0 до28. Если степень масштабного коэффициента равна 0, наибольшее число типа Decimal может быть равно ±79 228 162 514 264 337 593 543 950 335. Для степени 28 наибольшее число: ±7.9228162514264337593543950335, а самое меньшее ненулевое значение равно ±0.0000000000000000000000000001. Double 8 Отрицательные числа: от -1.79769313486232Е10308 до -4.94065645841247Е10-324. Положительные числа: от 4.94065645841247Е10-324 до 1.79769313486232Е10308. Integer 2 Все целые числа от -32768 до 32767. Long 4 Все целые числа от -2147483648 до 2147483647. Object 4 Используется для доступа к любому объекту, распознаваемому VBA. Сохраняет адрес объекта в памяти. Single 4 Отрицательные числа: от -3.402823Е1038 до -1.401298Е10-45 Положительные числа: от 1.401298Е10-45 до 3.402823Е1038 String (переменной длины) 10 байт 't-длина строки Используется для хранения текста. Может содержать от 0 символов до (приблизительно) 2 миллиардов символов. String (фиксированной длины) Длина строки (один байт на один символ) Используется для хранения текста. Может содержать от одного до (приблизительно) 654000 символов. Variant 16 байт + 1 байт/символ Тип Variant может хранить любой другой тип данных. Диапазон для данных типа Variant зависит от фактически сохраняемых данных. В случае текста диапазон соответствует строковому типу; в случае чисел диапазон такой, как у типа Double. Далее в этом разделе более подробно описывается каждый из приведенных в табл. 4.1 типов данных, кроме типа Object (тип Object рассматривается в отдельной главе). Типы данных, переменные и константы 93 Экспоненциальное представление В табл. 4.1 вы встретились с представлением данных, называемым экспоненциальным представлением (scientific notation), которое используется для отображения на внешних устройствах (монитор, принтер и т.д.) очень больших и очень малых чисел в компактном формате. В экспоненциальном представлении значения записываются без начальных и конечных нулей и слева от десятичного знака имеется только одна цифра. Число умножается на 10 в некоторой степени, чтобы показать, где на самом деле находится десятичный знак. Экспоненциальное представление компактно и читабельно по сравнению с обычным представлением числа с 300 нулями после него. Помните, что отрицательная степень приводит в результате к меньшему числу, а положительная — к большему. В исходном коде невозможно использовать надстрочные (superscript) символы, поэтому VBA использует вариацию экспоненциального представления, разработанную специально для компьютеров. В экспоненциальном представлении VBA используйте букву Е с последующей степенью. В следующей таблице приводятся примеры чисел в экспоненциальном и обычном представлении. -2.43Е2 -243 -1.43Е-2 -0.0143 5.5Е10 55 000 000 000 ЗЕ9 3 000 000 000 4.5Е-10 0.00000000045 1.6Е2 160 Вы можете преобразовывать большинство типов данных, приведенных в табл. 4.1, в другие типы. В следующей главе описывается, как VBA автоматически преобразовывает данные и как вы сами можете это делать. Тип Date VBA использует тип Date для хранения дат и времени. Тип Date использует восемь байтов памяти для каждой сохраняемой комбинации дата/время. При работе с данными типа Date следует знать, что VBA-типы Date не являются одними и теми же, что типы данных, используемые в рабочих листах Excel или базах данных Access, хотя они во многом похожи. Нет необходимости беспокоиться о том, как VBA хранит данные типа Date, — можно просто отображать, сохранять или манипулировать датами; VBA автоматически управляет всеми деталями преобразования последовательного числа в год, месяц, день и время. Когда VBA отображает даты, (например, при применении MsgBox), дата представляется в коротком формате, который используется данным компьютером. Аналогично, VBA отображает информацию о времени, сохраняемую с Date, используя 12- или 24-часовый временной формат для данного компьютера. (В Windows 98/NT 4.0/2000 вы можете изменять форматы дат и времени, выбрав значок Язык и стандарты на Панели управления.) VBA-тип Date является типом последовательных дат (serial Dates). (Последовательные даты сохраняют дату как число дней от заданной стартовой даты.) Базовой датой для VBA-типа Date является 30 декабря 1899. VBA использует отрицательные числа для представления дат ранее 12/30/1899 и положительные — для дат после 12/30/1899. Число 0 представляет саму дату 12/30/1899. По этой схеме 1 января 1900 записывается числом 2 (1/1/1990 — это 2 дня после 12/30/1899), 94 Глава 4 однако число -2 является датой 12/28/1899 (два дня до 12/30/1899). Чтобы убедиться в этом, напишите (например, в VBA Outlook) простой макрос: Sub DateTestO MsgBox d End Sub . В результате работы этого макроса на экран будет выдана базовая дата, как показано на рис. 4.1. Рис. 4.1 Базовой датой для VBA-типа Date является 30 декабря 1899 12/31/1899 Некоторые host-приложения VBA, такие как Excel, имеют свои собственные типы данных последовательных дат. Excel for Windows, например, также использует числа последовательных дат, но с другой базовой датой: 1 января 1900. VBA всегда использует одну и ту же базовую дату для последовательных дат типа Date, независимо от схемы дат host-приложения — VBA всегда использует дату 12/30/1899 в качестве базовой. В значении последовательной даты целая часть (цифры слева от десятичного знака) — это общее число дней от базовой даты. Последовательная дата VBA может иметь цифры справа от десятичного знака; эти цифры обозначают время дня как часть дня. Один час — это 1/24 дня (приблизительно 0,0416. Аналогично, одна минута — это 1/1440 дня, а секунда — 1/86400 дня. Вы можете вычитать одну дату из другой, добавлять к дате или вычитать числа для изменения ее значения. Например, если вам необходимо определить количество дней между двумя датами, просто вычитайте более раннюю дату из более поздней. Поскольку это значения типа Date, VBA «знает», что целью вычисления является получение разности в днях между двумя этими датами. Аналогично, если вам необходимо определить дату через 60 дней после данной даты, просто прибавьте 60 к этой дате. В VBA имеется несколько встроенных процедур (описанных в следующих главах) для отдельного извлечения года, месяца, дня, часов, минут и секунд из переменной типа Date. Числа VBA имеет шесть различных численных типов данных: Byte, Integer, Long, Single, Double и Currency. Численные типы данных используются для хранения (и манипулирования) чисел в различных форматах, в зависимости от конкретного типа. Численные типы предоставляют компактный и эффективный способ хранения чисел. Численный тип, заполняющий большую часть памяти (имеющий самый большой диапазон возможных значений), занимает не более восьми байтов памяти для хранения чисел, которые могут иметь до 300 цифр. Типы данных Byte, Integer и Long Integer — это целое число безо всякой дробной части. Числа 1, 3768 и 12 — это все целые числа; числа 1,5; 3,14; 17,21 не являются целыми. (Число 1,0 — не 1 Здесь и далее для обозначения действительных чисел используется знак запятой (,) поскольку имеется в виду обычная математическая запись числа. Типы данных, переменные и константы 95 целое, хотя дробная часть равна нулю; целые никогда не содержат десятичного знака, даже если десятичная часть является нулем). VBA предоставляет три различных целых типа данных: Byte, Integer и Long. Тип Byte — это наименьший из трех целых типов данных VBA и предназначен для хранения чисел только от 0 до 255. Тип Byte использует только один байт памяти (255 — это самое большое число, какое вы только можете получить с восемью битами). Вы не можете хранить отрицательные числа в типе Byte. Обычно типы Byte используются для хранения двоичных данных (графических, звуковых файлов и так далее). Тип Integer требует двух байтов памяти; диапазон чисел, которые вы можете хранить как тип Integer, составляет от -32768 до 32767. Поскольку диапазон для типа Integer сильно ограничен, в VBA имеется другой, больший тип: Long — (длинное) целое. Этот тип для хранения числа использует 4 байта памяти и имеет диапазон значений от -2147483648 до 2147483647. Byte, Integer и Long типы имеют пару преимуществ по сравнению с другими численными типами данных: целые требуют меньше памяти для хранения чисел, чем другие численные типы данных VBA, а математические операции и операции сравнения над числами Byte, Integer и Long типов быстрее, чем эти же операции для численных типов данных с плавающей точкой. Типы Byte, Integer и Long имеют различное применение. Наиболее часто они используются для кумулятивных вычислительных операций вследствие их компактного размера и более быстрой скорости выполнения арифметических операций. Используйте типы Byte, Integer и Long для чисел, которые не имеют дробной части. VBA автоматически преобразует данные типов Byte, Integer и Long в текст, когда вы выводите их на экран с использованием таких процедур, как MsgBox. Числа с плавающей точкой Числа с плавающей точкой (floating point numbers) могут иметь любое число цифр до или после десятичной точки (в пределах границ конкретного типа данных) и получили свое название вследствие того факта, что десятичная точка «плавает» из одной позиции в другую, в зависимости от того, сохраняется в памяти большое или малое значение. Числа 11,0123; -1107,1; 0,0125 и 435,67876 — это числа с плавающей точкой. Числа с плавающей точкой иногда называют также действительными (real) числами. Используйте типы данных с плавающей точкой всякий раз, когда вам требуется сохранить число, имеющее дробную часть. VBA имеет два различных типа данных с плавающей точкой: Single и Double. Для данных типа Single требуется 4 байта памяти, и этот тип может использоваться для хранения отрицательных чисел от -3,402823 х 1038 до -1,401298 х 10 45 и положительных от 1,401298 х 10'45 до 3,402823 х Ю38. Числа, хранимые с использованием типа Single, называются числами одинарной точности (Single-precision numbers). Для данных типа Double требуется 8 байтов памяти, и этот тип может использоваться для хранения отрицательных чисел от -1,79769313486232 х Ю308 до -4,94065645841247 х 10-324 и положительных от 4,94065645841247 х 10-324 до 1,79769313486232 х 1О308. Числа, хранимые с использованием типа Double, называются числами двойной точности (Double-precision numbers). Хотя числа одинарной и двойной точности имеют большие диапазоны, чем другие численные типы данных, у них имеется два небольших недостатка. Операции, выполняемые над числами с плавающей точкой, немного медленнее подобных операций над другими численными типами данных. Кроме того, числа, хранимые как типы данных с плавающей точкой, могут быть подвержены ошибкам округления. Как и в случае с целыми типами данных, VBA автоматически преобразует значения типа Single и Double в текст, когда вы отображаете их с помощью процедур, таких как MsgBox. Если число с плавающей точкой очень большое или очень малое, VBA отображает его в экспоненциальном представлении. 96 Глава 4 Тип данных Currency VBA-тип Currency — это число с фиксированной точкой (fixed-point number), то есть десятичная точка всегда находится в одном и том же месте — справа от десятичной точки всегда имеется четыре цифры. Используйте тип Currency для хранения чисел, когда точность крайне важна, что бывает при «денежных» вычислениях. Тип Currency требует 8 байтов памяти и может сохранять числа от -922337203685477,5808 до 922337203685477,5807. Математические операции над числами типа Currency имеют небольшие или не имеют ошибок округления, поэтому они точнее, чем операции над числами с плавающей точкой. Ошибки округления с числами типа Currency обычно возникают только тогда, когда вы умножаете или делите числа типа Currency на значения другого численного типа. Подобно обработке всех других численных типов данных VBA автоматически преобразует значения Currency в текст, когда вы их выводите на экран. Текстовые строки Любые текстовые данные, сохраняемые в программе VBA, называются строками (strings). Строки в VBA сохраняются с использованием типа данных String. Строки получили такое название, потому что текстовые данные обычно рассматриваются как строки символов. Строка может содержать текстовые символы любых типов: буквы алфавита, цифры, знаки пунктуации или различные символы. Строки в коде VBA всегда заключаются в двойные кавычки ("”). "Малый Браун", "Петр Первый”, "3,1" и ”1 000,00" — это строки. Существуют две категории строк: строки переменной длины, размер которых растет или уменьшается, и строки фиксированной длины, размер которых всегда остается одним и тем же. Все строки в VBA являются строками переменной длины, если только вы не задаете фиксированную длину (об этом будет рассказано далее в этой главе). Типы String играют важную роль во многих программах VBA. Большинство данных ввода пользователей (в диалоговых окнах, ячейках рабочих листов) — это строковые данные. Кроме того, поскольку вы можете отображать на экране только текст, все другие типы данных должны быть преобразованы в строковые данные перед тем, как вы сможете их вывести на экран. Многие встроенные процедуры VBA (подобные Msgbox) используют строковые данные во всех или в некоторых своих аргументах. Если вы широко используете Word VBA, то могли заметить, что процедуры манипулируют исключительно строковыми данными. VBA предоставляет несколько операторов для конкатенации (concatenate), то есть для соединения вместе и для сравнения строк. VBA имеет также несколько встроенных процедур, помогающих извлекать подстроки из более длинных строк, находить символы или слова в строке, изменять регистр букв в строке и так далее. В следующих главах описываются строковые операторы VBA и процедуры для манипулирования строками VBA. Логические значения Обычно VBA-программа (как и любые другие программы) «принимает» решения, проверяя, являются ли истинными различные условия. Для упрощения тестирования условий и обеспечения сохранения результатов такого тестирования в VBA имеется логический тип данных. Логические значения True и False называют булевыми (Boolean) значениями. (Их название связано с именем математика, разработавшего систему математической логики.) Логический тип данных VBA называют также типом Boolean. Boolean-тип VBA требует двух байтов памяти и может иметь одно из двух значений: True или False. Если вы отображаете тип Boolean на экране, VBA автома- Типы данных, переменные и константы 97 тически преобразует его в строку, содержащую либо слово True, либо False. Булевы значения получают как результат операции сравнения. Операция сравнения (comparison operation) имеет место при сравнении одного с другим, например, при сравнении двух чисел для определения, которое из них больше, или сравнении двух строк для определения, которая из строк находится ниже в алфавитном порядке. В следующей главе описываются различные операции сравнения VBA. Тип данных Variant Тип данных Variant — это особый тип данных, который может сохранять любые типы, приведенные в табл. 4.1, за исключением типа Object. VBA использует тип Variant для всех переменных, если только вы не объявляете явно тип переменной, как будет описано далее в этой главе. Данные типа Variant принимают характеристики определенного типа, который они сохраняют в данный момент. Например, если данные типа Variant содержат строковые данные, Variant принимает характеристики типа String. Если данные типа Variant содержат численные данные, Variant принимает характеристики какого-либо численного типа, обычно — Double, хотя типы Variant могут также иметь характеристики типов Integer, Long, Single или Currency. VBA использует для данных типа Variant наиболее компактное представление, возможное для конкретных значений, находящихся в данных. Если VBA сохраняет целое число в переменной типа Variant, это число обрабатывается как данные типа Integer или Long, в зависимости от его размера. Например, для VBA число 15 в типе Variant является данными типа Integer; VBA обрабатывает число 1 000 000 в Variant как данные типа Long. VBA сохраняет большинство чисел с плавающей точкой в данных типа Variant как тип Double и использует тип Variant так, что вам не всегда приходится беспокоиться об указании типов переменных, которые вы используете в коде. Любые переменные, для которых вы не объявляете специально тип, становятся типом Variant. Несмотря на то, что типы Variant удобны и избавляют от некоторой части работы при написании процедур, они требуют большего объема памяти, чем любой другой тип данных, за исключением больших строк. Кроме того, математические операции и операции сравнения над данными типа Variant выполняются медленнее, чем подобные операции над данными любого другого типа. В общем, следует избегать использования переменных Variant: если вы будете полагаться на переменные типа Variant, может сформироваться привычка неаккуратного программирования и вам будет трудно находить и устранять ошибки в программах. Переменные Переменные очень важны, поскольку они обеспечивают возможность в компьютерной программе временно сохранять и манипулировать данными. В этом разделе описывается, что такое переменная и как создавать переменные. Что такое переменная? Переменная (variable) — это имя, которое программист дает области компьютерной памяти, используемой для хранения данных какого-либо типа. Вы можете представлять себе переменную как ящик стола, в который можно положить любой отдельный элемент данных и хранить его для последующего использования. Имя переменной является идентифицирующей меткой для этого ящика стола. Содержимое ящика (значение переменной) может меняться, но наименование ящика 4 Программирование на VBA 2002 98 Глава 4 (имя переменной) остается тем же. Переменные VBA могут хранить любые типы данных, перечисленные в табл. 4.1. В некотором смысле переменная подобна именованной ячейке рабочего листа. В Excel вы можете давать имя ячейке в рабочем листе, а затем ссылаться на эту ячейку по ее имени так, что вам не приходится использовать или даже запоминать фактический адрес ячейки из строки и столбца каждый раз, когда необходимо сослаться на данные или формулы в этой ячейке. VBA (как и все системы программирования) справляется со всеми деталями нахождения конкретных мест в памяти компьютера вместо вас. Нет необходимости беспокоиться о конкретных адресах данных какой-либо переменной, просто используйте имя этой переменной для ссылки на сохраняемые данные. Переменные в операторах VBA используются таким же образом, что и переменные в алгебраических уравнениях. Переменная представляет числа, текстовые данные или другую информацию, которая точно не известна во время написания оператора, но будет в наличии и доступна при выполнении этого оператора. Всякий раз, когда имя переменной появляется в операторе, VBA вставляет в этот оператор фактическое значение, хранимое в текущий момент в участке памяти, на который ссылается переменная. В следующем примере, если переменная AnyNum содержит число 2, то весь оператор будет иметь в качестве результата 4: AnyNum + 2 В качестве другого, более сложного примера, рассмотрим формулу, вычисляющую, какую часть в процентах одно число составляет от другого: Percent = (Part / Whole) * 100 В этом простом операторе переменные с именем Part и Whole представляют два различных числа. Формула в этом операторе вычисляет, какую часть составляет значение, хранимое в переменной с именем Part, от значения, хранимого в переменной с именем Whole, а в переменную с именем Percent помещается результат вычисления. При выполнении этого оператора VBA находит все числа, хранимые в памяти, на которые ссылаются Part и Whole, и вставляет их в оператор перед выполнением любых вычислений. Если, например, до начала выполнения этого оператора значение, хранимое в переменной под именем (можно просто значение переменной) Part, было равно 5, а значение переменной Whole — 20, то результатом, который будет сохранен в переменной Percent, станет число 25. Выбор имен для переменных Можно выбирать любое имя для переменной за небольшими исключениями. В этом разделе сначала объясняются правила и ограничения VBA для имен переменных, а затем описываются некоторые принципы, которыми следует руководствоваться при выборе имен переменных. Идентификаторы Идентификатор (identifier) — это имя, которое вы даете элементам в создаваемых вами процедурах и модулях, таким как переменные. Термин идентификатор основывается на том факте, что имена, которые вы создаете, определяют конкретные участки памяти (в случае имени переменной), группы инструкций (в случае имени макроса или процедуры) или другие элементы программы. При выборе имени переменной необходимо соблюдать следующие правила: Имя переменной должно начинаться с буквы алфавита. После первой буквы имя переменной может состоять из любой комбинации цифр, букв или символов подчеркивания (_). Типы данных, переменные и константы 99 Имена переменных не могут содержать пробелы, точку (.) или любой другой символ, который VBA использует для обозначения математических операций и операций сравнения (=, +, - и так далее). Имена переменных не могут превышать 255 символов. Имя переменной не может дублировать определенные ключевые слова VBA. Если вы выберете имена переменных, дублирующие ключевые слова, называемые ограниченными ключевыми словами (restricted keywords), VBA отображает одно из нескольких возможных сообщений об ошибке синтаксиса. Имя переменной должно быть уникальным в рамках его области действия (scope). То есть имя переменной должно быть уникальным в пределах процедуры или модуля, в котором вы объявляете эту переменную. Некоторые примеры правильных имен переменных: Vari Pay_Date Ald_Item Percent Whole Part Linel2 Примеры неправильных имен переменных: New Item — Неправильно, потому что содержит символ пробела 5thDimension — Не начинается с буквы Dim — Дублирует ключевое слово VBA Week/Day — Содержит неверный символ: VBA интерпретирует косую черту как оператор деления _Рау — Содержит недопустимый символ в начале. Имена переменных не «чувствительны» к состоянию регистра (not case-sensitive), то есть написание имени переменной прописными или заглавными буквами не имеет значения. Имена FirstMyVar и firstmyvar представляют для VBA одно и то же. VBA регулирует написание имен переменных в вашем коде на основе заглавных букв, которые вы использовали в последний раз, когда вводили имя той или иной переменной. Например, если вы вводите имя FirstMyVar, а затем позже — имя переменной firstmyvar, VBA заменяет все вхождения имени First-MyVar на firstmyvar. При выборе имен переменных старайтесь делать их по возможности наиболее информативными: выбирайте имена, подобные AllSum, а не х или у. Хорошим именем для переменной, которая хранит значение, представляющее температуру в градусах Цельсия, является, например, CelsiusTemp или DegreesC. В примере с формулой процентного отношения из предыдущего раздела имена переменных Part и Whole были выбраны так, чтобы отражать назначение и использование чисел, которые они хранят. Создание переменных Самым простым способом создания переменной является использование ее в операторе VBA. VBA создает переменную и резервирует память для ячейки памяти переменной, когда эта переменная в первый раз появляется в операторе (обычно в операторе, сохраняющем значение данных в переменной). Сохранение значения данных в переменной называется присваиванием переменной (assigning the variable или making an assignment). Присваивание выполняется с помощью оператора присваивания, представляемого знаком (=). Следующая строка является примером присваивания значения переменной: MyVar = 25 4* 100 Глава 4 Этот оператор сохраняет численное значение 25 в ячейке памяти, заданной именем переменной MyVar. Если этот оператор первым использует данную переменную в процедуре, то VBA создает эту переменную, резервирует ячейку памяти для хранения данных этой переменной и затем сохраняет число 25 в ячейке памяти, заданной именем переменной. Если переменная MyVar уже существует, то VBA сохраняет число 25 в ячейке памяти, на которую ссылается MyVar. Новое значение заменяет любое, ранее сохраненное в MyVar значение, и предыдущее содержимое MyVar теряется. Создание переменной путем ее использования в операторе называется неявным объявлением переменной (implicit variable declaration). Используя переменную в операторе, вы неявно указываете (объявляете) VBA, что хотите создать эту переменную. Все переменные, которые VBA создает неявным объявлением переменной, имеют тип данных Variant. Неявное объявление переменных известно также как объявление переменных «на лету» (on-the-fly). Неявное объявление переменных удобно, но имеет потенциальные проблемы. Например, когда вы имеете переменную с именем MyVar и сделаете позже ошибку в имени, набирая MVar. В зависимости от того, где появится в вашем коде неправильное имя переменной, VBA может выдать ошибку времени исполнения или просто создать новую переменную. Если VBA создаст новую переменную, у вас могут возникнуть проблемы, которые очень трудно обнаружить. Неявное объявление переменных вызывает также проблемы, если вы записываете оператор присваивания, ошибочно полагая, что неявно объявляете новую переменную, тогда как вы на самом деле используете ранее созданную. В этом случае вы нечаянно уничтожаете ранее сохраненное значение. Это обычно не приводит к ошибке времени исполнения, но вызывает другие проблемы, причину которых трудно обнаружить. По этим и другим причинам VBA предоставляет вам возможность выполнять явное (explicit) объявление переменных. Явное объявление переменных имеет следующие преимущества: Ускоряется выполнение кода. VBA создает все объявленные явно переменные в модуле или процедуре перед выполнением кода процедуры. Скорость выполнения кода увеличивается на то количество времени, которое иначе необходимо для анализа и создания неявно объявляемых переменных. Уменьшается количество ошибок в результате неправильного написания имени переменной. Код становится более читабельным и понятным. Видя все объявления переменных в начале модуля или процедуры, пользователь может легко определить, какие переменные используются в этом модуле или процедуре. С помощью явного объявления переменных можно нормализовать выделение заглавными буквами в имени переменной. Если вы явно объявляете переменную, VBA всегда изменяет заглавные буквы в имени переменной в операторе VBA в соответствии с именем в объявлении переменной. Например, если вы явно объявляете переменную с использованием заглавных букв в имени Му Value, а затем позже введете имя этой переменной как myvalue, VBA заменяет myvalue на MyValue для соответствия выделению заглавными буквами в явном объявлении: MyValue > Для явного объявления переменных используйте VBA-оператор Dim со следующим синтаксисом: СИНТАКСИС Dim namel [, name2] nameN — это любой допустимый идентификатор переменной. Например: Типы данных, переменные и константы 101 Dim PentProfit Dim PentProfit, Gross_Income, Total_Costs Первый из вышеприведенных операторов указывает VBA создать переменную с именем PentProfit. (Ключевое слово Dim, между прочим, является сокращением слова Dimension). Все переменные, которые вы создаете с этой формой ключевого слова Dim, являются переменными типа Variant. Всякий раз, когда VBA создает новую переменную, эта переменная инициализируется: строки инициализируются пустыми строками (не содержат символов), числа — значением 0, переменные Boolean — значением False, даты — 30 декабря 1899 года. Переменную можно объявлять только один раз в отдельной процедуре или модуле. Так как оператор Dim находится перед любыми операторами, фактически использующими переменную, вы можете помещать его в любом месте в процедуре. В практике программирования хорошим правилом является собирать все явные объявления переменных в одном месте в начале процедуры. В листинге 4.2 приведена процедура HelloWorld из предыдущей главы, модифицированная для явного объявления переменной с именем HelloMsg, которую она использует для хранения текста, отображаемого оператором MsgBox. (Процедура HelloWorld в листинге 4.1 отображает диалоговое окно, показанное на рис. 4.2). Листинг 4.1. Процедура HelloWorld с явным объявлением переменной 1 Sub HelloWorld() 2 Dim HelloMsg ' переменная для MsgBox 3 HelloMsg = "Hello, World!" 4 MsgBox HelloMsg, , "Окно приветствия" 5 End Sub Оператор Dim (в строке 2) листинга 4.1 объявляет переменную HelloMsg и резервирует для нее область памяти (в данной подпрограмме HelloMsg — это переменная типа Variant). Строка 2 включает конечный комментарий, указывающий назначение этой переменной. В строке 3 выполняется присваивание переменной HelloMsg строки "Hello, World!". Далее (в строке 4) переменная HelloMsg используется как один из аргументов для процедуры MsgBox. Функция MsgBox отображает то же окно сообщения, что и раньше. Хотя MsgBox получает теперь свой первый аргумент из переменной, эта переменная содержит ту же строковую информацию, что была ранее (в листингах предыдущей главы) записана непосредственно в оператор MsgBox. Заметьте, что в результате мы получили окно сообщений, которое не несет информации о том, в каком приложении работает исходный макрос (ранее эта информация находилась в заголовке окна). Рис. 4.2 Окно сообщений, полученное процедурой HelloWorld Hello, World! Окно приветствия Задание типа данных переменной Все переменные в VBA, независимо от того, объявляются ли они неявно или явно, являются переменными типа Variant, если только вы не задаете тип переменной в объявляющем ее операторе. Объявление типизированных переменных (переменных, тип данных которых вы задаете) имеет несколько преимуществ: 102 Глава 4 Типизированные переменные ускоряют выполнение кода программ. Поскольку при объявлении вы указываете VBA тип переменной, выполнение программы ускоряется на то время, которое VBA потратил бы иначе на анализ переменной типа Variant, чтобы определить ее конкретный тип. Типизированные переменные повышают эффективность кода. Переменные типа Variant могут занимать гораздо больше памяти, чем переменные определенных типов. Типизированная переменная занимает только память, необходимую для этого определенного типа. Использование типизированных переменных может значительно сократить объем памяти, требуемый для вашей программы VBA; в некоторых случаях использование типизированных переменных может иметь значение с точки зрения того, достаточно ли памяти для работы вашей процедуры или нет. Программный код с типизированными переменными легче читать и понимать. Программы, использующие типизированные переменные, «помогают» обнаруживать некоторые типы ошибок программистов, например, недопустимое смешивание типов данных, потому что VBA отображает ошибки времени исполнения, которые не возникли бы, если бы переменные были нетипизированными. Существуют другие причины, по которым вам может понадобиться объявлять типизированные переменные. Например, несмотря на то, что переменные типа Variant могут сохранять даты, переменная типа Variant может неправильно сохранить дату из Excel. С переменными, объявленными явно с типом Date, такой проблемы не возникает. Тип переменной объявляется в том же операторе, который используется для объявления самой переменной. Можно объявлять типизированную переменную либо при неявном объявлении, либо при явном — с помощью Dim. При объявлении переменных типа String, можно также задавать длину строки. Использование Dim для объявления типизированных переменных Для объявления переменной и ее типа с помощью оператора Dim добавьте ключевое слово As перед именем переменной, а затем введите имя типа данных для этой переменной. Вот общий синтаксис для использования оператора Dim при объявлении типизированных переменных: СИНТАКСИС Dim varnamel [As typel] [, varname2 [As type2] ] [As type] VarnameN представляет любое допустимое имя переменной VBA, a type(N) — любое из имен типов данных VBA. Следующие строки показывают примеры правильного синтаксиса для объявлений типизированных переменных: Dim Счетчик As Single Dim Цена As Currency Dim ДатаПлатежа As Date Dim Сообщение As String Dim Counter As Integer Dim PentProfit As Single, Gross_Sales As Currency, Message As String Dim NetValue, PentProfit As Single После объявления типизированной переменной, независимо от того, объявляется ли эта переменная явно или неявно, и как задается тип, эта переменная сохраняет тот же самый тип столько времени, сколько она существует. Нельзя пере-объявить переменную или переопределить ее тип. Типы данных, переменные и константы 103 Использование символов определения типа для объявления типизированных переменных При неявном объявлении можно также задавать тип переменной, добавляя специальный символ, называемый символом определения типа (type-definition character), в конец имени переменной. В табл. 4.2 приводятся символы определения типа VBA и типы, которые они обозначают. Таблица 4.2. Символы определения типа Символ определения Тип ! Single @ Currency # Double $ String % Integer & Long Заметьте, что в этой таблице приведены только шесть символов определения типа; нет символов определения типа для Byte, Boolean, Date, Object или Array. Символы определения типа могут находиться только в конце имени переменной. Символы определения типа в VBA имеют свою историю. В ранних разновидностях языка BASIC символы определения типа были единственным способом задать тип переменной. Несмотря на то, что следует знать, что такое символы определения типа и как они используются, необходимость в их применении бывает редкой — использование оператора Dim с ключевым словом As намного легче и понятнее. Большинство программистов, работающих на VBA, не используют символы определения типа. В листинге 4.2 приведен еще один вариант процедуры HelioWorld, которая обсуждалась ранее. Листинг 4.2. Явное и неявное объявление типа 1 Sub HelloWorld() 2 Dim HelloMsg As String 3 HelloMsg = "Hello, World!" 4 Title$ = "Окно приветствия" 5 MsgBox HelloMsg, , Title$ 6 End Sub Эта версия процедуры Hello World работает во многом так же, как и предыдущие. Строка 1 содержит объявление процедуры. В строке 2 оператор Dim явно объявляет переменную HelloMsg. Поскольку оператор Dim включает ключевое слово As и имя типа String, переменная HelloMsg имеет тип String. Строка 3 присваивает текст сообщения строковой переменной HelloMsg. Строка 4 неявно объявляет переменную Title$ и в то же время присваивает переменной текст заголовка окна сообщения. Поскольку имя переменной Title$ имеет на конце символ определения типа для строки, эта переменная также имеет тип String. Наконец, строка 5 использует оператор MsgBox для отображения окна сообщения; в этом операторе и текст сообщения, и строка заголовка окна являются переменными: HelloMsg и Title$, соответственно. 104 Глава 4 После добавления символа определения типа к переменной необходимо включать символ определения типа каждый раз, когда вы используете имя переменной. Если бы символ определения типа был опущен в имени переменной Title$ в строке 5 (где Title$ используется первый раз после неявного типизированного объявления), то во время выполнения процедуры произошла бы runtime-ошибка. Использование Dim для объявления строковых переменных фиксированной длины Независимо от того, объявляются ли переменные типа String с помощью оператора Dim или добавлением символа определения типа $, создаваемые вами строковые переменные по умолчанию являются строками переменной длины. Строковые переменные переменной длины изменяют длину, в зависимости от длины строки, сохраняемой переменной. Иногда может понадобиться использовать строку фиксированной длины (fixed-length). Строки фиксированной длины всегда имеют одну и ту же длину. Они полезны, если необходимо обеспечить, чтобы текст, сохраненный в строковой переменной, всегда содержал одно и то же число символов. Можно использовать строки фиксированной длины, например, для выравнивания информации в столбцах при ее отображении или для обеспечения того, чтобы строковые данные, сохраняемые в отдельной переменной, никогда не превышали определенной длины. Существует только один способ объявления строковой переменной фиксированной длины: необходимо использовать оператор Dim. Следующая строка показывает общий синтаксис для создания строки фиксированной длины: СИНТАКСИС Dim varname As String * N Varname — это любое допустимое имя переменной, a N — это любое число от 1 до максимальной длины строки, равной примерно 2 миллиардам символов (Ранее 65 000 (64К) символов в Windows 3.1). Следующий оператор является примером объявления строки фиксированной длины: Dim LastName As String * 30 Символ (*), за которым следует число после ключевого слова String указывает VBA создать строковую переменную как строку фиксированной длины с заданной длиной (в этом случае — 30 символов). Область действия: доступность переменных Термин область действия (scope) относится к области процедуры или модуля VBA, где данная переменная, процедура или другой идентификатор, являются доступными. В этом разделе описываются два базовых уровня области действия: процедурный и модульный. Переменные, процедуры и идентификаторы, которые доступны только в процедуре, имеют область действия процедурного уровня, а те, которые доступны для всех процедур в модуле, имеют область действия модульного уровня. * Область действия процедурного уровня Переменная, объявленная в процедуре, является доступной только в этой процедуре. Например, переменная HelloMsg из строки 2 листинга 4.1, является доступной только в процедуре HelloWorld; никакая другая процедура не имеет доступа к этой переменной. В действительности, переменная HelloMsg реально существует только в то время, когда VBA фактически выполняет процедуру HelloWorld. Типы данных, переменные и константы 105 Поэтому говорят, что переменная HelloMsg имеет область действия процедурного уровня (procedure-level scope). Может быть, сначала это незаметно, но VBA ограничивает доступ к переменным посредством своих правил области действия для упрощения работы программиста. Поскольку переменная с областью действия процедурного уровня недоступна ни для какой процедуры, за исключением той, в которой объявляется эта переменная, можно не очень беспокоиться о дублировании имен переменных. Правила выбора имен переменных указывают, что имя переменной должно быть уникальным в ее области действия. Для переменных с областью действия процедурного уровня это означает, что вы не можете объявлять две переменные с одним и тем же именем в одной и той же процедуре. (Очевидно, что ни VBA, ни пользователь не могут определить, какую переменную вы намереваетесь использовать, если обе они имеют одно и то же имя). Поскольку область действия процедурного уровня ограничивает доступ к переменной процедурой, в которой объявляется эта переменная, вы можете использовать то же имя переменной в разных процедурах. Листинг 4.3 показывает две законченные процедуры. (HelloWorld в этом листинге отображает то же окно сообщения, которое было показано ранее на рис. 4.1.) Листинг 4.3. Область действия процедурного уровня 1 Sub HelloWorld() 2 3 4 5 End 6 7 Sub Dim HelloMsg 1 сохраняет текст для MsgBox HelloMsg = "HelloWorld!" MsgBox HelloMsg, , "Окно приветствия" Sub HelloDave() 8 9 10 11 End Dim HelloMsg ' сохраняет текст для Msgbox HelloMsg = "Hello, Dave!" MsgBox HelloMsg, , "Другое окно сообщения" Sub Строки 1-5 содержат ту же процедуру HelloWorld из листинга 4.1, которая работает точно так же. В модуль была добавлена процедура HelloDave, которая и начинается в строке 7 листинга 4.3. Процедура HelloDave работает так же, как процедура HelloWorld, просто она отображает другое текстовое сообщение и заголовок в своем диалоговом окне. На рис. 4.2 показано окно сообщений, отображенное процедурой HelloDave. Заметьте, что в строках 2 и 8 обе процедуры используют оператор Dim для объявления переменных с именем HelloMsg. Это разумно, потому что HelloMsg является хорошим описательным именем для содержимого и назначения переменной в обеих процедурах. Поскольку переменные HelloMsg объявляются внутри отдельных процедур и имеют область действия процедурного уровня, не возникает двусмысленности по поводу того, какую переменную будет использовать VBA. В процедуре HelloWorld VBA использует переменную HelloMsg, объявленную локально (строка 2 в листинге). В процедуре HelloDave VBA использует переменную HelloMsg, объявленную локально в этой процедуре (строка 8). Область действия модульного уровня Иногда необходимо, чтобы несколько процедур имели доступ к одной и той же переменной. Обычно эффективнее вычислить один раз какое-либо значение, сохранить его в переменной, а затем использовать эту переменную в нескольких процедурах, чем вычислять одно и то же значение снова и снова. 106 Глава 4 VBA позволяет объявлять переменные, доступные для нескольких процедур. Когда какая-либо переменная доступна всем процедурам в модуле, говорят, что эта переменная имеет область действия модульного уровня (module level). VBA ограничивает область действия переменной модульного уровня модулем, в котором объявляется эта переменная. (VBA предоставляет способы еще большего расширения области действия переменной; эти методы описываются далее.) Для того чтобы переменная была доступной для всех процедур в определенном модуле, поместите оператор Dim для нее в начало модуля перед любыми объявлениями процедур. В листинге 4.4 приведен модуль, содержащий две простые процедуры и единственное объявление переменной модульного уровня. Процедура HelloWorld в листинге 4.4 отображает то же окно сообщения, которое показано на рис. 4.2. Область в начале модуля перед любыми объявлениями процедур называют областью ............ (declaration) модуля, потому что именно туда следует помещать объявления переменных модульного уровня и другие директивы для VBA, влияющие на весь модуль Вы можете легко переходить к области объявлений любого модуля, выбирая Declarations в списке Procedure окна Code Листинг 4.4. Область действия переменной модульного уровня 1 Dim HelloMsg ' используется всеми процедурами в этом модуле 2 3 Sub HelloWorld() 4 HelloMsg = "Hello, World1" 5 MsgBox HelloMsg, , "Окно приветствия" 6 End Sub 7 8 Sub HelioDave () 9 HelloMsg = "Hello, Dave1" 10 MsgBox HelloMsg, , "Другое окно сообщения" 11 End Sub В этом листинге строки 3-6 содержат процедуру HelloWorld, а строки 8-11 — процедуру HelloDave. Обратите внимание на то, что ни одна из этих процедур не содержит операторов Dim. В строке 1 оператор Dim используется для объявления переменной с именем HelloMsg. Поскольку строка 1 объявляет переменную HelloMsg на уровне модуля, эта переменная доступна для всех процедур в одном и том же модуле. В строках 4 и 5 процедуры HelloWorld VBA использует переменную модульного уровня HelloMsg. Аналогично, в строках 9 и 10 процедуры HelloDave VBA использует ту же переменную модульного уровня HelloMsg. Использование переменных с одним и тем же именем в различных уровнях области действия Имя переменной должно быть уникальным в ее области действия. Точно так же, как нельзя объявлять две переменные с одним и тем же именем в одной процедуре, нельзя объявлять две переменные модульного уровня с одним именем в одном и том же модуле (и по тем же причинам). Однако можно иметь переменные с одним и тем же именем на разных уровнях области действия. Когда переменные имеют одно имя, но разные области действия, VBA использует переменную с наиболее локальной (local) областью действия. В листинге 4.3 были уже показаны две различные процедуры, каждая из которых объявляет свою переменную, но использует одно и то же имя для переменной. Поскольку эти переменные имеют область действия процедурного уровня, каждая процедура может использовать только свою локальную переменную. В листин Типы данных, переменные и константы 107 ге 4.5 приведен модуль, содержащий три процедуры, каждая из которых используют переменные с одним и тем же именем. Листинг 4.5. Комбинированная модульная и процедурная область действия 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Dim HelloMsg ' используется всеми процедурами в этом модуле, ' которые не имеют своей переменной HelloMsg Sub HelloWorld() HelloMsg = "Hello, World!" MsgBox HelloMsg, , "Greeting Box" End Sub Sub HelioDave() HelloMsg = "Hello, Dave!" MsgBox HelloMsg, , "Другое окно сообщения" End Sub Sub AnotherMessage() Dim HelloMsg ' локальное объявление HelloMsg = "Еще одно окно сообщения" MsgBox HelloMsg, , "Еще одно окно сообщения" End Sub В листинге 4.5 приведены три различные процедуры. Первые две уже использовались в листинге 4.4. Третья процедура AnotherMessage начинается в строке 13 и заканчивается в строке 17. AnotherMessage работает так же, как предыдущие процедуры, отображая сообщение в диалоговом окне с использованием оператора MsgBox. Заметьте, что строка 1 этого листинга объявляет переменную модульного уровня HelloMsg. Строка 14 в процедуре AnotherMessage также объявляет переменную с именем HelloMsg. При выполнении процедуры HelloWorld VBA использует переменную HelloMsg, объявленную в строке 1. HelloWorld не имеет переменных, объявленных локально, здесь невозможна двусмысленность, поэтому VBA использует переменную модульного уровня. Аналогично, при выполнении процедуры Hello-Dave VBA также использует переменную HelloMsg, объявленную в строке 1. Однако в процедуре AnotherMessage имеется свое объявление переменной HelloMsg (строка 14). При выполнении строк 15 и 16 VBA устраняет любую двусмысленность по поводу того, какую переменную HelloMsg следует использовать, выбирая наиболее локальную переменную: HelloMsg, объявленную как переменную процедурного уровня. Переменная модульного уровня HelloMsg, объявленная в строке 1, недоступна для процедуры AnotherMessage. Переменные процедурного уровня часто называют.........(local) переменны- ми, потому что их объявления являются локальными для выполняемой в данный момент процедуры. Персистенция: Определение того, как долго переменные удерживают свое значение Персистенция (persistence) — это термин, используемый для ссылки на продолжительность времени, в течение которого любая данная переменная удерживает значение, присвоенное ей. Значения, присвоенные переменным сохраняются только, пока переменная является активной в ее области действия. Когда переменная объявляется в процедуре, она существует только, пока VBA выполняет эту процедуру. Прй выполнении процедуры VBA резервирует область 108 Глава 4 памяти для всех переменных, объявленных локально в этой процедуре, независимо от того, объявляются переменные явно или неявно. После окончания процедуры VBA освобождает память, использовавшуюся локальными переменными, в общий пул имеющейся в наличии компьютерной памяти и локальные переменные этой процедуры прекращают существование. Например, в начале выполнения процедуры HelloWorld в листинге 4.1 VBA резервирует область памяти для переменной HelloMsg. Ко1да VBA заканчивает выполнение HelloWorld, память, зарезервированная для переменной HelloMsg, возвращается в общий пул имеющейся в наличии памяти с уничтожением любого значения, которое было сохранено в HelloMsg. Переменные процедурного уровня создаются каждый раз, когда процедура начинает выполняться, и уничтожаются, когда процедура перестает выполняться. Говоря более техническими терминами, локальная переменная является неопределенной или вне контекста (out of context) до тех пор, пока процедура, объявляющая ее, не начинает выполняться. Когда процедура, объявляющая переменную, перестает выполняться, переменная опять становится неопределенной. Значения переменных, объявляемых на уровне модуля, удерживаются в памяти столь долго, сколько VBA выполняет процедуру в этом модуле. При выполнении процедуры VBA фактически просматривает весь модуль, содержащий эту процедуру, и создает любые переменные модульного уровня. Пока VBA выполняет процедуру в этом модуле, значения переменных модульного уровня сохраняются. Требование явного объявления переменных Хотя неявное объявление переменных (объявление переменных просто их использованием) удобно, с ним связаны некоторые проблемы. Когда переменные объявляются неявно, существует риск нечаянно создать новую переменную, когда на самом деле необходимо использовать уже существующую, или использовать существующую переменную, когда пользователь намеревается создать новую. Обе эти ситуации приводят к ошибкам в коде, которые очень трудно отслеживать. (Bug — любая ошибка в коде, которая мешает его правильному выполнению или приводит к ошибочным результатам.) В этой книге уже рассказывалось, как использовать оператор Dim для объявления переменных и уменьшения проблем, связанных с неявным объявлением. Использование только оператора Dim для объявления переменных не всегда помогает обнаруживать или предотвращать небольшие ошибки, относящиеся к неявному объявлению переменных. Чтобы легче было в любое время обнаруживать ошибки, связанные с неявным объявлением переменных, VBA предоставляет команду Option Explicit. При использовании Option Explicit VBA требует объявления всех переменных (с помощью оператора Dim) перед их использованием. Команда Option Explicit в основном препятствует неявному объявлению переменных где-либо в модуле, содержащем эту команду. Чтобы установить режим, при котором VBA требует явного объявления для всех переменных в модуле, добавьте команду Option Explicit в область объявлений модуля, то есть в начало модуля перед любыми объявлениями переменных или процедур. В листинге 4.6 приведен тот же модуль, что и в листинге 4.4, но с добавленной командой Option Explicit. Листинг 4.6. Модульная команда Option Explicit 1 Option Explicit ' требует явного объявления переменных модуля 2 Dim HelloMsg ' используется всеми процедурами в этом модуле 3 Типы данных, переменные и константы 109 4 Sub HelloWorld() 5 HelloMsg = "Hello, World1" 6 MsgBox HelloMsg, , "Окно приветствия" 7 End Sub 8 9 Sub HelloDave() 10 HelloMsg = "Hello, Dave!" 11 MsgBox HelloMsg/ , "Другое окно сообщения 12 End Sub Кроме строки 1, все в этом модуле работает точно так же, как в листинге 4,4. Строка 1 модуля в листинге 4.6 содержит команду Option Explicit. Из-за этой команды все переменные в модуле должны объявляться оператором Dim. Если добавить неявное объявление переменных в этот модуль, VBA отображает сообщение об ошибке времени исполнения, утверждая, что эта переменная является необъявленной. Такие команды, как Option Explicit, называются директивами компилятора (compiler directives'). Директивы компилятора не способствуют тому, чтобы VBA выполнял какое-либо действие. Компилятор VBA является частью VBA, которая читает исходный код и компилирует (compiles) его в машинные инструкции, необходимые компьютеру для выполнения поставленной задачи. Директива компилятора просто инструктирует VBA о специфических правилах, которым должен следовать VBA при компиляции вашего исходного кода. Команда Option Explicit действует только на модуль, в котором она появляется. Если проект, содержащий этот модуль, содержит также другие модули, на них не действует команда Option Explicit. Необходимо включать команду Option Explicit в каждый модуль, для которого требуются явные объявления переменных. Поскольку включение Option Explicit во все модули является очень полезным, Редактор VB предоставляет способ автоматически включать эту команду в каждый новый модуль при его создании. Для того чтобы Редактор VB добавлял команду Option Explicit в каждый новый модуль, выберите опцию Require Variable Declaration (явное описание переменных) на вкладке Editor (редактор) диалогового окна Options (параметры) Редактора VBA, выполняя следующие шаги: 1. Выберите команду Tools | Options (Сервис | Параметры). Редактор VBA отображает диалоговое окно Options. 2. Щелкните на вкладке Editor (Редактор) для отображения параметров редактирования, если необходимо. 3. Выберите флажок Require Variable Declaration (явное описание переменных). 4. Выберите ОК. Редактор VB закрывает диалоговое окно Options. Теперь каждый раз, когда вы (или макрорекордер) вставляете новый модуль в проект, Редактор VB автоматически добавляет команду Option Explicit в начало модуля. Выбор опции Require Variable Declaration в диалоговом окне Options влияет только на новые модули; если вы хотите запросить явное объявление переменных в существующем модуле, вы должны добавить Option Explicit, редактируя модуль самостоятельно. Требование явного объявления переменных действует на все приложения, использующие Редактор VB; при запуске Редактора VB из Excel и установке опции Require Variable Declaration новые модули в Word будут также требовать явного объявления переменных. » W Глава 4 Константы Константа (constant) — это значение в программе VBA, которое не меняется. Примеры процедур, уже приведенные в этой книге, используют строковые константы типа "Hello World!" и "Другое окно сообщения". Константы, подобные им, называют литеральными константами (literal constants), потому что литеральное значение записывается непосредственно в код. В коде VBA можно также писать литеральные численные константы и даты; примеры численных литеральных констант включают числа 36, 3, 14 и 212. Примеры литеральных констант-дат включают даты #12/31/96# или #октябрь 28, 1997# (вы узнаете подробнее о написании констант-дат далее в этой главе). Если рассматривать большинство записанных макросов, то можно найти другие примеры литеральных констант. Константы можно изменять только редактированием исходного кода VBA. Константы, подобные строковым константам в процедуре HelloWorld, используются для предоставления данных, которые не изменяются (в отличие от переменных, которые используются для предоставления изменяемых данных). Можно использовать константы как аргументы для процедур и в математических или операциях сравнения. Константы не должны быть обязательно литеральными. VBA позволяет создавать именованные константы (named constants). Именованная константа, подобно переменной, имеет заданное ей имя; это имя представляет конкретное неизменяемое значение. Так же, как и в случае с переменной, VBA подставляет конкретное значение, на которое ссылается имя константы, в оператор в том месте, где VBA встречает именованную константу. Однако в отличие от переменной значение именованной константы никогда не изменяется; как и в случае с литеральной константой, единственным способом изменить значение, связанное с именованной константой, является редактирование исходного кода VBA. Используйте именованные константы для повышения читабельности процедур. Например, процедура, выполняющая геометрические вычисления, легче читается и более понятна, если использовать именованную константу Pi вместо литеральной константы 3,14. Именованные константы можно также использовать для более простого обновления и сопровождения процедур и программ. Например, в программе VBA, вычисляющей налогообложение фирмы, возможно изменение ставки налога когда-нибудь в будущем. Если поместить ставку налога в эту программу как литеральную константу, может оказаться затруднительным изменить программу, чтобы использовать новую ставку налога, — вам придется искать и изменять каждое вхождение значения ставки налога по всей программе. Если же вместо этого для ставки налога использовать именованную константу, то придется изменить значение ставки налога только в одном месте; в операторе, объявляющем именованную константу. В общем, следует использовать именованные константы вместо литеральных для значений, которые вы используете неоднократно в процедуре или модуле или для значений, которые трудно запомнить или невозможно сразу понять. Создание именованных констант ч При выборе имени константы соблюдайте те же правила и рекомендации, которым вы следуете при выборе имени переменной (см. раздел «Создание переменных» в начале этой главы). Как и в случае с переменной, необходимо объявлять именованную константу перед ее использованием. Однако в отличие от переменной необходимо всегда явно объявлять именованные константы, используя ключевое слово Const. Следующая строка показывает общий синтаксис для объявления именованных констант: Типы данных, переменные и константы 111 СИНТАКСИС Const namel = valuel [operator name2...] _ [, патеЗ = value3 [operator name4] ... ] Здесь nameN представляет любой допустимый идентификатор, valueN — любое значение данных: численное, строковое или дата, a operator — арифметическая или операция сравнения между двумя именами ранее описанных констант. Следующие строки показывают несколько объявлений именованных констант: Const Boilingpoint = 212 Const SalesTax = 8.25 Const Greeting = "Hello, Pete!" , Const PointTwo = 212, SalesTax2 = 8.25*2, Greeting2 = "Hello, " Const DangerZone = BoilingPoint + 50 Область действия констант Как и в случае с переменными, можно объявлять именованные константы в процедурах или в области объявлений в начале модуля. Константа, объявляемая в процедуре, имеет область действия процедурного уровня, а константа, объявляемая в области объявлений модуля, — область действия модульного уровня. Для именованных констант выполняются те же правила области действия, что и для переменных. Поскольку одной из главных целей использования именованной константы является предотвращение повторения или дублирования значений литеральных констант в процедурах, как правило, бывает необходимо, чтобы именованные константы были доступны всем процедурам в модуле. Поэтому следует помещать объявления констант на модульном уровне, чтобы у них была наибольшая область действия. Всякий раз, когда VBA встречает именованную константу в операторе, значение, связанное с константой, вставляется в этот оператор. Рассмотрим листинг 4.7, в котором показан законченный модуль. Эта процедура вычисляет площадь круга и сохраняет значение в переменной. Листинг 4.7. Использование констант: вычисление площади круга 1 Const Pi = 3.14 2 Dim CircleArea As Single 3 4 Sub Calc_CircleArea() 5 Dim Radius As Single 6 Radius = 5 7 CircleArea = Pi * (Radius * Radius) 8 MsgBox CircleArea, , "Area of Circle" 9 End Sub Строка 1 листинга 4.7 объявляет константу модульного уровня Pi, которая представляет приближение числа л. Строка 7 листинга содержит оператор, вычисляющий площадь круга; при выполнении этого оператора VBA вставляет значение 3.14 в место, занимаемое именем константы Pi. В процедуре Calc_CircleArea оператор MsgBox (в строке 8) отображает число 78.5. Обратите внимание на то, что переменная CircleArea объявляется на уровне модуля для того, чтобы значение, вычисленное в процедуре Calc_CircleArea, было доступным для других процедур в том же модуле. 112 Глава 4 Написание литеральных констант Даже если вы никогда не использовали литеральные константы в коде VBA (что невероятно), вам все же следует писать литеральные константы при объявлении именованных констант. Существует несколько правил, которые необходимо соблюдать при написании литеральных констант; далее описываются правила написания констант типа String, Integer, Date и Boolean. Константы String При написании литеральных строковых констант в коде VBA выполняйте следующие правила: Строковые константы должны быть заключены в двойные кавычки (”). Следующий пример не является допустимым, потому что не имеет кавычек: This is not a valid string constant. Пустая строковая константа (называемая нулевой строкой — null string или empty string) обозначается двумя двойными кавычками, между которыми ничего нет (""). Строковая константа должна вся находиться на одной и той же строке. Нельзя использовать символ продолжения строки для продолжения литеральной строковой константы на другой строке. Ни один из следующих примеров не является правильным, потому что строковая константа находится более, чем на одной строке: "Это пример неправильной строковой константы" "Это снова не_ правильная строковая константа" Если любой из этих примеров будет включен в процедуру, VBA выдаст ошибку времени исполнения и прекратит выполнение процедуры. Далее следует пример правильной строковой константы: "Пример правильной строковой константы" Если же вам необходимо написать константу на двух строках, используйте оператор конкатенации (см. следующую главу) и символ перехода на следующую строку, как показано ниже: "Теперь имеем " & _ "правильную строковую константу" Численные константы Данные правила применимы к литеральным численным константам; численные константы могут содержать любой из численных типов VBA. Численные константы должны состоять только из числовых символов от 0 до 9. Численная константа может начинаться со знака (-) и может содержать десятичную точку. Можно использовать экспоненциальное представление для численных констант. Никакие другие символы или знаки не допускаются в численных константах. Далее следуют примеры правильных численных констант: 12 -14.3 6.6Е2 Типы данных, переменные и константы 113 Константы Date VBA распознает константы даты в любом из нескольких различных форматов; необходимо помещать все константы даты между знаками фунта (#). Следующие строки показывают некоторые из форматов констант дат, которые распознает VBA: #2-5-97 21:17# ♦February 5, 1997 9:17рщ# # Mar-31-97# # 15 April 1997# Независимо от того, в каком из указанных форматов записывается литеральная константа типа Date, VBA переформатирует эту константу (когда курсор вставки будет убран со строки после записи константы) для соответствия одному из двух следующих форматов, в зависимости от того, содержит ли константа Date информацию о времени: # 2/5/97 9:17:00 PM# #2/5/97# Если пропустить знак (#) при записи литеральной константы даты, VBA не сможет правильно интерпретировать константу даты как дату. Вместо этого, VBA пытается оценить информацию о дате как имена переменных, численные константы и математические операторы. Например, VBA пытается интерпретировать следующую дату (в которой пропущены знаки фунта) как математическое выражение, включающее деление: 3/12/94 Не заключайте литеральные константы типа Date в кавычки, потому что VBA будет интерпретировать дату как строковую константу. Например, VBA интерпретирует следующую строку как строковую константу, а не как дату: "3/11/99" Константы Boolean Существует только две правильные константы типа Boolean: True и False. В операторах программ VBA для констант типа Boolean вы всегда должны использовать ключевые слова True и False. Когда вы записываете ключевые слова в макросы, пишите слова полностью и не используйте кавычки. Задание типа константы Когда вы объявляете именованную константу или используете литеральную константу, VBA «считает», что значение, представленное этой константой, имеет тип данных, наиболее согласующийся с выражением, присвоенным константе. Например, VBA работает с константой, содержащей строку, как с константой типа String при определении того, правильно ли константа сочетается с другими значениями данных. В VBA можно задать тип константы. Объявление конкретного типа данных для константы может повысить точность вычислений. При объявлении константы типа Double, например, VBA вычисляет результат математических операций, включающих эту константу, используя больший диапазон типа данных Double. Можно также задать тип константы как Integer, Long, Currency или другой, чтобы результаты математических операций, использующих эту константу, имели определенный тип. (Как вы узнаете из следующей главы, VBA определяет тип данных для результата вычислений, основываясь на типе значений, используемых в вычислении.) Для констант можно использовать типы данных Byte, Boolean, Integer, Long, Single, Double, Currency, Date или String (но не Object или Array). Объявление 114 Глава 4 типа для константы подобно объявлению типа для переменной, за исключением того, что объявление начинается с ключевого слова Const. Общий синтаксис для объявления типизированной константы следующий: СИНТАКСИС Const name As type = value [, name As type = value ] Здесь name — это любое допустимое имя константы, type — имя любого из типов данных VBA и value — значение, которое вы присваиваете константе. Следующая строка иллюстрирует правильное объявление константы с определенным типом: Const Pi As Double = 3.14 В этом примере константа Pi объявляется как тип Double. Можно также использовать символы определения типа для задания типа константы, как показано в следующем примере (действие которого такое же, как в предыдущем примере): Const Pi# = 3.14 Внутренние константы VBA предоставляет несколько внутренних констант (intrinsic constants), называемых также предопределенными константами (predefined constants). Внутренняя константа — это именованная константа, которая была определена разработчиками VBA. В Приложении р приведены все именованные константы VBA. В дополнение к константам, которые предопределяет VBA, host-приложение VBA также предопределяет несколько констант для использования с этим host-приложением. Например, Excel 2002 содержит несколько внутренних констант для использования с рабочими книгами Excel, таблицами и так далее. Аналогично, Word 2002 содержит несколько внутренних констант для работы с документами и шаблонами Word, тогда как Access 2002 содержит внутренние константы, имеющие отношение к различным операциям с базами данных и свойствам Access-объектов. Внутренние константы, определяемые VBA, все начинаются с букв vb для указания того, что они определяются языком Visual Basic for Applications (или Visual Basic). Например, константы vbOKOnly, vbOKCancel и vbAbortRetrylguore определяются VBA. Внутренние константы Excel 2002 начинаются с букв xl, чтобы было понятно, что они определяются Excel; некоторые из внутренних констант Excel — это xlChart, xlCountrySetting и xlWorksheet. Внутренние константы Word 2002 начинаются с букв wd, чтобы было понятно, что они определяются Word; вот некоторые внутренние константы Word: wdBackward, wdForward и wdToggle. Благодаря внутренним константам, легче использовать некоторые встроенные процедуры VBA, такие как оператор MsgBox, о котором вы уже знаете, и оператор InputBox, о котором рассказывается далее в этой главе. Хотя ни в одном из показанных уже примеров с оператором MsgBox не использовался его необязательный аргумент, вы можете вспомнить из предыдущих обсуждений, что MsgBox имеет необязательный аргумент, указывающий число кнопок в диалоговом окне; обычно для аргумента кнопок в MsgBox используются внутренние константы VBA. Внутренние константы, определяемые Excel, Word или другим host-приложением VBA, упрощают использование различных свойств и методов, принадлежащих этому host-приложению. (Подробнее о свойствах и методах вы узнаете из следующих глав.) Типы данных, переменные и константы 115 Поиск имеющихся внутренних констант с помощью Object Browser Для того чтобы увидеть полный список имеющихся в наличии внутренних констант, определяемых VBA или host-приложением, используйте Object Browser и выполняйте следующие шаги: 1. Нажмите Alt+Fll для активизации Редактора VB. 2. Выберите команду View | Object Browser (Вид | Просмотр объектов) (или щелкните на кнопке Object Browser на панели инструментов). Редактор VB отображает диалоговое окно Object Browser. На рис. 4.3 показано диалоговое окно Object Browser со списком констант VBA. После того как вы откроете диалоговое окно Object Browser, выполните следующие дополнительные шаги, чтобы увидеть внутренние константы VBA: 1. Выберите VBA в раскрывающемся списке диалогового окна Object Browser. 2. Выберите Constants в списке Classes (Классы). 3. Чтобы получить более подробную информацию об отдельной внутренней константе, выберите эту константу в списке Members Of'Constants'. После того как вы выберете константу в списке Members Of 'Constants', ее имя появится в нижней части диалогового окна Object Browser. Чтобы получить более подробную информацию о выбранной константе, щелкните на кнопке Help окна Object Browser (на кнопке со знаком вопроса). Внутренние константы VBA — одни и те же во всех host-приложениях VBA. Внутренние константы для некоторых приложений, например для Excel, доступны только тогда, когда вы работаете с VBA в этом приложении. Например, вы не сможете найти константу xlWorksheet Excel в окне Object Browser в Word, так как константа xlWorksheet доступна только тогда, когда вы используете VBA в Excel. Если для элемента, выбранного в списке Classes, имеется раздел справочной системы, кнопка Help окна Object Browser доступна, как показано на рис. 4.3. Щелкните на этой кнопке для доступа к справочному разделу для выбранного элемента. Не все объекты в окне Object Browser имеют дополнительный справочный раздел. Рис. 4.3 Используйте Object Browser для просмотра списков констант, определенных в VBA и host-приложениях Object Browser |<All Llbiaiies» Members of '«globals»' a ® Abs ActiveDocument eS? ActivePnnter Й? ActiveWindow e» Addins Й? AnswerWizard AppActivate Й" Application * Asc v ® AscB Classes ° <globals> «3 Addin <3 Addins <3 Adjustments «3 AnswerWizard «3 AnswerWizardFiles 13 Application «3 Assistant <3 AutoCaption aS AutoCaptions <AII Libraries» Для просмотра списка внутренних констант, определяемых host-приложени-ем VBA, выполняйте те же шаги, что описаны выше, но вместо VBA выбирайте библиотеку host-приложения в раскрывающемся списке Project/Library (Проект/ Библиотека). Например, чтобы просмотреть внутренние константы Excel, выберите Excel в раскрывающемся списке Project/Library; чтобы просмотреть внутренние константы Word, выберите Word в списке Project/Library. Можно просматривать 116 Глава 4 внутренние константы только для host-приложения VBA, из которого был запущен Редактор VB, если только вы не создаете ссылку на библиотеку другого host-приложения. f Получение данных от пользователя Информация этого раздела не связана с основной темой главы, но необходима для оставшегося материала этой и следующей главы. Получение данных от пользователя, сохранение их в переменной и отображение результатов действий, выполненных над ними, являются основными элементами, необходимыми для написания интерактивных процедур. [Интерактивная (interactive) процедура — это процедура, обменивающаяся информацией с пользователем, то есть процедура взаимодействует с пользователем, отображая сообщения и получая ввод]. Интерактивные процедуры часто бывают более полезными, чем макросы, создаваемые исключительно путем записи. Получая информацию от пользователя, интерактивная процедура может выполнять одни и те же операции, используя различные данные. Данные, вводимые пользователем, называются входными данными (input). Чтобы получить входные данные от пользователя процедуры, используйте функцию InputBox. [Функция (function) — это особый тип процедуры VBA, возвращающей значение]. Функция InputBox отображает диалоговое окно, содержащее текст, который запрашивает пользователя ввести некоторое значение, и текстовое окно для ввода этого значения. Диалоговое окно, отображаемое InputBox, содержит также командные кнопки ОК и Cancel. Функция InputBox имеет следующий синтаксис: СИНТАКСИС stringvar = InputBox (Prompt [, Title]) Здесь stringvar представляет любую переменную, которая может сохранять строку (либо переменную типа String, либо — Variant). Аргумент Prompt представляет любое строковое значение (литерал, константу или переменную). InputBox отображает эту строку как запрос в диалоговом окне; необходимо всегда предоставлять аргумент Prompt, поскольку это — обязательный аргумент (required argument). Аргумент Title является необязательным вторым аргументом для InputBox. Title представляет любое строковое значение (литерал, константу или переменную). InputBox отображает текст этой строки в строке заголовка диалогового окна. Если опустить аргумент Title, VBA отображает в строке заголовка диалогового окна InputBox слово "Input". В листинге 4.8 приведен код модуля с одной процедурой. В коде имеется объявление константы и переменной модульного уровня. Эта процедура, подобно процедуре в листинге 4.7, вычисляет площадь круга, но радиус круга получает от пользователя процедуры. Листинг 4.8. Получение входных данных при помощи оператора InputBox 1 Const Pi As Single =3.14 ' аппроксимация значения pi 2 Dim CircleArea As Single ' сохраняет вычисленную площадь круга 3 4 Sub Calc__CircleArea () 5 Const BoxTitle = "Площадь круга" 6 Dim Radius As Single, Temp As String Типы данных, переменные и константы 117 7 Temp = InputBox("Введите радиус круга", BoxTitle) 8 Radius = CSng(Temp) 9 CircleArea = Pi * (Radius * Radius) 10 MsgBox CircleArea, , BoxTitle 11 End Sub Строка 1 листинга 4.8 объявляет константу модульного уровня Pi. Строка 2 объявляет переменную модульного уровня CircleArea. Эти элементы объявляются на уровне модуля, чтобы они были доступны во всем модуле; другим процедурам в том же модуле может понадобиться доступ к значению Pi, а еще какой-то процедуре может понадобиться использовать значение для площади круга, после того, как оно будет вычислено. Строка 4 содержит фактическое объявление процедуры; как и раньше, эта процедура имеет имя Calc_CircleArea. Строка 5 объявляет константу процедурного уровня BoxTitle; эта константа имеет только локальный доступ в процедуре Calc_CircleArea. BoxTitle была объявлена локально в этой процедуре, потому что маловероятно использование этой константы в какой-либо другой процедуре; ее назначение — предоставлять фиксированный текст для строки заголовка всех диалоговых окон, отображаемых Calc_CircleArea. Обратите внимание на строку 7 листинга 4.8. Этот оператор вызывает функцию InputBox. Она отображает свой первый аргумент как текст в диалоговом окне, запрашивая у пользователя ввести значения какого-либо типа. В этом операторе InputBox отображает текст "Введите радиус круга", чтобы сообщить пользователям процедуры, какое значение они должны ввести. InputBox использует второй аргумент, представленный константой BoxTitle, в качестве заголовка диалогового окна. При выполнении оператора InputBox отображается диалоговое окно, показанное на рис. 4.4. Пользователь вводит число в текстовое окно и выбирает командную кнопку ОК или Cancel, чтобы закрыть диалоговое окно, как и любое другое окно Windows. Всякий раз, когда вы вызываете какую-либо функцию, необходимо как-то использовать значение, возвращаемое функцией. [Значение, возвращаемое функцией, называется результатом функции (function result)]. Часто функции используют результат, присваивая его какой-либо переменной, как показано в строке 7 в случае с функцией InputBox, результат которой присваивается переменной Тетр. Результат функции InputBox всегда является строкой (вот почему переменная Тетр была объявлена как String). Посмотрите еще раз на рис. 4.4. Если пользователь выбирает командную кнопку ОК, функция InputBox возвращает то, что пользователь ввел в текстовое окно, в качестве результата. Если пользователь выбирает командную кнопку Cancel (или нажимает клавишу Esc, или использует кнопку Close диалогового окна), InputBox в качестве результата возвращает пустую строку. Рис. 4.4 Диалоговое окно ввода, отображаемое функцией InputBox (в строке 7 листинга 4.8) Поскольку переменная Тетр была объявлена явно как String, значение строки должно быть преобразовано в численное значение перед тем, как можно будет его использовать в математических вычислениях. Строка 8 листинга 4.8 выполняет именно это, используя встроенную VBA-функцию CSng для преобразования пользовательских данных ввода в число с типом Single. CSng — это одна из нескольких функций преобразования данных, более подробно описанных в главе 5. Глава 5 Выражения в Visual Basic Теперь вы знаете, как записывать и редактировать макросы, писать собственные простые процедуры и создавать и использовать константы и переменные. В этой главе описывается, как объединять переменные и константы для создания новых значений. Выражение (expression) — это значение или группа значений, выражающая отдельное значение. Каждое выражение вычисляется до (или имеет результатом) отдельного значения. Выражение 2+5, например, имеет результатом 7. Выражения состоят из одной или более следующих частей: Константы (литеральные или именованные) Переменные (любого типа данных) ' Знаки операций Массивы Элементы массива Функции Все выражения имеют результатом одно значение определенного типа данных, о которых вы узнали в главе 4. Выражения могут также иметь результатом одно из специальных значений Empty или Null. VBA предоставляет ключевые слова Empty и Null для указания особых значений в переменной или выражении. Значение Empty представляет неинициализированную переменную типа Variant или результат выражения, содержащий неинициализированную переменную типа Variant. Значение Null представляет выражение, содержащее неверные данные. Вот некоторые примеры выражений: Выражение Описание 7 Содержит одно значение и имеет результатом число 7. "25" Содержит одно значение и имеет результатом символьную строку ”25". "То" & "day” Содержит два строковых значения и знак операции; имеет результатом одну строку "Today”. b /(р*10) Возвращает число, полученное делением содержимого переменной b на значение, полученное после умножения содержимого переменной р на константу 10. Value <= 17 Вычисляется до логического значения; в этом случае указывая, является ли содержимое переменной Value меньшим или равным константному численному значению 17. Знаки (обозначения) операций1 используются для объединения, сравнения или других действий над определенными значениями в выражении. Операциям присвоены имена, и они могут иметь обозначающий их знак, например, операция 1 В некоторых источниках вместо «знака операции» используется термин «оператор» (operator). Автор считает это не совсем удобным, поскольку в программировании чаще всего под «оператором» понимают инструкцию (statement), выполняющую некоторую работу, например, оператор присваивания. В данном же случае мы имеем дело с элементами, из которых формируется выражение, обычно являющееся частью оператора, например, присваивания. Выражения в Visual Basic 119 сложения имеет знак Когда вы используете какой-либо знак в выражении, элементы данных (переменные или константы), над которыми производится действие, называются операндами (operands); большинству операций требуется два операнда. В выражении 3+1, например, числа 3 и 1 являются операндами операции сложения (+). Выражение может содержать один, несколько знаков операции или ни одного. Выражения используются для выполнения вычислений и сравнения значений, для предоставления переменных в качестве аргументов различным функциям и процедурам VBA. Все выражения Visual Basic вычисляются до значения, имеющего один из типов данных Visual Basic. Далее следует перечень различных типов выражений VBA: Выражение типа даты (date expression) — это любое выражение, которое вычисляется до значения типа Date. Выражения Date могут включать константы типа Date, переменные, содержащие даты или числа, численные константы, даты, возвращаемые функциями, и знаки арифметических операций. Численное выражение (numeric expression) — это любое выражение, которое вычисляется до числа любого типа — Byte, Integer, Long, Single, Double или Currency. Численные выражения могут включать переменные, хранящие числа, численные константы, функции, возвращающие числа, и знаки арифметических операций. Численные выражения могут также включать строковые выражения, которые VBA преобразует в число. (Если все символы в строке являются цифрами, то VBA может преобразовать эту строку в численное значение; например, строку "436" в число 436.) Строковое выражение (string expression) — это любое выражение, которое имеет результатом значение типа String. Строковые выражения могут включать переменные, которые хранят строки, строковые константы, функции, возвращающие строки, или знаки (обозначения) операций конкатенации строк. Строковые выражения могут также включать численные выражения, которые VBA может преобразовать в строку. Логическое выражение (logical expression) — это любое выражение, которое вычисляется до значения типа Boolean: True или False. Логические выражения могут состоять из переменных, содержащих значения Boolean, констант Boolean, функций, возвращающих значения типа Boolean, знаков операций сравнения или логических операций. Объектное выражение (object expression) — это любое выражение, которое имеет результатом ссылку на объект. Совместимость типов данных Не все типы данных совместимы друг с другом, и нельзя использовать несовместимые типы данных в одном и том же выражении. Например, не имеет смысла арифметическое сложение строки с числом, так как такое выражение не является значащим и VBA не может его оценить. Многие типы данных совместимы друг с другом. Например, вы можете объединять различные численные типы данных в одном и том же выражении; VBA автоматически выполняет необходимые преобразования типа различных численных типов. VBA может также иногда автоматически преобразовывать другие типы данных так, чтобы все типы в выражении были совместимы, хотя это не всегда возможно. Например, типы String и Date совместимы с численными типами только при особых условиях, которые будут описаны далее. Очень важно контролировать и знать тип выражения, потому что если выражения содержат несовместимые типы, VBA выдает ошибку времени исполне 120 Глава 5 ния — ошибку несовпадения типов (type-mismatch). При обработке выражения, содержащего различные типы данных VBA сначала «пытается» устранить любое различие типов, преобразуя значения в выражении в совместимые типы данных. Если устранить какие-либо различия преобразованием типов не удается, отображается ошибка времени исполнения и процедура прекращает выполняться. Если вы присваиваете результат какого-либо выражения переменной, а тип переменной несовместим с типом результата этого выражения, VBA также отображает ошибку несовпадения типов. Аналогично, использование такого результата выражения в качестве аргумента для функции или процедуры также приводит к ошибке несовпадения типов, если тип данных аргументов и тип результата выражения являются несовместимыми. VBA предоставляет различные функции для преобразования информации одного типа в другой, например, строк в числа, чисел в строки и так далее (в предыдущей главе встречалась функция CSng, используемая для преобразования типа String в численный Single). Функции преобразования данных VBA описываются более подробно в главе 6. Автоматическое преобразование данных Visual Basic VBA использует различные правила для автоматического преобразования данных в совместимые типы и выбирает правила преобразования данных применительно к определенному выражению на основе конкретных типов и операторов, используемых в выражении. VBA выполняет автоматическое преобразование типов быстрее, если выражение содержит переменные типа Variant, потому что тип данных Variant не является фиксированным. Если выражение содержит литеральные константы, типизированные переменные или типизированные константы, VBA применяет более определенные правила преобразования типов, потому что тип данных этих элементов является фиксированным. (Помните, типизированная переменная или типизированная константа — это переменная или константа, для которой вы явно объявили тип данных либо с помощью ключевого слова As, либо символа определения типа, как было описано в предыдущей главе.) Следующие выражения иллюстрируют, как от типов данных и оператора зависят преобразования, выполняемые VBA: Выражение Описание и тип результата Num + Str Создает ошибку несовпадения типов, когда Num объявляется как численный тип, a Str — как тип String. Выполняется строковая конкатенация, когда Num является Variant, a Str объявляется как тип String; результат является типом String. Num + Str Выполняется арифметическое сложение, когда Num объявляется как численный тип, a Str — как Variant, или когда и Num, и Str являются типом Variant; результат — численный тип. Num + "3" Вызывает ошибку несовпадения типов, если Num объявлен численным типом. Выполняется строковая конкатенация, если Num является типом Variant; результат имеет тип String. 3 + Str Вызывает ошибку несовпадения типов, если Str объявлен как тип String. Выполняется арифметическое сложение, если Str является Типом Variant; результат является численным типом. (Заметьте, что это выражение никогда не имеет результатом строковую конкатенацию.) Выражения в Visual Basic 121 Выражение Описание и тип результата Num & Str Всегда выполняет строковую конкатенацию, независимо от типов переменных; результатом является тип String. Это выражение никогда не вызывает ошибки несовпадения типов. Обратите особое внимание'на последнее выражение. В нем используется оператор строковой конкатенации (&), который соединяет («склеивает») вместе две строки. Поскольку можно использовать этот оператор только со строками, VBA преобразует типы данных в этом выражении в строки, независимо от их оригинального типа данных и независимо от того, имеют ли какие-либо переменные в выражении определенный тип. По мере описания отдельных операторов в дальнейших разделах этой главы описываются также особые правила преобразования данных, которые VBA применяет для каждого отдельного оператора. Вы, наверное, уже заметили, что большинство из указанных выше выражений вызывают ошибку несовпадения типов только тогда, когда оба операнда в выражении имеют определенные и разные типы. Вы можете также заметить, что выражения не вызывают ошибку несовпадения типов, когда один из операндов является переменной типа Variant. Как было упомянуто выше, VBA легче всего выполняет автоматические преобразования типов с данными типа Variant. Не следует, однако, использовать типы Variant только для того, чтобы избежать ошибок несовпадения типов, поскольку игнорирование возможности использования встроенных типов может привести к другим ошибкам. Преобразования численных типов VBA обычно преобразует все численные типы данных в выражении в тип наибольшей точности, а затем дает этот тип результату выражения. Например, если выражение содержит численные значения с типами Integer и Single, результат выражения является типом Single — тип наибольшей точности в этом выражении. Если вы присваиваете результат численного выражения переменной с наименьшей точностью, чем фактический тип результата выражения, VBA округляет результат выражения до тех пор, пока его точность не совпадет с ожидаемым типом. Например, если вы присваиваете численное выражение, имеющее результатом число типа Double, переменной типа Integer, VBA округляет число двойной точности до типа Integer. Преобразования строк и чисел При преобразовании числа в строку VBA создает строку, содержащую все цифры этого числа и десятичный знак (если число имеет его). Число 3413.721, например, преобразуется в строку "3413,72". Если число очень большое или очень маленькое, VBA может создать строковое представление числа в экспоненциальной записи; например, число 0.0000000004927 преобразуется в строку "4,927Е-11". VBA может преобразовывать строку в число, если только эта строка содержит символьное представление числа в десятичном формате или экспоненциальном. Строки "988,6", "812", "-186,7”, ”1,ЗЕ10" представляют числа, и VBA может преобразовать их в числа. Строки "1.045", ”$74.550" и "С добрым утром!" не могут быть преобразованы в числа. 1 Точка используется для записи числа в коде. 122 Глава 5 Преобразования значений типа Boolean Когда VBA преобразует значения типа Boolean в числа, значение True преобразуется в 1, а значение False — в 0. Когда VBA преобразует число в тип Boolean, нуль преобразуется в False, а любое другое значение преобразуется в True. Когда VBA преобразует значения типа Boolean в строки, VBA использует строку "True" для True и "False" — для False. VBA не может преобразовывать строковые выражения в тип Boolean, но может преобразовывать численные выражения в значения этого типа. Когда вы используете значения типа Boolean в арифметических выражениях, VBA всегда преобразует их в числа, даже если все другие части этого выражения также являются переменными или константами типа Boolean. Преобразования значений типа Date Когда VBA преобразует тип данных Date в число, результатом является численное значение — число типа Double, которое содержит количество дней от 30 декабря 1899 (отрицательное число представляет дату, более раннюю, чем 12/30/1899). Десятичная часть числа (если имеется) выражает время дня как часть дня; 0 — это полночь, а 0.5 — это полдень. В VBA преобразование численных типов данных в типы Date является просто обратным преобразованию типа Date в число. Если выражение имеет результатом значение, находящееся вне диапазона типа данных для этого выражения, VBA отображает сообщение об ошибке переполнения. Если выражение содержит литеральную константу, иногда можно решить эту проблему, используя символ определения типа с литеральной константой, чтобы выражение имело результатом численный тип с большим диапазоном значений. Оператор присваивания (=) В предыдущей главе вы кратко познакомились с оператором {statement) присваивания (=). Этот оператор используется для присваивания результата выражения переменной. Оператор присваивания сохраняет любое значение, которое представлено выражением справа от оператора присваивания (=), в ячейке памяти, на которую ссылается переменная слева от оператора. Оператор присваивания имеет две синтаксические формы, обе из которых являются одинаково приемлемыми и выполняют одну и ту же задачу. Первая форма оператора присваивания использует ключевое слово Let и имеет следующий общий синтаксис: СИНТАКСИС Let varname = expression Переменная varname представляет любую переменную VBA, a expression — любое выражение VBA. Этот синтаксис является оригинальной формой оператора присваивания, использовавшейся в ранних версиях языка программирования Basic. Следующий оператор VBA является примером оператора присваивания Let: Let х = у ' присваивает переменной х значение, представленное . ' переменной у Вторая форма оператора присваивания более употребительна в программировании на VBA и широко используется в этой книге. Общий синтаксис этой формы оператора присваивания следующий: varname = expression Выражения в Visual Basic 123 Переменная varname — любая переменная, a expression — любое выражение. Далее следуют примеры этого более простого, более употребительного оператора присваивания (первая строка присваивает содержимое Y переменной X; вторая строка присваивает переменной SecondVar результат сложения 102 с содержимым FirstVar): X = Y SecondVar = 102 + FirstVar При выполнении оператора присваивания VBA сначала вычисляет выражение справа от оператора присваивания (=), а затем сохраняет результат выражения в переменной, имя которой находится слева от оператора присваивания. Новичкам в вопросах программирования бывают не сразу понятны операторы, подобные следующим: Номер = Номер + 1 ОбщаяСумма = ОбщаяСумма + ПодСумма Особенность этих операторов в том, что и слева, и справа от знака оператора появляется один и тот же идентификатор переменной. Чтобы понять, каким должен быть результат подобных инструкций, следует еще раз внимательно прочитать синтаксис оператора присваивания. Тогда станет ясно, что сначала в некоторую промежуточную ячейку памяти помещается результат вычисления (оценивания) выражения справа от оператора (для первого примера это — Номер + 1, для второго — ОбщаяСумма + ПодСумма), а затем этот результат помещается в ячейку памяти, соответствующую переменной, идентификатор которой находится слева от оператора "=". Более короткая форма оператора присваивания используется гораздо чаще, чем длинная, в основном потому, что короткая быстрее вводится с клавиатуры. Длинная форма оператора присваивания с ключевым словом Let часто рекомендуется для начинающих программистов, поскольку помогает отличать оператор присваивания от операции сравнения (равенства)- Хотя эти две конструкции используют один и тот же символ, не путайте оператор присваивания со знаком равенства (=), используемым для тестирования на равенство. Следующие два выражения приводят к совершенно разным результатам: первый — является оператом и присваивает значение 5 переменной First Vai; второй — является логическим выражением, которое имеет результатом True или False, в зависимости от того, содержит ли уже First Vai число 5: FirstVal = 5 ' присваивает число 5 переменной FirstVal (FirstVal =5) ' сравнивает содержимое FirstVal с числом 5 Заметьте, что вторая строка, фактически, не является законченным оператором VBA (хотя является законченным выражением), поскольку результат логического выражения никаким образом не используется; подобная строка в ваших процедурах может вызвать ошибку синтаксиса. Чтобы получить синтаксически верный оператор VBA, необходимо каким-то образом использовать результат этого выражения: присвоить его переменной, передать его в качестве аргумента функции или процедуре. Когда вы присваиваете результат выражения переменной с определенным типом данных, этот результат может иметь тип данных, совместимый с типом переменной, получающей новое значение. Во многих случаях, VBA может преобразовывать тип данных результата выражения в тип, совместимый с типом переменной, принимающей новое значение, если результат выражения и переменная еще не имеют совместимых типов. Переменным типа Variant может быть присвоен любой тип данных. 124 Глава 5 Запомните следующее: - . . >. Можно присваивать любую численную переменную или выражение любой другой переменной численного типа или переменной типа Variant. Если присваивается численное выражение типизированной переменной с меньшей точностью или диапазоном (как при присваивании типа Double типу Long), VBA округляет значение выражения для совпадения с точностью переменной, принимающей новое значение. Если переменной типа String присваивается переменная типа Variant, содержащая число, VBA автоматически преобразует это число в строку. (При присваивании типизированных численных переменных или численных констант переменной типа String происходит ошибка несовпадения типов.) Арифметические операции VBA может выполнять все обычные арифметические операции (реализуемые посредством арифметических выражений): сложение, вычитание, умножение и деление, а также возведение чисел в указанную степень и предоставляет дополнительные особые математические операции для целочисленного деления и деления по модулю. В табл. 5.1 приводятся знаки операций, которые можно использовать при написании арифметических VBA-выражений. (В этой таблице Ni — это любое допустимое численное выражение VBA.) Таблица 5.1. Знаки операций (обозначения), используемые в арифметических VBA-выражениях Знак Синтаксис Имя/Описание + Nl + N2 Сложение. Прибавляет N1 к N2. - Nl - N2 Вычитание. Вычитает N2 из N1. * Nl * N2 Умножение. Умножает N1 на N2. / Nl/ N2 Деление. Делит N1 на N2. \ Nl\ N2 Целочисленное деление. Делит N1 на N2, отбрасывая любую дробную часть так, чтобы результат был целым числом. Mod Nl Mod N2 Деление по модулю. Делит N1 на N2, возвращая только остаток операции деления. Nl Л N2 Возведение в степень. Возводит N1 в степень N2. Далее описывается подробно использование каждого знака. Сложение (+) Знак операции сложения (+) используется для выполнения операции простого сложения. Оба операнда должны быть численными выражениями или строками, которые VBA может преобразовать в число. Знак операции сложения можно также использовать для построения арифметических выражений с данными типа Date. Для большего понимания следующего материала войдите в редактор VBA (выберите Сервис | Макрос | Редактор Visual Basic). Далее щелкните на кнопке View Code в Project Window. В появившемся Code Window набирайте предлагаемые далее небольшие программы и, если вам этого будет не достаточно, можете проводить свои собственные эксперименты с кодом. Выражения в Visual Basic 125 Введите в Code Window код листинга 5.1. Листинг 5.1. Пример использования знака операции "+" 1 Sub list5_01() 2 ' Примеры арифметических выражений со знаком "+" 3 Dim Nl, N2, N3 As*Integer 4 5 Nl = 1 ' присваивание значения переменной N1 6 N2 = 2 ' присваивание значения переменной N2 7 N3 = Nl + N2 ' сложение; результат — в N3 8 MsgBox (N3) ' Вывод N3 в диалоговом окне 9 10 End Sub Видимо, здесь нечего объяснять. Понятно, что при запуске этого кода (Run | Run Sub/UserForm) на экране появится диалоговое окно с числом 3. Тип данных результата выражения сложения обычно тот же, что и наиболее точный тип в этом выражении. Например, если выражение содержит оба типа Integer и Long, результатом такого выражения будет тип Long. Однако существуют некоторые исключения, в частности, если выражение включает переменные типа Variant. Далее перечисляются эти исключения: 1. Результатом сложения типа Single и Long является Double. 2. Если складывать тип Date с любым другим типом данных, результатом выражения всегда будет тип Date. 3. Если результат выражения сложения присваивается переменной Variant, имеющей в данный момент тип Integer, и если результат выражения больше, чем (переполняет) диапазон значений для типа Integer, то VBA преобразует результат в Long. После присваивания переменная Variant также имеет тип Long. 4. Если результат выражения сложения присваивается переменной Variant, имеющей в данный момент тип Long, Single или Date, и если результат выражения переполняет диапазон численного типа, VBA преобразует результат в Double. После присваивания переменная типа Variant также имеет тип данных Double. 5. Если любой операнд в выражении сложения является равным Null или вычисляется до Null, то результатом выражения сложения также будет Null. (Null — это особое значение, которое можно присваивать только переменным типа Variant для обозначения того, что они не содержат действительных данных.) Порядок точности для численных типов данных VBA от наименее точного до наибо-ZffOu лее точного следующий: Byte, Integer, Long, Single, Double, Currency. В листинге 5.2 содержится код, демонстрирующий правила преобразования выражений со знаком ”+", приведенные в последнем перечне. Листинг 5.2. Преобразования типов в выражениях со знаком "+" 1 Sub list5_02() 2 ' Примеры арифметических выражений со знаком "+" 3 4 Dim SI As Single 5 Dim LI As Long 6 Dim II As Integer 126 Глава 5 7 Dim DI As Date 8 Dim VI, V2 As Variant 9 10 ’ инициализация переменных 11 si = з.ззз 12 Ll = 3.333 13 Il = 1111 14 DI = Now ' получить значение текущей даты'и времени 15 16 MsgBox TypeName(SI + Ll) , vbOKOnly, "Single + Long" 17 MsgBox TypeName(DI + Ll), vbOKOnly, "Date + Long" 18 19 VI = Il ' переменная типа Variant становится типа Integer 20 MsgBox TypeName(VI), vbOKOnly, "V1=I1" 21 22 VI = VI + 99999 ' переменная типа Variant становится типа Long 23 MsgBox TypeName(VI), vbOKOnly, "VI + 99999” 24 25 VI = Dl ' переменная типа Variant становится Date 26 VI = VI + 99999999 ' переменная типа Variant становится Double 27 MsgBox TypeName(Vl), vbOKOnly, "VI = Dl; VI = VI + 99999999" 28 29 VI = Null + 1 ' переменная типа Variant становится Null 30 MsgBox TypeName(VI) , vbOKOnly, "VI = Null + 1" 31 32 Ena Sub На рис. 5.1 приведен ряд диалоговых окон, которые отображаются на экране во время выполнения кода листинга 5.2. Заметим, что довольно часто начинающие программировать не уделяют этим вопросам должного внимания; это иногда приводит к непонятным для них результатам. Рис. 5.1 Диалоговые окна, отображаемые при выполнении кода листинга 5 2 Вычитание (-) Знак операции вычитания (-) выполняет две задачи. Он используется либо для построения арифметических выражений вычитания, либо для обозначения унарного минуса. Унарный минус {unary minus) — это знак минус, который помещают перед числом для указания того, что это — отрицательное число. Знак минус можно также помещать перед переменной или другим выражением для обозначения того, что значение переменной или выражения должно быть отрицательным. Поместить унарный минус перед переменной или выражением означает то же, что умножить это число на —1. Следующие выражения содержат унарный минус: Выражения в Visual Basic 127 -10 литеральная отрицательная константа -MyVar делает отрицательным любое число, сохраненное в MyVar -(MyVar +10) делает отрицательным результат сложения 10 и MyVar Следующие несколько выражений показывают примеры использования знака вычитания для построения арифметических выражений: Now - 60 результат выражения имеет тип Date 40 - MyVar разность между 40 и MyVar AnyVar - SomeVar разность между AnyVar и SomeVar Оба операнда в выражении вычитания должны быть численными переменными или выражениями, или строковым выражением, которое VBA может преобразовать в число. Знак операции вычитания можно также использовать для построения арифметических выражений с данными типа Date. Тип данных результата выражения вычитания обычно является тем же, что и наиболее точный тип данных в этом выражении. VBA следует тем же правилам для определения типа данных результата выражения вычитания, что и для выражений, использующих знак операции сложения, но имеются следующие дополнительные правила: Если один из операндов в выражении вычитания является типом Date, то результат выражения имеет тип Date. Если оба операнда в выражении являются типом Date, то результат выражения имеет тип Double. В листинге 5.3 приведен код, демонстрирующий эти дополнительные правила. Листинг 5.3. Дополнительные правила преобразования типов в выражениях со знаком операции " 1 Sub list5_03() 2 ' Примеры арифметических выражений со знаком 3 Dun DI, D2 As Date 4 5 DI = Now ' получить значение текущей даты и времени 6 D2 = Now - 5 7 8 gg = MsgBox(TypeName(D2), vbOKOnly, "Now - 5") 9 gg = MsgBox(TypeName(DI - D2), vbOKOnly, "DI - D2") 10 11 End Sub На рис. 5.2 приведены диалоговые окна, которые отображаются на экране во время выполнения кода листинга 5.3. Рис. 5.2 Диалоговые окна, отображаемые при выполнении кода листинга 5.3 128 Глава 5 i—S Несмотря на то, что можно конкатенировать (объединять) две строки вместе с по-мощью знака (+), нельзя использовать знак (-), чтобы отделить какую-либо стро-ку. Вместо этого для отделения строк можно использовать VBA-функции Mid, Left или Right. Эти функции описываются в следующей главе. Умножение (*) Знак операции умножения (*) используется для построения арифметических выражений с умножением; результатом выражения умножения является произведение двух операндов. Оба операнда в выражении умножения должны быть численными выражениями или строками, которые VBA может преобразовать в число. Следующие примеры иллюстрируют правильный синтаксис для арифметических выражений с умножением: 4 * 10 ' умножение 4 на 10; результат равен 40 NumVar * 2 ' результат — произведение NumVar и 2 NumVar * OtherVar ' результат — произведение NumVar и OtherVar Тип данных результата выражения умножения обычно тот же, что и наиболее точный тип в этом выражении. VBA следует тем же правилам для определения типа данных результата выражения умножения, что и для выражений, использующих сложение. В выражениях умножения все переменные Variant, которые содержат значения типа Date, преобразуются в численные значения. Деление (/) Знак операции деления (/) иногда называют знаком деления чисел с плавающей точкой или действительных чисел, чтобы отличать от знака целочисленного деления, который описан в следующем разделе. В выражениях деления первый операнд делится на второй операнд; результатом деления является частное. Оба операнда в выражении деления с плавающей точкой должны быть численными выражениями или строками, которые VBA может преобразовать в числа. Следующие выражения иллюстрируют использование знака операции деления: 27/3 ' деление 27 на 3 MyNumVar / 20 1 деление значения в переменной MyNumVar на 20 MyNumVar / MyOtherVar ' делит значение в переменной MyNumVar ' на значение в переменной MyOtherVar Если любой операнд в выражении деления имеет значение Null, то результатом выражения также является Null. Тип данных выражения со знаком деления с плавающей точкой — обычно Double, но имеется следующее исключение: Если оба операнда в выражении деления имеют тип Integer или Single, то результат выражения деления с плавающей точкой имеет тип Single, если только результат выражения не переполняет диапазон значений для типа Single. Если результат переполняет диапазон для типа Single, то VBA преобразует результат в тип Double. Деление любого числа на нуль приводит к ошибке времени исполнения. Правила математики утверждают, что деление числа на нуль невозможно. Из-за этого мате-J магического правила VBA всегда генерирует ошибку времени исполнения, когда встречает выражение, у которого делитель равен нулю. Понятно, что трудно представить себе программу, в которой в качестве делителя будет выступать литеральный нуль. Обычно деление на нуль возникает в результате того, что за несколько шагов до выполнения деления переменная-делитель «неожиданно» для программиста становится равной нулю. Если вы не уверены в «адекватности поведения» делителей в вашем коде, вставляйте операторы тестирования этих делителей на равенство нулю перед выполнением деления. После самого полного тестирования кода эти операторы можно будет либо убрать совсем, либо закомментировать до следующей модификации программы. Выражения в Visual Basic 129 Целочисленное деление (\) Целочисленное деление подобно делению с плавающей точкой, кроме того, что выражения, использующие оператор целочисленного деления (\), всегда имеют результатом целое число без дробной части. Оба операнда в выражении целочисленного деления должны быть численными выражениями или строками, которые VBA может преобразовать в числа. Следующие примеры выражений иллюстрируют правильный синтаксис для целочисленного деления: 4 \ 3 ' деление 4 на 3; возвращает значение 1 9 \ NumVar ' деление 9 на содержимое NumVal MyVar \ NumVar ' деление MyVar на NumVar В целочисленном делении VBA округляет каждый операнд (если необходимо) до числа типа Integer или Long перед выполнением операции деления. VBA отбрасывает любой дробный остаток результата выражения целочисленного деления. Например, выражение деления с плавающей точкой 19/5 имеет результатом 3.8, в то время как выражение целочисленного деления 18 \ 5 имеет результатом 3. Заметьте, что VBA не округляет частное целочисленного деления, результат просто укорачивается до целого числа. Тип данных результата выражения целочисленного деления — либо Integer, либо Long; VBA использует наименьший тип данных, который соответствует результату выражения. Если какой-либо операнд в выражении целочисленного деления является равным Null, то результатом выражения также будет Null. Деление по модулю (Mod) Деление по модулю дополняет целочисленное деление. При делении по модулю выражение возвращает только остаток операции деления как целое. Оба операнда в выражении деления по модулю должны быть численными выражениями или строками, которые можно преобразовать в число. Следующие примеры выражений иллюстрируют деление по модулю: 8 Mod 2 ' возвращает значение О 5.1 Mod 3 ' возвращает значение 2 6 Mod NumVar ' если NumVar содержит 3, возвращает О При делении по модулю VBA округляет каждый операнд (если необходимо) до числа типа Integer или Long перед выполнением деления так же, как при целочисленном делении. Тип данных результата выражения деления по модулю — это Integer или Long. VBA использует наименьший тип, который подходит для результата выражения. Если какой-либо операнд в выражении деления по модулю является Null, то результатом выражения также будет Null. Возведение в степень (л) Знак операции возведения в степень (") используется в арифметических выражениях для возведения в степень числа или выражения. Показатель степени указывает, сколько раз число (или выражение) должно быть умножено на самое себя: З3 — это то же, что и 3 х 3 х 3. Чтобы записать З3 как арифметическое выражение VBA, используйте следующее: 3 Л 3 Оба операнда в выражении возведения в степень должны быть численными выражениями или строками, которые VBA может преобразовать в числа. Операнд слева от знака возведения в степень может быть отрицательным числом, только если операнд справа является целым. Если какой-либо операнд является равным Null, то результатом выражения возведения в степень также будет Null; иначе результат выражения будет иметь тип Double. 5 Программирование на VBA 2002 130 Глава 5 Операции сравнения Операции сравнения иногда также называют операциями отношения (relational operators). Чаще всего операции сравнения используются для того, чтобы задать критерии для принятия решения или сформулировать описание условий, при которых группа команд должна быть повторена (организация циклов). Результатом любой операции сравнения является значение типа Boolean: True или False. Операции сравнения используются для сравнения литеральных, константных или переменных значений любого сходного типа. В табл. 5.2 перечислены имеющиеся в VBA знаки операций сравнения и описано их назначение (Е в этой таблице представляет любое действительное выражение VBA). Таблица 5.2. Знаки (обозначения) операций сравнения Операция/ Оператор Синтаксис Наименование/описание = El = Е2 Равенство. True, если El равно E2, иначе — False. < El < Е2 Меньше, чем. True, если El меньше, чем Е2, иначе — False. <= <= Меньше, чем или равно. True, если Е1 меньше или равно Е2, иначе — False. > > Больше, чем. True, если Е1 больше, чем Е2, иначе — False. >= >= Больше, чем или равно. True, если Е1 больше или равно Е2, иначе — False. о о Не равно. True, если Е1 не равно Е2, иначе — False. Is El is E2 Оба операнда должны быть значениями типа Object. True, если El ссылается на тот же самый объект, что и Е2, иначе — False. Like El Like E2 Подобие. Оба операнда должны быть значениями типа String. True, если El совпадает с образцом, содержащимся в Е2, иначе — False. Если оба операнда в выражении сравнения имеют один и тот же тип данных, VBA выполняет простое сравнение для этого типа. Если, например, оба операнда являются строками, VBA выполняет сравнение строк; если оба операнда являются датами, то VBA выполняет сравнение дат и так далее. Следующие выражения иллюстрируют использование различных операторов сравнения: MyVal = 55 результат True, если MyVal содержит 55 7 <> 5 результат True: 7 не равно 5 NumVar <57 True, если NumVar меньше, чем 57 Now > #5/30/1997 True, если текущая дата (результат функции Now) больше, чем 30 мая 1997 "Joe" < ' "Sam" True; "Joe" меньше, чем "Sam" (в соответствии с алфавитом) "Pat" c "Patricia" True; "Pat" короче, чем "Patricia" Выражения в Visual Basic 131 Помните, что значения дат VBA могут включать информацию о времени. Когда сравниваются значения дат, VBA, фактически, сравнивает информацию о дате и времени. Поэтому, даже если месяц, день и год двух дат являются одними и теми же, они могут не быть равны друг другу, если временные части значения даты различны. Например, дата #1/10/97# меньше, чем дата #1/10/97 9:00:00АМ#. В первой дате нет никакого значения времени, и VBA «полагает», что время составляет 00:00:00. Несмотря, на то что год, месяц и день во второй дате те же, что и в первой, она имеет более позднее время и, следовательно, является большей, чем первая дата. Если оба операнда в выражении сравнения имеют определенные типы (либо — константы, либо — типизированные переменные) и эти типы не являются совместимыми, VBA выводит на экран сообщение об ошибке несовпадения типов. Если один или оба операнда в выражении сравнения являются переменными типа Variant, VBA «пытается» преобразовать тип Variant в какой-либо совместимый тип, если необходимо. Если преобразование данных необходимо, a VBA не может преобразовать Variant в совместимый тип, отображается сообщение об ошибке времени исполнения. Поскольку не всегда легко определить, будет ли VBA выполнять численное сравнение или строковое, когда в выражении сравнения смешаны численные и строковые значения, следует всегда использовать одну из VBA-функций преобразования типов (например, CStr) для явного преобразования значений в числа или строки/чтобы оба операнда в выражении сравнения имели один и тот же тип данных. (Функции преобразования описаны в следующей главе.) Сравнение строк Сравнение строк немного сложнее, чем сравнение чисел. В VBA строка равна другой строке, только когда обе строки содержат точно такие же символы в точно таком же порядке и обе строки имеют одну и ту же длину. Рассмотрим следующие выражения: "abc" = "abc" True; обе строки одинаковые "abc" = abc False; строки не одинаковые В первом выражении строки равны одна другой: обе содержат те же символы и в том же порядке и имеют одну и ту же длину. Во втором выражении строки не равны одна другой, строка в правой части оператора имеет по одному символу пробела в начале и в конце строки. VBA не игнорирует начальные или конечные символы пробела при сравнении строк. При сравнении строк операторами отношения, VBA сравнивает каждую строку слева направо посимвольно. Следующие несколько примеров выражений иллюстрируют сравнение строк: "abb" < "abc" True "aab" < "abb" True 2abc" < "abc True “abed” > “abc” True Будьте внимательны при сравнении строк фиксированной и переменной длины. Помните, что строки фиксированной длины всегда содержат одно и то же количество символов и что размер строки переменной длины увеличивается и уменьшается в зависимости от размера строки, сохраняемой в ней. 5* 132 Глава 5 Двоичное и текстовое сравнение строк До сих пор в этой главе выражения сравнения строк включали только строки, состоящие из символов нижнего регистра. VBA предоставляет два различных способа сравнения символов различных регистров. Первый метод, который VBA использует для сравнения строк, называется бинарным {binary) или двоичным сравнением и является методом сравнения по умолчанию. Чтобы понять, как работает двоичное сравнение, необходимо помнить, что вся информация в компьютере сохраняется в виде чисел. Для сохранения текста компьютер использует схему, в которой каждый отображаемый символ имеет уникальный номер. Для представления в компьютере все буквы некоторого алфавита имеют уникальные последовательные номера. Обычно буквы верхнего регистра (например, A-Z) имеют меньшие номера, чем буквы нижнего регистра (a-z). Число, соответствующее определенной букве или другому символу, называется кодом символа {character code). При выполнении двоичного сравнения строковой информации, VBA использует фактический бинарный эквивалент числа для каждого символа, так как при этом сравнивается каждая пара символов. Поскольку буквы верхнего регистра имеют меньшие двоичные номера, буквы верхнего регистра располагаются в алфавитном порядке перед буквами нижнего регистра. Другими словами, для VBA при двоичном сравнении строк, строка "ААА" меньше, чем строка "ааа”. Второй тип сравнения, предлагаемый VBA, называется текстовым {text) сравнением. В текстовом сравнении VBA не использует двоичный эквивалент для каждого символа и «рассматривает» буквы верхнего регистра как эквивалентные буквам нижнего регистра. В текстовом сравнении строка "АВС" равна строке "abc”. Выбор метода сравнения строк Для выбора метода сравнения строк, имеющегося в VBA (двоичного или текстового), используйте директиву Option Compare: Option Compare [Text I Binary] Чтобы задать двоичное сравнение строк, используйте ключевое слово Binary: Option Compare Binary Директиву Option Compare можно использовать только на модульном уровне, и она влияет только на сравнения, выполняемые процедурами в этом отдельном модуле. Обычно директиву Option Compare помещают в область объявлений модуля перед объявлениями переменных или процедур. Если команды Option Compare в коде нет, VBA использует двоичные сравнения. Сравнение строки с шаблоном Оператор1 Like дает возможность выполнять особый тип операции сравнения строк и его можно использовать только со строками. Like тестирует строку для определения того, совпадает ли она с заданным шаблоном (образцом). Оператор Like можно использовать для выполнения поиска в текстовой информации для нахождения всех слов или фраз, совпадающих с определенным шаблоном. Поиск такого типа часто называют нечетким поиском {fuzzy search). Строго говоря, Like является обозначением операции сравнения и входит в состав логического выражения. То же самое касается и оператора Is, и логических операторов, рассматриваемых далее. Выражения в Visual Basic 133 Общий синтаксис для оператора Like следующий: СИНТАКСИС StrExprl Like StrExpr2 StrExprl — любое строковое выражение VBA. StrExpr2 — строковое выражение, специально созданное для задания шаблона, который оператор Like сравнивает с StrExprl. Результатом выражения Like является True, если первый операнд (StrExprl) совпадает с шаблоном во втором операнде (StrExpr2); иначе результатом выражения будет False. Оба операнда в этом выражении должны быть строковыми выражениями, или VBA отобразит сообщение об ошибке несовпадения типов. Шаблон, с которым должна сравниваться строка, задается с использованием различных специальных символов. В табл. 5.3 содержатся методы и символы для создания образцов совпадения для оператора Like. Таблица 5.3. Символы совпадения с образцом для оператора Like Символ образца Соответствие # Любая одиночная цифра от 0 до 9. * Любое количество символов в любой комбинации или отсутствие символов. ? Любой одиночный символ. [list] list — это список определенных символов. Совпадение с любым одиночным символом в списке. [Hist] list — это список определенных символов. Совпадение с любым одиночным символом, не имеющимся в списке. Следующее выражение является равным True, если AnyStr содержит строки такие, как "Sadie”, "Salone", "Sophie”, "Steve" и так далее: AnyStr Like "S*e" Следующее выражение является равным True, если AnyStr содержит строки такие, как "Реппу", "Percy", "Patty" и так далее: AnyStr Like "Р???у" Используйте две последние спецификации символов совпадения из табл. 5.3 для указания отдельных символов, совпадение или несовпадение с которыми вам необходимо. Следующие выражения показывают, как использовать квадратные скобки с символьным списком. Данное выражение является равным True, если AnyStr содержит "big" или "bid", или — False, если оно содержит "bit" или "bin": AnyStr Like "bi[dg]" Следующее выражение является равным True, если AnyStr содержит "big", "bid" или "bin", или — False, если оно содержит "bit": AnyStr Like "bi[!t]" Еще одно выражение является равным True, если AnyStr содержит "bin" или "bit", или — False, если AnyStr содержит "bid" или "big": AnyStr Like "bi[!dg]" Можно также использовать квадратные скобки для указания диапазона символов, совпадение или несовпадение с которыми необходимо: 134 Глава 5 AnyStr Like "ci[a-f]" , AnyStr Like "ci[!a-f]” Результат первого из приведенных выше примеров является равным True, если AnyStr содержит "cia", "cib", "cic", "cid", "cie" или "cif" и False — иначе. Второе выражение обратно первому и является равным False, если AnyStr содержит одну из строк ”cia”, "cib", "cic", "cid", "cie", "cif". Второе выражение является равным True для любой строки, содержащей первые две буквы ci и не заканчивается на буквы от а до f. Когда вы указываете диапазон символов, необходимо указывать диапазон от наименьшего до наибольшего символа. Например, [a-f] — правильный диапазон, но [f—а] — нет. VBA игнорирует пары квадратных скобок, в которых ничего не заключено ([]). Поскольку левая квадратная скобка ([), знак вопроса (?), символ номера (#) и символ (*) имеют особое значение в строке шаблона, необходимо заключать их в квадратные скобки, если вы хотите, чтобы они были частью шаблона. Например, если необходимо узнать, заканчивается ли строка вопросительным знаком, используйте следующее выражение (которое является равным True, если AnyStr содержит любое число или комбинацию символов, заканчивающуюся знаком вопроса): , AnyStr Like "*[?]" Правая скобка (]) и восклицательный знак (!) также имеют особое значение в строке шаблона; для достижения совпадения с этими символами необходимо помещать их вне квадратных скобок списка символов. Например, чтобы определить, заканчивается ли строка восклицательным знаком, используйте следующее выражение (которое является равным True, если AnyStr содержит любое число или комбинацию символов, заканчивающуюся восклицательным знаком): AnyStr Like "*!" Для совпадения со знаком дефиса в строке шаблона поместите дефис в начало или в конец списка символов внутри квадратных скобок. Помещение дефиса в любое другое место задает диапазон символов. Следующее выражение показывает, как сопоставлять с символом дефиса (это выражение является True, если AnyStr содержит "big-headed", "pig-headed", "plug-ugly", "tag-along" и так далее): AnyStr Like ”*д[-]*" ' True На результат сравнения строк, которое использует оператор Like, оказывает также влияние инструкция Option Compare. Если задано двоичное сравнение строк, то оператор Like различает буквы верхнего и нижнего регистра. Если выбрана установка текстового сравнения, оператор Like не чувствителен к состоянию регистра. Использует ли VBA в данный момент двоичное или текстовое сравнение, также влияет на то, какие символы оператор Like включает в различные диапазоны, задаваемые пользователем. Если, например, был задан диапазон [e-i], а опция сравнения установлена на двоичное сравнение, то только символы е, f, g, h и i совпадают с указанным диапазоном. Если опция сравнения установлена на текстовое сравнение, то диапазон [e-i] включает еще несколько символов — (Е, е, И, и, Й, й, К, к, Ё, ё, F, f, G, g, Н, h, I) и i. Если необходимо только узнать, является ли строка частью другой строки, исполь-/^у\ зуйте VBA-функцию Instr вместо оператора сравнения Like. Например, если необ-ходимо только определить, является ли строка "big" частью строки "bigger", исполь-зуйте функцию Instr, функции VBA описываются в главе 6 Выражения в Visual Basic 135 Сравнение объектов VBA имеет следующий оператор сравнения — Is. Этот оператор можно использовать только для сравнения выражений типа Object. Выражения, включающие оператор Is, всегда имеют результатом значение типа Boolean. Результатом оператора Is является True, если оба выражения типа Object ссылаются на один и тот же объект; в противном случае результатом является False. VBA предоставляет оператор Is, потому что никакой другой из операторов сравнения не является значащим, когда он используется с выражениями типа Object. Выражения типа Object, на самом деле, являются адресами в памяти, ссылающимися на определенный объект в host-приложении (Excel, Word, Access или каком-либо другом приложении, реализующем VBA). Более подробно объекты описываются в главе 10. Логические операторы Чаще всего логические операторы VBA используются для объединения результатов отдельных выражений сравнения, чтобы создать сложные критерии для принятия решений в процедуре, или для создания условий, при которых группа операторов должна повторяться. Можно использовать любое действительное выражение, имеющее результат типа Boolean, в качестве операнда для логического оператора или число, которое VBA может преобразовать в значение типа Boolean. Для VBA 0 является эквивалентным Boolean-значению False, а любое другое численное значение — значению True. Обычно результатом логической операции является значение типа Boolean, хотя некоторые логические операции могут иметь результатом особое значение Null, если один или больше операндов имеют значение Null. Поскольку VBA интерпретирует особое значение Empty как 0, операнды в логических выражениях, содержащие Empty, обрабатываются так, как если бы они содержали Boolean-значение False. В табл. 5.4 приведены логические операторы, имеющиеся в VBA, вместе с синтаксисом и кратким описанием работы. (Е в этой таблице представляет собой любое допустимое выражение с результатом типа Boolean, такое как операция сравнения.) Таблица 5.4. Логические операторы Оператор Синтаксис Имя/Описание And El And E2 Конъюнкция. True, если оба Е1и Е2 имеют значение True, иначе — False. Or El Or E2 Дизъюнкция. True, если одно выражение или оба (Е1 и Е2) являются равными True; иначе — False. Not Not El Отрицание. True, если Е1 имеет значение False; False, если El является равным True. Xor El Xor E2 Исключение. True, если Е1 является равным True или Е2 является равным True; иначе — False. Eqv El Eqv E2 Эквивалентность. True, если Е1 имеет то же самое значение, что и Е2; иначе — False. Imp El Imp E2 Импликация. False, когда Е1 является равным True и Е2 равно False; иначе — True. 136 Глава 5 Логические VBA-операторы And, Not и Or подобны функциям рабочего листа AND, NOT и OR, встроенным в Excel. Однако Excel не имеет эквивалентных функций для VBA-операторов Eqv, Imp или Хог. Таблицы истинности Таблица истинности (truth table) — это таблица, показывающая все возможные комбинации значений для определенного типа логической выражения и его результаты. Большинство таблиц истинности имеют три столбца. Первый столбец предназначен для значения первого операнда, второй — для значения второго операнда, а последний столбец всегда содержит значение результата выражения. Каждая строка в таблице предназначена для определенной комбинации значений. Рассмотрим следующую строку из таблицы истинности оператора And: False True False В этой строке первый операнд — это False, второй операнд — True, а результат операции And является равным False. Эта строка в таблице истинности означает, что результатом выражения False And True является False. And Оператор And выполняет логическую конъюнкцию. Результатом операции And является значение True, только когда оба операнда являются равными True; иначе — False. Оператор And имеет следующий синтаксис: СИНТАКСИС » г Operandl And 0perand2 Operandl и Operand.2 являются любыми допустимыми логическими выражениями VBA. (Логическое выражение (logical expression) — это любое выражение VBA, которое имеет результатом значение типа Boolean: True или False.] Следующая таблица истинности показывает результаты операции And. Operandl Operand2 Результат выражения True True True True False False False True False False False False Оператор And можно использовать не только для двух операндов. Результатом этого оператора с несколькими операндами будет значение True, если все операнды в выражении равны True. Например: (2 > 5) And (7 > 3) And (3 > 1) Это выражение имеет результатом False. Обратите внимание, что операнды в этом выражении являются выражениями сравнения; заметьте также круглые скобки вокруг выражений, которые составляют операнды оператора And: Круглые скобки указывают VBA на необходимость вычислить выражение внутри скобок перед вычислением других частей этого выражения. Кроме того, круглые скобки делают выражение более читабельным, группируя вместе связанные части выражения. Скобки, используемые для группировки частей выражения в подвыражение, являются общей особенностью выражений всех типов: численных, строковых, дат и сравнения, так же как и логических выражений. Выражения в Visual Basic 137 Or Оператор Or выполняет логическую дизъюнкцию и его часто называют включающим «ИЛИ» (inclusive or). Результатом операции Ог является значение True, когда хотя бы один из операндов равен значению True; иначе (если все операнды — False) результатом является значение False. Оператор Or имеет следующий общий синтаксис: СИНТАКСИС Operandl Or 0perand2 Operandl и Operand.2 являются любыми допустимыми логическими выражениями VBA. Следующая таблица истинности показывает результаты операции Or. Operandl Operand2 Результат выражения True True True True False True False True True False False False Оператор Or можно использовать не только для двух операндов. Результатом оператора с несколькими операндами будет значение True, если хотя бы один операнд в выражении равен True. Например: (2 > 5) Or (7 > 3) Or (3 > 1) Это выражение имеет результатом True. Сравните с предыдущим примером. Операторы And и Or можно комбинировать в одном выражении. Например, значение следующего выражения равно True: ( (2 > 5) Or (7 > 3) ) And ( (3 > 1) Or (8 < 10) ) Not Оператор Not выполняет логическое отрицание; он инвертирует любое значение, к которому применяется. Оператор Not использует только один операнд и имеет результатом значение True, если операнд является равным False, или — False, если операнд — True. Оператор Not имеет следующий общий синтаксис: СИНТАКСИС Not Operand Operand — это любое допустимое логическое выражение VBA. Следующая таблица истинности' показывает результаты операции Not: Operand Результат выражения True False False True Подумайте над результатом следующего выражения и используйте среду VBA для проверки своих рассуждений. 138 Глава S ((2 > 5) Or (7 > 3) ) And Not ((3 > 1) Or (8 < 10)) Код для тестирования этого выражения совсем простой (см. листинг 5.4) и приведен только с целью напомнить о том, что мы изучаем программирование на VBA. Все, что мы обсуждаем, следует проверять, даже если вам кажется это очень понятным. « Листинг 5.4. Очень простой тест логического выражения 1 Sub list5_04() 2 3 dd = ( (2 > 5) Or (7 > 3) ) And Not ((3 > 1) Or (8 < 1C) ) 4 gg - MsgBox(dd, vbOKOnly) 5 6 End Sub Xor Оператор Xor выполняет логическое исключение. Чаще его называют исклю чающим «ИЛИ» (exclusive or). Результатом операции Хог является True, когда какой-либо операнд (но не оба), является равным True; иначе результатом будет значение False. Оператор Хот имеет следующий общий синтаксис: п'.; СИНТАКСИС . ? Operandl Xor Operand2 Operandl и Operand2 — это любые допустимые логические выражения VBA. Следующая таблица истинности показывает результаты операции Хот: Operandl Operand2 Результат выражения True True False True False True False True True False False False Листинг 5.5 содержит код, полученный из кода листинга 5.4 заменой оператора Or на Хот. Проверьте, совпадает ли ожидаемый вами результат с тем, который выдает VBA. Листинг 5.5. Отличие оператора Or от Хог 1 Sub list5 04 () 2 3 dd = ((2 > 5) Xor (7 > 3)) And Not ((3 > 1) Xor (8 < 10)) 4 gg = MsgBox(dd, vbOKOnly) 5 4 6 End Sub Eqv Оператор Eqv является операцией логической эквивалентности; использование оператора Eqv подобно тестированию на равенство. Результатом операции Eqv является значение True, когда оба операнда будут равными True; иначе — False. Выражения в Visual Basic 139 Оператор Eqv имеет следующий синтаксис: СИНТАКСИС '-"Ш Operandl Eqv Operands Operandl и Operand.2 — это любые допустимые логические выражения VBA. Следующая таблица истинности показывает результаты операции Eqv: Operandl Operand2 Результат выражения True True True True False False False True False False False True Если любой операнд в выражении операции Eqv является равным Null, то результатом также будет значение Null. Imp Оператор Imp выполняет логическую операцию импликации. Оператор Imp тестирует взаимосвязь между двумя логическими значениями, когда справедливость одного значения подразумевает справедливость другого значения; в качестве результата операция Imp имеет значение True, только когда второй операнд не противоречит первому. Оператор Imp имеет следующий синтаксис: СИНТАКСИС х вл - Operandl Imp Operands Operandl и Operand2 — это любые допустимые логические выражения VBA. Следующая таблица истинности показывает результаты операции Imp. Operandl Operand2 Результат выражения True True True True False False False True True False . , False True~ Результат логической импликации может быть равным True, даже когда первое условие является значением False, в то время как второе условие является значением True. Однако результат логической импликации не может быть значением True, если первое условие является равным True, а второе — False. Результаты логической импликации не являются такими же интуитивными и понятными, как результаты других логических операторов; к счастью, использование оператора логической импликации редко бывает необходимо. Конкатенация строк VBA дает возможность объединять (склеивать) строки вместе для образования более длинных строк. Присоединение одной строки к другой называется конкате 140 Глава 5 нацией (concatenation) строк. Конкатенация строк чрезвычайно полезна и довольно проста, хотя имеются некоторые трудности, о которых необходимо знать. Использование конкатенации строк Конкатенацию строк чаще всего используют для формирования строк из различных источников в процедуре, чтобы создавать пользовательские сообщения и выводить на их экран. В листинге 5.6 приведена процедура VBA Excel, которая запрашивает у пользователя имя файла рабочей книги, открывает эту рабочую книгу и затем выбирает определенный рабочий лист (в данном случае — рабочий лист с именем Отчет о продажах). Листинг 5.6. Конкатенация строк 1 Sub Open2DataEntry() 2 ' Демонстрация конкатенации строк 3 4 Const BoxTitle = "Установка входных данных" 5 Const ShtName = "Отчет о продажах" 6 7 Dim Fname As String 8 9 ' получить от пользователя имя рабочей книги 10 Fname = InputBox("Введите имя рабочей книги:", BoxTitle) 11 12 Workbooks.Open FileName:=Fname 1 открыть книгу 13 14 Activeworkbook.Sheets(ShtName).Select ' выбрать рабочий лист 15 16 ' сообщение пользователю о том, что книга открыта 17 MsgBox "Рабочая книга " & Fname & " открыта, " & ShtName & _ 18 " выбран.", , BoxTitle & " завершена" 19 End Sub Заметьте, что оператор конкатенации используется только в строках 17-18. Вся остальная часть программы предназначена для описания строковых констант и подготовки строковых переменных, используемых в операторе MsgBox, в котором получается строка из нескольких констант и переменных. Если вы выполняете эту процедуру и вводите имя Bookl при запросе на ввод имени файла, оператор MsgBox в строках 17-18 отображает диалоговое окно, показанное на рис. 5.3. (Этот пример предполагает, что вы действительно имеете рабочую книгу с именем Bookl.xls в текущей папке; в противном случае VBA отображает ошибку времени исполнения. Если вы будете экспериментировать с этим листингом, убедитесь, что вы вводите правильное имя рабочей книги.) Рис. 5.3 Оператор InputBox (строка 10) отображает окно для ввода наименования рабочей книги; оператор MsgBox (строки 17-18) отображает окно с сообщением о результате Выражения в Visual Basic 141 Операторы конкатенации строк VBA имеет два знака операции для конкатенации строк; в следующих параграфах описывается каждый из этих знаков и их использование. Знак & можно использовать только для конкатенации строк; этот знак не имеет другого назначения или функции в VBA. Все примеры в этой книге используют знак & для конкатенации .строк — это предпочтительный знак конкатенации строк, потому что он не оставляет никаких сомнений относительно того, какую операцию вы намереваетесь выполнить. Общий синтаксис знака & такой: СИНТАКСИС Operand! & Operands [& Operands ...] Operandl и Operand2 — любые допустимые строковые или Численные выражения. Если один или оба операнда являются численными выражениями, VBA преобразует числа в строки перед выполнением операции конкатенации. Тип данных результата конкатенации строк — это всегда тип String. Если операнд в выражении конкатенации строк является равным Null или Empty, VBA интерпретирует этот операнд как строку нулевой длины (то есть строку, которая не содержит никаких символов). Если вы не отделяете знак & от имени переменной (перед ним), по крайней мере, одним пробелом, VBA «полагает», что вы хотите использовать символ & как символ определения типа Long вместо знака операции конкатенации. Эта ситуация имеет различные результаты: в некоторых случаях VBA преобразует переменную или результат выражения в число с типом данных Long (как в листинге 5.7), в других случаях отображает сообщение о какой-либо ошибке синтаксиса или времени исполнения. Если вы уже объявили все переменные с конкретными типами (что является хорошей практикой в программировании), VBA отобразит сообщение об ошибке. Листинг 5.7. 1 Sub list5_07О 2 dd& = 99 3 дд = MsgBox(TypeName(dd), vbOKOnly, " dd& = 99 ") 4 End Sub Рис. 5.4 Результат выполнения кода листинга 5.7 Для конкатенации строк можно также использовать знак операции "+". Знак операции "+" имеет синтаксис и требования к операндам такие же, как и знак &, только с одним главным отличием. Знак операции имеет исторические корни в оригинальных версиях языка программирования BASIC. В этих ранних версиях языка BASIC не уделялось большого внимания различию между конкатенацией строк и сложением. Однако в VBA главным назначением знака "+" является арифметическое сложение. Всякий раз при обработке выражения, использующего знак "+", VBA сначала «пытается» выполнить арифметическое сложение. VBA выполняет конкатенацию строк со знаком ”+", только если один из операндов является строковым выражением и не может быть преобразован в число или если оба операнда являются строками. 142 Глава 5 Используйте знак & для конкатенации строк, чтобы избежать двусмысленности по поводу того, какую операцию необходимо выполнять, и чтобы обеспечить выполнение конкатенации строк VBA. Не используйте знак "+" для конкатенации строк, потому что выражения, использующие этот знак, могут быть неоднозначными для VBA и пользователей, которые будут читать ваш код. Приоритеты выполнения операций при вычислении сложных выражений Сложное (составное) выражение (complex expression) — это любое выражение, образованное из двух или более выражений. Многие из записываемых вами выражений — это сложные выражения, особенно, если они определяют управление последовательностью выполнения кода в процедурах или представляют различные математические формулы. При вычислении сложных выражений VBA следует таким правилам: Части выражения, заключенные в круглые скобки, всегда вычисляются в первую очередь. Если выражение, заключенное в круглые скобки, является другим сложным выражением, VBA применяет эти же правила к выражению в круглых скобках. Конкретные операции выполняются в зависимости от иерархии операторов. (Иерархия различных операторов VBA показана в табл. 5.5.) Когда операторы имеют равный уровень приоритета, они вычисляются в порядке слева направо. VBA вычисляет выражения в следующем порядке: Знаки арифметических операций. Знаки конкатенации строк. Операторы сравнения. Логические операторы. В табл. 5.5 приведена иерархия операторов VBA. Операторы/операции перечислены в порядке от самого высокого приоритета до самого низкого. Операторы, помещенные в одной и той же строке этой таблицы, имеют равный приоритет. Операторы с равным приоритетом вычисляются слева направо так, как они появляются в выражении. Таблица 5.5. Иерархия операторов/операций от наивысшего до самого низкого приоритета Оператор/знак Комментарии Возведение в степень, наивысший приоритет. ! - Унарный минус. *,/ Умножение и деление имеют равные приоритеты; они вычисляются по мере появления в выражении слева направо. \ Mod I +, - Сложение и вычитание имеют равный приоритет; они вычисляются по мере появления в выражении слева направо. Выражения в Visual Basic 143 Оператор/знак Комментарии & Всякая конкатенация строк выполняется после любых арифметических операций в выражении и перед любыми операциями сравнения или логическими операциями. Like=, <>, Is Все операторы сравнения имеют равные приоритеты и вычисляются по -мере появления в выражении слева направо. Используйте круглые скобки для группирования операторов сравнения в выражениях. Not And Or Xor Eqv Imp НЛПМ Лк Использование функций Visual Basic Вы уже пользовались встроенными VBA-функциями: InputBox и MsgBox. Теперь, когда вы знаете все о выражениях, пора научиться включать функции в выражения. При чтении этой главы не очень полагайтесь на правильность синтаксиса приведенных здесь функций. Печатные издания часто содержат ошибки. Ошибки встречаются и в справочных системах локализованных продуктов. Правильнее будет рассматривать эту главу как введение в мир функций и получение общего представления о функциях как необходимых составляющих системы программирования. Точный синтаксис каждой функции следует проверять в справочной системе VBA. Функции Функция (function) — это встроенная формула, выполняющая действия над выражениями и генерирующая значение. Функция всегда возвращает значение, которое VBA вставляет в программу в том месте, где появляется имя функции. Функции VBA делятся на несколько групп в зависимости от типа операции или вычисления, которое они выполняют. Функции используются для выполнения таких задач, как: Преобразование текстовых строк в другие типы данных. Получение данных о текстовых строках. Преобразование других типов в текстовые строки. Форматирование чисел или других типов данных для отображения. * Манипулирование или генерирование значений данных. * Получение информации о файлах, драйверах диска или среде, в которой VBA работает в данный момент времени. В этой главе рассказывается о различных категориях функций и описываются подробно наиболее важные функции VBA и их использование. В последующих главах описываются другие функции VBA, перечисленные в этой главе и связанные с темами последующих глав. Кроме того, вы узнаете, что можно создавать собственные функции для использования в процедурах VBA. В этой книге вы уже встречались с примерами процедур и функций VBA. Не путайте термины функция и процедура. Обычно процедура выполняет определенную задачу (или группу задач) подобно тому, как определенная команда меню в Excel, Word или другом приложении выполняет конкретную задачу. Функция оперирует одним или более значениями и возвращает некоторое результирующее значение (как формула в ячейке рабочего листа Excel). Использование функций в выражениях Чтобы использовать функцию, просто вводите имя функции в оператор VBA вместе с любыми аргументами, которые требуются для этой функции, в том месте в операторе, где вам необходимо использовать результат функции. [Помещение Использование функций Visual Basic 145 имени функции в оператор VBA для активизации функции называют вызовом (calling) функции.] При использовании функций в выражениях следуйте таким правилам: Можно использовать результат функции как часть выражения. Можно присваивать результат функции какой-либо переменной. Можно использовать результат функции для предоставления значения в список аргументов другой процедуры или функции. Функции имеют списки аргументов, заключенные в круглые скобки. В основном функцию можно использовать для предоставления значения в любом месте в любом операторе VBA, где может быть оправданно использование значения константы или переменной. В листинге 6.1 приведена процедура для демонстрации вызова функции в выражениях. Листинг 6.1. Использование функций 1 Sub FuncDemo() 2 Dim s__Date As String 3 Dim d_Time As Date 4 s_Date = CStr(Now) 5 d_Time = Time 6 MsgBox "Сегодня: " & s_Date 7 MsgBox "Текущее время: " & d_Time 8 End Sub В строках 2-3 объявлены две переменные: s_Date с типом String и d_Time с типом Date. В строке 4 переменная s_Date получает значение текущей даты в виде строки, так как после вызова функции Now (получить системную дату) результирующее значение преобразуется функцией CStr в строку. Переменная d_Time принимает значение системного времени. В строках 6-7 с помощью оператора MsgBox значения переменных выводятся на экран (рис. 6.1) в диалоговых окнах. Обратите внимание на то, что, поскольку выражение в строке 7 содержит оператор конкатенации строк (&), для вывода в диалоговом окне переменной d_Time нет необходимости преобразования ее в строку. Поскольку эта синтаксическая «вольность» отсутствует во многих других языках программирования, я бы не советовал часто пользоваться этими VBA-возможностями. К тому же это не способствует стремлению к аккуратности при написании кода. Рис. 6.1 Результат выполнения кода листинга 6.1 Аргументы и возвращаемое значение функции Как вы уже видели в листинге 6.1, некоторые функции требуют одного или более аргументов, другие — нет. Функции, которые не требуют аргументов, обычно просто выбирают значение, недоступное иначе. Например, функция Time, возвращающая текущее системное время компьютера, не требует никаких аргументов, а функцию CStr вызывать без аргументов бессмысленно. Чтобы использовать функцию, не имеющую аргументов, просто введите имя функции в программу, как в следующих операторах: СистемноеВремя = Time MsgBox Now 146 Глава б Другие функции требуют одного или более аргументов. Функция Sqr, например, возвращает корень квадратный числа; чтобы Sqr вычислила корень квадратный, необходимо предоставить число, как показано в следующих операторах: r_Val =16 Root = Sqr(r_Val) Значения предоставляются функции помещением их в список аргументов. Список аргументов следует заключать в круглые скобки и, если в списке находится более одного аргумента, отделять каждый аргумент запятой. Тип данных значения, возвращаемого функцией, зависит от этой конкретной функции. Большинство функций возвращают значения типа Variant, хотя некоторые функции возвращают данные определенных типов, таких как String, Double и Integer. VBA во многих случаях может автоматически преобразовывать результат какой-либо функции в данные типа, совместимого с другими типами значений в выражении, содержащем эту функцию, точно, как VBA преобразует типы данных в присваиваниях переменных и вычислении выражений. Все правила совместимости типов данных, приведенные в главе 5, которые применимы к переменным Variant и типизированным переменным и константам, применимы также к значениям, возвращаемым функциями. Игнорирование результата функции Как правило, значение, возвращаемое функцией, должно быть каким-либо образом использовано: путем включения результата функции в выражение, в список аргументов, или путем присваивания его некоторой переменной. Однако в некоторых случаях можно не использовать возвращаемое функцией значение. Ранее было упомянуто, что VBA-процедура MsgBox имеет необязательный второй аргумент, позволяющий определять, сколько командных кнопок появляется в окне сообщения. Можно использовать этот аргумент командных кнопок в процедуре MsgBox для отображения сообщения, которое задает пользователю вопрос и дает возможность ответить на него путем выбора командной кнопки в окне сообщения. Если вы используете этот необязательный аргумент для MsgBox, то можно получить от MsgBox значение, указывающее, какую кнопку выбрал пользователь. В действительности, процедура MsgBox является функцией, хотя чаще всего используется как процедура. До сих пор во всех примерах этой книги аргумент командных кнопок в операторах MsgBox был опущен. Если при вызове MsgBox аргумент командных кнопок не указывается, MsgBox отображает диалоговое окно, содержащее только одну кнопку. Поскольку диалоговое окно MsgBox до сих пор содержало только одну кнопку, не имело значения, каков результат функции MsgBox, и поэтому результат функции MsgBox игнорировался в коде. VBA предоставляет несколько встроенных констант для определения кнопок в окне сообщения MsgBox (Далее в книге эти константы описываются более подробно. Список всех VBA-констант приведен в Приложении Б.) Одна из этих констант (vbYesNo) указывает MsgBox, что в отображаемое окно сообщения следует включить кнопку Yes и кнопку No. Следующий оператор выводит диалоговое окно, показанное на рис. 6.2: MsgBox "Вам видны две кнопки?" , vbYesNo, "Демонстрация кнопок" При использовании этого оператора имеется одна проблема: результат пользовательского выбора никаким образом не возвращается; код по-прежнему не использует результат функции MsgBox. Для выборки результата функции Msgbox необходимо изменить этот оператор: нужно заключить список аргументов в круглые скобки и изменить оператор так, чтобы он каким-то образом использовал результат функции. Обычно резуль Использование функций Visual Basic 147 тат функции MsgBox присваивается какой-либо переменной и можно позже тестировать этот результат в другом операторе, чтобы определить, какую кнопку, фактически, выбрал пользователь процедуры. Следующая строка показывает оператор MsgBox, измененный так, что он возвращает значение: Код_ответа = MsgBox ("Вам видны две кнопки9" , vbYesNo, _ "Демонстрация кнопок") При выполнении этого оператора VBA отображает то же самое диалоговое окно, показанное на рис. 6.2. Когда пользователь выбирает кнопку Yes или No, VBA закрывает диалоговое окно и сохраняет число, соответствующее выбранной кнопке, в переменной Код_ответа. Рис. 6.2 Диалоговое окно MsgBox, демонстрирующее результат включения в список параметров аргумента кнопок Демонстрация кнопок Вам видны две кнопки9 Yes | К(о j Два последних примера использования MsgBox иллюстрируют важный факт, касающийся функций: опуская круглые скобки вокруг списка аргументов функции, вы указываете VBA на то, что необходимо игнорировать результат функции. Когда круглые скобки опускаются, VBA интерпретирует вызов функции, как если бы это был вызов процедуры, и не возвращает результат. Вернемся опять к примерам в начале этой главы и в функциях, использовавшихся в листинге 6.1, обратим внимание на то, что все операторы, вызывающие функцию VBA, включают круглые скобки вокруг списка аргументов функции, даже когда список аргументов содержит только один аргумент. Функции, не имеющие аргументов, не требуют круглых скобок при их вызове. Нет смысла в игнорировании результата каждой функции VBA, и не всегда это желательно. Игнорирование результата функции полезно только при работе с функциями (такими как MsgBox), которые выполняют некоторую задачу, а возвращение ими результата является только частью их работы. Результат функции игнорируют, когда хотят, чтобы функция выполняла некоторые действия, но результат этих действий необязательно использовать в коде. Функция MsgBox, например, выполняет отображение сообщения в диалоговом окне в качестве основной задачи. (В главе 8 показано, как использовать MsgBox, чтобы дать возможность пользователю программы делать выбор, влияющий на выполнение программы.) При попытке игнорировать результат функции, не имеющей аргументов (такой, как функция Now), или любой другой функции, результат которой не может не использоваться, VBA отображает сообщение об одной из нескольких возможных ошибках времени исполнения в зависимости от конкретной функции, хотя обычно появляется сообщение об ошибке синтаксиса или несовпадения типов. Обычно VBA запрещает игнорирование результата функции, имя которой является ключевым словом VBA (такой, как CStr или других функций преобразования), и тех функций, единственным назначением которых является предоставление некоторого возвращаемого значения, например, математических. Использование именованных аргументов функции Ранее в книге указывалось, что аргументы процедуры необходимо перечислять в определенном порядке. Также необходимо перечислять в определенном порядке и аргументы функции. Функции с несколькими аргументами используют 148 Глава 6 положение аргумента в списке аргументов для определения того, какое значение получает конкретный аргумент. Например, для MsgBox первый аргумент является сообщением, второй — это число и тип кнопок для диалогового окна, третий — заголовок диалогового окна. Несмотря на то, что второй аргумент MsgBox, определяющий командные кнопки для диалогового окна, является необязательным и был опущен во всех примерах и упражнениях до сих пор в книге, все же необходимо включать отмечающие запятые для второго аргумента в список аргументов. Пропуск отмечающих запятых для второго аргумента приводит к ошибке несовпадения типов. Как вы могли уже заметить, легко нечаянно опустить отмечающие запятые или переставить значения аргументов в функциях, имеющих необязательные аргументы или несколько аргументов, несмотря на помощь свойства Auto Quick (Краткие сведения) Редактора VB. Пропуск или перестановка аргументов в списке аргументов функции могут привести к ошибкам несовпадения типов. Ошибка (что еще хуже) может быть не обнаружена. Чтобы предотвратить ошибки программирования и сделать более легким использование функций, имеющих необязательные аргументы, VBA предоставляет альтернативу перечислению значений в списке аргументов в определенном порядке. Можно также передавать значения аргументов функции, используя именованные аргументы (named, arguments) функций. Следующие строки показывают два оператора MsgBox, которые имеют один и тот же результат; первый оператор использует обычный метод перечисления аргументов, а второй — метод именованных аргументов (оба оператора игнорируют результат функции MsgBox): MsgBox AnyMsg, , AnyTitle MsgBox Prompt:=AnyMsg, Title:=AnyTitle Второй оператор использует именованные аргументы для Prompt (сообщение или запрос) и Title (определяет заголовок окна сообщения), присваивая значение каждому именованному аргументу. Символ, который присваивает значение именованному аргументу (:=), не является в точности тем же обычным оператором присваивания (=). Если опустить двоеточие (:) во время присваивания значения именованному аргументу, VBA не обязательно обнаружит ошибку синтаксиса, но не может интерпретировать этот оператор правильно. Когда VBA выполняет этот оператор, он отображает одну из нескольких возможных ошибок времени исполнения, часто — ошибку несовпадения типов. При использовании именованных аргументов нет необходимости включать отмечающие запятые для необязательных аргументов. Обратите внимание, во втором из приведенных выше операторов нет отмечающей запятой между аргументами для запроса и заголовка в отличие от первого оператора. На самом деле, именованные аргументы не должны появляться в каком-либо определенном порядке. Вс втором операторе можно поместить аргумент Title перед аргументом Prompt, кав показано далее: MsgBox Title:=3аголовок0кна, Prompt:=Сообщение MsgBox все равно использует значение, присвоенное аргументу Title, в качест ве заголовка диалогового окна. При использовании именованных аргументов VB/ использует имя аргумента для определения того, какое значение этот аргумент представляет. После столь долгого повествования о пользе функции MsgBox приведем, нако нец, ее полный синтаксис. СИНТАКСИС MsgBox(Prompt [, Buttons} [, Title] [, HelpFile, Context}} Единственным обязательным аргументом для MsgBox является аргумент Prompt, который может быть любым строковым выражением и содержит ин Использование функций Visual Basic 149 формацию, выводимую в диалоговом окне. Все другие аргументы являются необязательными (об этом говорят квадратные скобки, в которые заключены эти аргументы вместе с разделяющими запятыми). Аргумент Title содержит строку для заголовка диалогового окна. Без этого аргумента в заголовке будет выведено наименование host-приложения, из которого запускается программа на VBA. Аргумент HelpFile — это строковое выражение, содержащее имя справочного файла Windows; обычно это — файл, который вы уже должны были создать с помощью Windows Help Compiler. Аргумент Context — это численное выражение, указывающее раздел в справочном файле, относящийся к отображаемому диалоговому окну, например, 0 обычно относится к оглавлению справочного файла. Аргумент Buttons является численным выражением, которое задает количество и тип кнопок в диалоговом окне MsgBox. Buttons указывает также кнопку по умолчанию в диалоговом окне и, содержит ли это диалоговое окно стандартные значки Windows: Critical, Information, Exclamation или Question для предупредительных сообщений и запросов пользователя. В табл. 6.1 приведены значения аргументов-констант функции MsgBox и их назначение, а в табл. 6.2 — возвращаемые значения-константы функции. Таблица 6.1. Аргументы-константы функции MsgBox Константа Назначение vbAbortRetrylgnore Отображает командные кнопки Стоп, Повтор, Пропустить (Abort, Retry, Ignore). vb ApplicationM odal Для продолжения работы с приложением пользователь должен ответить на запрос (или закрыть) этого диалогового окна. Любые другие приложения Windows, работающие в фоновом режиме, продолжают выполняться. vbCritical Отображает в диалоге значок критического предупредительного сообщения (Critical Message) Windows (красный кружок). vbDefaultButtonl Первая командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefaultButton2 Вторая командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefau!tButton3 Третья командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefaultButton4 Четвертая командная кнопка в диалоговом окне является кнопкой по умолчанию. vbExclamation Отображает значок ("!") предупреждения (Warning Message); обычно используется для отображения важной информации или предупреждения, не требующего ответа. vblnformation Отображает значок ("i”) информации (Information Message); обычно используется для отображения важной информации, кроме предупреждения. vbMsgBoxHelpButton Добавляет к диалоговому окну кнопку Справка (Help); при щелчке на кнопке Справка открывается файл, который задан в аргументе HelpFile, в разделе, заданном аргументом Context. 150 Глава б Константа Назначение vbOKCancel Отображает кнопки OK и Отмена (OK, Cancel). vbOKOnly Отображает только кнопку ОК; то же самое происходит при опускании аргумента Buttons. vbQuestion Отображает значок запроса (Query icon) Windows ("?"); обычно используется, чтобы задать пользователю очень важный вопрос или выдать предупредительное сообщение, требующее ответа. vbRetryCancel Отображает кнопки Повтор и Отмена (Retry, Cancel). vbSystemModal При отображении диалоговое окно остается впереди других окон (даже при переключении на другое приложение), пока не будет закрыто. vbYesNo Отображает кнопки Да и Нет (Yes, No). vbYesNoCancel Отображает кнопки Да, Нет и Отмена (Yes, No, Cancel). Таблица 6.2. Возвращаемые значения-константы функции MsgBox Константа Означает, что пользователь выбирает кнопку vbAbort Стоп (Abort) vbCancel Отмена (Cancel) vblgnore Пропустить (Ignore) vbNo Нет (No) vbOK ОК vbRetry Повтор (Retry) vbYes Да (Yes) Другой наиболее часто используемой для обмена данными с пользователем функцией является InputBox. В главе 4 был приведен краткий синтаксис этой функции, а ниже — полный: СИНТАКСИС InputBox(Prompt [, Title] [, Default] [, XPos][, YFos] [, HelpFile, Context]) Prompt — это любое строковое выражение. Аргумент Prompt является единственным обязательным аргументом для InputBox; все другие — необязательные. Title — это строка, используемая в качестве заголовка для окна ввода (как и для функции MsgBox). Default также является любым строковым выражением и используется как значение по умолчанию для пользовательского ввода. Следующий оператор, например, запрашивает пользователя ввести имя файла и предлагает имя NEWFILE в качестве значения по умолчанию. Диалоговое окно, выводимое на экран этим оператором и отображающее значение по умолчанию, показано на рис. 6.3. User_Input = InputBox("Введите имя файла: ", _ "Создать файл", "NEWFILE") Использование функций Visual Basic 151 Рис. 6.3 Используйте необязательные аргументы функции InputBox для задания значения по умолчанию Как вы могли уже заметить, диалоговое окно InputBox отображается в центре экрана. Можно выводить это окно в другом месте на экране, особенно, если необходимо, чтобы были открыты и оставались видимыми другие диалоговые окна. Аргументы XPos и YPos могут быть любыми численными выражениями. Эти аргументы позволяют указать, где в активном окне появляется окно ввода, и являются координатами верхнего левого угла диалогового окна: XPos — горизонтальное расстояние от левого края окна; YPos — это вертикальное расстояние от верхнего края окна. Оба расстояния измеряются в твипах (twips); один твип равен 1/20 точки (точка — это измерение шрифта печати). Поскольку точка составляет 1/72 часть дюйма, то один твип приблизительно равен 0,0007 дюйма. Будьте внимательны при задании положения диалогового окна InputBox. Вы можете задать позиции для аргументов XPos и YPos настолько большими, что диалоговое окно совсем не появится на экране, потому что его положение выйдет за правый или нижний край окна. При этом, хотя диалоговое окно и невидимо, оно является активным, ни один из элементов управления, которые вы видите на экране, не будет работать до тех пор, пока вы не отреагируете на «невидимое» диалоговое окно. Последние два необязательных аргумента для функции InputBox — это HelpFile и Context. Они имеют то же назначение, что и подобные аргументы функции MsgBox. Если вы задаете HelpFile или Context, необходимо задавать оба аргумента (эти аргументы заключены в одни квадратные скобки). Всякий раз, когда указывается справочный файл для окна ввода, VBA автоматически добавляет командную кнопку помощи в диалоговое окно. VBA не включает Windows Help Compiler; если вы хотите создать собственные пользовательские справочные файлы, необходимо от Microsoft получить Windows Help Compiler отдельно или использовать средства независимых поставщиков программного обеспечения. При вызове InputBox можно использовать именованные аргументы. Для этого просто применяйте имена аргументов: Prompt, Title, Default, XPos, YPos, HelpFile и Context. Следующий оператор выдает такое же диалоговое окно, что и показанное на рис. 6.3, но здесь применяются именованные аргументы: User_Input = InputBox(Prompt:="Введите имя нового файла: ”, _ Title:="Создать файл", Default:="NEWFILE”) Обратите внимание, что этот оператор имеет круглые скобки вокруг списка аргументов. Необходимо всегда заключать список аргументов в круглые скобки при использовании результата функции, независимо от того, используете ли вы именованные аргументы при вызове функции. Нельзя смешивать именованные аргументы с обычным списком аргументов в одном и том же вызове функции. Необходимо использовать либо именованные аргументы, либо список обычных аргументов для каждого отдельного вызова функции. Для определения имен аргументов функции используйте всплывающее окно Auto Quick Info (Краткие сведения), появляющиеся при вводе имени функции (в Редакторе VBA). Можно также использовать Object Browser для вставки имени функции и добавления в список именованных аргументов в программном коде, как описано далее в этой главе. 152 Глава 6 Использование других функций VBA Встроенные функции VBA делятся на несколько категорий на основе общего назначения функций (математические, преобразования данных, даты и времени, строковые и работы с диском). В следующих разделах обсуждаются категории функций и описываются их действия. К сожалению, невозможно описать подробно каждую функцию VBA в рамках этой книги. Однако большинство функций VBA, такие как математические функции, являются довольно ясными из их названия и не требуют подробного объяснения. Другие функции, такие как функции преобразования типа данных и обработки строк, описаны более подробно. VBA-функции обработки строк имеют важное значение, поэтому отдельный раздел этой главы посвящен способам их использования. Математические функции VBA предоставляет стандартный набор математических функций. В табл. 6.3 приведены математические функции, имеющиеся в VBA. В этой таблице N означает любое численное выражение; все аргументы функций являются обязательными, если только не указано иначе. Таблица 6.3. Математические функции VBA Функции(ар-гументы) Возвращает/действие Abs(N) Возвращает абсолютное зфчейке N. Atn(N) Возвращает арктангенс N как угол в радианах. Cos(N) Косинус угла N, где N — это угол, измеренный в радианах. Exp(N) Возвращает константу е, возведенную в степень N. (е — это основание натуральных логарифмов и она (приблизительно) равна 2,718282). Fix(N) Возвращает целую часть N. Fix не округляет число, а отбрасывает любую дробную часть. Если N является отрицательным, Fix возвращает ближайшее отрицательное целое большее, чем или равное N. Int(N) Возвращает целую часть N. Int не округляет число, а отбрасывает любую дробную часть. Если N является отрицательным, Int возвращает ближайшее отрицательное целое меньшее, чем или равное N. Log(N) Возвращает натуральный логарифм N. Rnd(N) Возвращает случайное число; аргумент является необязательным. Используйте функцию Rnd только после инициализации VBA-генератора случайных чисел оператором Randomize. Sgn(N) Возвращает знак числа: -1, если N — отрицательное; 1, если N — положительное; 0, если N равно 0. Sin(N) Возвращает синус угла; N — это угол, измеренный в радианах. Sqr(N) Возвращает корень квадратный из N. VBA отображает ошибку времени исполнения, если N — отрицательное. Tan(N) Возвращает тангенс угла; N — угол в радианах. Использование функций Visual Basic 153 Функции Fix и Int укорачивают целые, то есть они отбрасывают дробную часть числа без округления. Единственное различие между функциями Fix и Int — это то, как они обрабатывают отрицательные числа. Дополнительные тригонометрические функции можно выводить из базовых математических функций VBA. Например, если необходимо вычислить котангенс угла, для его нахождения можно использовать формулу 1/Тап(х). В главе 7 описывается, как писать собственные функции для создания производных математических функций. Функции преобразования данных Visual Basic предоставляет несколько функций для преобразования одного типа данных в другой. Используйте эти функции для устранения ошибок несовпадения типов и обеспечения явного контроля за типами данных в выражениях. Например, при получении сообщения об ошибке несовпадения типов в определенном выражении можно преобразовать значения в выражении в типы, совместимые друг с другом, используя функции преобразования. Или же можно сохранять результат выражения в диапазоне численного типа Single (большинство численных выражений имеют результатом значение типа Double); в таком случае следует использовать функцию CSng для преобразования результата выражения в число типа Single, как показано в листинге 6.2. Листинг 6.2. Использование функции CSng 1 Sub CSngDemoO 2 Dim d_Varl As Double 3 Dim s_Var2 4 d_Varl = 412 5 s_Var2 = CSng(352 / 17) 6 MsgBox TypeNartie(s_Var2) 7 End Sub Проверьте, как работает код листинга 6.2. В табл. 6.4 приведены функции преобразования данных в VBA. В этой таблице N — это любое численное, S — любое строковое, а Е —- выражение любого типа. Аргументы каждой функции являются обязательными, если не указано иначе. Таблица 6.4. Функции преобразования данных Функция(ар-гументы) Возвращает/действие Asc(S) Возвращает число кода символа, соответствующее первой букве строки S. Буква "А", например, имеет код символа 65. Chr(N) Возвращает строку из одного символа, соответствующего коду символа N, который должен быть числом между 0 и 255, включительно. Код символа 65, например, возвращает букву "А". Format(E, S) Возвращает строку, содержащую значение, представленное выражением Е, в формате в соответствии с инструкциями, содержащимися в S. Hex(N) Возвращает строку, содержащую шестнадцатиричное представление N. Oct(N) Возвращает строку, содержащую восьмиричное представление N. 154 Глава 6 Функция(ар-гументы) Возвращает/действие RGB(N, N, N) Возвращает целое типа Long, представляющее значение основных цветов изображения. N в каждом аргументе должно быть целым в диапазоне 0 — 255, включительно. Аргументы (слева направо) — это значения для красного, зеленого и синего цвета. Str(N) Возвращает строку, эквивалентную численному выражению N. Val(S) Возвращает численное значение, соответствующее числу, представленному строкой S, которая должна содержать только цифры и одну десятичную точку, иначе VBA не может преобразовать ее в число. Если VBA не может преобразовать строку в S, то функция Vai возвращает 0. CBool(N) Возвращает Boolean-эквивалент численного выражения N. CByte(E) Возвращает численное значение типа Byte (от 0 до 255); Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CCur(E) Возвращает численное значение типа Currency; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CDate(E) Возвращает значение типа Date. Е может быть любым допустимым выражением (строкой или числом), представляющим дату в диапазоне 1/1/100 — 12/31/9999, включительно. CDbl(E) Возвращает численное значение типа Double; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. Cint(E) Возвращает численное значение типа Integer; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CLng(E) Возвращает численное значение типа Long; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CSng(E) Возвращает численное значение типа Single; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CStr(E) Возвращает значение типа String; Е — любое допустимое численное или строковое выражение. CVar(E) Возвращает значение типа Variant; Е — любое допустимое численное или строковое выражение. Наиболее часто используемые функции — это функции (объединенные в конце табл. 6.4 в группу), начинающиеся с буквы С (от слова conversion), за которыми следует сокращение имени типа: CStr, CSng, CDbl и так далее. Функции даты и времени VBA-функции даты и времени обычно используются для получения текущей даты и времени, разбиения значения даты на ее составляющие части или для преобразования строк и чисел в значения типа Date. Использование функций Visual Basic 155 В таблице 6.5 приведены VBA-функции даты и времени и их действие. В этой таблице N — любое допустимое численное выражение, a D — любое допустимое выражения типа Date (включая значения типа Date, числа или строки, которые VBA может преобразовать в дату). Все аргументы функций в этой таблице являются обязательными, если не указано иначе. Таблица 6.5. функции даты и времени Функции(аргумен-ты) Возвращает/действие Date Возвращает системную дату. Можно также использовать эту функцию как процедуру для установки системных часов компьютера. Более подробно можно узнать из справочной системы VBA. Time Возвращает системное время компьютера как значение типа Date. Можно также использовать эту функцию как процедуру для установки системных часов. Более подробно можно узнать из справочной системы VBA. Now Возвращает системную дату и время. Year(D) Возвращает целое, являющееся частью выражения типа Date и содержащее год. Год возвращается как число между 100 и 9999. Month(D) Возвращает целое, являющееся частью выражения типа Date, содержащее месяц. Месяц возвращается как число между 1 и 12, включительно. Day(D) Возвращает целое, являющееся частью выражения типа Date и содержащее день. День возвращается как число между 1 и 31, включительно. Weekday(D) Возвращает целое, содержащее день недели для выражения типа Date. День недели возвращается как число между 1 и 7, включительно; 1 — это воскресенье, 2 — понедельник и так далее. WeekdayName(Nl, B, N) Возвращает строку с наименованием дня недели, номер которого задается параметром N1. Hour(D) Возвращает целое, содержащее часы как часть времени, содержащегося в выражении типа Date. Часы возвращаются как число между 0 и 23, включительно. Если выражение D не содержит значения времени, то Hour возвращает 0. Minute(D) Возвращает целое, содержащее минуты как часть времени в выражении типа Date. Минуты возвращаются как число между 0 и 59, включительно. Если выражение D не содержит значения времени, Minute возвращает 0. Second(D) Возвращает целое, содержащее секунды как часть времени в выражении типа Date. Секунды возвращаются как число между 0 и 59, включительно. Если выражение D не содержит значения времени, Second возвращает 0. DateAdd(S, N, D) Возвращает значение [тип Variant (Date)], содержащее дату, к которой добавлен заданный интервал времени. 156 Глава 6 Функции(аргумен-ты) Возвращает/действие DateDiff(S, Dl, D2[, N1 [, N2 ]]) Возвращает значение [тип Variant (Long)] числа временных интервалов между двумя определенными датами. DatePart(S, D,[, N1 [, N2]]) Возвращает определенную часть [тип Variant (Integer)] заданной даты. DateSerial(N, N, N) Возвращает значение последовательной даты для заданной даты. Слева направо аргументы представляют год, месяц и день. Аргумент года должен быть целым числом между 100 и 9999, месяца — между 1 и 12, дня — между 1 и 31 (все диапазоны являются включающими). TimeSerial(N, N, N) Возвращает значение последовательного времени. Слева направо аргументы представляют часы, минуты и секунды. Аргумент часов должен быть целым числом между 0 и 23, аргументы минут и секунд должны оба быть числами 0 и 59 (все диапазоны являются включающими). DateValue(E) Возвращает значение типа Date, эквивалентное дате, заданной аргументом Е, который должен быть строкой, числом или константой, представляющей дату. TimeValue(E) Возвращает значение типа Date, содержащее время, заданное аргументом Е, который может быть строкой, числом или константой, представляющей время. Timer Возвращает число, представляющее количество секунд от полуночи в соответствии с системным временем компьютера. Некоторые из перечисленных функций уже использовались в примерах этой книги, другие — будут использоваться далее. Строковые функции Строковые функции VBA часто применяются для нахождения заданных строк внутри других строк, для сравнения одной строки с другой и копирования выбранных частей строк. Строковые функции VBA используются довольно часто, потому что строковые данные очень важны и встречаются в каждом приложении VBA — Word, Excel, Access или другом host-приложении VBA. Часто необходимо манипулировать строковыми данными, полученными как пользовательский ввод функцией InputBox. В других случаях строковые данные появляются в коде VBA как имена файлов для документов Word, рабочих книг Excel, баз данных Access и других типов данных, сохраняемых в файлах на дисках. В Word важность манипулирования строковыми данными очевидна: данные, сохраняемые в документах Word, в основном являются ничем иным, как строковыми данными. Строковые данные также важны в Excel в качестве имен рабочих листов, именованных диапазонов данных и так далее. В этом разделе приводятся имеющиеся в VBA строковые функции; в последующем разделе более подробно описывается, как использовать наиболее важные и полезные строковые функции. В табл. 6.6, где приведены основные строковые функции VBA, N — это любое допустимое численное выражение, aS — это любое допустимое строковое выражение. Все аргументы функций являются обязательными, если не указано иначе. Использование функций Visual Basic 157 Таблица 6.6. Строковые функции Функция(аргумент) Возвращает/действие InStr([Nl,] SI, S2[, N2]) Возвращает положение S2 в SI. Nl — начальное положение для поиска; N2 определяет тип сравнения. N1 и N2 необязательны. Если N2 опускается, то для поиска используется текущая установка Option Compare. InStrRev(Sl, S2 [, Nl[, N2]]) Возвращает позицию появления строки S2 внутри S1, в направлении от конца (или N1) к началу строки. N2 определяет тип сравнения. Если N2 опускается, то для поиска используется текущая установка Option Compare. LCase(S) Возвращает строку (тип String), содержащую копию S со всеми символами верхнего регистра, преобразованными в символы нижнего регистра. Left(S, N) Возвращает строку; копирует N символов из S, начиная с левого крайнего символа S. Len(S) Возвращает число символов в S, включая начальные и конечные пробелы. LTrim(S) Возвращает копию строки S после удаления символов пробела из левой части строки (начальные пробелы). Mid(S, Nl, N2) Возвращает строку; копирует N2 символов из S, начиная с позиции символа в S, заданной аргументом Nl. N2 является необязательным; если N2 опущен, то Mid возвращает все символы в строке S от позиции N1 до конца строки. Right(S, N) Возвращает значение типа String; копирует N символов из S, начиная с правого крайнего символа S. Например, Right("outright", 5) возвращает строку "right". RTrim(S) Возвращает копию строки S после удаления символов пробела из правой части строки (конечные символы). Space(N) Возвращает строку пробелов длиной N символов. StrComp(Sl, S2, N) Сравнивает SI с S2 и возвращает число, обозначающее результат сравнения: -1, если SI < S2; 0, если SI = S2; 1, если SI > S2. N является необязательным и указывает, следует ли выполнять сравнение с учетом регистра. Если N опускается, строки сравниваются с использованием текущей установки Option Compare. StrConv(S, N) Возвращает строку, преобразованную в новую форму в зависимости от числового кода, заданного аргументом N. VBA предоставляет внутренние константы для использования с функцией StrConv; наиболее полезными являются: vbProperCase (преобразует строку так, что каждая буква, начинающая слово, становится заглавной), vbLowerCase (преобразует строку в буквы нижнего регистра) и vbUpperCase (преобразует строку в буквы верхнего регистра). String(N, S) Возвращает строку длиной N символов, состоящую из символа, заданного первым символом в S. Например, String(5, "х") возвращает строку "ххххх". 158 Глава 6 Функция(аргумент) Возвращает/действие Trim(S) Возвращает копию строки S после удаления начальных и конечных символов пробела из этой строки. UCase(S) Возвращает S со всеми символами нижнего регистра, преобразованными в символы верхнего регистра. Несколько перечисленных в табл. 6.6 функций преобразования типа данных относятся также к манипулированию строками: Chr, Format, CStr, в частности. Использование функций для манипулирования строками Манипулирование строковыми данными является важной частью многих программ, особенно программ, которые взаимодействуют с пользователем. Интерактивные программы должны манипулировать строками по двум причинам: для формулировки сообщений, которые необходимо отображать для пользователя, и из-за того, что входные данные пользователя вводятся в вашу программу (посредством MsgBox) как строковые данные. Чем лучше вы научитесь манипулировать строками, тем вероятнее, что вы будете способны отображать приемлемые, согласованные сообщения для пользователя вашей программы. Кроме того, чем лучше вы умеете манипулировать строками, тем вероятнее, что вы сможете успешно анализировать строки, вводимые пользователем вашей программы. VBA имеет различные функции в качестве средств, помогающих манипулировать строковыми данными. В этом и следующем разделах описывается, как использовать наиболее важные строковые функции и некоторые из функций преобразования данных для выполнения как простых, так и сложных операций над строковыми данными в программах. » Удаление ненужных символов Иногда строки в программе содержат ненужные символы пробелов в конце или в начале строки. Эти начальные и конечные пробелы появляются по разным причинам. Один из наиболее распространенных случаев появления начальных или конечных пробелов — когда используется функция InputBox для получения данных ввода от пользователя. InputBox возвращает весь текст, вводимый пользователем, включая любые лишние символы пробела. Если пользователь вводит лишние символы пробела перед или после фактического значения ввода, функция InputBox возвращает эти символы как часть вводимой строки. Другая распространенная причина начальных и конечных символов — когда используется содержимое строковой переменной фиксированной длины. Строка фиксированной длины всегда имеет одну и ту же длину, и VBA при необходимости дополняет данные, присвоенные этой строковой переменной (обычно конечными пробелами), чтобы заполнить объявленную длину строки. В результате всякий раз, когда используется строка фиксированной длины, возникает вероятность того, что она будет содержать конечные пробелы. Посторонние начальные или конечные пробелы в строке могут вызвать различные проблемы: некоторые — только «косметические», другие — более серьезные. Когда строки транслируются для вывода на экран, лишние пробелы могут привести к большим промежуткам в тексте, при этом отображается неприемлемый и трудночитаемый текст. В других случаях посторонние начальные и конечные пробелы могут повлиять на сравнения строк, на сообщаемую длину строки и на некоторые другие факторы. Это может привести к тому, что строковое значение не будет использо Использование функций Visual Basic 159 ваться в каком-либо другом выражении или процедура выдаст ошибочный результат. В любом из этих случаев может возникнуть серьезная проблема. В VBA имеются три функции, специально предназначенные для удаления нежелательных начальных и конечных пробелов из строки. Первая функция — RTrim — удаляет символы пробела из правой части строки (конечные пробелы). Вторая функция — LTrim — удаляет символы пробела из левой части строки (начальные пробелы). Третья функция — Trim — удаляет как начальные, так и конечные пробелы из строки. Эти функции на самом деле не изменяют строку; вы передаете строку, из которой должны быть вырезаны пробелы, как аргумент функции, и функция возвращает копию строки с удаленными лишними пробелами. Процедура в листинге 6.3 демонстрирует использование функций удаления пробелов из строки. Листинг 6.3. Демонстрация функций RTrim, LTrim и Trim 1 2 3 4 5 6 7 8 9 Sub TrimDemo() Dim ExSpace As String ExSpace = " mad dog " msg = "{" & ExSpace & "}" MsgBox ”{" & ExSpace & "}”, , "До изменения" MsgBox "{" & RTrim(ExSpace) & , "Без правых пробелов" MsgBox "{" i LTrim(ExSpace) i , "Без левых пробелов" MsgBox "{" & Trim(ExSpace) s , "Без пробелов" End Sub В строке 3 переменной ExSpace (объявленной в строке 2) присваивается строка " mad dog " (с начальными и конечными пробелами). В строке 4 используется функция MsgBox для отображения еще неизмененной строки ExSpace. Строковое выражение для аргумента MsgBox конкатенирует пару фигурных скобок вокруг строки ExSpace, чтобы показать, имеются ли начальные или конечные пробелы в строке. Строки 5-7 листинга 6.3 — каждая используют одну из трех функций для удаления начальных и конечных пробелов из строки ExSpace; каждая строка использует MsgBox для отображения результата функции удаления пробелов. Результат работы кода представлен на рис. 6.4. Рис. 6.4 Диалоговые окна как результат выполнения кода листинга 6 3 { mad dog} Без правых пробелов Без левых пробелов OK (mad dog } Без пробелов {mad dog} Следует использовать функцию Trim для удаления начальных и конечных пробелбв из строк перед их сравнением; этим предотвращается влияние начальных и конечных пробелов на сравнение строк, что обычно не является существенным для пользователя, но имеет значение для VBA. 160 Глава 6 Определение длины строки Часто бывает необходимо знать длину строки (количество символов находится в строке), особенно при форматировании сообщений для пользователя или при форматировании строковых данных, вводимых процедурой в рабочий лист Excel или документ Word. VBA имеет функцию Len, позволяющую получать длину строки. Следующий оператор показывает общий синтаксис для этой функции: СИНТАКСИС Len(VString} VString — любое допустимое строковое выражение VBA. Следующий оператор показывает использование функции в операторе присваивания: StrLen = Len ("VBA") ' возвращает 3 Как и ранее, строки фиксированной длины представляют особый случай. Поскольку строка фиксированной длины имеет всегда одну и ту же длину, функция Len всегда возвращает объявленную длину строки. Например, при объявлении FirstName в качестве строковой переменной, имеющей длину 20 символов, функция Len всегда возвращает 20 как длину строки в FirstName; даже если в переменной сохранено имя Bob, имеющее длину только 3 символа, все остальные символы из 20 являются символами пробела. Обычно целью использования функции Len является определение того, сколько символов имеется в строке, исключая начальные или конечные пробелы. Вернемся к примеру с FirstName; если необходимо узнать фактическую длину имени, сохраненного в переменной, используйте оператор, подобный следующему: NameLen = Len(Trim(FirstName)) В этом операторе функция Trim удаляет любые начальные или конечные пробелы из строки в переменной, а функция Len сообщает длину результирующей строки. Если FirstName содержит "Москва", то переменная NameLen будет иметь результатом значение 6. Сравнение и поиск строк В главе 5 было описано, как сравнивать строки, используя операторы сравнения, и объяснялось действие установок Option Compare Binary и Option Compare Text. VBA имеет также две функции для сравнения строк. Первая функция — StrComp просто сравнивает две разные строки. При некоторых обстоятельствах лучше использовать StrComp вместо операторов сравнения (=, <, >) для сравнения строк, потому что StrComp позволяет указывать, следует ли выполнять бинарное или текстовое сравнение (независимо от установки Option Compare модульного уровня) для этого определенного сравнения. Например, если необходимо, чтобы большинство строковых сравнений игнорировали регистр (верхний или нижний) символов при сравнении строк, добавьте оператор Option Compare Text к этому модулю. После этого можно выполнить конкретное сравнение строк, являющееся чувствительным к регистру: используйте VBA-функцию StrComp и задавайте сравнение с учетом регистра. Использование функции StrComp Общим синтаксисом для функции StrComp является выражение: СИНТАКСИС StrComp (Stnngl, String2 [, Compare]) Stringl и String2 — любые два строковых выражения, которые необходимо сравнить. Необязательный аргумент Compare может быть любой из следующих предопределенных констант: Использование функций Visual Basic 161 vbBinaryCompare — для сравнения двух строк с помощью бинарного (с учетом регистра) сравнения; vbTextCompare — для сравнения двух строк с помощью текстового (без учета регистра) сравнения; vbDatabaseCompare — имеет значение только в Microsoft Access; в этом случае строковое сравнение использует любой метод сравнения, установленный для текущей базы данных. При использовании константы vbDatabaseCompare в каком либо другом программном продукте VBA, а не в Access VBA, отображается сообщение об ошибке времени исполнения, констатирующее наличие недопустимого аргумента процедуры. Если аргумент Compare опускается, StrComp использует текущую установку Option Compare. При выполнении StrComp сравниваются две строки с использованием заданного метода сравнения и возвращается одно из следующих значений: -1, если Stringl меньше String2 0, если Stringl и String2 равны друг другу 1, если Stringl больше String2 Процедура в листинге 6.4 демонстрирует функцию StrComp. Листинг 6.4. Демонстрация функции StrComp 1 Sub Demo_STRComp() 2 Const Умолчание = " STRComp" 3 Dim СтрокаВвода As String ' 4 СтрокаВВода = InputBox(Prompt:="Введите некоторый текст:", _ — 5 Title:="Сравнение строк", 6 . Default:= Умолчание) 7 MsgBox StrComp(СтрокаВвода, Умолчание, vbTextCompare) 8 End Sub В строке 2 объявляется константа для использования в качестве текста по умолчанию в последующем операторе InputBox. В строке 3 объявляется строковая переменная СтрокаВвода для сохранения результата функции InputBox. Строки 4-6 являются одним оператором, вызывающим функцию InputBox для получения строки от пользователя. Вызов функции InputBox использует именованные аргументы и задает заголовок диалогового окна и предлагаемое значение по умолчанию. Результат функции InputBox присваивается переменной СтрокаВвода. Строка 7 содержит вызов функции StrComp; оператор использует MsgBox для вывода возвращаемого значения функции StrComp непосредственно на экран. В результате код определяет, принял ли пользователь текст по умолчанию или ввел отличную от этого текста строку. Использование функции InStr Другая VBA-функция сравнения строк, InStr, дает возможность определить, содержит ли одна строка другую строку. Эта функция полезна в ряде случаев. Например, используйте InStr, если необходимо определить, содержит ли введенная пользователем строка определенное слово. Другой пример: используйте InStr, если необходимо определить, содержит ли строка символы, не позволяющие преобразовать ее в число. 6 Программирование на VBA 2002 162 Глава 6 Синтаксис функции InStr: СИНТАКСИС InStr([Start, ] Stringl, String2 [, Compare]) Stringl и String2 — любые допустимые строковые выражения. InStr проверяет, содержится ли Stringl в String2. Необязательный аргумент Start является любым численным выражением; этот аргумент (если используется) указывает положение символа в Stringl, с которого должна начинаться проверка. Необязательный аргумент Compare определяет, должна ли InStr использовать двоичное или текстовое сравнение. Допустимыми значениями для аргумента Compare функции InStr являются те же предопределенные константы, которые используются функцией StrComp: vbBinaryCompare, vbTextCompare и vbDatabaseCompare. Функция InStr возвращает число, обозначающее положение символа в Stringl, где было обнаружено String2; если InStr не находит String2 в Stringl, то она возвращает 0. Если Stringl (или String2) равно Null, то InStr возвращает Null. Листинг 6.5 демонстрирует использование InStr. Листинг 6.5. Демонстрация функции InStr 1 Sub Demo_InStr() 2 Const Умолчание = "InStr" 3 Dim СтрокаВвода As String 4 СтрокаВвода = InputBox(Prompt:“"Введите некоторый текст:", 5 Title: ^''Сравнение строк", __ б Default:= Умолчание) 7 MsgBox InStr(1, СтрокаВвода, Умолчание, vbTextCompare) 8 End Sub В строке 7 проверяется, содержится ли в строке СтрокаВвода строка, обозначенная константой Умолчание. Используется текстовое сравнение, указано начальное положение для поиска. InStr начинает поиск строки Умолчание с первого символа строки СтрокаВвода. Разбиение строки на меньшие части Во многих процедурах бывает необходимо разбить строку на составляющие части. Например, может понадобиться проанализировать вводимую пользователем строку, чтобы определить, содержит ли она более одного слова и, если содержит, разделить ее на отдельные слова. Примеры такой обработки строк встречаются в последующих главах. функция Left VBA имеет три функции для выделения подстрок из больших строк. (Под строка — это любая строка, которая является или может быть частью большей строки). Первая из них — это функция Left, возвращающая копию определенной части строки. Далее следует синтаксис функции Left: СИНТАКСИС Left(String, Length) Здесь String — любое допустимое строковое выражение, a Length — любое численное выражение. Функция Left возвращает копию String, начиная Использование функций Visual Basic 163 с первого символа и включая количество символов, заданных с помощью Length. Если Length является числом, большим, чем фактическая длина String, то Left возвращает все строковое выражение String. В следующем операторе Left копирует первые 16 символов строки OldStr и возвращает эти символы кар строку; этот оператор присваивает результат функции Left переменной NewStr. Если OldStr содержит строку "В пустыне чахлой и скупой", то NewStr будет содержать "В пустыне чахлой" (после выполнения этого оператора). NewStr = Left(OldStr, 16) Функция Right Другая VBA-функция подстроки — это функция Right. Далее следует синтаксис Right: СИНТАКСИС • Right(String, Length) Здесь String представляет любое допустимое строковое выражение, a Length — любое численное выражение. Функция Right возвращает копию String, начиная с последнего символа в строке и включая справа налево количество символов, указанное с помощью Length. Если Length является числом, большим, чем фактическая длина String, то Right возвращает все строковое выражение String. Функция Right всегда копирует символы от конца строки, действуя в направлении к началу строки. > В следующем операторе функция Right возвращает последние восемь символов строки OldStr. Если переменная OldStr содержит строку "В пустыне чахлой и скупой", этот оператор сохраняет строку "и скупой" в переменной NewStr. NewStr = Right(OldStr, 8) В бизнес-приложениях функция Right может быть полезна, например, при выделении из некоторого ключевого поля номера накладной. Для того чтобы создать уникальный номер накладной, которая создается на складе с кодом, например, "1011" за определенную дату, можно сформировать номер как строку вида: '101101022001002' Здесь первые четыре символа обозначают код склада, следующие восем символов содержат дату, а последние три — номер накладной, начиная с первой в текущий день. Если код склада всегда содержит четыре символа, то для быстрого (с смысле краткости кода) выделения любого значения из всей строки можно использовать функцию Mid (см. далее). Если же код склада может содержать различное количество символов, то удобнее пользоваться функцией Right. Функция Mid Можно извлечь подстроку из середины строки, а не из правой или левой ее части. Такая ситуация может возникнуть при извлечении отдельных слов из строки текста. Для извлечения подстроки из середины другой строки VBA имеет функцию Mid. Функция Mid имеет следующий общий синтаксис: СИНТАКСИС Mj,d (String, Start [, Length]) Здесь String — любое строковое выражение, тогда как Start и Length — это любые численные выражения. Функция Mid возвращает копию String, начи 164 Глава 6 ная с положения символа в String, задаваемого с помощью аргумента Start. > Необязательный аргумент Length определяет количество копируемых в Mid символов из String. Если Start содержит большее число, чем фактическая длина String, то Mid возвращает пустую строку. Следующий оператор показывает пример функции Mid: NewStr = MidfOldStr, 10, 5) Если переменная OldStr содержит строку "Беспечный сын природы”, то этот оператор сохраняет строку ” сын " в переменной NewStr. Использование символов, которые нельзя ввести с клавиатуры Иногда необходимо включить в строку какой-либо символ, для которого нет соответствующей клавиши на клавиатуре, например, букву греческого языка, символ для йены или символ авторского права. Может потребоваться также включить какой-либо символ, который уже имеет особое значение для VBA, такой как символ кавычек ("). Вы не можете включать символы, подобные кавычкам, непосредственно в строку, потому что VBA всегда «подразумевает», что этот символ начинает или заканчивает строку. Следующий оператор, например, приводит к ошибке времени исполнения или ошибке синтаксиса: MsgBox "This "cannot" work" Хотя этот оператор может предназначаться для вывода на экран строки, VBA не может выполнить его. Поскольку кавычки (") указывают VBA на то, что литеральная строка либо начинается, либо заканчивается, VBA разбивает вышеприведенный аргумент MsgBox на три части: строку "This ", имя переменной cannot и еще одну строку " work". Чтобы включить в строку символы, которые невозможно ввести с клавиатуры, или которые имеют особое значение для VBA, используйте VBA-функцию Chr. Функция Chr имеет следующий синтаксис: СИНТАКСИС Chr(Charcode) Здесь Charcode — любое численное выражение, являющееся допустимым кодом для набора символов, используемого компьютером. Аргумент Charcode должен быть числом от 0 до 255. Как вы помните из обсуждения двоичного и текстового сравнения строк, компьютер сохраняет буквы во внутренней памяти как числа и использует схему, в которой каждый символ имеет собственный уникальный номер. Функция Chr принимает код отдельного символа в качестве аргумента и возвращает строку, содержащую соответствующий этому коду символ. Чтобы просмотреть список кодов, которые распознает VBA, и соответствующих им символов, откройте справочную систему VBA и найдите раздел Character sets. Например, при поиске кода символа кавычек (") обнаруживаем, что кавычки имеют код 34. Используя функцию Chr для предоставления кавычек, следующий оператор отображает диалоговое окно, приведенное на рис. 6.5: MsgBox Chr(34) & "Кто здесь?" & Chr(34) & " - " & Chr(34) & "Я странник!" & Chr(34) & " - был ответ" Можно также управлять форматированием отображаемых сообщений, добавляя специальные символы к строкам. Один из символов, которые можно получить с помощью функции Chr — это символ возврата каретки (код символа 13). Это — символ, генерируемый компьютером всякий раз при нажатии клавиши Enter на Использование функций Visual Basic 165 клавиатуре и указывающий на начало новой строки при использовании его в тексте. Как показано на рис. 6.6, следующий оператор использует Chr для добавления символа возврата каретки в конкатенированную строку так, чтобы полученное диалоговое окно содержало несколько строк. Рис. 6.5 Пример использования функции Chr Microsoft Word 'Кто здесь’" - "Я странник!" - был ответ Диалоговое окно, показанное на рис. 6.6, может быть получено с помощью следующего (одного!) оператора: MsgBox "Выхожу один я на дорогу;" & Chr(13) & _ "Сквозь туман кремнистый путь блестит;" & Chr (13) & _ "Ночь тиха. Пустыня внемлет богу," & Chr (13) & _ "И звезда с звездою говорит." & Chr (13) & Chr (13) & _ " М.Ю. Лермонтов" & Chr (13) Рис. 6.6 Использование функции Chr с константой 13 в качестве параметра окрывает возможности форматирования текста в окне функции MsgBox Microsoft Word Выхожу один я на дорогу. Сквозь туман кремнистый путь блестит, Ночь тиха Пустыня внемлет богу, И звезда с звездою говорит МЮ Лермонтов Поскольку символы, используемые для начала новой строки, являются очень важными при форматировании сообщений и других строковых данных, которыми манипулируют VBA-процедуры, VBA имеет несколько предопределенных констант для этих символов, чтобы не было необходимости использовать функцию Chr: vbCr — символ возврата каретки (код символа 13). Эта константа является эквивалентом выражения: Chr(13). Включение vbCr в строку приводит к тому, что VBA и большинство приложений Windows начинают новую строку при выводе строки на экран. В некоторых случаях, например, при пересылке строки на принтер, символ возврата каретки просто приводит к перемещению курсора в начало текущей строки без перехода к следующей строке. vbLf — символ смещения на одну строку (код символа 10). Эта константа эквивалентна выражению: Chr(10). Включение vbLf в строку приводит к тому, что VBA и большинство приложений Windows начинают новую строку при отображении строки. В некоторых случаях, например, при пересылке строки на принтер, символ смещения на одну строку просто приводит к перемещению курсора к следующей строке без возврата к левому краю области печати. vbCrLf — символ возврата каретки/смещения на одну строку; эквивалентен выражению: Chr(13) & Chr(10). Помещение этого символа в строку приводит к тому, что VBA начинает новую строку при отображении строки. Например, при пересылке текста на принтер или для текстовых файлов DOS-формата, необходимо использовать vbCrLf для перемещения курсора к новой строке и к левому краю области печати. vbNewLine представляет символ(ы), используемый при создании новой строки для программной платформы, в которой выполняется ваша процедура 166 Глава 6 VBA. Применяйте константу vbNewLine в процедурах, которые должны использоваться либо в Windows, либо в Macintosh-версиях MS приложений. vbTab — символ табуляции (код символа 9). Этот символ создается при нажатии на клавишу Tab на клавиатуре. Константа vbTab эквивалентна выражению: Chr(9). Можно включать символы табуляции в строки для выравнивания данных в столбцах. С учетом вышесказанного последний оператор можно переписать в виде: MsgBox "Выхожу один я на дорогу;" & vbCr & "Сквозь туман кремнистый путь блестит," & vbCr & _ "Ночь тиха. Пустыня внемлет богу," & vbCr & "И звезда с звездою говорит." & vbCr & vbCr & vbTab & vbTab & "М.Ю. Лермонтов" 4 vbCr ’ Форматирование значений данных Хотя VBA может автоматически преобразовывать любой тип данных в строку для отображения с помощью функции MsgBox или для вставки в рабочий лист Excel (документ Word или соответствующий объект другого приложения), формат данных, который выбирает VBA, может не совпадать с желаемым. При преобразовании числа в строку VBA не добавляет в строку разделитель тысяч, символы доллара или другое числовое форматирование. Кроме того, если число очень большое или очень малое, VBA создает строку, представляющую это число в экспоненциальном формате. Например, VBA преобразует число 3145.25 в строку "3145.25". Если это число представляет сумму в долларах, может оказаться предпочтительнее преобразовать его в строку, содержащую символ доллара и разделитель тысяч: "$3,145.25". Аналогично, при преобразовании дат VBA всегда использует короткий формат даты и времени, используемый операционной системой компьютера, и всегда отображает и дату, и время. Вы можете использовать другой формат даты или времени или отображать только дату или только время. Для получения почти любого формата дат при преобразовании чисел или дат в строки можно использовать функцию Format; можно даже использовать функцию Format для форматирования строковых данных в соответствии с определенным шаблоном. Можно также создавать пользовательские экранные форматы, если вам необходимо, чтобы данные появлялись в каком-либо особом формате. VBA-функция Format идентична функции Format в Excel и использует те же символы-заполнители форматирования данных, что Excel и Access. Синтаксис оператора Format следующий (приведен из справочной системы VBA): г СИНТАКСИС Format[Expression[, Format[, Firstdayofweek[, Firstweekofyear]]]) Здесь аргументы означают: i Expression любое допустимое выражение (обязательный); I Format допустимое выражение именованного или определенного пользователем формата (необязательный); Firstdayofweek константа, которая определяет первый день недели (необязательный); Firstweekofyear константа, которая определяет первую неделю года (необязательный). Использование функций Visual Basic 167 Для аргументов Firstdayofweek и Firstweekofyear в VBA имеются именованные константы, о которых можно узнать из справочной системы VBA в разделе Date Constants. Чтобы использовать функцию Format, можно либо задать предопределенный формат (называемый именованным форматом (named format)), либо создать образ определенного формата, используя комбинации особой группы символов, называемых символами заполнителями (placeholders). Используйте образ, который создается с помощью символов-заполнителей, если ни один из именованных форматов не отвечает вашим запросам. Примером этих методов использования функции Format могут быть следующие операторы MsgBox (каждый отображает одно и то же диалоговое окно, показанное на рис. 6.7); первый оператор использует именованный формат, второй — образ с символами-заполнителями: MsgBox Format(#2/27/1976#, "Long Date") MsgBox Format(#2/27/1976#, "dd mmmm yyyy") Рис. 6.7 Использование функции Format для изменения строкового формата значения даты 27 February 1976 Friday February 27, 1976 Microsoft Word OK Внимательный читатель все же заметит, что в русской версии Window 98 сообщения в окнах немного отличаются. Табл. 6.7 содержит доступные именованные форматы и объясняет их действие. Таблица 6.7. Именованные форматы для использования с функцией Format Именованный формат Действие General Date Форматирует информацию о дате и времени в последовательное число даты, используя установки формата даты и времени для вашего компьютера. То же, что VBA-преобразование по умолчанию последовательных дат в строки. Long Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Long-формата даты. Medium Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Medium-формата даты. Short Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Short-формата даты. Long Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Long-форма-та времени. Medium Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Medium-формата времени. Short Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Short-формата времени. 168 1 Глава 6 Именованный формат Действие General Number Форматирует число в строку без каких-либо особых символов. Действие такое же, как VBA-преобразование по умолчанию чисел в строки. Currency Форматирует число с символом денежной единицы, разделителем тысяч и только двумя десятичными разрядами. Символ денежной единицы и десятичный разделитель определяются локальными установками Windows. Fixed Форматирует число так, чтобы всегда была, по крайней мере, одна цифра перед десятичным разделителем и, по крайней мере, две цифры после него. Standard Форматирует число с разделителем тысяч так, чтобы была, по крайней мере, одна цифра перед десятичным разделителем и, по крайней мере, две цифры после него. Percent Форматирует число как процентное отношение, умножая его на 100 и добавляя символ процента. Например, 0.21 возвращается как 21%. Scientific Форматирует число в обычный экспоненциальный формат. Yes/No Использование этого формата приводит к тому, что функция Format возвращает строку "Да" ("Yes"), если форматируемое число ненулевое, и возвращает строку "Нет" ("No") для любого нулевого значения. Этот именованный формат наиболее часто используется со значениями типа Boolean. True/False Использование этого формата приводит к тому, что функция Format возвращает строку "Истина" ("True"), если форматируемое число ненулевое, и строку "Ложь" ("False") для любого нулевого значения. Этот именованный формат наиболее полезен со значениями типа Boolean. On/Off Использование этого формата приводит к тому, что функция Format возвращает строку "Вкл" ("On"), если форматируемое число ненулевое, и строку "Выкл" ("Off”) для любого нулевого значения. Наиболее часто используется со значениями Boolean. Форматы long, medium и short date и time можно изменять посредством Панели управления (Windows Control Panel). Можно также изменять символы, используемые для разделителя тысяч и десятичного разделителя (на Панели управления). Если вам необходимо создавать пользовательские форматы для чисел, дат или времени, нужно создать строку, содержащую символы-заполнители, для задания образа форматирования, который должна будет использовать функция Format при преобразовании значений в строку. В табл. 6.8 приведены пользовательские символы-заполнители, применяемые для создания образов форматов с применением функции Format. Кроме того, в табл. 6.8 используется как пример численное значение 1234,5. Полужирным шрифтом выделены символы-заполнители, которые вводятся из окружающего текста. Использование функций Visual Basic 169 Таблица 6.8. Символы-заполнители для создания пользовательских форматов Символ-заполнитель Действие 0 Цифровой символ, отображает цифру, если таковая находится в этой позиций, или 0, если — нет. Можно использовать символ 0 для отображения начальных нулей для целых чисел и конечных нулей в десятичных дробях; 00000.000 отображает 00124,500. # Цифровой символ, отображает цифру, если таковая находится в этой позиции, иначе — не отображает ничего. Символ-заполнитель # эквивалентен 0, кроме того, что начальные и конечные нули не отображаются; #####.### отображает 1234,5. $ Отображает знак доллара; $###,###.00 отображает $1 234,50. Десятичный символ-заполнитель, отображает десятичную точку в обозначенной позиции в строке символов-заполнителей 0; #.##.## отображает 1234,5 % Символ процента, умножает значение на 100 и добавляет знак процента в позицию, указанную символами-заполнителями 0; #0.00% отображает число 0.12345 как 12,35% (12,345 округляется до 12,35). , (запятая) Разделитель тысяч, добавляет запятые как разделители тысяч в строках символов-заполнителей 0 и #. ###,###,###.00 отображает 1 234,50. Е—, е— Отображает значения в экспоненциальном формате со знаком порядка только для отрицательных значений; #.####Е—00 отображает 1,2345Е03; 0,12345 отображается как 1,2345Е-01. Е+, е+ Отображает значения в экспоненциальном формате со знаком порядка для положительных и отрицательных значений; #.####Е+00 отображает 1,2345Е+03. / Отделяет день, месяц и год для форматирования значений дат. mm/dd/yy отображает 06/06/97. Символы "/" можно заменять на символы дефиса для отображения как 06-06-97. ш Указывает, как отображать месяцы в датах; m отображает 2, mm — 02, mmm — фев, mmmm — Февраль. d Указывает, как отображать дни в датах; d отображает 1, dd отображает 01, ddd — Пт, dddd — пятница. У Отображает день года как число от 1 до 366. УУ Указывает, как отображать годы в датах; уу отображает 99, УУУУ — 1999. q Отображает квартал года как число от 1 до 4. W Отображает день недели как число (1 — это воскресенье). WW Отображает неделю года как число от 1 до 54. : (двоеточие) Отделяет часы, минуты и секунды в значениях формата времени; hh:mm:ss отображает 02:02:02. h Указывает, как отображать часы; для значения времени 02:01:38 h отображает 2, hh отображает 02. 170 Глава 6 Символ-заполнитель Действие п Минутный символ-заполнитель для времени; для значения времени 02:01:08 п отображает 1, а пп отображает 01. S Секундный символ-заполнитель для времени; для значения времени 02:01:08 s отображает 8, и ss отображает 08. АМ/РМ Отображает время в 12-часовом формате времени с добавленными AM и PM; h:nn АМ/РМ отображает 4:00 РМ. Альтернативные форматы включают am/pm, А/P и а/р. @ Символьный заполнитель, отображает пробел, если не имеется соответствующего символа в форматируемой строке. @@@@ отображает строку Hi с двумя начальными пробелами, (порядок заполнения по умолчанию — справа налево). < Отображает все символы в верхнем регистре. > Отображает все символы в нижнем регистре. При использовании функции Format для форматирования строк и чисел можно создавать дополнительные секции в образе формата, чтобы изменять формат отображения в соответствии с форматируемым значением. Секции в образе формата разделяются точкой с запятой (;). Например, следующий образ содержит две секции и форматирует отрицательные числа иначе, чем положительные: $###,###Л#0.00;$(###,###,##0.00) Вышеприведенный образ форматирует число 1234567,89 как $1 234 567.89 и форматирует —1234567,89 как $(1 234 567.89). Можно для форматирования строки иметь две секции в образе формата. Если образ формата содержит только одну секцию, этот образ применим ко всем форматируемым строкам. Если образ формата содержит две секции, первая секция применима к строковым данным, а вторая — к значениям Null и строкам нулевой длины (то есть к строкам, которые не содержат символов, представленных с помощью ""). Рассмотрим следующий оператор, отображающий результат функции Format, используемый с образом из двух частей для строк. MsgBox Format(strData, " (@@@) - @@@ - @@@@; не номер телефона”) Приведенный выше оператор отображает (510) - 555 - 1212 в результирующем окне сообщения, если переменная strData содержит "5105551212". Если переменная strData содержит строку нулевой длины (""), то предыдущий оператор отображает в окне сообщения строку «не номер телефона». Для форматирования числовых значений можно иметь до четырех различных секций в образе формата. Первая секция используется для положительных чисел, вторая — для отрицательных чисел, третья — для нулевых значений, а четвертая — для значений Null. Следующий образ формата содержит четыре секции: $###,###,##0.00; $(###,###,##0.00); 0.00; "Null value" Приведенный выше образ формата форматирует отрицательные числа с круглыми скобками, указывает, что нулевые значения должны быть показаны как 0.00, и возвращает текстовое сообщение, если форматируемое значение равно. Null. Этот образ формата форматирует число 1234567,89 как строку "$1 234 567.89". Число —1234567,89 форматируется в строку "$(1 234 567.89)". Значение 0 форматируется в строку "0.00", тогда как значение Null форматируется в строку "Null value". Кроме общей функции форматирования, вы можете использовать функции специального форматирования, приведенные в таблице 6,9 и в Приложении Г. Использование функций Visual Basic 171 Таблица 6.9. Функции специального форматирования Функция Назначение FormatCurrency(E [, N [, I [,U [, G]]]]) Возвращает выражение, отформатированное как денежное (валютное) выражение с использованием значения, заданного на вкладке Денежная единица окна Свойства: Язык и стандарты, доступного из Панели управления. FormatDateTime(D [,N]) Возвращает выражение, отформатированное, как дата или время. FormatNumber(E [,N [, I [, U [, G]]]]) Возвращает выражение, отформатированное, как число. FormatPercent(E [, N [, I [, U [, G]]]]) Возвращает выражение, отформатированное, как процентное отношение (умноженное на 100) с конечным знаком процента ( %). Функция FormatCurrency возвращает выражение, отформатированное как денежное (валютное) выражение с использованием значения, заданного на вкладке Денежная единица окна Свойства: Язык и стандарты, доступного из Панели управления. Синтаксис функции FormatCurrency следующий (приведен из справочной системы VBA): СИНТАКСИС FormatCurrency(Expression[, NumDigitsAfterDecimal [, IncludeLeadingDigit [, UseParensForNegativeNumbers [, GroupDigits]]]]) Здесь аргументы означают: Expression Выражение для фоматирования (обязательный). NumDigitsAfterDecimal Численное значение, определяющее количество отображаемых знаков справа от десятичной точки. Значение по умолчанию для этого аргумента равно -1, что означает использование региональных настроек (необязательный). IncludeLeadingDigit Константа трех состояний, определяющая, следует ли отображать ведущий ноль для дробных чисел (необязательный). UseParensFor- NegativeNumbers Константа трех состояний, определяющая, следует ли помещать отрицательные значения внутри круглых скобок (необязательный). GroupDigits Константа трех состояний, определяющая, группировать ли цифры с помощью ограничителей, заданных региональными настройками (необязательный). Агументы IncludeLeadingDigit, UseParensForNegativeNumbers и GroupDigits могут принимать только значения констант: vbTrue, vbFalse и vbUseDefault (True, False и Использовать региональные настройки компьютера). В качестве примера приведем код небольшой программы и результат ее работы (рис. 6.8) в виде последовательно выдаваемых на экран диалоговых окон. 172 Глава б Листинг 6.6. Демонстрация функции Formatcurrency 1 Sub MyMacroO 2 'Пример использования функции FormatCurrency 3 Dim MyDoublel As Double, MyDouble2 As Double 4 MyDoublel = -22323.123 5 MyDouble2 = 0.000123 6 * 7 MsgBox Formatcurrency(MyDoublel, 7) 8 9 MsgBox Formatcurrency(MyDouble2, 7, vbTrue) 10 MsgBox Formatcurrency(MyDouble2, 7, vbFalse) 11 12 MsgBox Formatcurrency(MyDoublel, 7, vbTrue, vbTrue) 13 MsgBox Formatcurrency(MyDoublel, 7, vbTrue, vbFalse) 14 MsgBox Formatcurrency(MyDoublel, 7, vbTrue, vbTrue, vbTrue) 15 ЯИДВИ1 Рис. 6.8 Пример использования функции Formatcurrency $0 0001230 ок 16 End Sub Синтаксис функции FormatDateTime следующий (взят из справочной системы VBA): СИНТАКСИС FormatDateTime(Date[,NamedFormat]) Здесь аргументы означают: Date Дата для фоматирования (обязательный). NamedFormat Чиленное значение, указывающее, необходимый формат. Если опущен, используется vbGeneralDate (необязательный). Аргумент NamedFormat может принимать следующие значения: Константа Значение Описание vbGeneralDate 0 Отображать дату и/или время. Если в аргументе Date имеется часть даты, дата отображается в коротком формате. Если в аргументе Date имеется часть времени, она отображается в длинном формате. Использование функций Visual Basic 173 Константа Значение Описание vbLongDate 1 Отображать дату с использованием длинного формата, установленного на компьютере в региональных настройках. | vbShortDate 2 * Отображать дату с использованием короткого 1 формата, установленного на компьютере в региональных настройках. | vbLongTime 3 Отображать время с использованием временного формата, установленного на компьютере : в региональных настройках. vbShortTime 4 Отображать время с использованием формата 24-hour (hh:mm). В качестве примера приведем код небольшой программы и результат ее работы (рис. 6.9) в виде последовательно выдаваемых на экран диалоговых окон. Листинг 6.7. Демонстрация функции FormatDateTime 1 Sub MyMacroO 2 ' Пример использования функции FormatDateTime 3 Dim MyDate As Date 4 MyDate = Now() 5 6 MsgBox FormatDateTime(MyDate, vbGeneralDate) 7 MsgBox FormatDateTime(MyDate, vbLongDate) 8 MsgBox FormatDateTime(MyDate, vbShortDate) 9 MsgBox FormatDateTime(MyDate, vbLongTime) 10 MsgBox FormatDateTime(MyDate, vbShortTime) 11 12 End Sub Microsoft Word Microsoft Word |X( Microsoft Word <X| Microsoft Word JX1 Microsoft Word 3/1/2003 6:05:46 PM Saturday, March 01, 2003 ILj*ZJ 3/1/2003 |f bk | 6-05.46 PM |r ok | 18.05 If. "<%. 1 Рис. 6.9. Пример использования функции FormatDateTime Синтаксис функции FormatNumber следующий (приведен из справочной системы VBA): СИНТАКСИС FormatNumber(Expression[,NumDigitsAfterDecimal [, IncludeLeadingDigit [,UseParensForNegativeNumbers [, GroupDigi ts] ] ] ])' Здесь аргументы означают то же, что и в функции FormatCurrency. В качестве примера приведем код небольшой программы и результат ее работы (рис. 6.10) в виде последовательно выдаваемых на экран диалоговых окон. 174 Глава 6 Листинг 6.8. Демонстрация функции FormatNumber 1 Sub MyMacrot) 2 ' Пример использования функции FormatNumber 3 Dim MyDouble As Double 4 MyDouble = 112233.4455 5 6 MsgBox FormatNumber(MyDouble) 7 MsgBox FormatNumber(MyDouble, vbFalse) 8 MsgBox FormatNumber(MyDouble, vbTrue) 9 MsgBox FormatNumber(MyDouble, , vbFalse) 10 MsgBox FormatNumber(MyDouble, , vblrue) 11 MsgBox FormatNumber(MyDouble, , , vblalse) 12 End Sub Рис. 6.10 Пример использования функции FormatNumber Microsoft Word SI Microsoft Word *1 Microsoft Word 112,233 45 112,233 45 112,233 45 OK OK Синтаксис функции FormatPercent следующий (приведен из справочной системы VBA): • СИНТАКСИС • V- ’ • FormatPercent(Expression[,NumDigitsAfterDecimal [, IncludeLeadingDigit [,UseParensForNegativeNumbers [, GroupDigits]]]]) Здесь аргументы означают то же, что и в функции FormatCurrency. В этой главе приведены не все функции, которые имеются в VBA. В VBA есть функции, которые позволяют «общаться» с другими приложениями, получать информацию об ошибках времени исполнения, получать информацию о массивах и манипулировать объектами различных host-приложений в Word и Excel. Некоторые из них описываются в других главах. Использование функций host-приложений Кроме функций, встроенных в Visual Basic for Applications, из кода VBA доступны некоторые функции host-приложения VBA. (Помните, что host-приложение — это приложение, в котором разрабатываются процедуры VBA такие, как Word, Excel, PowerPoint, Outlook, или FrontPage). Специфические функции host-приложения, доступные для VBA, зависят от определенного host-приложения, в котором выполняется работа. В Excel, например, имеются различные функции, выполняющие математические, логические, финансовые и статистические операции над данными в рабочих листах. Многие (хотя и не все) из этих функции Excel доступны из кода VBA. Использование функций Visual Basic 175 Функции host-приложения, доступные для VBA, не являются частью VBA, они являются частью host-приложения. Функции рабочих листов Excel, например, не являются частью языка программирования VBA; они являются частью host-приложения Excel. Не каждое host-приложение VBA содержит функции, которые можно использовать в VBA. Функции, доступные для VBA в одном host-приложении, могут не быть доступными в другом. Если вы намереваетесь писать процедуры VBA, которые могут выполняться любым host-приложением, не используйте функции из host-приложения, потому что они могут не быть доступными во всех приложениях. Например, если необходимо написать процедуру для использования в Word, Excel, Access или Microsoft Project, не используйте функций Excel в операторах VBA. Чтобы использовать функцию, принадлежащую какому-либо host-приложению, обращайтесь к функции посредством программного объекта (Application). Объект Application VBA представляет host-приложение и все его ресурсы. (Объекты более подробно описываются далее.) Помимо нескольких функций, преобразующих различные измерения набора текста в дюймы и наоборот, Word не имеет функций приложений, доступных в VBA. По этой причине в данной главе основное внимание при объяснении использования функций host-приложений уделяется использованию функций host-приложений в Excel. Более вероятно, что вы будете использовать функции host-приложения в Excel, поскольку Excel разработан специально для манипулирования числовыми данными в формате рабочих листов. В результате Excel содержит много функций для использования в формулах рабочих листов. Функции рабочих листов Excel применяются для выполнения таких задач, как нахождение суммы целого столбца цифр, для выполнения финансовых вычислений (например, нахождение текущей величины займа) и для выполнения статистического анализа данных. Хотя многие математические функции Excel дублируют математические функции VBA, Excel содержит намного больше специализированных статистических и финансовых функций, чем VBA. При программировании Excel-операций в Excel VBA может понадобиться использовать многие из функций рабочих листов, являющихся частью Excel. В качестве примера следующий оператор использует Excel-функцию Мах, возвращающую самое большое число в ее списке аргументов: MsgBox Application.Мах(9, 1, 3, 2) ' Отображает 9 В этом операторе обратите внимание на то, что за словом Application следует точка (.) и затем — имя функции Мах без пробелов. Эта точка, называемая точкой-разделителем (dot separator), указывает на то, что оператор ссылается на функцию Мах, которая является частью объекта Application. При использовании функций host-приложения в операторах VBA необходимо включать ключевое слово Application и точку-разделитель перед именем каждой функции. Например, чтобы использовать какие-либо функции рабочих листов Excel в операторах VBA, необходимо включать ключевое слово Application и точку-разделитель (.) перед именем каждой функции Excel. Результат функции Excel нельзя игнорировать. Необходимо всегда включать круглые скобки в вызов функции Excel и всегда каким-либо образом использовать результат функции: как значение в выражении, аргумент для другой функции или процедуры или в операторе присваивания. Если вы опытный пользователь рабочих листов Excel, вы могли уже заметить, что Excel имеет много функций, имеющих те же имена, что и некоторые функции, перечисленные в табл. 6.3-6.6. Эта ситуация может также наблюдаться и в других host-приложениях: host-приложение имеет функции, имена которых дублируют имена функций, имеющихся в VBA, 176 Глава 6 Поскольку необходимо всегда указывать ключевое слово Application, когда используется функция host-приложения, то не бывает неясно для VBA или пользователя, на какую функцию (VBA или приложения) ссылается оператор. Следующий фрагмент кода, например, показывает два оператора в Excel VBA: Rslt = Log(AnyNum) Rslt = Application.Log(AnyNum) Первый оператор вызывает VBA-функцию Log; второй'— вызывает Excel-функцию LOG. Чтобы использовать VBA-версию функции, просто пишите имя функции; чтобы использовать версию функции host-приложения, включайте ключевое слово Application. Функции host-приложений, имеющие те же имена, что и функции VBA, не обязательно выполняют те же самые задачи и выдают те же самые результаты. Например, Excel-функция LOG отличается от VBA-функции Log, и эти функции возвращают разные ответы: Excel-функция LN — это функция, совпадающая с действием VBA-функции Log. Внимательно изучите действие и результат функции host-приложения перед тем, как использовать ее вместо функции VBA, в противном случае процедуры могут выдавать ошибочные результаты. Не каждая функция host-приложения доступна VBA. Например, некоторые функции Excel, дублирующие функции VBA, недоступны, потому что в этом нет смысла. Конкретнее, Excel-функции Date, Year, Month, Day, Hour, Minute и Second дублируют VBA-функции Date, Year, Month, Day, Hour, Minute и Second как по своему действию, так и по назначению. Никакая из этих функций Excel недоступна для VBA. Иногда некоторые функции host-приложений недоступны для VBA независимо от того, дублируют они функции VBA или — нет. Если вы не уверены, доступна ли определенная функция host-приложения для VBA, используйте Object Browser, чтобы проверить, включает ли список Members (Компонент) эту функцию, при выбранном Application в списке Classes (Классы) и при выбранном host-приложении в списке Project/Library (Проект/ Библиотека). Если нужной функции нет в списке, то она недоступна для VBA. Чтобы узнать, какие функции имеются в Excel (или любом другом приложение), и узнать, каково назначение и как использовать эти функции, обращайтесь к справочной системе и ищите раздел для слова functions. В заключение отметим очень полезное дополнительное свойство функции InputBox приложения Excel, которого нет в VBA. Дело в том, что InputBox в Excel имеет необязательный параметр Туре, задающий тип вводимого значения. Это можно использовать в качестве дополнительного контроля вводимой информации. Параметр Туре может принимать следующие значения: Значение Что означает 0 Формула 1 Число 2 Текст (строка) 4 Логическое значение (True или False) 8 Ссылка на ячейку, как объект диапазона 16 Значение ошибки, такое как #N/A 64 Массив значений Вы можете использовать в качестве аргумента Туре сумму доступных значений. Например, для ввода как текстовых, так и числовых значений можно задавать значение 1+2. Глава 7 Создание и использование функций и функций-процедур Из шестой главы вы узнали, что такое функция и как использовать встроенные функции VBA и host-приложений VBA, таких как Excel. Из этой главы вы узнаете, как создавать собственные пользовательские функции, как работать с ними в host-приложениях VBA. В частности, вы узнаете, как сделать так, чтобы ваши собственные функции были доступны рабочим листам Excel. Функции-процедуры и определенные пользователем функции Перед тем как начать писать собственные функции, вам необходимо ознакомиться с терминологией и понятиями, используемыми при обсуждении создания функций в VBA. Функция-процедура (или функция) — это особый вид процедуры VBA, возвращающей результат. Пользовательские функции-процедуры, как и встроенные функции VBA, могут иметь необязательные и именованные аргументы. Функции можно использовать для обеспечения значениями выражений (присваивания) или в качестве аргументов других функций и процедур. Создание новой функции состоит из написания программных операторов, которые определяют: 1) аргументы, используемые функцией; 2) действия, выполняемые функцией; 3) значение, возвращаемое функцией. Для того чтобы можно было использовать ваши'функции в Excel, необходимо выполнять некоторые дополнительные правила (ограничения). Word не имеет встроенных функций, которые использовались бы подобно Excel-функциям рабочих листов. Word дает возможность вставлять в документ в виде полей информацию различных типов данных, таких как текущая дата и время, имя документа, оглавление и так далее. Word не содержит функций для выполнения статистических вычислений или других аналитических задач, для чего и предназначен Excel. Следовательно, функции, создаваемые с помощью VBA, имеют различное применение в Excel и Word; В Excel можно использовать функции VBA для расширения коллекции встроенных функций рабочих листов. Другие host-приложения VBA, такие как Access, также позволяют применять создаваемые вами VBA-функции для расширения и улучшения встроенной коллекции функций. С «точки зрения» Excel используемые им функции-процедуры VBA, являются определенными пользователем функциями (user-defined functions). Этот термин позволяет отличать функции, написанные пользователем, от встроенных функций Excel. Хотя все определенные пользователем функции являются также функциями-процедурами, не все функции-процедуры отвечают требованиям определенной пользователем функции. Функция-процедура — это наиболее общий термин для создаваемых пользователем функций; термин «определенная пользователем функция» описывает определенный тип функции-процедуры, который может использовать Excel. Нельзя 178 Глава 7 использовать функцию-процедуру, которая не отвечает требованиям определенной пользователем функции в формулах рабочих листов Excel; можно использовать такие функции только в операторах ваших собственных процедур. Далее в этой главе будет использоваться термин «функция» вместо «функция-процедура», когда будет понятно, о чем идет речь. Создание функций-процедур > Для записи функции-процедуры нельзя использовать макрорекордер, хотя можно редактировать записанный рекордером макрос и превращать его в функцию-процедуру. Написание функции-процедуры Функции-процедуры очень похожи на процедуры VBA, которые вы уже умеете записывать. Основное различие между функцией-процедурой и другими процедурами, помимо того, что функции возвращают значение, а процедуры — нет, состоит в том, что вместо ключевых слов Sub и End Sub, с которыми вы уже знакомы, в функции-процедуре используются ключевые слова Function и End Function. Функция-процедура имеет следующий синтаксис: СИНТАКСИС Function Name([Arglist]) [As Type] ' VBA Statements [Name - expression] End Function Каждая функция-процедура начинается ключевым словом Function, за которым следует имя функции, Name представляет имя, выбранное для этой функции. При написании имен функций необходимо соблюдать те же правила, что и при написании имен других идентификаторов в VBA: они должны начинаться с буквы, не могут содержать пробелов или каких-либо символов арифметических, логических операторов или операторов отношения и не могут дублировать ключевые слова VBA. После имени функции следует список ее аргументов, который заключается в круглые скобки. Здесь Arglist представляет список аргументов функции и является необязательным. Туре — любой тип возвращаемого значения функции. Если только не определяется иначе, результат, который возвращает функция-процедура, имеет тип Variant. Как вы узнали ранее, значения, сохраняемые или обрабатываемые как тип Variant, занимают больше памяти, чем любой другой тип данных, и на их обработку уходит больше времени. Следует задавать тип данных результата функции по тем же причинам, по каким задается тип переменных и констант: для ускорения выполнения кода, более эффективного использования памяти, получения более легкого и понятного кода и для нахождения ошибок программирования (при этом необходимо хорошо знать правила преобразования типов в VBA). Необязательный элемент синтаксиса Name = expression представляет присваивание функции (function assignment), которое указывает VBA, какое значение должна возвращать функция. Хотя эта часть функции является необязательной, следует всегда включать оператор присваивания в функции-процедуры. Наконец, объявление функции заканчивается ключевыми словами End Function. Создание и использование функций и функций-процедур 179 Даже если функция не имеет аргументов, как VBA-функции Now, Date и Time, в объявлении функции необходимо использовать круглые скобки. Например, можно написать функцию-процедуру, возвращающую имя файла, содержащего текущую рабочую книгу, так, чтобы можно было вставлять имя файла в ячейку рабочего листа. Такой функции не нужны аргументы, ей не требуется никакая внешняя информация для выполнения работы, и она будет иметь подобное объявление: • Function ThisBookName() Обычно функция предназначается для выполнения некоторого вычисления или другого манипулирования определенными данными и для возвращения результата этого манипулирования. Как вы уже знаете, информация встроенным функциям VBA передается заданием значений в списке аргументов функции. При объявлении функции-процедуры необходимо указывать имя каждого аргумента, передаваемого функции; имена аргументов в списке следует отделять друг от друга запятой и писать в соответствии с правилами, применяемыми к любому идентификатору VBA. Имена, предоставляемые пользователем в списке аргументов, подобны переменным: они ссылаются на значение, предоставляемое в то время, когда вызывается функция, независимо от того, вызывается ли функция оператором VBA или host-приложением. Имена аргументов имеют ту же область действия, что и переменные, объявляемые локально в функции-процедуре, то есть недоступны вне функции-процедуры, в списке аргументов которой они объявляются. Вернемся к описанию синтаксиса и к строке, содержащей оператор Name = expression. Эта строка представляет присваивание функции; Name — имя функции, a expression — любое выражение, создающее значение, которое должна возвращать функция. Присваивание функции указывает VBA, какое значение будет возвращать функция. Заметьте, что присваивание функции использует имя функции-процедуры и присваивает ему значение, как если бы это была переменная. Функции-процедуры могут не иметь совсем или иметь один или несколько различных операторов присваивания функции. Первый пример функции, который вы изучите, помогает манипулировать строками. Как вы помните из предыдущей главы, функция Len возвращает длину строки, включая любые начальные или конечные пробелы. Если необходимо определить длину строки, исключая начальные и конечные пробелы, можно использовать вложенные (nested) вызовы функции (один вызов функции внутри другого), подобные следующему: StrLen = Len(Trim(AnyStr)) Этот тип операции хорошо подходит для функции-процедуры. Использовать один вызов пользовательской функции-процедуры проще и легче, чем повторять запись вложенного вызова функции. Листинг 7.1 показывает как раз такую простую функцию-процедуру LenTrim, которая возвращает длину строки, исключая начальные и конечные пробелы. Листинг 7.1. Простая функция-процедура LenTrim 1 Function LenTrim(tStr) ' Определение функции 2 LenTrim = Len(Trim(tStr)) ' Возвращаемое значение 3 End Function В строке 1 содержится объявление функции LenTrim, начинающееся с обязательного ключевого слова Function. После имени функции открываются круглые скобки, что указывает VBA на начало списка аргументов. Далее следует имя аргу 180 Глава 7 мента (tStr). Имя аргумента сообщает VBA, что функции-процедуре при ее вызове должен передаваться один аргумент. Как вы уже, наверное, успели заметить, при нажатии на клавишу Enter после ввода ключевого слова Function, имени функции и списка аргументов Редактор VB автоматически вставляет ключевые слова End Function, как и в случае, когда вы вводите ключевое слово Sub для создания процедуры. Если этого не происходит, возможно, при написании строки-заголовка была допущена ошибка синтаксиса. Строка 2 функции LenTrim — это строка, которая выполняет всю (пока небольшую) работу функции и также содержит аргумент функции для LenTrim. При вычислении выражения Len(Trim(tStr)) VBA принимает строку, полученную посредством аргумента tStr, и передает ее VBA-функции Trim для удаления начальных или конечных пробелов. Результат функции Trim, в свою очередь, используется как аргумент функции Len. Затем VBA присваивает результат функции Len имени функции LenTrim. LenTrim возвращает длину строки аргумента, исключая начальные или конечные пробелы. Наконец, в строке 3 функция заканчивается ключевыми словами End Function. После выполнения этой строки VBA возвращается к оператору процедуры, вызвавшему функцию LenTrim, и вставляет результат функции LenTrim в этот оператор в том месте, где появляется имя функции. Для вызова функции LenTrim используйте оператор, подобный следующему, который отображает результат LenTrim для строки ” Excel 2000 MsgBox LenTrim (" Excel 2000 ") В этом операторе строка аргумента имеет четыре начальных и четыре конечных пробела, и длина строки (как указывает VBA-функция Len) равна 18 символам. Функция LenTrim сообщает длину строки без начальных и конечных пробелов; вышеуказанный оператор отображает число 10. Создание определенных пользователем функций для Excel Функции-процедуры с некоторыми ограничениями на их действия называются определенными пользователем функциями (или сокращенно UDF-user-defined functions), и только их может использовать Excel в формуле ячейки рабочего листа. Все ограничения определенных пользователем функций происходят из одного базового ограничения: UDF не может никаким образом изменять среду Excel. Это означает, что определенная пользователем функция не может выбирать, вставлять, удалять или форматировать никакие данные в рабочем листе, таблице или другом листе. UDF также не может добавлять, удалять или переименовывать листы или рабочие книги, не может изменять экранное представление и так далее. Например, нельзя использовать функцию-процедуру как определенную пользователем функцию в Excel, если она выделяет ячейки или изменяет каким-то образом текущий рабочий лист. Кроме того, UDF не может устанавливать свойства объекта или использовать методы объекта; в большинстве случаев установка свойств объекта или использование его методов приводят к изменениям в среде Excel (объекты, методы и свойства описываются в главе 10). Определенная пользователем функция может осуществлять выборку значений свойств объекта и выполнять любые методы объекта, которые не изменяют среду Excel. Обычно определенная пользователем функция должна только выполнять вычисления или манипулирование на основе данных, полученных из ее списка аргументов или выбранных из Excel. Функцию LenTrim, показанную в листинге 7.1, можно использовать как определенную пользователем функцию, поскольку она отвечает всем требованиям UDF. Следует помнить о том, что ни VBA, ни Excel не отображают сообщение об ошибке, если в качестве UDF используется функция, в которой нарушены правила Создание и использование функций и функций-процедур 181 для определенных пользователем функций. Такая функция просто не может возвращать результат. Например, при попытке вставить значение в рабочий лист Excel, используя функцию-процедуру, нарушающую правила для определенных пользователем функций, ячейка с такой функцией отображает Excel-сообщение об ошибке #VALUE!, обозначающее, что функция или формула для этой ячейки не может возвращать допустимый результат. VBA запрещает присваивание несовместимого типа результату функции в любой функции-процедуре, которая имеет объявленный тип данных для ее результата. Если, например, вы ошибочно написали оператор присваивания функции так, что присваивается, допустим, тип Integer результату функции с объявленным типом String, то VBA отображает ошибку несовпадения типа. В случае присваивания типа данных, который не является тем же, что объявленный возвращаемый тип для функции-процедуры, но является совместимым, то VBA преобразует значение типа, определенного для функции при возврате результата функции. Например, если присваивается тип Double функции, результат которой был объявлен как Long, то VBA не выдает никакой ошибки, а просто преобразует Double в тип Long (при возвращении результата функции). Объявление типа функции имеет еще один результат: если функция-процедура заканчивается без выполнения оператора присваивания функции, VBA возвращает строку нулевой длины для функций типа String и 0 — для функций-процедур, возвращающих численный тип. Нетипизированная функция-процедура, которая заканчивается без выполнения оператора присваивания функции, возвращает результат типа Variant, содержащий специальное значение Empty. Листинг 7.2 показывает функцию LenTrim, модифицированную так, что она всегда возвращает значение типа Long. Листинг 7.2. Задание типа функции LenTrim 1 Function LenTrim(tstr) As Long 2 ' возвращает длину tStr без ведущих и хвостовых пробелов 3 LenTrim = Len(Trim(tstr)) 4 End Function Следует выбирать тип результата функций-процедур, требующий наименьшего объема памяти, но вмещающий полный диапазон возможных значений, которые может возвращать функция. Для функций общего назначения численных или математических наиболее характерным типом для результата функции является Double. Объявление типов данных для аргументов функции Если только не было определено иначе, VBA передает все аргументы в функцию-процедуру как типы Variant. Можно объявлять определенные типы данных для каждого аргумента в списке аргументов. Аргументы с определенными типами используются по тем же знакомым причинам, по каким используются типизированные переменные или результаты функции. Определение типов аргументов для функции-процедуры также помогает пользователю при вызове функции вводить аргументы правильного типа в правильном порядке. Для объявления определенных типов аргументов функции-процедуры, используйте ключевое слово As, за которым следует имя нужного типа данных после имени аргумента в списке аргументов. Листинг 7.3 показывает функцию LenTrim, модифицированную так, чтобы она принимала только данные типа String в аргументе tStr. 182 Глава 7 Листинг 7.3. Определение типа данных аргумента функции LenTrim 1 Function LenTrim(tstr As String) As Long 2 ' возвращает длину tstr без ведущих и хвостовых пробелов 3 LenTrim = Len(Trim(tstr)) 4 End Function За исключением объявления функции-процедуры (в строке 1), листинг 7 3 идентичен листингу 7.2. После того как тип аргумента объявлен, VBA при вызове функции LenTrim допускает в качестве аргумента появление только значений типа String. Вызов LenTrim с каким-либо другим типом (даже Variant) в качестве аргумента вызывает ошибку несовпадения типа (конкретнее, несовпадение типа аргумента — argument type mismatch). Использование функций-процедур в VBA Используйте собственные функции-процедуры в операторах VBA так же, как любые встроенные функции VBA; все правила и условия по использованию встроенных функций применимы к пользовательским функциям-процедурам. Помните, что при вызове функции необходимо включать список аргументов в круглых скобках, если только вы не собираетесь игнорировать результат функции. Как и в случае со встроенными функциями VBA, можно игнорировать результат вашей собственной функции, хотя это редко бывает необходимо. Если нужно использовать именованные аргументы в ваших собственных функциях-процедурах, просто используйте имена из списка аргументов в объявлении функции-процедуры. Например, чтобы использовать именованный аргумент в вызове функции LenTrim (листинг 7.3), применяйте оператор, подобный следующему (AnyStr и MyStnng — строковые переменные): AnyStr = SLen(tstr:=MyString) Если вам трудно запомнить все именованные аргументы для одной из своих функций, убедитесь, что свойство Auto Quick Info (краткие сведения) включено. Если это так, Редактор VB отображает всплывающее окно с перечнем именованных аргументов вашей функции, как для встроенных функций VBA. На рис. 7.1 показано Code Window, в котором зафиксирован процесс ввода кода для вызова функции LenTrim из листинга 7.1; обратите внимание на всплывающее окно, ото- Рис. 7.1 Свойство Auto Quick Info позволяет отображать всплывающее окно, показывающее список аргументов вашей собственной функции, как и для встроенных функций VBA 'Л Micr»s»ff Vjtu«l - Norrn»| - [ModuleJ (Cede)] . fife Edit View Insert Format Cebug Run Xool^ £dd Ins Window Help I (General) pTest-LenTfhn Function LenTrim(tstr As String) As Long Ч"- ИЦ! i д ihv rib i T f / LenTrim = Len(Trim(tstr)) Function End Йй-М а* '> ц Sub End Test_LenTrim {) Dim Inputstring As String Inputstring = InputBox{ Введите строку с пробелами') msgbox lentrimf Sub LenTnm(tSfrArSfr/n^As Long Создание и использование функций и функций-процедур 183 бражающее имя функции, ее именованные аргументы и возвращаемый тип этой функции. Свойство Auto Quick Info можно включать и отключать, выбирая Tools | Options (Сервис | Параметры) для отображения диалогового окна Parameters (Параметры). Щелкните на вкладке Editor (Редактор) для отображения опций Редактора VB и затем установите или отмените установку флажка Auto Quick Info (краткие сведения). Использование инструмента Object Browser для нахождения функций-процедур Если вы не можете вспомнить, в каком модуле сохранили некоторую функцию, можно использовать Object Browser для определения того, какие из ваших функций-процедур доступны в данный момент, и для быстрого отображения исходного VBA-кода вашей функции. Чтобы использовать Object Browser, запустите его, как вы уже научились это делать: выберите команду View | Object Browser (Вид | Просмотр объектов) или щелкните кнопку Object Browser на панели Редактора VB для отображения окна Object Browser. Вы уже знаете, как использовать Object Browser для отображения доступных функций VBA или функций host-приложений. Раскрывающийся список Project/Library (Проект/Библиотека) отображает все открытые в данный момент файлы приложения, как и всегда присутствующую опцию VBA. Для отображения пользовательских функций (и других процедур) в определенном проекте VBA (документе Word, рабочей книге Excel или каком-либо другом документе host-приложения) выполняйте следующие шаги: 1. Выберите наименование проекта в раскрывающемся списке Project/Library. На рис. 7.2 показано окно Object Browser с выбранным в Project/Library-списке элементом Project (в Excel подобный элемент называется VBAProject). Окно Project Explorer указывает имя файла, в котором сохранен проект (в круглых скобках после имени проекта). Рис. 7.2 Используйте Object Browser для нахождения VBA-функций 'Л Microsoft Visual Basic - ChapterOT - [Object Browser] Е~~|В|Я Elfe Edt Ytew Insert Format £>et>ug Bun Tools &dd-lns Window Help - ® X В A • H %i« - ► II X «ff ® Г |proj.ct _d_d dll 1 j»J« Search Results 1 Library | Class 1 Member 1 Classes ° IS'obais* ^iMpduhl ] SI ThlsDocument Members of'Module V E LenTrim ^1 * T»st_L*nTrim I Public Function LenTrlm(fSfr As String) As Long * Member of Ptniert Mi-dule1 Возвращает длину строки без ведущих и хвостовых пробелов v После того как был выбран проект в окне Project/Library, список Classes (Классы) содержит перечень всех модулей и других объектов в выделенном проекте. 2. Выберите модуль в списке Classes. После этого список Members of<class> (Компонент) содержит перечень всех процедур и функций, объявленных в выбранном модуле. 3. Выберите функцию или процедуру, исходный код которой необходимо просмотреть, в списке Members of<class> (Компонент). 184 Глава 7 4. Щелкните на кнопке Show (показать) для отображения исходного кода функции или процедуры. Редактор VB открывает соответствующий модуль и помещает курсор на первую строку после объявления функции или процедуры. Можно также копировать текст из окна Object Browser для своих функций и процедур в буфер Windows (Clipboard) так же, как и в случае со встроенными функциями VBA. Помните, что кнопка Show в окне Object Browser включается, только если исходный код для выбранной функции или другой процедуры доступен. Не пытайтесь использовать диалоговое окно Macros (открываемое с помощью команды Tools | Macros (Сервис | Макрос)) для выполнения функции-процедуры. VBA «ожидает», что функция-процедура предназначена для того, чтобы возвращать значение, поэтому нет смысла только в выполнении функции. По этой причине VBA не перечисляет функции-процедуры в списке Macro Name (Имя макроса) в диалоговом окне Macros. Это демонстрируется на рис. 7.3, где в списке макросов имеется только программа Test_LenTrim. Рис. 7.3 VBA не перечисляет функции-процедуры в списке Имя окна Макрос Имя Макрос ActDocuml AutoExec MAIN AutoExit MAIN MyMacro RunFIneReader MAIN j ВьГ.ОПНИТо ~j Орюдка Изменить ВыделитьТекст Замены НумерацияЗтрок Создать Удалить Срган'Ватор Макросы из | Активных шаблонов Отмена Описание | Макрос создан 01 03 2003 Владимир Ввод описания функции-процедуры с помощью инструмента Object Browser Вернемся к рис. 7.2. В списке Members of<class> (Компонент) выбрана функция LenTrim из листинга 7.3. Заметьте, как и в случае со встроенными функциями VBA и функциями host-приложения, имя функции и ее аргументы отображаются в нижней части окна Object Browser (под списками Classes и Members). Однако в отличие от встроенных функций VBA, никакого описания назначения функции не появляется. Для добавления описания к каждой из ваших функций или процедур можно использовать Object Browser. Описание, вводимое для функции с помощью окна Object Browser, появляется не только в окне Object Browser, но и в Function Wizard (мастере функций) Excel. Обеспечение функции-процедуры описанием помогает другим пользователям использовать вашу функцию в формуле ячейки рабочего листа. Чтобы ввести описание для функции-процедуры, выполните следующие шаги: 1. Выберите функцию-процедуру в окне Object Browser, как было описано ранее. 2. Щелкните правой кнопкой мыши на функции, к которой необходимо добавить описание, и выберите Properties (Свойства) во всплывающем меню. Редактор VB отображает диалоговое окно Member Options (Параметры компонента), показанное на рис. 7.4. Создание и использование функций и функций-процедур 185 3. Введите описание для функции (или процедуры) в текстовое окно Description (Описание). На рис. 7.4 показано описание функции LenTrim, уже введенное в текстовое окно Description. 4. Щелкните на ОК. Вы вновь оказываетесь в окне Object Browser. Рис. 7.4 Вводите полезные описания для функций и процедур в диалоговое окно Member Options Member Options Name LenTrim I I Cescrptton. Cancel । I Возвращает длину строки без ——— ведущих и хвостовых пробелов Help File Help Context ID l° Help j Использование функций пользователя / в рабочих листах Excel Чтобы использовать свои функции (определенные пользователем) в Excel, вводите имя функции и ее аргументы как формулу в ячейку рабочего листа так же, как вы вводите любую встроенную функцию Excel. Если вы не можете запомнить имя определенной пользователем функции или ее аргументы, можно найти эту функцию в списке Function name для категории User-Defined, указанной в списке Function category диалогового окна Paste Function. [Отобразить диалоговое окно Paste Function (Мастер функций) Excel можно, щелкая на кнопке Paste Function (Вставка функции) на панели инструментов или выбирая в меню Insert | Function (Вставка | Функция).] Вставляйте функции VBA из диалогового окна Paste Function, как любые встроенные функции Excel. При необходимости в этом же окне вставляйте и значения для аргументов функции. Если при использовании определенной пользователем функции (UDF) в ячейке рабочего листа отображаемым результатом является значение ошибки #VALUE!, внимательно проверьте код в вашей функции-процедуре, чтобы убедиться, что он не нарушает каких-либо правил для определенных пользователем функций. Ни Excel, ни VBA не препятствуют использованию в ячейке рабочего листа функции-процедуры, которая нарушает UDF-правила. Однако поскольку функция-процедура нарушает UDF-правила, VBA не выполняет эту функцию, а возвращает ячейке значение ошибки #VALUE!. При написании функции-процедуры помните, что особым назначением функции является возвращение какого-либо значения. Пишите простые и значимые функции. Обычно функция должна содержать программный код, необходимый только для выполнения некоторых вычислений или манипулирования данными; функция никогда не должна выполнять действия, не относящиеся непосредственно к созданию ее возвращаемого значения. Пишите функцию всякий раз, когда вам необходимо использовать одну и ту же математическую формулу более двух-трех раз. Как показывают примеры в этой главе, функции-процедуры полезны также при манипулировании и другими данными, а не только числами. Даже если выражение для какого-либо вычисления может быть совсем простым, все же следует писать функцию-процедуру, если вы используете это выражение часто. Таким образом вы устраняете вероятность ошибки при вводе выражения и даете этому выражению значащее имя. Хотя можно игнорировать результаты функций-процедур, следует все же так писать функции-процедуры, чтобы игнорирование их результатов не имело смыс 186 Глава 7 ла. Другими словами, функции не должны выполнять действия, кроме абсолютно необходимых для выдачи нужных возвращаемых результатов. Не считайте VBA-функцию MsgBox примером для написания функций. Функция MsgBox выполняет уникальную задачу в VBA; в результате она делает намного большую работу с большим количеством опций, чем обычно выполняют функции. И, наоборот, считайте VBA-функции StrComp, Mid, функции преобразования данных CStr и CDbl и так далее примером того, как должна действовать функция-процедура. Каждая функция выполняет одну задачу и возвращает один результат без изменения исходных данных, содержащихся в переданных ей аргументах. Не пытайтесь использовать передаваемые по ссылке аргументы для создания функции, возвращающей более одного результата, используя возвращаемое значение функции и один или больше модифицированных аргументов для получения результатов. Функция никогда не должна изменять исходные данные в передаваемых ей аргументах. В главе 9 будет показано, что существуют обоснованные условия, при которых следует модифицировать значения в аргументах, передаваемых по ссылке; при этих условиях необходимо использовать процедуру, а не функцию. Следите за тем, чтобы ваши функции не изменяли передаваемые по ссылке аргументы; используйте ключевое слово ByVai для передачи аргументов по значению. (Подробнее об этом читайте также в главе 9.) Многие ваши программы должны использоваться не только в программах или рабочих листах, для которых вы первоначально написали функцию-процедуру. Функция LenTrim, которая обсуждалась в этой главе, например, является функцией общего назначения и может быть полезной в целом ряде различных выражений в разных процедурах. Поскольку функция-процедура в документе открытого проекта доступна для любого открытого в данный момент документа в одном и том же приложении, можно собрать универсальные функции в один проект. Объединяя функции-процедуры общего назначения в одном проекте, можно создать библиотеку (library) функций. Например, можно поместить все ваши универсальные Excel-функ-ции-процедуры в файл рабочей книги с именем MyFunctions.xls. Другой пример: можно поместить все ваши универсальные Word-функции в документ шаблона с именем MyFunctions.dot и т.д. Следите за тем, чтобы создаваемая вами функция содержала присваивание функции. То есть чтобы функция возвращала результат, отличный от пустого значения по умолчанию типа Variant, строки нулевой длины типа String или нулевого численного значения. Следите за тем, чтобы программный код функции отвечал всем правилам для определенных пользователем функций, описанных в начале этой главы, если вы предполагаете использовать функцию как UDF в Excel. Создание функций для Excel При написании функций-процедур для использования в качестве UDF в рабочих листах Excel необходимо знать несколько фактов, помимо общих требований для определенных пользователем функций: Определенные пользователем функции, которые будут использоваться в Excel, не должны иметь имена, похожие на записи ссылок на ячейку типа А1 или R1C1. Любые строковые (текстовые) данные, возвращаемые из VBA в Excel, не должны иметь более 255 символов в длину. Если UDF возвращает строку, имеющую больше 255 символов в длину, в ячейку рабочего листа, Excel укорачивает строку до максимальной длины 255 символов перед вставкой ее в ячейку. При написании UDF, возвращающей значение даты для Excel убедитесь, что задаете тип результата функции как Date. Excel применяет формат Date для результата функции в ячейке рабочего листа только, если результат имеет VBA-тип Date. Создание и использование функций и функций-процедур 187 Существует еще одно обстоятельство, связанное с тем, в какой момент времени Excel фактически вызывает определенную пользователем функцию для вычисления или повторного вычисления формулы ячейки рабочего листа, частью которой является UDF. По умолчанию Excel вызывает UDF для повторного вычисления формулы ячейки рабочего листа всякий раз при изменении значений, используемых для аргументов функции, во многом так же, как для любой формулы рабочего листа. Однако можно задать UDF так, чтобы Excel повторно вычислял ее при повторном вычислении любой ячейки в рабочем листе. Следует помечать UDF как изменяющуюся (volatile) всякий раз, когда значения ее аргументов не получаются из значений других ячеек рабочего листа. Например, предположим, функция с именем Общая_Стоимость вычисляет стоимость услуг поставщика сети Internet с учетом НДС (налог на добавленную стоимость). UDF может иметь два аргумента: один для определения ячейки рабочего листа, содержащей значение стоимости услуг без учета НДС, а другой — для определения ячейки рабочего листа, содержащей процентную ставку НДС. Поскольку аргументы функции Общая_Стоимость определяют координаты ячейки, изменение содержимого ячейки не меняет значение аргументов функции Общая_Стоимость. При редактировании содержимого ячеек общей стоимости или общей прибыли, Excel не вычисляет повторно функцию Общая_Стоимость, поэтому функция Общая_Стоимость может выдать ошибочные результаты. Если пометить эту UDF как изменяющуюся, она будет всегда отображать правильное значение, потому что Excel будет всегда повторно вычислять ее при каждом изменении любой ячейки в рабочем листе. Определенная пользователем функция, которая перевычисляется при каждом изменении любой ячейки в рабочем листе Excel, называется изменяющейся функцией. Чтобы пометить UDF как изменяющуюся, добавьте следующий оператор к функции сразу за ее объявлением: Application.Volatile Этот VBA-оператор помечает UDF как изменяющуюся функцию, и такая функция на самом деле является особым типом процедуры. Эта процедура называется методом (method), принадлежащим Excel. (Методы подробно описываются в главе 10.) Поскольку метод принадлежит Excel, необходимо при использовании метода Volatile задавать объект Application, точно так же, как необходимо задавать объект Application при использовании функции Excel в операторе VBA. Листинг 7.4 показывает изменяющуюся функцию с именем Общая_Стоимость. Листинг 7.4. Изменяющаяся определенная пользователем функция в Excel 1 Function Общая_Стоимость(Сумма As Currency, _ 2 Ставка_НДС As Single) As Currency 3 Application.Volatile 4 Общая_Стоимость = Сумма * (Ставка_НДС / 100#) + Сумма 5 End Function Функция Общая_Стоимость имеет два обязательных аргумента: Сумма и Ставка_НДС. Один аргумент (Сумма — стоимость услуг без учета НДС) имеет тип Currency, другой (Ставка__НДС процентная ставка НДС) — тип Single, так как представляет обычно число не более 100. Объявление функции заканчивается указанием того, что возвращаемое функцией значение имеет тип Currency, так как возвращает значения, представляющие деньги. Строка 3 содержит оператор Application.Volatile; как и требуется, он является первым оператором в функции после объявления функции. Оператор Application.Volatile «регистрирует» определенную пользователем функцию с помощью Excel так, что Excel вызывает ее для перевычисления формулы ячейки рабочего 188 Глава 7 листа, в которой появляется функция, каждый раз при перевычислении любой ячейки в рабочем листе. Однако не следует злоупотреблять методом Application.Volatile. Если все функции рабочего листа будут изменяющимися, это может привести к ненужным перевычислениям, что увеличивает общее время, необходимое.для перевычисления рабочего листа. В качестве еще одного примера рассмотрим способ представления некоторых данных с использованием функции пользователя. Необходимо решить следующую задачу. У нас имеется таблица с данными о товарах: наименования, цены и т.д. Эта таблица, в частности, может использоваться для формирования так называемых «прайс-листов». Цены на товары меняются так часто, что менеджеры едва успевают менять «ценники» на товары (небольшие листочки с информацией о наименовании и цены товара) (рис. 7.5). Эти «ценники» нам нужно формировать в одном из листов Excel (например, Лист1), поскольку таблицу с товарами из какого-либо источника данных также легко помещать именно в Excel (рис. 7.6). Рис. 7.5 «Ценник» с информацией о товаре наименование и цена (в руб) ЧП «Петров П В » Stellar 7 Цена 32 руб. Рис. 7.6 Таблица с информацией о товарах (код, наименование, цены в $ и руб ) г - -V . - ~ ... . .. UJ Microsoft Excel - CENA . оа И] файл Правка &ид Вставка Формат Сервис Данные Qkho Справка . fl X н 100% - ’’ ArialCyr - 10 F2 ’ f, » ж JK Ч » > » /\ В с D A 1 *457019133044 (3DL) Stellar 7 4 30 32 00 — 2 [046119185028 (3DO) Alone in the Dark 2 2 00 50 00 3 66019084733 (3DO) Bazookatone 2 00 52 00 4 *046119185440 (3DO) Cowboy Casino 2 60 49 00 5 '098019120214 (3DO) CPU Back 2 60 33 00 i 6 *006019111551 (3DO) Cyberdillo 2 00 52 00 7 *417119155215 (3DO) FIFA Soccer'95 2 60 65 00 8 407119115731 (3DO) Fun n Games 2 70 33 00 9 437019112950 (3DO) Micro Cosm 3 50 33 00 10 *26019093837 (3DO) Myst 2 00 65 00 11 *437019113204 (3DO) Night Trap (2cd) 6 80 65 00 . 12 *086019143136 (3DO'i Olimnic Soccer з sn 33 00 'M < ► H \Лист1/Лист2 X ЛистЗ / |<| Г 0Т080 NUM 1 ► г Для решения этой задачи следует к проекту VBAProject( CENA.XLS) добавить модуль и в этом модуле создать две функции, как показано на рис. 7.7. Далее в другом рабочем листе (например, Лист2) необходимо заполнить, например, три ячейки первой строки заголовком ЧП «Петров П.В.» — наименование торгующей организации (рис. 7.5). В ячейки второй строки следует записать формулы =пе\у_пате(Лист1!В1), =пе\у_пате(Лист1!В2) и =пе\у_пате(Лист1!ВЗ), соответственно. В ячейки третьей строки остается поместить формулы =СЕ-ХА(Лист1!П1), =СЕХА(Лист1!П2) и =СЕХА(Лист1!ПЗ), соответственно (считаем, что цены в рублях записаны в колонке D). Сразу же после выполнения этих операций на этом листе должна появиться информация о товарах в том виде, как это показано на рис. 7.8. Создание и использование функций и функций-процедур 189 Рис. 7.7 Функции CENA и new_name в модуле проекта для форматирования данных в виде «ценников» 1 >Р1- V». 1 ЛзХ CENA.XLS - Модуль 1 (Code) СЗ jOj_________________________. - Й VBAProject (СЕ1ЧА XLS) «Microsoft Excel Objects S ThisWorkbook j О Лист! (Лист!) Й) Лист2 (Лист2) ® ЛистЗ (ЛистЗ) Modules <4$ Модуль! * VBAProject (PERSONAL .XLS) |(G«neraO ▼ | jnewjiame ~ Function CENA(А) "Г3 CENA = "Цена " & А & " руб " ~~ ~End Function Function new_name(name) ‘ 3 - Len(RTrim(name)) n3 = InStr (name, ") ") + 2 I new_name = Mid(name, n3, j - n3 + 1) End Function Рис. 7.8 Необходимо заполнить только первые несколько строк с использованием функций CENA и new_name для форматирования данных в виде «ценников» Осталось совсем немного — выделить ячейки A1-D3, поместить курсор мыши в правый нижний угол ячейки D3 (курсор должен принять вид темного крестика), протащить курсор вниз на число ячеек кратное трем и с удовольствием наблюдать на экране довольно легко получившиеся «ценники» (рис. 7.9). Если данные о товарах изменились, следует только исправить их в листе Лист!. Рис. 7.9 Задача форматирования данных в виде «ценников» решена ©Microsoft Excel - CENA С рта IS)*] файл гравка Вид Встдека Формат Сервис Данные Окно У В <* 60% ’ ” AnalCyr * 10 т ж А ч А1 ’г f„ ЧП «Петров П В » ^правка Ж 5® -J _ в X А ' 8 с 1 2 3 Л. в 7 е 9 ЧП .Петро» П В » Stellar? Цена 32 руб. ЧП «Петро» П В » Alone in the Dark 2 Цена 50 руб. ЧП «Петро» П В • Bazookatone Цена 52 руб. ЧП «Петро» П В * Cowboy Casino Цена 49 руб. ЧП «Петро» П В » CPU Back Цена 33 руб. ЧП «Петро» ПВ» Cyberdillo Цена 52 руб. ЧП «Петро» П 6 • FIFA 5оссеГ95 Цена 65 руб. ЧП «Петро» П В » Fun n Games Цена 33 руб. ЧП «Петро» П В • Micro Cosm Цена 33 руб. н < ► и\ Лист! \Лист2/ ЛистЗ / |« »|[ Готово Глава 8 Изменение порядка выполнения операторов в VBA До сих пор вы писали процедуры и функции, которые VBA выполняет только в линейном порядке. Во многом так же VBA выполняет записанный рекордером макрос: VBA начинает выполнение кода с первого оператора после строки объявления процедуры или функции и продолжает выполнять каждый оператор построчно до тех пор, пока не будет достигнут оператор End Sub или End Function, отмечающий конец определения этой процедуры или функции, или до тех пор, пока не возникнет runtime-ошибка (на это, очевидно, полагаться не стоит). Подобные процедуры и функции, хотя и способны выполнять очень сложные задачи, не могут менять порядок выполнения операторов-инструкций при определенных обстоятельствах. На самом деле очень часто встречаются такие ситуации, когда необходимо, чтобы процедуры или функции выполняли различные действия при разных условиях. Например, если вы пишите процедуру, которая получает имя рабочей книги от пользователя, а затем открывает эту рабочую книгу, может понадобиться, чтобы ваша процедура имела возможность создать рабочую книгу, если книга еще не существует. В подобной ситуации необходимо, чтобы процедура выполняла те или иные операторы, предоставляя пользователю возможность создать рабочую книгу. Команды, изменяющие порядок выполнения операторов, часто используют оценку конкретных элементов данных для выбора различных предопределенных действий. Например, можно написать процедуру, проверяющую, все ли числа столбца в рабочем листе находятся в диапазоне от 1 до 10. Эта процедура может проверять каждый элемент ввода в столбце отдельно и выполнять некоторый набор операторов, когда встречается элемент ввода вне указанного диапазона. Изменение порядка выполнения операторов не всегда связано с реакцией на возникающие в процессе работы программы проблемы. Если вам необходимо, чтобы пользователь процедуры делал некоторый выбор по поводу последующего действия процедуры, можно использовать функцию InputBox для получения текстового ввода от пользователя или использовать функцию MsgBox, давая возможность пользователю делать выбор щелчком на командной кнопке в окне сообщения. После получения пользовательского выбора процедура должна выполнить действие, соответствующее этому выбору. Конечно, процедуры не могут на самом деле «принимать решения» так же, как это делает человек. Однако процедуры «могут выбирать» предопределенные действия на основе простых условий и «принимать» относительно сложные решения, объединяя более простые решения. При использовании VBA-операторов изменения порядка выполнения операторов определяется условие или набор условий, при которых VBA выполняет ту или иную ветвь (branch) кода процедуры. Поскольку такие операторы влияют на последовательность выполнения программы, их часто называют операторами управления потоком (flow control) или операторами управления программой (program control), но на практике они более известны как операторы условного и безусловного перехода (conditional и unconditional branching). Оператор условного перехода — это структура, которая выбирает ту или иную ветвь кода процедуры на основе некоторого предопределенного условия или группы условий. Оператор безусловного перехода — это оператор, просто изменяющий по- Изменение порядка выполнения операторов в VBA 191 следовательность выполнения кода процедуры независимо ни от какого конкретного условия. Условный переход используется гораздо чаще, чем безусловный. При выполнении оператора условного перехода, такого как If...Then, VBA сначала оценивает указанное условие. Если условие равно True, VBA выполняет заданную группу операторов. Чтобы определить условие для оператора условного перехода, используется логическое выражение. При выполнении оператора безусловного перехода (GoTo) VBA немедленно начинает выполнение операторов, указанных командой перехода. Критерии, на основе которых VBA «принимает решение» в операторах условного перехода, определяются путем создания логического выражения, описывающего условие, при котором необходимо выполнение или невыполнение определенной серии операторов. Для создания логических выражений в операторах перехода используются различные операторы сравнения и логические операторы VBA (которые были описаны в главе 5). Простой выбор Простейшими VBA-операторами изменения порядка выполнения кода являются операторы If...Then и If...Then...Else. Оператор If...Then позволяет VBA выбрать единственную альтернативную ветвь выполнения процедуры. Связанный с ним оператор If...Then...Else дает возможность VBA выбирать из двух альтернативных ветвей кода процедуры на основе оценки того, является ли указанное условие равным True. Оператор If...Then позволяет выбрать единственную альтернативную ветвь кода в процедуре или функции. Оператор If...Then имеет две различные формы синтаксиса. Простая форма — это однострочный оператор If...Then: СИНТАКСИС If Condition Then Statements Condition — любое логическое выражение, a Statements — один, несколько или ни одного оператора VBA; все операторы должны помещаться в одной и той же строке. При выполнении подобного оператора VBA сначала оценивает логическое выражение, представленное с помощью Condition-, если это логическое выражение равно True, то выполняется оператор (или операторы) после ключевого слова Then до конца строки. Затем VBA возобновляет выполнение кода с первого оператора после строки, содержащей оператор If...Then. Если логическое выражение, представленное с помощью Condition, равно False, то выполняется первый оператор в строке после строки, содержащей оператор If...Then, без выполнения альтернативной ветви. Следующий фрагмент процедуры показывает типичный однострочный оператор If...Then If temperature > 100 Then MsgBox "Слишком горячо!" Можно включать несколько операторов VBA в одну строку, отделяя каждый из них двоеточием (:), как показано в следующем примере: Statementl : Statement2 : StatementN В этой строке Statementl, Statement2 и StatementN каждый представляет один допустимый оператор VBA. Можно включать столько операторов в одну строку, сколько необходимо до максимальной длины строки для модуля. Однако строки со многими операторами трудно читать и понимать. Обычно следует помещать только один оператор в каждую строку. 192 Глава 8 В листинге 8.1 приведен код функции, которая принимает от пользователя новое наименование книги в виде строки и, если строка пустая (не содержит символов, кроме пробелов), выдает сообщение об этом. Листинг 8.1. Функция GetBookName 1 Function GetBookName() As String 2 Dim ITitle As String, IPrmpt As String, IDflt As String 3 4 ITitle = "Ввод наименования книги" 5 IPrmpt = "Введите наименование новой книги" 6 IDflt = "Книга1" 7 - 8 ' использование InputBox для получения имени файла. 9 GetBookName - Trim(InputBox(prompt:=lPrmpt, _ 10 Title:=lTitle, 11 Default:=lDfIt)) 12 13 ' проверить наличие строки ввода 14 If Len(GetBookName) = 0 Then _ 15 MsgBox "Наименование не введено!" 16 17 End Function ' GetBookName Операция получения наименования функции (строка 9) совмещена с удалени-' ем ненужных пробелов посредством функции Trim. Обратите внимание на строку 15, которая содержит однострочный оператор If...Then (символ перехода на новую строку не является причиной считать оператор неоднострочным: это — только возможность написания более длинного оператора, чем позволяет размер страницы). При выполнении строки 15 VBA сначала оценивает условное выражение Len(GetBookName) = О, которое возвращает значение True, если пользователь ввел строку, состоящую только из пробелов (здесь была использована ранее обсуждавшаяся функция LenTrim). В этом случае выполняется оператор: MsgBox "Наименование не введено!" Если выражение Len(GetBookName) = О возвращает False, то VBA не выполняет оператор после ключевого слова Then. Видимо, сейчас вам уже не трудно будет написать процедуру тестирования функции, поэтому мы не будем на этом останавливаться, а сразу перейдем к «критике» функции. Недостатком этой функции является то, что в случае ввода в диалоговом окне функции InputBox одних пробелов мы только получим об этом сообщение, а функция GetBookName возвратит нам пустую строку. Если мы только тестируем эту функцию, ничего плохого в этом случае не произойдет. А что, если нам нужно создать с полученным наименованием какой-либо объект: книгу, лист, файл? На этот случай необходимо всегда формировать какое-то запасное (по умолчанию) имя. На самом деле в этом и заключается смысл создания оболочки вокруг функции InputBox. Если бы все пользователи были «правильными», можно было бы всегда обходиться функцией InputBox, поскольку «правильные» пользователи никогда не догадались бы в качестве имени новой книги ввести пробелы. Итак, нам нужно, чтобы функция ввода наименования книги всегда возвращала непустую строку, даже если пользователь решил пошутить и сломать вашу программу. Для этого необходимо, кроме сообщения о том, что шутка оценена, присвоить возвращаемому значению функции имя по умолчанию, например, то, которое было ранее предложено пользователю, но отвергнуто им. Для этого рассмотрим следующую форму оператора If...Then. Изменение порядка выполнения операторов в VBA 193 Вторая форма синтаксиса оператора If...Then называется блоком (block) оператора If. В блоке оператора If...Then условие и операторы записываются в отдельных строках, как показано в следующей синтаксической форме: СИНТАКСИС If Condition Then Statements „ End If Здесь Condition, как и в однострочном операторе If...Then, представляет логическое выражение, определяющее условие, при котором VBA следует выполнить альтернативные операторы. Statements — это один, несколько или ни одного оператора VBA; операторы могут находиться в одной или нескольких строках. Наконец, ключевые слова End If указывают VBA, что достигнут конец альтернативной ветви операторов. Ключевые слова End If должны появляться в отдельной строке, хотя в эту строку можно включать конечный комментарий (см. следующую ниже диаграмму). Как и в случае с однострочным оператором If...Then, VBA сначала оценивает логическое выражение, представленное с помощью Condition. Если это выражение равно True, VBA выполняет операторы в альтернативной ветви, начиная с первого оператора в строке, после строки, содержащей ключевые слова If...Then. VBA продолжает выполнение операторов в альтернативной ветви до тех пор, пока не достигнет ключевых слов End If. Затем продолжается выполнение операторов, начиная с первого оператора после End If. Изменим код функции GetBookName, как показано в листинге 8.2. Листинг 8.2. Функция GetBookNameZ 1 Function GetBookName2() As String 2 Dim llitle As String, IPrmpt As String, lDflt As String 3 4 llitle = "Ввод наименования книги" 5 IPrmpt = "Введите наименование новой книги" 6 lDflt = "Книга1" 7 8 ' использование InputBox для получения имени файла. 9 GetBookName2 = Trim(InputBox(prompt:=lPrmpt, _ 10 Title:=lTitle, _ 11 . Default:=lDfIt)) 12 13 ' проверить наличие строки ввода 14 If Len(GetBookName2) = 0 Then 15 MsgBox "Наименование не введено!" 16 GetBookName2 = lDflt ' имя по умолчанию 17 End If 7 Программирование на VBA 2002 194 Глава 8 18 19 End Function ' GetBookName 20 ' 21 Sub test_GetBookName2() 22 ' Тестирование функции GetBookName2 23 NewBookName = GetBookName2() 24 MsgBox NewBookName 25 End Sub , Листинг 8.2 содержит код уже обсужденной функции GetBookName2, которая никогда не возвращает пустую строку, и тестирующей процедуры, использующей MsgBox для отображения результата вызова GetBookName2. В некоторых случаях при вводе наименования нового файла (книги) удобнее задавать конкретное имя по умолчанию, которое зависит от каких-либо дополнительных условий. Это требует ввода имени по умолчанию в качестве аргумента функции. Но, с другой стороны, хотелось бы оставить возможность использовать функцию ввода без аргументов. Поэтому прежде, чем рассматривать далее более сложные конструкции операторов управления последовательностью выполнения кода, обсудим такую возможность VBA, как необязательные аргументы функции. Использование необязательных аргументов Обычно аргументы, которые приводятся в списке аргументов функции-процедуры, должны предоставляться каждый раз, когда вызывается функция; эти аргументы являются обязательными {required). Вы уже знаете о необязательных аргументах функции по работе с VBA-функциями InputBox и MsgBox. Но, что самое замечательное, вы также можете использовать необязательные аргументы для ваших собственных функций-процедур. При включении необязательных аргументов в список аргументов необходимо перечислять сначала все обязательные аргументы; после первого необязательного аргумента все последующие аргументы в этом списке должны быть также необязательными. Можно даже определять тип данных и значение по умолчанию для необязательных аргументов функции. Для создания необязательного аргумента вставьте VBA-ключевое слово Optional перед именем этого аргумента в списке аргументов при объявлении функции-процедуры. Листинг 8.3 содержит очередную версию функции GetBookName, которая позволяет указать в качестве необязательного аргумента имя новой книги. С помощью встроенной функции IsMissing в коде определяется факт использования необязательного аргумента при вызове функции GetBookName. Если аргумент не был введен, функция использует свою внутреннюю строковую константу в качестве наименования книги. Листинг 8.3. Функция GetBookName3 1 Function GetBookName3(Optional IDflt) As String 2 Dim ITitle As String, IPrmpt As String 3 4 ITitle = "Ввод наименования книги" 5 IPrmpt = "Введите наименование новой книги" 6 7 1 11 включен ли IDflt в список аргументов 8 If IsMissing(IDflt) Then IDflt - "Книга1" 9 10 ' использование InputBox для получения имени файла. 11 GetBookName3 = Trim(InputBox(prompt:=lPrmpt, __ 12 Title:=lTitle, 13 Default:=lDfIt)) Изменение порядка выполнения операторов в VBA 195 14 15 ' проверить наличие строки ввода 16 If Len(GetBookName3) = 0 Then 17 MsgBox "Наименование не введено!" 18 GetBookName3 - IDflt 1 имя по умолчанию 19 End If 20 21 End Function ',GetBookName 22 23 24 Sub test_GetBookName3() 25 ' Тестирование функции GetBookName2 26 27 ' вызов функции без параметра 28 NewBookName = GetBookName3() 29 MsgBox "Наименование новой книги: " & NewBookName 30 31 ' вызов функции с параметром 32 NewBookName = GetBookName3(IDfIt:="Книга20") 33 MsgBox "Наименование новой книги: " & NewBookName 34 End Sub Продолжим рассмотрение операторов, позволяющих изменять последовательность выполнения кода процедуры или функции. Выбор ветви с помощью lf...Then...Else Оператор If...Then дает возможность задавать одну альтернативную ветвь операторов в процедуре. Однако часто бывает необходимо выбрать одну из двух различных ветвей операторов в зависимости от определенного условия. Для этого VBA предоставляет операторы If...Then...Else и If...Then...ElseIf. Как и If...Then, VBA-оператор If...Then...Else имеет две формы: однострочную и блочную. Синтаксис однострочного оператора If...Then...Else следующий: СИНТАКСИС If Condition Then Statements Else ElseStatements Condition — любое допустимое логическое выражение. Statements — один или несколько операторов VBA. Как и в однострочном операторе If...Then, все операторы и ключевые слова однострочного If...Then...Else должны находиться в одной и той же строке. При выполнении однострочного оператора If...Then...Else VBA сначала оценивает логическое выражение, представленное с помощью Condition; если это выражение равно True, VBA выполняет операторы (представленные с помощью Statements) между ключевыми словами Then и Else и возобновляет выполнение кода с первого оператора после строки, которая содержит If...Then...Else. Если логическое выражение, представленное с помощью Condition, равно False, VBA выполняет операторы после ключевого слова Else до конца строки (представленные с помощью ElseStatements) и продолжает выполнение кода с первого оператора после строки, содержащей If...Then...Else. В следующей строке показан типичный пример однострочного оператора If...Then...Else: If Вес > 100 Then MsgBox "Тяжело!" Else MsgBox "He так тяжело!" В этом примере, если значение переменной Вес больше 100, то условное выражение равно True и VBA выполняет оператор MsgBox для отображения сообщения [ "Тяжело!". Если переменная Вес содержит число, равное или меньшее 100, то рас 7* 196 Глава S сматриваемое условие равно False и VBA выполняет оператор MsgBox после ключевого слова Else для отображения сообщения "Не так тяжело!”. Как видно из примера однострочного оператора If...Then...Else, однострочную форму не всегда просто читать. Кроме того, поскольку все элементы однострочного оператора If...Then...Else должны находиться в одной и той же строке, размер и количество операторов, которые можно включать в альтернативные ветви выполнения, ограничиваются имеющимся в строке местом. Блок операторов If...Then...Else легче читать и понимать и, поскольку можно располагать операторы в разных строках внутри блока оператора If...Then...Else, он не имеет ограничения по размеру и числу операторов, которые можно помещать в альтернативные ветви. Блок оператора If...Then...Else имеет следующий синтаксис: СИНТАКСИС If Condition Then Statements , Else ElseStatements End If Condition — любое допустимое логическое выражение; Statements и ElseStatements представляют один, несколько или ни одного оператора VBA. При выполнении блока оператора If...Then...Else VBA сначала оценивает логическое выражение, представленное с помощью Condition. Если это выражение равно True, то VBA выполняет все операторы (представленные с помощью Statements) между ключевым словом Then и ключевым словом Else. Затем VBA возобновляет выполнение кода с первого оператора, появляющегося после ключевых слов End If, которые указывают на конец блока оператора If...Then...Else. Если логическое выражение, представленное с помощью Condition, равно False, VBA выполняет все операторы (представленные с помощью Els'eState-ments) между ключевым словом Else и ключевыми словами End If. Затем VBA продолжает выполнение кода с первого оператора, появляющегося после ключевых слов End If. Как и в блоке оператора If...Then, ключевые слова End If должны помещаться в отдельной строке, хотя в эту строку можно добавлять конечный комментарий (см. следующую наже диаграмму). Оператор If...Then...Else выбирает одну или другую ветвь, но никогда не выбирает обе ветви одновременно. В следующем примере (листинг 8.4) показан типичный блок оператора If...Then...Else: Листинг 8.4. функция GetBookName4 1 Function GetBookName4(Optional lDflt) As String 2 Dim llitle As String, IPrmpt As String, IVar As String 3 Изменение порядка выполнения операторов в VBA 197 4 ITitle = "Ввод наименования книги" 5 IPrmpt = "Введите наименование новой книги" 6 7 1 включен ли IDflt в список аргументов 8 If IsMissing(IDflt) Then IDflt = "Книга1" 9 10 ' использование InputBox для получения имени файла. 11 IVar = Trim(InpufeBox(prompt:=lPrmpt, _ 12 Title:=lTitle, 13 Default:=lDfIt)) 14 15 ' проверить наличие строки ввода 16 If Len(lVar) = 0 Then 17 MsgBox "Наименование не введено!" 18 GetBookName4 = IDflt ' имя по умолчанию 19 Else 20 GetBookName4 = IVar 21 End If 22 23 End Function ' GetBookName Никаких преимуществ у этого кода по сравнению с кодом листинга 8.3 нет, но здесь был использован оператор If...Then...Else и строки 16-21 представляют собой более понятный код. Этот пример содержит тот же оператор, приводимый для однострочного If...Then...Else, но теперь использует форму блока. Сложный выбор Вы узнали, как создавать операторы перехода, выбирающие одну или одну из двух альтернативных ветвей кода процедуры. Однако часто бывает необходимо выполнить более сложный выбор в процедурах, выбирая между тремя, четырьмя и более ветвями. Вложенные операторы lf...Then При необходимости принятия более сложных решений можно помещать оператор If...Then или If...Then...Else внутрь другого оператора If...Then или If...Then... Else, что называется вложением операторов (nesting). (Вложение означает помещение одного типа структуры управления выполнением кода внутрь другой.) (См. следующую ниже диаграмму.) 198 Глава 8 Хотя можно вкладывать и однострочные формы операторов If...Then и If... Then...Else, такие операторы трудно понимать. При вложении If ...Then и If...Then... Else используйте для ясности блочную форму этих операторов. Листинг 8.5 показывает простую процедуру для иллюстрации того, как работают вложенные операторы If...Then...Else. Процедура EvalDiscount получает от пользователя количество покупемого клиентом товара (числовое значение), а затем оценивает это число и определяет скидку, на которую может рассчитывать клиент. Листинг 8.5. Вложенные операторы lf...Then...Else 1 Sub EvalDiscount() 2 ' Определение скидки (в %) в зависимости от 3 1 количества продаваемого товара . < 4 Dim IStr As String 5 , Dim IntNum 6 IntNum = Application.InputBox( _ 7 prompt:=”Введите количество товара", _ 8 Title:="Процедура EvalDiscount”, _ 9 Type:=l) 10 If Not (TypeName(IntNum) = "Boolean") Then 11 12 If IntNum > 1000 Then 13 IStr = "10" 14 Else 15 If IntNum > 500 Then 16 IStr = "6" - .17 Else 18 IStr = "0" 19 ' End If 20 End If ' 21 MsgBox "Скидка " & IStr & "%" 22 Else 23 MsgBox "Количество не указано" 24 End If 25 26 End Sub Написанная так процедура будет работать только в Excel, так как она использует метод Application.InputBox. Этот метод применен для того, чтобы не дать пользователю во время работы функции InputBox ввести что-либо, кроме числа. VBA отображает сообщение об ошибке, если пользователь вводит не число (рис. 8.1), и ожидает до тех пор, пока пользователь не введет численное значение или не выберет кнопку Cancel. Если пользователь, не вводя данные в окне функции Application.InputBox, щелкнет на кнопке OK, VBA также выдаст сообщение об ошибке (рис. 8.2). Рис. 8.1 Сообщение Excel при неправильном вводе в окне функции Application.InputBox (при работе с Office Assistant) Microsoft Excel Неверное число Обратите внимание на степень защищенности программы листинга 8.5 от неправильных действий пользователя. Во-первых, функция Application.InputBox не дает возможности ввести в окно ввода нечисловое значение. Во-вторых, если поль- Изменение порядка выполнения операторов в VBA 199 Рис. 8.2 Сообщение Excel при щелчке на кнопке ОК без ввода данных в окне функции Application.lnputBox (при работе с Office Assistant) Microsoft Excel Ошибка в формуле. • Для получения дополнительных сведений нажмите кнопку "Справка". • Чтобы получить помощь по использованию функции, выберите команду "Функция" (меню "Вставка"). • Старайтесь не использовать вне формул знак равенства (=) и минус (-) или ставьте перед ними одиночную кавычку (1). е Справка ;ок' зователь использует «спасительную» кнопку Cancel, чтобы отказаться от ввода, программа (в строке 10) проверит результат ввода, который при щелчке на кнопке Cancel имеет тип Boolean, и выберет необходимую ветвь оператора If...Then...Else. При щелчке на кнопке Cancel выполнится оператор в строке 23 и на экран будет выдано сообщение о том, что количество товара не указано. Использование lf...Then...Elself VBA предоставляет сокращенную версию оператора If...Then...Else, являющуюся сжатым эквивалентом вложенных операторов If...Then...Else, показанных в листинге 8.5. Такой краткой формой является оператор If...Then...ElseIf. Оператор If...Then...ElseIf имеет следующий синтаксис: СИНТАКСИС .... If Conditionl Then Statements Elself Condition2 El selfStatements [Else ElseStatements] End I f Conditionl и Condi.ti.on2 — любые логические выражения; Statements, ElselfS-tatements и ElseStatements — один, несколько или ни одного оператора VBA. При выполнении оператора If...Then...ElseIf VBA сначала оценивает логическое выражение, представленное с помощью Conditionl. Если это выражение равно True, то VBA выполняет все операторы (представленные с помощью Statements) между ключевыми словами Then и Elself. Затем VBA возобновляет выполнение кода с первого оператора после ключевых слов End If, которые указывают на конец оператора If...Then...ElseIf. Если логическое выражение Conditionl равно False, VBA оценивает логическое выражение, представленное с помощью Condition2. Если выражение Соп-dition2 равно True, VBA выполняет все операторы (представленные с помощью ElselfStatements) между ключевым словом Elself и ключевыми словами End If (или необязательным Else). Затем VBA продолжает выполнение кода с первого оператора, появляющегося после ключевых слов Endlf. Ключевые слова End If должны находиться на отдельной строке. 200 Глава 8 Если логическое выражение Conditions равно False, то VBA пропускает Elself-Statements и продолжает выполнение кода с первого оператора после ключевых слов End If. Можно по желанию включать оператор Else в оператор If...Then...ElseIf. Если логическое выражение Condition! и логическое выражение Conditions равны False и имеется оператор Else, то VBA выполняет операторы, представленные с помощью ElseStatements. После выполнения операторов ElseStatements VBA продолжает выполнение кода с первого оператора после ключевых слов End If (см. следующую наже диаграмму). В следующем листинге (8.6) показано, как с учетом вышеизложенного можно изменить строки 12-20 листинга 8.5. Листинг 8.6. Использование lf...Then...Elself 1 Sub EvalDiscount2() 2 ' Определение скидки (в %) в зависимости от 3 ' количества продаваемого товара 4 Dim IStr As String 5 Dim IntNum 6 IntNum = Application.InputBox( _ 7 prompt: ="Введите количество товара", »_ 8 Title:="Процедура EvalDiscount2", _ 9 Type:=l) 10 If Not (TypeName(IntNum) = "Boolean") Then 11 12 If IntNum > 1000 Then 13 IStr = "10" 14 Elself IntNum > 500 Then 15 IStr = "5" Изменение порядка выполнения операторов в VBA 201 16 Else 17 IStr = "О" 18 End If 19 MsgBox "Скидка " & IStr & "%" 20 Else 21 MsgBox "Количество не указано" 22 End If 23 24 End Sub Этот оператор If...Then...ElseIf действует точно так же, как вложенный оператор If...Then...Else в строках 12-20 листинга 8.5, и с теми же результатами, только эта форма более компактна. При желании можно включать более одного предложения Elself в оператор If...Then...ElseIf; все предложения Elself следуют перед Else. VBA выполняет операторы в предложении Elself, если только логическое выражение в Elself равно True. Использование оператора If...Then...ElseIf является вопросом профессионального предпочтения. Многие программисты считают, что их код более понятен и удобен при использовании вложенных операторов If...Then...Else и избегают использования оператора If...Then...ElseIf. Первоначально оператор If...Then...ElseIf был добавлен в BASIC для обеспечения возможностей, которые обеспечиваются оператором Select...Case (описывается в следующем разделе); он остается в VBA для легкой трансляции существующих программ с BASIC на VBA. При выполнении выбора из нескольких вариантов оператор Select...Case превосходит вложенный оператор If...Then...Else или еще более компактный оператор If...Then...ElseIf. Оператор Select...Case Примеры использования вложенных операторов If...Then...Else и If...Then... Elself показывают, что эти операторы позволяют выбирать из трех ветвей кода, но что если необходимо выбрать между 5, 8 или 10 различными возможными действиями? Для выполнения выбора из нескольких возможных ветвей кода можно вкладывать операторы If...Then...Else на много уровней вглубь, но уследить за ходом выполнения ветвей становится прогрессирующе труднее. Альтернативно, можно было бы добавить дополнительные операторы Elself в оператор If...Then...ElseIf с оператором Elself для каждой условной ветви. Оператор If...Then...ElseIf имеет подобную проблему: когда имеется много операторов Elself, оператор If...Then... Elself становится трудно читать и сопровождать. К «счастью», VBA имеет условный оператор перехода для использования в случаях, когда необходимо выбирать из большого количества различных ветвей кода: оператор Select Case. Он работает во многом так же, как множество независимых операторов If, но он более понятен для того, кто пишет код, и того, кто читает этот код. Ключевые слова Select Case используются со многими операторами Case, где каждый оператор Case проверяет появление другого условия и выполняется только одна из ветвей Case. Ветвь Case может содержать один, несколько или ни одного оператора VBA. Оператор Select Case имеет следующий синтаксис: СИНТАКСИС Select Case TestExpression Case ExpressionListl statements! Case ExpressionList2 statements2 Case ExpressionListN 202 Глава 8 statementsN [Case Else ElseStatements] End Select TestExpression — любое численное или строковое выражение. ExpressionListl, ExpressionList2 и ExpressionListN — (каждый) представляют список логических выражений, отделенных запятыми. Statements!, • statements2, statementsN и ElseStatements (каждый) представляют один, несколько или ни одного оператора VBA. В Select Case можно включать столько операторов Case ExpressionList, сколько необходимо (см. следующую наже диаграмму). При выполнении VBA-оператора Select Case сначала оценивается TestExpression, а затем сравнивается результат этого выражения с каждым выражением, перечисленным в каждом ExpressionList. Если значение, представленное с помощью TestExpression совпадает с выражением в ExpressionList для одного из Case, VBA выполняет операторы для этого предложения Case. Если значение TestExpression совпадает более, чем с одним оператором Case, VBA выполняет только операторы в первом совпадающем предложении Case. Часто TestExpression — это просто имя одной переменной, математическое или численное, а не логическое выражение. Выражения в ExpressionList — это обычно логические выражения. После завершения выполнения операторов в первом совпадающем операторе Case VBA продолжает выполнение кода с первого оператора после ключевых слов End Select, которые обозначают конец Select Case. Если значение TestExpression не совпадает ни с каким из Case, а необязательный Case Else присутствует, VBA выполняет операторы, представленные с помощью ElseStatements перед переходом к оператору после Select Case. Изменение порядка выполнения операторов в VBA 203 В отдельных операторах Case выражение ExpressionList может состоять из одного или более выражений, отделяемых запятой. Список ExpressionList имеет следующий синтаксис: СИНТАКСИС expression!, expression2, expressionN Выражения в ExpressionList могут быть любыми численными, строковыми или логическими выражениями. Выражение в ExpressionList может также определять диапазон значений при использовании оператора То: expression! То expression2 Например, для определения диапазона чисел от 10 до 150 в операторе Case ExpressionList используется следующее выражение: Case 10 То 150 Для выбора ветвей на основе сравнения, является ли TestExpression больше, меньше или равным какому-либо значению, или на основе какого-либо другого реляционного сравнения, используйте следующий синтаксис: СИНТАКСИС Is Comparisonoperator expression В этой строке ComparisonOperator — это любые VBA-операторы отношения, кроме операторов Is и Like; expression — любое выражение VBA. Для выполнения операторов в ветви Case, когда, например, TestExpression больше 10, используется следующее выражение: Case Is > 10 Ключевое слово Is здесь — это не то же самое, что оператор Is. В этом операторе Is означает ссылку на TestExpression. Листинг 8.7 представляет пример оператора Select Case. Листинг 8.7. Оператор Select Case 1 Sub EvalDiscount3() 2 ' Определение скидки (в %) в зависимости от 3 ’ количества продаваемого товара 4 Dim IStr As String 5 Dim IntNum 6 IntNum = Application.InputBox( 7 promptВведите количество товара", 8 Title:="Процедура EvalDiscount3", 9 Type:=l) 10 If Not (TypeName(VarWeight) = "Boolean") Then 11 Select Case IntNum 12 Case Is > 1000 13 IStr = "10" 14 Case Is > 500 15 IStr = "5 " 16 Case Else 17 IStr = "0 " 18 End Select 19 MsgBox "Скидка " & IStr & "%" 20 Else 21 MsgBox "Количество не указано" 22 End If 23 End Sub 204 Глава 3 Обратите внимание на строки 11-18. После рассмотрения двух предыдущих примеров эти строки не могут не вызвать вздох облегчения. Эта конструкция хороша и простотой для понимания, и легкостью при наращивании новых условий. В остальном код этого примера переписан из предыдущих листингов. Безусловный переход Оператор безусловного перехода, пожалуй, самый спорный оператор во всех языках программирования. В ранних языках он являлся почти единственным средством организации циклических выполнений блоков кода. Сторонники структурного программирования посвящают много времени критике программ и языков программирования, в которых используется этот оператор. Поэтому не очень увлекайтесь применением этого оператора в своем коде и старайтесь вспоминать о нем только в чрезвычайных ситуациях, когда все другие средства уже испробованы и не помогли. Оператор безусловного перехода всегда изменяет порядок выполнения операторов в процедуре или функции VBA. При этом VBA не проверяет никаких условий (отсюда термин безусловный (unconditional)), а просто переходит к выполнению кода с другого места. VBA имеет только один оператор безусловного перехода: GoTo. Существует очень мало причин для использования оператора GoTo; в действительности процедуры, которые используют несколько операторов GoTo, трудны для понимания. Почти в каждом случае, когда вы можете использовать оператор GoTo, можно использовать один из операторов If, оператор Select Case или одну из структур организации циклов, о которых вы узнаете в главе 11, для выполнения той же задачи с большей легкостью и ясностью. Оператор GoTo остался от ранних версий языка программирования BASIC, которые не имели сложного оператора принятия решений Select Case, описанного в этой главе, или мощных структур организации циклов. Программисты, работавшие с ранними версиями BASIC, использовали GoTo для имитации результатов более сложных операторов VBA. Следует знать, как оператор GoTo работает в качестве оператора безусловного перехода, главным образом для того, чтобы понимать, как действует обработчик ошибок GoTo, но также потому что вам может встретиться эта команда, используемая другими программистами. Оператор GoTo имеет следующий синтаксис: СИНТАКСИС GoTo line Выражение line представляет любую допустимую метку или номер строки в той же процедуре или функции, которая содержит оператор GoTo. При выполнении оператора GoTo VBA немедленно переходит к выполнению оператора в строке, определенной с помощью line. Метка строки (line label) — это особый тип идентификатора, который задает определенную строку по имени. Метки строк имеют следующий синтаксис: СИНТАКСИС Name: Выражение пате — любой допустимый идентификатор VBA. Метка строки может начинаться в любом столбце в строке, если она является первым непустым символом в строке. Номер строки (line number) — в основном, то же самое, что и метка строки, но он является просто номером, а не идентификато Изменение порядка выполнения операторов в VBA 205 ром. Использование номеров строк в процедурах VBA является крайне нежелательным, следует всегда использовать метку строки вместо них. В листинге 8.8 показана процедура, демонстрирующая наиболее обоснованное использование оператора GoTo в процедуре VBA: эта процедура использует оператор GoTo для перехода к концу процедуры при выборе пользователем командной кнопки Отмена (Cancel) в окне ввода. Листинг 8.8. Пример использования оператора GoTo 1 Sub EvalDiscount4() 2 ' Определение скидки (в %) в зависимости от 3 ' количества продаваемого товара 4 Dim IStr As String 5 Dim IntNum 6 IntNum = Application.InputBox( _ 7 prompt:“"Введите количество товара", _ 8 Title : “''Процедура EvalDiscount4 " , _ 9 Type:=l) 10 11 If TypeName(VarWeight) = "Boolean" Then GoTo EndSubCancel 12 13 Select Case IntNum 14 Case Is > 1000 15 IStr = "10" 16 Case Is > 500 17 IStr = "5 " 18 Case Else 19 IStr = "0 " 20 End Select 21 22 MsgBox "Скидка " & IStr & "%" 23 GoTo EndSub 24 25 EndSubCancel: ' обработка отмены ввода в окне InputBox 26 MsgBox "Количество не указано" 27 28 EndSub: ' успешное окончание работы 29 30 End Sub В строке 11 определяется, были ли введены данные в окне диалога. Если пользователем была выбрана кнопка Отмена, код продолжает выполняться со строки 25, на которую указывает метка EndSubCancel. Если же данные введены успешно, процедура продолжает выполняться со строки 13. В строке 23 снова встречается оператор безусловного перехода для того, чтобы обойти строку 26 и не выдавать сообщения о том, что количество не было введено. Еще раз отметим, что так процедуры писать не нужно. Это — просто пример оператора GoTo. И лучше пока забыть о существовании этого оператора. Использование MsgBox для обеспечения возможности выбора До сих пор вы использовали оператор MsgBox с целью отображения сообщений для пользователя в диалоговых окнах с заголовками. Как уже отмечалось в главе 6, при помощи необязательного аргумента Buttons можно использовать VBA-процедуру MsgBox как функцию для получения выбора от пользователя в от 206 Глава 8 вет на сообщения или вопросы, которые отображает ваша процедура. Для многих простых вариантов выбора использование функции MsgBox для получения ответа от пользователя является гораздо более легким, чем получение текстового ввода с помощью функции InputBox и последующий анализ этого текста для определения того, какой выбор сделал пользователь. При включении аргумента Buttons с необходимыми круглыми скобками оператор MsgBox работает подобно функции и отображает окнб сообщения, содержащее различные командные кнопки. MsgBox возвращает численный результат, указывающий, какую командную кнопку выбрал пользователь. Число и тип командных кнопок, отображаемых диалоговым окном MsgBox, задается с помощью аргумента Buttons. В листинге 8.9 показана простая процедура, которая демонстрирует использование аргумента Buttons. Листинг 8.9. Использование MsgBox и аргумента Buttons для получения пользовательского ввода 1 Sub Demo_MsgBoxFunction() 2 ' Процедура демонстрирует MsgBox, используемую как функция 3 4 Const mTitle = "Демонстрация кнопок MsgBox" 5 Dim Resp As Integer 6 7 Resp = MsgBox(prompt:="Выберите кнопку", _ 8 Title:=mTitle, 9 Buttons:=vbYesNoCancel + vbQuestion) 10 Select Case Resp 11 Case Is = vbYes 12 MsgBox prompt:="Вы выбрали кнопку 'Да'”, _ 13 Title:=mTitle, _ , 14 Buttons:=vblnformation 15 Case Is = vbNo 16 MsgBox prompt:="Вы выбрали кнопку 'Нет'", _ 17 Title:=mTitle, _ 18 Buttons:=vblnformation 19 Case Is = vbCancel 20 MsgBox prompt:="Вы выбрали кнопку 'Отмена'", _ 21 Title:=mTitle, _ 22 Buttons:=vbCritical 23 End Select 24 End Sub Процедура Demo_MsgBoxFunction демонстрирует использование оператора MsgBox как функции, результаты различных аргументов Buttons и оценку значения, которое возвращает функция MsgBox. Диалоговое окно, в котором пользователю необходимо сделать выбор, представлено на рис. 8.3. Результаты работы кода этой процедуры при всех трех (по отдельности, конечно) выборах представлены на рис. 8.4. Рис. 8.3 Окно кода листинга 8.9 предоставляет пользователю выбор из трех кнопок Выберите кнопку Yes No Cancel Изменение порядка выполнения операторов в VBA 207 Рис. 8.4. Такие сообщения можно получить при выборе различных кнопок в диалоговом окне функции MsgBox Аргумент Buttons для MsgBox позволяет задавать количество и тип кнопок и наличие или отсутствие в окне сообщения одного из значков Windows для обозначения предупредительного сообщения (Warning message), сообщения запроса (Query message), информационного сообщения (Information message) и критического предупредительного сообщения (Critical Warning message). Можно также использовать аргумент Buttons для определения того, какая из отображаемых кнопок (кнопка 1, 2, 3 или 4) является кнопкой по умолчанию в окне сообщения. Каждый раз можно задавать только один тип кнопки, один значок и одну кнопку по умолчанию. В строке 9 (часть оператора вызова функции MsgBox, начинающегося в строке 7) константа vbYesNoCancel определяет, что диалоговое окно MsgBox должно содержать три командные кнопки: кнопку Yes (Да), кнопку No (Нет) и кнопку Cancel (Отмена). Константа vbQuestion определяет, что окно сообщения должно содержать значок сообщения запроса (Query message) Windows. Как только пользователь выбирает командную кнопку в окне сообщения, VBA возвращает численное значение, соответствующее выбору пользователя. В строке 7 результат функции MsgBox присваивается переменной Resp. VBA использует различные значения в зависимости от того, какую командную кнопку выбрал пользователь: одно значение для обозначения кнопки Yes, другое — для обозначения кнопки No и еще одно — для кнопки Cancel. Функция MsgBox может также отображать окна с кнопками Abort (Стоп), Retry (Повтор) и Ignore (Пропустить) в различных комбинациях. Поскольку каждая кнопка имеет свое определенное возвращаемое значение, VBA имеет несколько внутренних констант для представления возможных возвращаемых значений функции MsgBox. Полный список значений констант VBA, которые может возвращать MsgBox, приведен в главе 6. В строке 10 начинается оператор Select Case, который оценивает значение, возвращаемое функцией MsgBox в строке 7 и сохраняемое в переменной Resp. Тестовое выражение для оператора Select Case — это сама переменная Resp, поэтому VBA сравнивает значение в переменной Resp, чтобы проверить, совпадает ли оно с каким-либо условием Case ь операторе Select Case. Помните, что можно увидеть все доступные внутренние константы, имеющие отношение к MsgBox, в окне Object Browser (Просмотр объектов). Для просмотра внутренних констант аргумента Buttons выберите VBA в списке Project/Library (Проект | Библиотека) в окне Object Browser, а затем выберите VbMsgBoxStyle в списке Classes (Классы); список Members of 'VbMsgBoxStyle' (Компонент) отображает внутренние константы для значений аргумента Buttons. Если вы выберете VbMsg-BoxResult в списке Classes, список Members of 'VbMsgBoxResult' отображает внутренние константы для возвращаемого значения функции MsgBox. Остается один элемент, который можно задать с помощью аргумента Buttons для MsgBox и который не был включен в листинг 8.9: можно указать, является ли первая, вторая, третья или четвертая командная кнопка в окнах MsgBox кнопкой по умолчанию. Как вы видели до сих пор, MsgBox обычно делает первую командную кнопку в своем окне кнопкой по умолчанию. Посмотрите на рис. 8.3 и обратите внимание, 208 Глава 8 что кнопка Yes помечена как кнопка по умолчанию. Если после того, как VBA отобразит это диалоговое окно, пользователь нажимает на клавишу Enter, VBA действует так, как если бы пользователь выбрал клавишу Yes. Вам может понадобиться, чтобы кнопкой по умолчанию была какая-либо другая кнопка, а не первая в списке в окне сообщения. Например, если вы используете MsgBox для запроса от пользователя подтверждения удалить рабочий лист в рабочей книге, может быть предпочтительнее, чтобы командной кнопкой по умолчанию была кнопка No, а не кнопка Yes; поскольку удаленный рабочий лист не может быть восстановлен, имеет смысл помочь пользователю избежать нечаянного подтверждения удаления при простом нажатии на клавишу Enter. Чтобы изменить командную кнопку по умолчанию, добавьте одну из внутренних констант VBA — vbDefaultButtonl, vbDefaultButton2, vbDefaultButton3 или vbDefaultButton4 — к аргументу Buttons. Следующий фрагмент процедуры показывает оператор MsgBox из строк 7-9 листинга 8.9, модифицированный так, чтобы командной кнопкой по умолчанию в окне сообщения была кнопка No: Resp = MsgBox(prompt:="Выберите кнопку", _ Title:=mTitle, _ Buttons:=vbYesNoCancel + vbQuestion + _ VbDefaultButton2) При выполнении этого оператора VBA отображает диалоговое окно, показанное на рис. 8.5. Это окно идентично окну, показанному ранее на рис. 8.3, за исключением того, что добавление значения vbDefaultButton2 к аргументу Buttons делает вторую кнопку (в данном случае — кнопку No) кнопкой по умолчанию. Рис. 8.5 Сравните это диалоговое окно с окном, показанным на рис. 8 3. Заметьте, что кнопка No является теперь командной кнопкой по умолчанию как результат добавления vbDefaultButtonZ к аргументу Buttons. Глава 9 Дополнительные свойства процедур и функций Теперь, когда вы знаете уже достаточно много о процедурах и функциях, а также об управлении выполнением кода на VBA, рассмотрим некоторые дополнительные свойства процедур и функций, использование которых открывает новые возможности для написания хорошего кода. Раннее окончание процедур, функций и целых программ Существуют обстоятельства, такие как отмена окна ввода пользователем или отсутствие некоторых ожидаемых данных, при которых нет смысла продолжать выполнение процедуры или функции. Если у вас имеется программа, содержащая процедуры, которые вызывают другие функции и процедуры, вы можете задать условия, при которых вся программа должна прекращать выполнение: например, отсутствует рабочий лист, диапазон, документ и так далее. VBA имеет операторы Exit и End, которые дают возможность либо завершать процедуру или функцию, либо останавливать всю программу. Использование оператора Exit Для того чтобы процедура или функция прекратила выполнение, используется одна из двух доступных форм VBA-оператора Exit, в зависимости от того, необходимо ли завершить функцию или процедуру. Оператор Exit имеет две синтаксические формы: СИНТАКСИС Exit Sub Exit Function Exit Sub и Exit Function работают одинаково и имеют один и тот же результат; Exit Sub используется для окончания процедуры, a Exit Function — для окончания функции. Сначала рассмотрим простой пример — листинг 9.1, который отличается от листинга 8.8 тем, что в нем нет оператора GoTo. Листинг 9.1. Пример использования оператора Exit Sub 1 2 3 4 5 6 7 8 1 Sub EvalDiscountb() 2 1 Определение скидки (в %) в зависимости от 3 ' количества продаваемого товара 4 Dim IStr As String 5 Dim IntNum 6 IntNum = Application.InputBox( _ 7 prompt:^"Введите количество товара", 8 Title:="Процедура EvalDiscountb", 210 Глава 9 9 Туре:=1) 10 11 If TypeName(VarWeight) = "Boolean" Then 12 MsgBox "Количество не указано" 13 Exit Sub 14 End If • . 15 " ' 16 Select Case IntNum . 17 Case Is > 1000 18 IStr = "10" 19 . Case Is > 500 20 IStr = "5 " 21 Case Else 22 IStr = "0 " 23 End Select 24 25 MsgBox "Количество: " & Str(IntNum) S ". Скидка " S IStr 4 "%" 26 27 End Sub В строках 11-14 этой процедуры содержится код проверки того, была ли выбрана пользователем в окне ввода кнопка Cancel. Если это — так, программа выдает сообщение о том, что вес не был введен, и прекращает выполнение кода оператором Exit Sub. Для такой небольшой задачи это — самый подходящий код. Видимо, даже сторонники структурного программирования не найдут здесь причин для критики, хотя оператор Exit Sub также нельзя отнести к структурным языковым конструкциям. В листинге 9.2 приведена процедура MakeSalesRpt_Chart, в которой также для раннего окончания процедуры используются операторы Exit Sub. Причиной раннего окончания процедуры является отказ пользователя от ввода имени рабочего листа (в Excel). Можно только представить последствия выполнения кода без проверки того, ввел ли пользователь имя листа для дальнейшей его обработки! Листинг 9.2. Использование оператора Exit Sub 1 Sub MakeSalesRpt_Chart() 2 ' Запрашивает имя листа, содержащего исходные данные, 3 ' затем запрашивает диапазон ячеек с данными для диаграммы. 4 1 11 Далее запрашивается имя листа для помещения в него круговой 5 ' диаграммы. Затем процедура создает диаграмму и использует 6 ' метод Chartwizard для получения круговой диаграммы 7 8 Const sTitle = "Отчет о продажах" , 9 10 Dim SrcShtName As String 1 11 Dim SourceRng As String 12 Dim DestShtName As String 13 14 ' получить имя исходного листа 15 SrcShtName = InputBox(prompt:= _ 16 "Введите имя листа, " & _ 17 "содержащего данные для диаграммы", _ 18 Title:=sTitle) 19 ' проверить: введено ли имя 20 If Len(Trim(SrcShtName)) = 0 Then 21 MsgBox "Имя с данными не введено - конец работы" 22 Exit Sub 23 End If 24 ' выбор листа, на который указал пользователь 25 Sheets(SrcShtName).Select 26 Дополнительные свойства процедур и функций 211 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ' получить диапазон (с данными) SourceRng = InputBox(prompt:= _ "Введите диапазон с данными для диаграммы, " & _ "используя R1C1 формат:", _ Title:=sTitle) ' проверка: введен ли диапазон If Len(Trim(SourceRng)) = 0 Then MsgBox "Диапазон данных не введен - конец работы" Exit Sub End If ' получить имя листа для помещения в него диаграммы DestShtName = InputBox(prompt:= _ "Введите имя листа для диаграммы:", _ Title:=sTitle) ' проверка: не выбрана ли Отмена If Len(Trim(DestShtName)) = 0 Then MsgBox "Лист для диаграммы не введен " & _ конец работы" Exit Sub End If ' выбор листа и создание диаграммы Sheets(DestShtName).Select ActiveSheet.ChartObjects.Add(96, 37.5, 234, 111).Select ' использование метода Chartwizard для создания диаграммы With Sheets(SrcShtName) ActiveChart.Chartwizard Source:=.Range(SourceRng), _ Gallery:=xlPie, _ Format:=7, _ PlotBy:=xlColumns, _ . CategoryLabels:=1, _ SeriesLabels:=1, _ HasLegend:=l, _ Title:="0тчет о продажах" End With End Sub Процедура MakeSalesRpt_Chart является отредактированной версией записанного рекордером макроса Excel 2000. Сначала был записан макрос для создания фрагмента диаграммы. Затем этот макрос был скопирован в другой модуль и отредактирован с добавлением объявления различных констант и переменных. В процедуру были добавлены операторы VBA для ввода данных от пользователя и оценки вводимых данных. (Заметьте, что процедура работает только в Excel.) В переменной SrcShtName сохраняется (строки 15-18) имя рабочего листа, в котором содержатся данные для графического изображения, в SourceRng (строки 28-31) — диапазон данных для диаграммы, в DestShtName (строки 39-41) — имя рабочего листа для помещения в него диаграммы. После каждого ввода данных результат операции ввода проверяется. Если данные не введены, работа процедуры заканчивается оператором Exit Sub. Оператор Exit Sub приводит к тому, что VBA немедленно прекращает выполнение кода процедуры. После выполнения операторов Exit Sub VBA прекращает выполнение текущей процедуры и возвращается к выполнению той процедуры или функции, которая вызвала процедуру, содержащую оператор Exit Sub. Используйте оператор Exit Sub или Exit Function вместо GoTo для раннего окончания процедуры или функции. Оператор Exit Sub более очевидно показывает, что процедура закончит выполнение. И, следовательно, ее легче писать, читать и понимать. 212 Глава 9 Использование оператора End Вы уже знакомы с ключевыми словами End Sub и End Function, используемыми для сообщения VBA о достижении конца процедуры или функции. Эти ключевые слова-инструкции указывают VBA прекратить выполнение кода текущей процедуры или функции и возобновить выполнение кода процедуры или функции, которая вызвала текущую процедуру или функцию; если текущая процедура не была вызвана другой процедурой, VBA прекращает выполнение всех операторов. Одним из хороших принципов программирования является принцип модульности. Процедура не должна содержать бесконечно длинный код, части которого выполняют совершенно не связанные между собой задачи. Следует помещать в каждую процедуру небольшой и функционально законченный код, который легко читать и сопровождать. Например, хорошо понимается код со следующей структурой: Sub ГлавнаяПроцедура() ' Вызов процедуры Процедура! Call Процедура! ' Вызов процедуры Процедура? Call Процедура? ' Вызов процедуры Процедура? Call Процедура? End Sub Sub Процедура!() ' Код процедуры End Sub Sub Процедура? () ' Код процедуры End Sub Sub Процедура?() ' Код процедуры End Sub Можно также встретить и следующий код: Sub ГлавнаяПроцедура() ' Вызов процедуры Процедура! Call Процедура! End Sub * Sub Процедура!() ' Вызов процедуры Процедура? Call Процедура? t End Sub Sub Процедура?() ' Вызов процедуры Процедура? Call Процедура? End Sub Sub Процедура?() ' Код процедуры End Sub Обратите внимание на то, что в этих фрагментах кода процедуры не возвращают никаких результатов свой работы. Это может быть только в случае, когда эти процедуры по очереди обрабатывают какие-то общие данные, выполняя над ними определенные действия. Результатами этих действий могут быть либо сами преобразованные данные, либо новые (и тоже общие) данные. Представим такую ситуацию, когда обработка данных одной процедурой зависит от результатов обработки этих данных другой процедурой, выполняемой рань Дополнительные свойства процедур и функций 213 ше. Вполне возможно, что по каким-то причинам (пользователь неправильно ввел имя листа с данными, вообще отказался от ввода, неправильно введены числовые и другие данные) одна из процедур не подготовила данные для обработки следующей процедурой. В этом случае весь процесс обработки данных следует прекратить и в дальнейшем никаких процедур не вызывать, т.е. просто закончить работу всей программы. При этом даже необязательно возвращаться в вызывающую процедуру, особенно если предусмотреть перед каждым выходом из программы вывод окна с сообщением о том, почему и где было прервано выполнение кода. Для полного завершения выполнения программы с помощью VBA используйте ключевое слово End одно в отдельной строке: End При выполнении этого оператора VBA прекращает все выполнение операторов процедуры и функции. Любые имеющиеся переменные перестают существовать и их значения теряются. В листинге 9.3 показана функция GetBookName, которая полностью заканчивает любую программу, выполняемую VBA, если пользователь отменяет окно ввода. Листинг 9.3. Прекращение выполнения программы оператором End 1 Function GetBookName(ByVai IDflt As String, _ 2 Optional Prmpt, _ 3 Optional ITitle) As String 4 ' включен ли параметр Prmpt в список аргументов? 5 If IsMissing(Prmpt) Then Prmpt = "Введите имя книги:" 6 7 ' если IDflt не является пустой строкой, преобразовать 8 ' ее к верхнему регистру, иначе присвоить IDflt имя 9 If IDflt О "" Then 10 IDflt = UCase(IDflt) 11 Else 12 IDflt = "NEWFILE.XLS" 13 End If 14 15 ' использовать InputBox для получения имени файла 16 GetBookName = InputBox(prompt:“Prmpt, _ 17 Title:“ITitle, 18 Default:=lDfIt) 19 20 21 ' проверка: не была ли произведена отмена 22 If Len(Trim(GetBookName)) = 0 Then 23 MsgBox prompt:“"Окончание программы", Title:“ITitle 24 End 25 End If 26 End Function 27 28 29 Sub TestGetBook_Name() 30 ' Тестирование функции GetBookName 31 32 MsgBox GetBookName(IDflt_ 33 ITitle:“''Тестирование выхода из программы") 34 End Sub Пишите процедуры или функции, использующие оператор End, для отображения некоторого сообщения пользователю о том, что будет происходить и почему, перед оператором, который фактически содержит оператор End. В противном случае пользователи вашей процедуры могут не понять, почему процедура или программа, которую они используют, внезапно прекратила работу. Если программа 214 Глава 9 перестанет выполняться вследствие какого-либо действия пользователя, такого как отмена окна ввода, без объяснения, пользователь процедуры может никогда не узнать, почему процедура заканчивается; в действительности, пользователи склонны считать, что это происходит из-за ошибки в процедуре. Не забывайте закрывать рабочие книги или выполнять другую сервисную работу перед выполнением оператора End, чтобы пользователю программы не приходилось, например, доделывать наполовину законченные диаграммы или иметь дело с рабочими книгами, которые имеют несохраненные данные, когда ваша программа прекращает выполнение. Дополнительные свойства необязательных аргументов Необязательные аргументы функции могут объявляться с типом (иначе, по умолчанию, они имеют тип Variant). Тип необязательного аргумента объявляется по тем же причинам, что и тип обязательного аргумента: для того, чтобы правильно использовать функции и обнаруживать операторы, которые передают функции неверные значения. Тип необязательного аргумента объявляется тем же способом, что и тип обязательного аргумента — с помощью ключевого слова As. Следующий фрагмент кода показывает объявление функции с типом необязательного аргумента nChar как Long: Function UpCase(tStr As String, Optional nChar As Long) As String Всякий раз при объявлении необязательного аргумента функции VBA резервирует место для этого аргумента. Поскольку необязательные аргументы могут присутствовать или не присутствовать во время вызова функции, можно указать VBA присваивать необязательному аргументу значение по умолчанию. VBA использует значение по умолчанию каждый раз, когда функция вызывается без этого включенного конкретного необязательного аргумента. Значение по умолчанию присваивается необязательному аргументу с помощью знака равенства (=) и предоставления константного значения так же, как при объявлении именнованной константы. Function GetBookName5(Optional IDflt As String - "Книга1") As String Листинг 9.4 содержит функцию GetBookName5, полученную из подобной функции листинга 8.4. Здесь необязательный аргумент объявлен с типом и значением по умолчанию. S Функция IsMissing работает только с необязательными аргументами типа Variant. Для всех других типов необязательных аргументов VBA инициализирует значение J аргумента, как для любой новой переменной (строки имеют нулевую длину и численные типы равны 0), a IsMissing всегда возвращает False. Чтобы обнаружить пропущенный типизированный необязательный аргумент, тестируйте его на равен-ство 0 или строке нулевой длины. Листинг 9.4. Функция GetBookName5 1 Function GetBookName5(Optional IDflt As String = "Книга1") As String 2 Dim ITitle As String, IPrmpt As String, IVar As String 3 4 ITitle = "Ввод наименования книги" 5 IPrmpt = "Введите наименование новой книги" 6 7 ' использование InputBox для получения имени файла. 8 IVar = Trim(InputBox(prompt:=lPrmpt, _ 9 Title:=lTitle, 10 Default:=lDfIt)) Дополнительные свойства процедур и функций 215 11 12 ' проверить наличие строки ввода 13 If Len(lVar) = 0 Then 14 MsgBox "Наименование не введено!" 15 GetBookName5 = lDflt ' имя по умолчанию 16 Else 17 GetBookName5 = IVar 18 End If 19 20 End Function ' GetBookName 21 22 ' Тестирование функции GetBookName5 23 Sub Test_GetBookName5() 24 MsgBox GetBookName5("Новая_Книга") 25 End Sub Сравните этот код с кодом листинга 8.4. Не правда ли, этот код более изящен? Управление передачей аргументов Теперь, когда вы знаете, как создавать функции-процедуры с типизированными и необязательными аргументами, кажется, что еще можно делать с аргументами, чтобы программы обладали большими возможностями? Оказывается, существуют механизмы, которые VBA использует для фактической передачи (и возвращения) данных-аргументов функции-процедуре, и вы можете управлять этими механизмами. Передача аргументов по ссылке и по значению Существует два способа, которыми VBA передает информацию в функцию-процедуру: по ссылке (by reference) и передача аргументов по значению (by value). По умолчанию VBA передает все аргументы по ссылке. При передаче данных функции посредством аргумента по ссылке VBA на самом деле только передает адрес памяти, который ссылается на исходные данные, определенные в списке аргументов функции во время вызова функции. Это означает, что если функция изменяет значения в любом из аргументов, исходные данные, переданные функции посредством этого аргумента, также изменяются. При передаче аргумента по значению VBA делает копию исходных данных и передает эту копию функции. Если функция изменяет значение в аргументе, передаваемом по значению, изменяется только копия данных; исходные данные не изменяются. Передача по ссылке позволяет с помощью функции изменять исходные данные, передаваемые функции посредством аргумента; передача же по значению не позволяет изменять значение исходных данных. Поскольку передача по ссылке позволяет функции изменять значение исходных данных ее аргументов, аргументы, передаваемые по ссылке, могут получить нежелательные побочные значения. Листинг 9.5 содержит код функции Sconcat, которая объединяет две строки, передаваемые ей как параметры по ссылке. Перед объединением строк из них удаляются начальные и хвостовые пробелы. При этом операторы удаления пробелов в качестве промежуточных переменных используют сами аргументы, таким образом меняя их значения. Результат работы программы тестирования функции Sconcat приведен на рис. 9.1. Листинг 9.5. Побочные результаты функции Sconcat 1 Function Sconcat(argl As String, arg2 As String) As String 2 argl = Trim(argl) 3 arg2 = Trim(arg2) 216 Глава 9 4 Sconcat = argl S arg2 5 End Function i 6 7 Sub Test_Sconcat() 8 Dim al As String, a2 As String > 9 al = " Значение al: " 10 a2 = " Значение a2: " 11 MsgBox al S a2, , "До вызова Sconcat" 12 MsgBox Sconcat(al, a2), , "При вызове Sconcat" 13 : MsgBox al S a2, , "После вызова Sconcat" 14 : End Sub Рис. 9.1. Результаты тестирования функции Sconcat из листинга 9 5 Из рис. 9.1 видно, что после вызова функции Sconcat значения переменных al и а2 изменились. Определение способа передачи аргумента Понятно, что побочные результаты, вызванные изменением функцией значений в аргументах, передаваемых по ссылке, являются необязательными и в большинстве случаев — нежелательными. Они могут привести к серьезным проблемам в программах. Часто бывает трудно отследить проблемы, вызванные побочными результатами, потому что редко причина какого-либо изменения значения переменной является очевидной. (Побочный результат (side effect) — это общий термин для обозначения любого изменения в значении переменной в среде выполняющейся программы, которое не запрограммировано явно.) Для предупреждения таких побочных результатов необходимо, чтобы функция работала с копией значения аргумента, а не с исходными данными. Можно было бы, конечно, объявить локальную переменную в функции-процедуре и копировать аргумент в эту локальную переменную. Копирование значений аргумента в локальные переменные функции обычно нежелательно. Дополнительные переменные увеличивают объем памяти, необходимой для функции, и количество выполняемой программистом работы. Дополнительные переменные могут также привести в беспорядок программный код, усложняя его до ошибочного. Более легкий и предпочтительный способ обеспечить работу функции только с копиями значения аргумента, а не с исходным значением — это указать VBA, что аргумент должен передаваться по значению, а не по ссылке. (Помните, передача по значению дает функции копию значения аргумента; передача по ссылке открывает функции доступ к исходным данным в аргументе.) Чтобы явно указать, передает VBA аргумент по значению или по ссылке, используйте ключевое слово ByVai или ByRef перед аргументом, для которого необходимо задать метод передачи. Как можно понять по именам ключевых слов, при использовании ByVai VBA передает аргумент по значению, а при ByRef — по ссылке. Изменим объявление функции Sconcat2 (листинг 9.6) с целью передачи ей аргументов по значению и протестируем получившийся код. Дополнительные свойства процедур и функций 217 Листинг 9.6. Устранение побочных результатов функции Sconcat в функции Sconcatl 1 Function Sconcat2(ByVai argl As String, ByVai arg2 As String) As String 2 argl = Trim(argl) 3 arg2 = Trim(arg2) 4 Sconcat2 = argl S arg2 5 End Function 6 7 Sub Test_Sconcat2() 8 Dim al As String, a2 As String 9 al = ” Значение al: " 10 a2 = " Значение a2: " 11 MsgBox al S a2, , "До вызова Sconcat2" 12 MsgBox Sconcat2(al, a2), , "При вызове Sconcat2" 13 MsgBox al S a2, , "После вызова Sconcat2" 14 End Sub Обратите внимание на то, что значения переменных al и а2 не изменились после вызова функции Sconcat2. До вызова Sconcati Значение а 1: Значение а2: Рис. 9.2. Результаты тестирования функции Sconcat2 из листинга 9.6 Не следует объявлять аргументы по значению (ByVai), если только функция-процедура не изменяет этот аргумент, потому что передача аргументов по значению может использовать больше памяти и времени для выполнения, чем при передаче аргументов по ссылке — передача аргументов по значению приводит к тому, что VBA делает копию данных для аргумента. Объявляйте аргумент с ключевым словом ByVai для передачи его по значению, если у вас имеются сомнения, следует ли передавать этот конкретный аргумент по ссылке или по значению: потери в объеме памяти и скорости при передаче по значению не слишком велики. Кроме того, передача аргумента по значению эффективнее и делает код более понятным, чем создание вашей собственной копии значения аргумента в локальной переменной. Рекурсия В конце этой главы, посвященной написанию пользовательских функций-процедур, необходимо объяснить еще одно важное понятие, хотя оно и не является непосредственно частью процесса создания функций-процедур VBA. Более того, этот материал предназначен не для начинающих программистов и может быть пропущен при первом чтении данной книги. Рекурсивная (recursive) функция или процедура — это функция или процедура, которая вызывает сама себя. Почти во всех случаях, рекурсия является ошибкой программирования и приводит к полному сбою программы. Наиболее общим симптомом возникновения этой проблемы является ошибка из-за нехватки памяти или ошибка из-за нехватки памяти в стеке. Стек (stack) — это временная рабочая область компьютерной памяти. VBA использует стековую память для сохранения внутренних результатов выражений, копий аргументов функций, передаваемых 218 Глава 9 по значению, результатов функций-процедур и в других случаях, когда необходима временная рабочая область. Примеры рекурсивных функций1 Самый простой пример, который может продемонстрировать рекурсивную функцию, это — пример функции возведения числа в степень. Алгоритм функции fPower основан на том факте, что число, возведенное в степень п, равно этому же числу, умноженному само на себя в степени n—1. Например, 23 равно 2х23-1 или 2х22. Листинг 9.7 содержит код функции fPower, возвращающей степень числа. В качестве аргументов функция принимает число и степень, в которую нужно возвести это число. Листинг 9.7. Функция fPower пример рекурсии 1 Function fPower(num As Double, pwr As Integer) As Double 2 3 ' рекурсивное возведение в степень If pwr = 0 Then 4 5 fPower = 1 Else ' окончание рекурсии 6 7 8 9 10 11 12 fPower = num * End If End Function Sub Test_fPower() MsgBox fPower(2, 3) End Sub fPower(num, pwr - 1) ' рекурсия Функция fPower имеет два обязательных аргумента: num и pwr, и возвращает результат типа Double. В строке 6 функция вызывает сама себя. Чтобы понять, как работает функция fPower, рассмотрим порядок выполнения кода функции, вызванной процедурой Test_fPower. В этом случае при первом обращении аргумент num (и всегда) имеет значение 2, a pwr — значение 3. В строке 3 начинается оператор If...Then, который определяет момент прекращения рекурсии. Здесь проверяется, равно ли значение переменной pwr нулю. В этом вызове значение pwr равно 3, поэтому выполнение функции продолжается в строке 6. В строке 6 выполняется присваивание функции; выражение, присваиваемое результату функции fPower, указывает на то, что результат функции равен значению num, умноженному на результат следующего вызова функции fPower со вторым аргументом, равным pwr—1. Если подставить литеральные промежуточные значения для этого примера в данное выражение, вызов функции fPower в строке 6 в этом месте будет следующим: FPower(2,2) Это — второй вызов функции fPower; значение аргумента pwr теперь равно 2. В строке 3 проверяется, равно ли нулю значение аргумента pwr; если — нет, VBA снова выполняет присваивание функции в строке 6. Выражение в присваивании функции вызывает функцию fPower снова, передавая pwr—1 в качестве второго аргумента. Если мы опять подставим литеральные промежуточные значения для этого примера в выражение в строке 6, вызовом функции fPower в этом месте будет: FPower(2,1) 1 К сожалению, автор не имел достаточно времени, чтобы придумать пример рекурсии, который бы относился к области бизнеса и был достаточно простым. Дополнительные свойства процедур и функций 219 В этом третьем вызове функции fPower значение pwr теперь равно 1. В строке 3 проверяется, не равно ли нулю значение аргумента pwr; если — нет, то присваивание функции в строке 6 выполняется третий раз, приводя в результате к четвертому вызову fPower. В четвертом вызове функции fPower значение pwr равно О; результатом проверки (в строке 3) на равенство нулю значения аргумента pwr является True, и VBA выполняет строку 4, заканчивая рекурсию. Строка 4 — это еще один оператор присваивания функции, на этот раз присваивающий число 1 как результат функции. (Любое число, возведенное в степень О, равно 1). В вызовах 1-3 функции fPower функция не возвратила никакого результата; VBA не может полностью вычислить выражение в операторе присваивания функции (строка 6) до тех пор, пока серия рекурсивных вызовов не прекращается в четвертом вызове функции fPower. Теперь, когда функция fPower возвращает результат, рекурсивный процесс прекращается, и каждый отдельный вызов функции fPower возвращает ее результат. Четвертый вызов fPower возвращает число 1 в выражение в строке 6 третьего вызова функции fPower. Подставим литеральные промежуточные значения из примера, и это выражение будет равно 2x1. Результат, возвращаемый третьим вызовом функции fPower, равен 2. VBA возвращает это значение 2 выражению присваивания функции во втором вызове функции так, что (подставляем литеральные промежуточные значения) это выражение равно теперь 2x2. Второй вызов функции fPower возвращает 4 выражению присваивания функции первого вызова функции fPower. Снова подставляются литеральные значения, и выражение из первого вызова функции fPower равно теперь 2x4. Наконец, исходный первый вызов функции fPower возвращает значение 8 — правильный результат возведения 2 в третью степень. Если вы хотите проследить последовательность передачи аргументов функции fPower, вставьте перед строкой 3 следующий оператор: MsgBox num & " и " & pwr При этом в процессе тестирования предыдущего примера вы увидите последовательность окон, отображенную на рис. 9.3. Рис. 9.3. Окна с промежуточными результатами работы функции fPower На самом деле, нет необходимости писать функцию fPower: VBA оператор возведения в степень (") имеет такой же результат. Функция fPower была выбрана для иллюстрации рекурсии, потому что она предоставляет самый простой пример работы рекурсии. Рассмотрим пример функции нахождения наибольшего общего делителя двух целых чисел с помощью классического алгоритма Евклида, который заключается в следующем: 1) имеются два целых числа а и Ь; 2) если остаток от деления а на b равен нулю, то b — уже наибольший общий делитель, иначе выполнить: (аО = b), (al= a Mod b), а = аО, b = al и вернуться к началу пункта 2. 220 Глава 9 Листинг 9.8. Функция GCD пример рекурсии 1 Function GCD(a As Integer, b As Integer) As Integer 2 If (a Mod b) = 0 Then 3 GCD = b 4 Else 5 GCD = GCD(b, (a Mod b)) 6 End If • 7 End Function 8 9 Sub Test_GCD() 10 Dim d As Integer 11 MsgBox GCD(a:=342, b:=612) 12 End Sub Структура кода этой рекурсивной функции очень похожа на структуру предыдущего примера, поэтому, видимо, нет надобности анализировать ее так же подробно. В результате тестирования функции GCD при помощи процедуры Test_GCD будет получен результат 18, который и является наибольшим общим делителем исходных чисел. Как избежать случайной рекурсии и других проблем Теперь, когда вы знаете о том, как работает рекурсивная функция-процедура, вы готовы к рассмотрению недостатков рекурсивных программ. Одним из наиболее очевидных недостатков рекурсивных функций и процедур является то, что их часто трудно понимать. Другой недостаток заключается в том, что они используют большой объем памяти; каждый раз, когда рекурсивная функция вызывает сама себя, VBA передает все ее аргументы снова и для результата функции резервируется область памяти. Объем памяти, используемый серией вызовов рекурсивной функции, может быть значительным в зависимости от размера аргументов (в байтах) и размера возвращаемого функцией значения (в байтах). Почти всякую задачу, которую можно выполнить с помощью рекурсивной функции, можно также выполнить с помощью структуры цикла без дополнительных потерь памяти; структуру цикла часто легче понять, чем функцию, выполняющую работу посредством рекурсии. (Структуры цикла описываются в главе 11.) Нечаянная рекурсия — это довольно распространенная ошибка программирования, особенно для начинающих программистов. Когда вы начинаете разрабатывать свои функции, легко ошибиться при написании оператора присваивания функции и нечаянно создать оператор, который вызывает функцию рекурсивно, вместо присваивания результата функции. Поскольку вы указываете VBA, какое значение должно быть возвращено как результат функции с помощью присваивания функции, легко также забыть, что имя функции не является переменной, и попытаться работать с именем функции как с именем переменной; такие попытки обычно приводят к случайным рекурсивным вызовам. Если вы случайно создали рекурсивную функцию-процедуру, маловероятно, что рекурсия когда-либо закончится. Рекурсивные функции должны разрабатываться очень тщательно, чтобы обязательно было какое-либо условие, прекращающее рекурсивные вызовы. Если функция не тестирует какое-либо условие, чтобы явно завершать рекурсию (как делает функция fPower), вызовы рекурсивной функции продолжаются до тех пор, пока у VBA не заканчивается память (с возникновением ошибки времени исполнения). Обычно при выполнении функции, которая содержит нечаянный рекурсивный вызов, компьютер как бы прерывает работу на несколько секунд перед тем, как VBA отображает ошибку времени исполнения из-за нехватки памяти. Глава 10 Объекты и коллекции, введение Эта глава посвящена одной из самых интересных тем в программировании. Материал, представленный здесь, может восприниматься по-разному в зависимости от уровня подготовленности читателя. Общепризнанным считается мнение о том, что объектно-ориентированное программирование легче воспринимается теми, кто не слишком много времени занимался традиционным (модульным) программированием. Поскольку эта книга в основном предназначена для тех, кто вообще никогда не программировал (для этого так подробно и разбираются многочисленные примеры), то имеется надежда, что и этот материал будет понятен и заинтересует читателя. По крайней мере, именно после прочтения этой главы можно начинать «по-настоящему» программировать в VBA. VBA является идеальным инструментом для изучения основ объектно-ориентированного программирования, так как имеет встроенные объекты (рабочие книги и листы, ячейки, документы и выделенные фрагменты текста), их свойства и методы. Эти объекты — не выдумка, они реальны, их необходимость ощутима. Поэтому для иллюстрации объектов, свойств и методов не нужно обращаться к объектам, не имеющим никакого отношения к программированию, например, автомобилям с их свойствами (цвет, размер, скорость) и методами (изменение скорости, подача сигнала и т.д.). На примере объектов, свойств и методов, с которыми работает VBA, можно создавать свои собственные, полезные вам объекты. Можно к свойствам и методам встроенных объектов VBA добавлять новые, связанные с вашими задачами. Объекты В середине 80-х годов была разработана новая концепция в компьютерном программировании, известная как объектно-ориентированное программирование (object-oriented programming, OOP). Популярность объектно-ориентированного программирования с годами возрастает; новый Рабочий стол (desktop) в Windows 95, Windows NT 4.0 и Active Desktop в Windows 98/2000/XP, фактически воплощают многие объектно-ориентированные принципы. Центральная идея объектно-ориентированного программирования заключается в том, что программное приложение (как и реальный мир вокруг нас) должно состоять из особых объектов, каждый из которых имеет собственные специфические качества и поведение. Объектно-ориентированное приложение организует данные и выполняемые операторы программного кода в связанные объекты, что облегчает разработку, организацию и работу со сложными структурами данных и действиями, выполняемыми над этими данными (или с ними). Каждый объект в программном приложении содержит данные и операторы, связанные вместе и образующие единый элемент. Большинство приложений содержат много различных типов объектов. В Excel 2000/2002 объектами являются рабочие книги, листы, диапазоны данных, таблицы, графические объекты, диалоговые окна и само приложение Excel. В Word 2000/2002 объектами являются документы, диапазоны текста, таблицы, графические объекты, диалоговые окна и само приложение Word. 222 Глава 10 То, что вы узнаете из этой главы, поможет вашей работе с VBA не только в Word и Excel. Все host-приложения VBA, такие как Access 2000/2002 и Microsoft Project, имеют объекты, доступные для VBA таким же образом, как объекты Word и Excel. Объекты в других host-приложениях VBA существуют по тем же причинам, что и объекты в Word и Excel. Конкретные объекты в host-приложении VBA варьируют в зависимости от приложения. Объекты в Access, например, — все имеют отношение к базам данных и манипулированию базами данных, тогда как объекты в Excel связаны с понятиями рабочих листов, книг и так далее. Свойства объекта Как и объекты реального мира, объекты VBA имеют различные присущие им качества или свойства (properties). Объекты в Word и Excel имеют свойства, определяющие их вид и поведение: текст в документе Word может отображаться или не отображаться полужирным шрифтом или курсивом, рабочий лист Excel может быть видимым или нет, строки в рабочем листе или таблице имеют свойство высоты, столбцы имеют свойство ширины и так далее. Свойства регулируют вид и поведение объекта. Чтобы изменить вид и поведение объекта, необходимо изменить его свойства. В Excel можно изменить поведение рабочего листа, изменяя свойство вычисления с автоматического на ручное, или можно изменить вид рабочего листа, задав новый цвет для текста или графики в листе. В Word можно изменить поведение документа, изменяя свойство, которое регулирует показ орфографических ошибок во время набора текста; можно изменить вид документа, задав новые значения для свойств разметки страницы. Чтобы узнать о текущем виде и поведении объекта, необходимо узнать о его свойствах. Вы можете определить диск, папку и имя рабочей книги Excel или документа Word, рассмотрев свойство FullName этой рабочей книги или документа. Некоторые свойства объекта можно изменять, некоторые — нет. Например, в рабочей книге Excel можно изменить имя автора книги, изменяя свойство Author, но нельзя изменить свойство Name рабочей книги. (Свойство Name рабочей книги содержит имя файла на диске и не может быть изменено без создания нового дискового файла или переименования файла рабочей книги вне Excel). Некоторые объекты имеют свойства с одними и теми же или подобными именами: объекты Application, Workbook и Worksheet в Excel — все имеют свойство Name. Каждый объект рабочего листа сохраняет данные для своих свойств внутри самого рабочего листа вместе с пользовательскими данными. [Пользовательские данные (user data) — это любые данные, сохраняемые объектом, которые поступают непосредственно от пользователя подобно данным, содержащимся в ячейках рабочего листа.] Методы объекта Объекты реального мира почти всегда имеют тот тип присущего им поведения или действия, который они могут выполнить. Объекты VBA также имеют поведение и возможности, называемые методами (methods). Объект рабочей книги Excel, например, имеет встроенную способность добавлять к себе новый рабочий лист — метод добавления рабочих листов (называемый Add). Другой пример: документ Word имеет встроенную способность проверять орфографию текста в документе — метод проверки орфографии (называемый, как вы могли догадаться, CheckSpelling). Методы изменяют значения свойств объектов; методы выполняют также действия с данными (или над данными), сохраняемыми объектом. Методы во многом похожи на процедуры VBA, с которыми вы уже знакомы, но связаны с объектом; к методам объекта можно обратиться, только используя объект. Это может казаться сложным, но на деле все проще. Для вызова метода объекта (функции обработ Объекты и коллекции, введение 223 ки данных объекта) указывается не только наименование метода, но и объект (имя), которому принадлежит метод. Одной из причин того, что объектно-ориентированное программирование стало популярной техникой проектирования, является то, что оно позволяет разработчикам программного обеспечения создавать более эффективные программы с совместно используемым кодом. Вместо сохранения отдельной копии кода для каждого метода каждого объекта VBA-объекты одного и того же типа совместно используют код своих методов. Несмотря на то, что объекты одного и того же типа совместно используют код для своих методов, метод считается частью объекта; когда вы вызываете определенный метод для конкретного объекта, метод воздействует только на объект, посредством которого вы обращаетесь к этому методу. После того как объект создан (если это — не встроенный объект), нет необходимости беспокоиться о том, как работают его методы и как объект сохраняет или манипулирует данными. Все, что нужно знать, — как указать объект и как указать метод, который необходимо использовать (или определенное свойство, которое нужно выбрать и изменить). Встроенный код для объекта VBA выполняет остальную работу автоматически. Классы объекта Программные объекты группируются в иерархические классы или коллекции объектов, как объекты реального мира вокруг нас. Все объекты в одном и том же классе имеют одни и те же (или подобные) свойства и методы. Каждый класс объектов может содержать один или несколько подклассов. Объекты, принадлежащие к определенному классу объектов, называются членами (members) этого класса. MS Word, Excel, Access, PowerPoint, Outlook и т.д. принадлежат к общему классу объектов — host-приложений VBA. При запуске Word 97/2000/2002 на вашем компьютере вы создаете экземпляр Word 97/2000/2002. При наличии достаточных ресурсов памяти в компьютере вы можете запустить Word более одного раза; каждый раз при запуске Word будет создаваться еще один экземпляр Word. Каждый раз при создании или открытии документа в Word создается экземпляр объекта Document. Аналогично, каждая копия Excel 97/2000/ 2002, выполняемая на компьютере, является экземпляром приложения Excel, а каждая рабочая книга, открытая в данный момент, является экземпляром объекта Workbook. VBA дает возможность пользователю создавать собственные классы объектов, добавлением модуля класса в проект. Ваш модуль класса должен содержать все определения свойств и методов для объекта. После описания нового класса вы можете создавать его экземпляры (объекты этого типа). Использование объектов Операторы программ VBA, использующие объекты, обычно выполняют одно или несколько из следующих действий: определяют текущее состояние или статус объекта путем выборки значения, сохраняемого в определенном свойстве; изменяют состояние или статус объекта установкой значения, сохраненного в определенном свойстве; используют один из методов объекта, обеспечивая выполнение объектом одной из его встроенных задач. Например, можно определить имя активного в данный момент рабочего листа в Excel, выполняя выборку строки, сохраняемой в свойстве Name рабочего листа. (Свойство Name рабочего листа содержит имя рабочего листа, как показано на ярлычке листа.) Чтобы изменить имя рабочего листа, необходимо присвоить новую 224 Глава 10 строку свойству Name этого рабочего листа. Для добавления рабочего листа в рабочую книгу используется метод Add рабочей книги. Прежде чем применять свойства и методы некоторого объекта, их следует сначала определить. В операторах VBA используйте следующий общий синтаксис для определения свойства или метода объекта: СИНТАКСИС Object.identifier Object — любая допустимая ссылка на объект. Объектные ссылки создаются заданием переменной для ссылки на объект или использованием методов или свойств объектов, возвращающих объектную ссылку. Identifier — любое допустимое имя свойства или метода; VBA отображает сообщение о runtime-ошибке при попытке использовать свойства или методы, которые не являются в действительности частью указанного объекта. Если вы запустите в среде VBA Word процедуру листинга 10.1, то получите нечто подобное тому, что вы видите на рис. 10.1, т.е. в диалоговом окне функции MsgBox будет отображено наименование активного документа, хотя сама процедура может принадлежать другому документу (открытому, но не активному). Листинг 10.1. Активный документ 1 Sub ActDocum() 2 MsgBox "Активный документ: ” & ActiveDocument.Name 3 End Sub Рис. 10.1 Результат выполнения кода листинга 10 1 Обратите внимание на то, что точка (.) отделяет объектную ссылку от имени свойства или метода. В некотором смысле эта точка-разделитель также соединяет объектную ссылку с идентификатором свойства или метода. Поскольку вы обращаетесь к свойству или методу посредством объекта, необходимо определять объектную ссылку и идентификатор свойства или метода вместе. Точка-разделитель указывает VBA, где заканчивается объектная ссылка и где начинается идентификатор свойства или метода. В то же самое время точка-разделитель соединяет объектную ссылку и имя свойства или метода для образования единого идентификатора в операторе VBA. В табл. 10.1 приведены несколько из наиболее важных объектов (с точки зрения программиста VBA) в Excel 2000/2002. В таблице показано имя объекта и краткое описание этого объекта. (Имейте в виду, что Excel содержит намного больше объектов, чем перечислено в табл. 10.1.) Таблица 10.1. Общие объекты Excel 2000/2002 Объект Описание Application Само приложение Excel (host-приложение) Chart Диаграмма в рабочей книге Объекты и коллекции,введение 225 Объект Описание Font Этот объект содержит атрибуты шрифта и стиля для текста, отображаемого в рабочем листе Name Заданное имя для диапазона ячеек рабочего листа Range Диапазон ячеек (одна или более) или именованный диапазон в рабочем ливте Window Любое окно в Excel; окна используются для отображения рабочих листов, диаграмм и т.д. Workbook Открытая рабочая книга Worksheet Рабочая таблица в книге В табл. 10.2 перечислены наиболее важные объекты в Word 2000/2002. В таблице приводится имя объекта и краткое описание этого объекта. (Имейте в виду, что Word содержит намного больше объектов, чем перечислено в табл. 10.2.) Таблица 10.2. Общие объекты Word 2000/2002 Объект Описание Application Само приложение Word (host-приложение) Bookmark Отдельная закладка в документе Document Открытый документ Font Содержит атрибуты шрифта и стиля для текста, отображаемого в объекте Paragraph Отдельный параграф в документе Range Непрерывная область в документе Style Встроенный или определенный пользователем форматирующий стиль в документе Table Отдельная таблица в документе TableOfContents Отдельная таблица содержания документа Template Шаблон документа Window Любое окно в Windows Из таблиц 10.1 и 10.2 видно, что Excel 2000/2002 и Windows 2000/2002 имеют похожие объекты. Использование свойств объектов Свойства объектов можно использовать только двумя способами: получать значение свойства или устанавливать его. Как уже было упомянуто в начале этой главы, не все свойства объекта изменяемы. Свойства объектов, которые нельзя изменять, называют свойствами, доступными только на чтение (read-only); свойства, которые можно устанавливать, называют свойствами, доступными на чте-ние/запись (read-write). Свойства обычно содержат численные, строковые, значения типа Boolean, хотя некоторые свойства могут возвращать значения типа Object или другие типы данных. 8 Программирование на VBA 2002 226 Глава 10 Обращение к свойству объекта имеет следующий синтаксис: СИНТАКСИС Object.Property Object — допустимая объектная ссылка VBA, тогда как Property представляет любое допустимое имя свойства для объекта, на который выполняется ссылка. Свойства используются в выражениях так же, как любое другое значение переменной или константы. Можно присваивать значение свойства переменной, использовать свойства объектов в выражениях как аргументы к функциям и процедурам или как аргументы для методов какого-либо объекта. Чтобы присвоить некоторой переменной значение свойства объекта, используйте следующий синтаксис: СИНТАКСИС Variable = Object.Property Variable — любая допустимая переменная, имеющая совместимый со свойством объекта тип; Object — любая допустимая ссылка на объект, a Property — любое допустимое имя свойства для объекта, на который выполняется ссылка. В следующем примере строка, сохраняемая в свойстве Name рабочего листа Excel, на которую ссылается объектная переменная aSheet, присваивается переменной AnyStr: AnyStr = aSheet.Name Можно также использовать свойство объекта непосредственно в каком-либо выражении или в качестве аргумента функции или процедуры. Следующие строки представляют обоснованное использование свойства объекта (в каждой строке InstSheet является объектной переменной, заданной для ссылки на рабочий лист Excel): MsgBox InstSheet.Name AnyStr = "Эта ячейка имеет имя: " & InstSheet.Name MsgBox LCase(InstSheet.Name) Почти каждый объект в VBA имеет свойство, которое содержит его имя. Следующий оператор использует MsgBox для отображения свойства FullName в объекте рабочей книги Excel; свойство FullName содержит имя диска, путь к папке и имя файла рабочей книги: MsgBox InstBook. FullName В приведенном выше примере InstBook — это переменная, заданная для ссылки на объект открытой рабочей книги. Если InstBook ссылается на рабочую книгу с именем Sales.xls в папке Му Documents, то окно сообщения, вызываемое приведенным выше оператором, отображает строку "C:\My Documents\SALES.XLS". Чтобы задать свойство объекта, просто присвойте свойству новое значение, используя следующий синтаксис: СИНТАКСИС Object.Property = Expression Object — любая допустимая объектная ссылка, Property — любое свойство объекта, на который выполняется ссылка, a Expression — любое выражение VBA, которое вычисляется до типа, совместимого со свойством. Объекты и коллекции,введение 227 Следующая строка, например, изменяет имя рабочего листа, на который ссылается объектная переменная InstSheet, присваивая значение свойству Name листа: InstSheet.Name = "Первый квартал" Следующий пример изменяет текст, отображаемый в строке состояния в нижнем левом углу окна приложения, присваивая строку свойству StatusBar объекта Application (объект Application — это host-приложение VBA, в данном случае — Excel): Application.StatusBar = "Генерировать отчет за третий квартал" Используйте свойство Application.StatusBar в своих процедурах для отображения сообщений о действиях, которые выполняет процедура, особенно если некоторые из этих действий занимают много времени (например, сортировка длинного списка). Добавляя сообщение в строку состояния, вы даете знать пользователю, что процедура все еще работает. Используйте оператор, подобный следующему: Application.StatusBar = "Сообщение о текущих действиях" Не забывайте возвращать управление строке состояния при работе в Excel. В Excel необходимо устанавливать свойство Application. StatusBar в False, когда процедура выполнена, иначе Excel продолжает отображать заданное вами сообщение строки состояния. Используйте оператор, подобный следующему, для удаления сообщения из строки состояния и возврата управления строке состояния: Application.StatusBar = False В табл. 10.3 перечислены некоторые из наиболее употребительных или полезных свойств объектов в Excel 2000/2002 версии Visual Basic for Applications. В таблице представлено имя свойства, тип и значение, а также объекты, которые имеют это свойство. Таблица 10.3. Наиболее употребительные свойства объектов в Excel 2000/2002 Свойство Тип/Что означает Где найти ActiveCell Object: активная ячейка в рабочем листе Application, Window ActiveChart Object: активная диаграмма Application, Window, Workbook ActiveSheet Object: активный лист Application, Window, Workbook Address Возвращает координаты ячейки указанного объекта Range Cells Диапазон объекта Range Application, Range, Worksheet Charts Коллекция диаграмм Application, Workbook Count Integer: число объектов в коллекции Все объекты коллекции Formula String: формула для ячейки рабочего листа Диапазон Index Integer: число объектов в коллекции Worksheet Name String: имя объекта Application, Workbook и в других объектах Path String: драйвер и каталог, в котором сохранен объект Addin, Application, Workbook 8* 228 Глава 10 Свойство Тип/Что означает Где найти Saved Boolean: сохранялась ли рабочая книга после последних изменений Workbook Selection Object: текущий выделенный фрагмент Application, Window Sheets Коллекция листов рабочей книги Application, Workbook StatusBar String: сообщение в статусной строке Application ThisWorkBo ok Object: рабочая книга, из которой выполняется текущая процедура Application Type Integer: число, указывающее тип объекта Window, Worksheet, Chart Visible Boolean: отображается или нет объект на экране Application, Worksheet, Range и в других объектах Value (варьируется): действительное значение, отображаемое в ячейке Range Workbooks Коллекция рабочих книг Application Worksheets Коллекция рабочих листов Application, Workbook Некоторые свойства из таблицы 10.3 использованы в коде листинга 10.2. Чтобы посмотреть, как работает этот код, запустите Excel 2000/2002, выберите, например, лист с именем Sheet2 и переименуйте его в Лист для тестов. Введите в ячейку, например, С6, следующий текст Содержимое активной ячейки. В этот момент среда Excel готова к запуску кода листинга 10.2 и выглядит, как показано на рис. 10.2. Войдите в Редактор VBA и введите код листинга 10.2. Рис. 10.2 Среда Excel подготовлена для запуска кода листинга 10 LJ Microsoft Excel * Книга1 В1) Файл Правка Вид Вставка Формат Сервис Данные Окно Справка - в х £r U " Times New Roman -12 - ж к н иг 4- afc tjs Й? > • А - ” С6 -г fi, Содержимое активной ячейки ~CTp0Ka<tK]pMynj р G' —- 1 2 3 4 — 5 6 j |Содерж1|мое активной ячепкп 7 “ 8 и < ► н\Лист1/Лист2 /ЛистЗ / ]<| | >|Г~ Готово NUM Листинг 10.2. Активный лист, ячейка 1 Sub TestObjectOl() 2 ' имя активного листа 3 MsgBox ActrveSheet.Name 4 5 ' адрес активной ячейки 6 MsgBox ActiveCell.Address 7 Объекты и коллекции, введение 229 8 ' содержимое активной ячейки 9 MsgBox ActiveCell.Formula 10 11 End Sub Процедура при помощи функции MsgBox по очереди отобразит окна, представленные на рис. 10.3. Рис. 10.3 Результат выполнения кода листинга 10.2 Microsoft Excel [Xj Microsoft Excel |Ц£| Microsoft Excel Лист1 Содержимое активной ячейки Г '"ок :ок' ; Г” ок i Как видите, даже небольшие знания об объектах дают некоторые дополнительные возможности для работы со средой Excel. Но все еще впереди. В табл. 10.4 приведены некоторые из наиболее употребительных или полезных свойств объектов в Word 2000 версии VBA. В таблице представлено имя свойства, тип, значение и объекты, которые имеют это свойство. Таблица 10.4. Употребительные и полезные свойства объектов Word 2000/2002 Свойство Тип/Значение Имеется в объектах ActiveDocument Object: активный документ Application ActivePrinter String: имя активного принтера Application Active W indow Object: активное окно Application, Document Count Long: число объектов в коллекции Во всех объектах коллекций Name String: имя объекта Application, Bookmark, Dictionary, Document и в других Path String: драйвер и путь к папке, в которой сохранен объект Addin, Application, Dictionary, Document и в других Range Object: часть документа, содержащаяся в указанном объекте Bookmark, Paragraph, Selection, Table и в других Saved Boolean: был ли сохранен текст после последнего изменения Document, template Selection Object: текущий выделенный фрагмент Application, Pane, Window StatusBar String; сообщение строки состояния Application Visible Boolean: отображается объект на экране или нет Application, Border Перед подробным изучением свойств и методов встроенных объектов приведем некоторые примеры использования свойств и методов из таблицы. 230 Глава 10 Запустите Word 2000/2002. Откройте два документа. В одном из них в Редакторе VBA создайте новый модуль и введите код листинга 10.3. Листинг 10.3. Активный документ 1 Sub ActDocum() 2 3 MsgBox ActiveDocument Name, , _ 4 "Наименование активного документа" 5 6 MsgBox ActiveDocument Path, , _ 7 "Путь сохранения документа" 8 9 ActiveDocument Close ' закрыть активный документ 20 11 MsgBox ActiveDocument Name, , _ 12 "Наименование активного документа" 13 End Sub В строках 3-4 записан оператор, который выдает на экран имя активного документа (рис. 10.4 а) с помощью процедуры MsgBox. Следующий оператор (в строках 6-7) выдает окно, в котором указывается путь к месту хранения файла на диске (рис. 10.4 Ь). Не менее, чем два предыдущих, интересен оператор в строке 9. Этот оператор закрывает активный документ! Заметьте, это делается не при помощи привычного меню, а из кода VBA. Более того, предварительно пользователю (что необязательно и может быть отключено) задается вопрос, не следует ли сохранить последние изменения в документе (рис. 10.4 с). Последнее окно (рис. 10.4 d) функции MsgBox связано с оператором в строках 11-12; здесь сообщается об имени (ставшего активным) другого документа. Если запустить код листинга 10.3 из текущего активного документа, то он не выполнится до конца, так как закрытие документа прервет выполнение кода: редактор VBA закроется вместе с документом. b) Рис. 10.4 Результат работы кода листинга 10 3 Объекты и коллекции,введение 231 Использование методов объекта Методы объекта используются в операторах VBA так, как использовались бы любые встроенные процедуры VBA. Метод объекта имеет следующий синтаксис: СИНТАКСИС Object.Method Для методов объектов, имеющих обязательные и необязательные аргументы, используйте такой синтаксис: Object.Method Argument!, Arguments, Arguments... В обеих строках синтаксиса Object представляет любую допустимую объектную ссылку VBA, a Method — имя любого метода, принадлежащего объекту, на который выполняется ссылка. Во второй строке синтаксиса Argument!, Аг-gument2 и так далее представляют аргументы в списке аргументов метода. Как в случае с аргументами для вызова процедуры VBA, необходимо перечислять аргументы метода в определенном порядке, отделяя каждый аргумент в списке запятой и включая отмечающие запятые (place holding commas) для пропущенных необязательных аргументов. Метод может иметь один или несколько аргументов в своем списке или не иметь их совсем; аргументы метода могут быть обязательными или необязательными. Пример: рабочие книги Excel имеют метод Activate, который делает рабочую книгу активной и активизирует первый лист в книге. Если задать переменную InstBook для ссылки на объект рабочей книги, то приведенный ниже оператор активизирует эту рабочую книгу (в последующих разделах этой главы описывается, как задать переменную для ссылки на объект): InstBook.Activate Хотя метод Activate не имеет аргументов, многие методы объектов имеют один или более аргументов. В следующем примере вызывается метод SaveAs объекта рабочей книги Excel; используется один обязательный аргумент и один из нескольких необязательных аргументов. ActiveWorkbook.SaveAs Filename:="D\VBA2000\NEWFILE.xls", _ FileFormat:=xlNormal Word-объекты Document также имеют методы Activate и SaveAs с похожими аргументами. Первый оператор, приведенный ниже, активизирует документ, на который ссылается переменная InstDoc, а второй — использует метод SaveAs документа для сохранения активного документа под другим именем: InstDoc.Activate ActiveDocument.SaveAs Filename:="E:\VBA2000\Chapl0.doc" Многие объекты имеют методы, которые возвращают значения так же, как это делает функция. Чтобы использовать значение, возвращаемое методом, необходимо поместить список аргументов метода в круглые скобки и включить вызов метода в оператор присваивания или другое выражение, точно так же, как при использовании функции. Можно также игнорировать результат, возвращаемый методом. Чтобы игнорировать результат метода (если он имеет результат), вызовите метод без круглых скобок вокруг списка аргументов, как если бы метод не Возвращал результата. Пример: Excel-метод Address (который принадлежит объекту Range) возвращает адрес диапазона ячеек в рабочем листе как строку. В следующем примере показан оператор VBA, который использует метод Address (myRange — это объектная переменная, которая ссылается на диапазон ячеек в рабочем листе): MsgBox myRange.Address 232 Глава 10 Если переменная myRange ссылается на первую ячейку в рабочем листе, то оператор MsgBox в приведенной выше строке примера отображает строку $А$1. Хотя в этом примере метод Address вызывается без каких-либо аргументов, он, на самом деле, имеет несколько необязательных аргументов. Эти необязательные аргументы определяют стиль адреса ячеек рабочего листа, возвращаемого методом, а также, являются ли координаты ячеек абсолютными или относительными. В следующем примере показан вызов метода Address с, его третьим необязательным аргументом (который определяет стиль возвращаемых координат ячеек): MsgBox myRange.Address(, , xlRlCl) В этом операторе необходимо в список аргументов метода включать отмечающие запятые для пропущенных необязательных аргументов, как для любой другой процедуры или функции. Поскольку аргумент ссылочного стиля является третьим аргументом, ему предшествуют две отмечающие запятые в списке аргументов. xlRlCl — это внутренняя константа Excel, указывающая на то, что координаты ячеек рабочего листа используют стиль записи R1C1; если объектная переменная myRange ссылается на ячейку во второй строке и третьем столбце, то отображается строка R2C3 (вторая строка, третья колонка). Методы имеют также именованные аргументы, как и другие процедуры и функции VBA. Можно переписать последний пример, используя именованные аргументы, следующим образом: MsgBox myRange.Address(Referencestyle:=X1R1C1) Используйте именованные аргументы, чтобы было легче читать код VBA. В каждом из следующих примеров показан оператор, вызывающий метод SaveAs объекта рабочей книги Excel (этот метод не возвращает результат) для сохранения рабочей книги под другим именем (объектная переменная InstBook ссылается на рабочую книгу): InstBook.SaveAs "NEWNAME.XLS", xlNormal, , , , True InstBook.SaveAs FileName:="NEWNAME.XLS" , _ FileFormat:=xlNormal, _ GreateBackup:=True Оба оператора используют только три из шести необязательных аргументов для метода SaveAs. Первый оператор использует стандартный список аргументов, второй — именованные аргументы. Намного легче понять назначение и действие второго обращения к методу SaveAs, чем первого. Между методом объекта и любой другой процедурой VBA (встроенной или пользовательской) имеется одно существенное отличие — метод принадлежит определенному объекту и метод можно использовать, обращаясь к нему только посредством этого объекта. Часто можно распознать вызов методов в коде VBA по тому факту, что метод связан со ссылкой на объект с помощью точки-разделителя, как показано в примерах этого раздела. В табл. 10.5 приведены некоторые из наиболее употребительных или полезных методов в Excel 2002 версии VBA. В таблице представлено имя, краткое описание метода и объекты, имеющие этот метод. Таблица 10.5. Общеупотребительные и полезные методы объектов Excel 2000/2002 Метод Назначение Имеется в объектах Activate Активизирует объект Window, Workbook, Worksheet, Range и в других объектах Calculate Выполняет вычисления в открытой рабочей книге, рабочем листе или диапазоне Application, Range, Worksheet Объекты и коллекции, введение 233 Метод Назначение Имеется в объектах Clear Удаляет данные, сохраненные в указанном объекте Range Close Закрывает указанный объект Window, Workbook, Workbooks Justify Выравнивает тек<;т, сохраненный в указанном объекте Range Run Выполняет указанную процедуру или функцию Application, Range Save Сохраняет файл рабочей книги Application, Workbook SaveAs Сохраняет указанный объект в другом файле Workbook, Worksheet Select Выбирает указанный объект Range, Sheets, Worksheets SendKeys Пересылает нажатия клавиши в диалоговые окна в host-приложении Application Volatile Регистрирует функцию как изменяющуюся (см. гл. 6) Application Вернитесь к листу с именем Лист для тестов в рабочей книге Excel, занесите какую-либо информацию в ячейки листа и выделите какую-нибудь ячейку, например, как показано на рис. 10.5. Выполните код листинга 10.4. Листинг 10.4. Метод Clear для ячейки и диапазона 1 Sub TestMethodsOl() 2 1 тестирование метода Clear 3 4 ' содержимое активной ячейки 5 ' до применения метода Clear 6 MsgBox ActiveCell.Formula, , "До метода Clear" 7 8 ’ выполнения Clear 9 ActiveCell.Clear 10 11 ' содержимое активной ячейки 12 ' после применения метода Clear 13 MsgBox ActiveCell.Formula, , "После метода Clear" 14 15 ' Очистить диапазон ячеек: 16 Range("C6:D7").Clear 17 18 End Sub Сначала в результате выполнения кода этого листинга (строка 6) на экран выдается в диалоговом окне содержимое активной ячейки С4. Метод ActiveCell.Clear очищает эту ячейку, а оператор в строке 13 выдает на экран пустое сообщение. Наконец, оператор в строке 16 очищает диапазон ячеек C6:D7. Рабочий лист имеет вид, представленный на рис. 10.6. Обратите внимание на то, как задается диапазон ячеек для выполнения метода Clear. В табл. 10.6 приведены некоторые из наиболее употребительных или полезных методов в Word 2000/2002 версии VBA. В таблице приведено имя метода, краткое описание метода и объекты, имеющие этот метод. 234 Глава 10 Рис. 10.5 Содержимое листа до выполнения кода листинга 10.4 Рис. 10.6 Содержимое листа после выполнения кода листинга 10.4 Таблица 10.6. Наиболее употребительные и полезные методы объектов Word 2000/2002 Метод Назначение Имеется в этих объектах Activate Активизирует объект Window, Document, Pane и в других объектах CheckSpelling Проверяет орфографию указанного документа или диапазона Document, Range Close Закрывает указанный объект Window, Document Delete Удаляет указанный объект или удаляет символы и слова Bookmark, Range и в других объектах GoTo Перемещает курсор в начальное положение элемента, такого как страница, закладка или поле; возвращает объект Range Document, Range, Selection Printout Печатает указанный объект Application, Document, Envelope, Window Объекты и коллекции,введение 235 Метод Назначение Имеется в этих объектах Run Выполняет указанную процедуру или функцию Application Save Сохраняет указанный объект Document, Template SaveAs Сохраняет документ в другом файле Document Select Выбирает указанный объект Bookmark, Document, Field и в других объектах Рассмотрим подробнее метод SaveAs, который уже использовался в примерах этой главы. Для метода SaveAs необходимы дополнительные параметры, так как нет смысла сохранять документ под тем же именем методом, отличным от Save (на самом деле, Save тоже имеет необязательные параметры). Чтобы получить список параметров метода, можно воспользоваться системой Auto Quick Info. Как только вы наберете строку ActiveDocument.SaveAs( система подсказки выдаст на экран список всех параметров метода SaveAs, как это обычно делается для обычных функций (рис. 10.7). Рис. 10.7 Система Auto Quick Info для методов работает так же, как и для функций MsgBox ActiveDocument.Name "Наименование активного документа" MsgBox ActiveDocument.Path, , _ "Путь сохранения документа" ActiveDocument .Close ’ j п;рытъ г.кигангй MsgBox ActiveDocument.Name, , _ "Наименование активного документа" End Sub Sub SaveDocumO End ActiveDocument.SaveAs (| I Sub SaveAs([Fi7eNa/ne], [Fi/eFormaf], [LockCommenfs], [Password], [AddFoRecentFi/es], [WnfePassword], [ReadOnfy Recommended], [EmbedTrueTypeFonts], [SaveNativePictureFormaf], [Sai/eFormsDafa], | [Sai/eAsAOCQ-effer], [Encoding], [InsertLineBreaks], [AllowSubstifutions], ......[LineEnding], [AddBiDiMarks]) Согласно выданному системой Auto Quick Info всплывающему окну метод SaveAs имеет довольно много аргументов, хотя все они — необязательные. Если интуитивно вам непонятно назначение параметров какой-либо функции в окне Auto Quick Info, обратитесь за помощью к справочной системе. Для этого либо выделите, например, строку ActiveDocument.SaveAs и нажмите клавишу F1, либо в окне Microsoft Visual Basic Help откройте вкладку Contents, выберите последовательно разделы: Microsoft Word Visual Basic Reference, Methods, S, SaveAs Method. В результирующем окне вы получите исчерпывающую информацию о синтаксисе метода SaveAs: 236 Глава 10 СИНТАКСИС expression.SaveAs(FileName, FileFormat, LockComments, Password, AddToRecentFiles, WritePassword, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter} Все параметры метода, кроме expression, — необязательные и описываются в справочной системе следующим образом: expression — выражение, возвращающее объект Document. FileName — аргумент типа Variant. Является новым именем сохраняемого документа. По умолчанию это — текущие папка и имя файла. Если документ еще ни разу не сохранялся, используется имя по умолчанию (например, Docl.doc). Если документ с именем FileName уже существует, он будет перезаписан без сообщения об этом пользователю. FileFormat — аргумент типа Variant. Формат, в котором сохраняется документ. Может быть одной из следующих WdSaveFormat-констант: wdFormat-Document, wdFormatDOSText, wdFormatDOSTextLineBreaks, wdFormatEn-codedText, wdFormatHTML, wdFormatRTF, wdFormatTemplate, wdFormat-Text, wdFormatTextLineBreaks или wdFormatUnicodeText. LockComments — аргумент типа Variant. Чтобы блокировать документ для комментариев, должен иметь значение True. Password — аргумент типа Variant. Строка пароля для открытия документа. AddToRecentFiles — аргумент типа Variant. True — для добавления имени файла к списку недавно используемых документов в меню File. WritePassword — аргумент типа Variant. Строка пароля для сохранения изменений в документе. ReadOnlyRecommended — аргумент типа Variant. True — для того, чтобы Word устанавливал статус «только на чтение» при открытии документа. EmbedTrueTypeFonts — аргумент типа Variant. True — для сохранения TrueType-шрифтов вместе с документом. SaveNativePictureFormat — аргумент типа Variant. Если в документ импортировались графические изображения других платформ (например, Macintosh), True — для сохранения только Windows-версии импортированных изображений. SaveFormsData — аргумент типа Variant. True — для сохранения данных, введенных пользователем в форму как записи. SaveAsAOCELetter — аргумент типа Variant. Если документ имеет прикрепленный файл электронной почты, True — для сохранения документа как АОСЕ-письма (файл электронной почты сохраняется). В справочной системе очень подробно приведено описание каждого метода, и следует почаще прибегать к ее услугам. Впрочем, Редактор VBA постоянно предлагает эту помощь в процессе вашей работы с ним. Объявление объектных переменных Возможно, вы помните из главы, посвященной типам данных, что в дополнение к типам Byte, Integer, Long, Single, Double и String VBA также имеет тип Object. Переменные или выражения типа Object ссылаются на объект VBA или на объект, принадлежащий host-приложению, такой как Excel-объекты Workbook, Worksheet и Range или Word-объекты Document, Range, Paragraph. Как и в случае с другими типами VBA, можно объявлять переменные в модулях, процедурах и функциях с определенным типом Object, что показано в следующем операторе: Dim myObject As Object Объекты и коллекции, введение 237 Можно задавать переменную myObject, создаваемую предшествующим оператором Dim, чтобы она содержала ссылку на любой объект VBA или объект host-приложения. Если вы собираетесь использовать переменную типа Object для некоторых специфических типов объектов, можно также объявлять объектную переменную для этого специфического типа объекта: Dim InstBook As Workbook Объектную переменную InstBook, создаваемую этим оператором Dim, можно использовать только для сохранения ссылок на объекты Workbook; при попытке присвоить переменной InstBook ссылку на объект Range или Worksheet VBA отображает сообщение об ошибке несовпадения типов. Аналогично, следующее предложение объявляет объектную переменную, которая может сохранять только объекты Document: Dim InstDoc As Document Можно использовать VBA-функцию IsObject для определения того, образует ли переменная или выражение допустимую объектную ссылку. Функция IsObject имеет следующий синтаксис: СИНТАКСИС IsObject(Object) Object представляет переменную или выражение, которое необходимо протестировать; IsObject возвращает значение True, если Object является допустимой объектной ссылкой, и False — иначе. Для определения объектного типа переменной, можно также использовать VBA-функцию TypeName (в предыдущих главах эта функция уже применялась). Объект в выражениях Объектное выражение (object expression) — это любое выражение VBA, которое определяет отдельный объект. Все объектные выражения должны вычисляться до единственной объектной ссылки (ссылки на объект); объектные выражения используются с единственной целью — создание ссылок на специфические объекты в ваших программах VBA. Объектное выражение может состоять из объектных переменных, объектных ссылок или объектного метода или свойства, которое возвращает объект. Все последующие примеры являются правильными объектными выражениями (использующими объекты Excel): Application Имя объекта: ссылается на объект приложения Application. ActiveSheet Объектное свойство, которое возвращает ссылку на объект: активный лист Application. W orkbooks Объектный метод, который возвращает коллекцию объектов: все открытые рабочие книги ABook Объектная переменная: инициализированная в операторе Set, ссылается на объект Нельзя использовать переменные типа Object или объектные выражения в арифметических, логических или операциях сравнения. Объектная ссылка, созданная с помощью объектного выражения или сохраненная в объектной переменной, в действительности, является только адресом, указывающим место в памяти компьютера, где сохранен объект, на который выполняется ссылка. Поскольку 238 Глава 10 объектная ссылка — это адрес памяти, арифметические, логические операторы и операторы сравнения не имеют смысла. Перед использованием объектной переменной для ссылки на объект необходимо задать эту переменную, чтобы она содержала ссылку на нужный объект. Присваивание объектной ссылки объектной переменной отличается от присваиваний других переменных; чтобы присвоить объектную ссылку объектной переменной, используйте оператор Set. • Оператор Set имеет следующий синтаксис: СИНТАКСИС Set Var = Object Var — это любая объектная переменная или переменная типа Variant. Object — любая допустимая объектная ссылка; это может быть другая объектная переменная или объектное выражение. Если Var — переменная, объявленная с каким-либо определенным типом (например, Range или Workbook), этот тип должен быть совместим с объектом, на который ссылается Object. В следующем фрагменте программы типы переменной и объектов используются правильно (для объектов Excel): Dim InstSheet As Worksheet Set InstSheet = Application.ActiveSheet Следующий фрагмент программы VBA имеет в результате ошибку несовпадения типов потому, что свойство ActiveSheet возвращает объект Worksheet, а не Workbook: Dim InstBook As Workbook Set InstBook = Application.ActiveSheet Чтобы задать отдельный объект в выражении или объектную переменную для ссылки на этот объект, используйте методы и свойства, возвращающие объекты, такие как свойства Active Workbook и ActiveSheet объекта Application или метод Cells объекта Worksheet (в Excel). Аналогичные принципы применимы в Word: используйте свойство ActiveDocument объекта Application для получения ссылки на текущий документ и так далее. Хотя стандартные операторы сравнения (<, <=, >, >=, о, =) не являются значимыми при использовании с объектами, VBA предоставляет один оператор сравнения, предназначенный исключительно для использования с объектными выражениями и переменными — оператор (операцию) Is. Оператор Is имеет следующий синтаксис: СИНТАКСИС Objectl Is Object2 Object 1 и Object2 — любые допустимые объектные ссылки. Используйте оператор Is для определения того, обозначают ли две объектные ссылки один и тот же объект. Результат операции сравнения Is равен True, если объектные ссылки являются одними и теми же, иначе — False. В листинге 10.5 показана VBA-процедура для Excel, выполняющая резервную копию активной рабочей книги. Можно использовать подобную процедуру, если необходимо предоставить пользователю легкий способ сохранять копию активной рабочей книги под другим именем без изменения имени файла активной рабочей книги в памяти, как это делается с помощью команды File | Save As (Файл | Сохранить как...). Объекты и коллекции, введение 239 Листинг 10.5. Процедура создания резервной копии активной рабочей книги 1 Sub SaveActiveBook() 2 ' Создает копию активной рабочей книги под новым именем, 3 1 используя метод SaveCopyAs. Новое имя имеет добавку "_Ьр" 4 5 Dim FName As String 1 имя файла-копии 6 Dim OldComment As String ' комментарии 7 8 ' сохранить комментарии исходного файла 9 OldComment = ActiveWorkbook.Comments 10 11 ' добавить новые комментарии к backup-файлу 12 ActiveWorkbook.Comments = "Резервная копия файла " & _ 13 ActiveWorkbook.Name & _ 14 ", выполненная процедурой SaveActiveBook" 15 16 1 Сформировать новое имя файла из исходного 17 FName = Left(ActiveWorkbook.Name, _ 18 InStr(ActiveWorkbook.Name, ".") - 1) & "_bp.xls" 19 20 ' добавление к имени файла пути 21 FName = ActiveWorkbook.Path & s FName 22 23 ActiveWorkbook.SaveCopyAs Filename:=FName 24 ActiveWorkbook.Comments = OldComment ' восстановить комментарии 25 End Sub В этой процедуре используются два объекта Excel, их свойства и методы. Объектная ссылка ActiveWorkbook является свойством Excel-объекта Application, которое возвращает объектную ссылку на активную в данный момент рабочую книгу. (В следующем разделе вы узнаете, что обычно можно опускать объектную ссылку для свойств и методов объекта Application.) В строке 9 копируется строка свойства Comments объекта ActiveWorkbook в переменную OldComment. Затем в строках 12-14 задается новое значение для свойства Comments объекта ActiveWorkbook (это свойство изменяется и для исходной рабочей книги). Свойство Comments этого объекта содержит текст комментария, обычно вводимого вами в диалоговое Properties (Окно свойств), которое Excel отображает при сохранении рабочей книги в первый раз или при использовании команды File | Properties (Файл | Свойства). На рис. 10.8 приведено окно Properties для файла, который был получен в результате резервного копирования. Обратите внимание на поле Comments. В этом поле должен находиться текст, который можно получить, если перед строкой 16 вставить оператор: MsgBox ActiveWorkBook.Comments В строках 17-19 формируется имя нового файла из имени текущего. Этот оператор использует функции Left и InStr, помогая создать новое имя файла для резервной копии активной рабочей книги. Функция InStr возвращает положение разделителя имени файла (.) в свойстве Name объекта ActiveWorkbook. (Свойство Name рабочей книги содержит имя файла рабочей книги). Результат функции InStr определяет, сколько символов функция Left копирует из свойства Name объекта ActiveWorkbook. Поскольку функция InStr возвращает позицию разделителя имени файла (.), Left возвращает имя файла, не включая разделитель и расширение XLS. К полученному имени добавляется строка "_bp.xls". В строке 21 к пути, получаемому при помощи метода ActiveWorkbook.Path, добавляется имя нового файла. Строка 23 использует метод ActiveWorkbook.SaveCopyAs для сохранения активной рабочей книги с новым именем файла на текущем диске и каталоге; имя файла активной рабочей книги в памяти остается тем же. 240 Глава 10 Рис. 10.8 Убедитесь в правильности комментариев при резервном копировании активной рабочей книги Наконец, в строке 24 восстанавливается оригинальное содержимое свойства ActiveWorkbook.Comments; файл активной рабочей книги теперь находится точно в таком же состоянии, в каком он был перед тем, как начинается выполнение этой процедуры. Ссылка на объекты с помощью With...End With Как видно из листинга 10.5, процедуры могут ссылаться на один и тот же объект часто с помощью нескольких операторов в одной строке. Каждый оператор в листинге 10.5 в строках с 9 по 23 использует свойство или метод объекта, на который ссылается Active Workbook. VBA предоставляет особую структуру — структуру With...End With, позволяющую ссылаться на свойства или методы, которые принадлежат одному и тому же объекту, без задания всей объектной ссылки каждый раз. Структура With...End With имеет следующий синтаксис: СИНТАКСИС With Object ' операторы, использующие свойства и методы Object End With Object — это любая допустимая объектная ссылка. В листинге 10.6 показана процедура SaveActiveBook2, на этот раз со структурой With...End With. Листинг 10.6. Добавление к процедуре SaveActiveBook структуры With...End With 1 2 3 1 Sub SaveActiveBook?() 2 1 Создает копию активной рабочей книги под новым именем, 3 ' используя метод SaveCopyAs. Новое имя имеет добавку "_Ьр2" Объекты и коллекции, введение 241 4 5 Dim FName As String 'имя файла-копии 6 Dim OldComment As String 'комментарии 7 8 With ActiveWorkbook 9 ' сохранить комментарии исходного файла 10 OldComment = .Comments 11 12 ' добавить новые комментарии к backup-файлу 13 .Comments = "резервная копия файла " s .Name S _ 14 ", выполненная процедурой SaveActiveBook2" 15 16 ' Сформировать новое имя файла из исходного 17 FName = Leftf.Name, InStr(.Name, ".") - 1) & "_bp2.xls" 18 19 FName = .Path & "\" S FName 20 21 .SaveCopyAs Filename:=FName 22 .Comments = OldComment 'восстановить комментарии 23 End With 24 End Sub Эта версия процедуры работает точно так же, как показанная в листинге 10.5. Здесь используется структура With...End With. Строка 8 начинается с ключевого слова With, за которым следует объектная ссылка ActiveWorkbook, начиная таким образом всю структуру With...End With. В строке 10 содержимое свойства ActiveWorkbook.Comments присваивается строковой переменной OldComment. Заметим, что на этот раз только точка-разделитель (.) включается в начало свойства Comments. Поскольку этот оператор находится внутри структуры With ActiveWorkbook, VBA «знает», что объектной ссылкой для свойства .Comments является ActiveWorkbook. Все сказанное относится ко всем остальным операторам, использующим свойства объекта ActiveWorkbook. Наконец, строка 23 завершает структуру With...End With ключевыми словами End With. Не забывайте сохранять любые данные, которые хотите изменить только на некоторое время. Процедура SaveActiveBook2, например, изменяет свойство Comments активной рабочей книги. SaveActiveBook2 использует переменную для сохранения оригинального комментария перед выполнением изменений, а затем восстанавливает оригинальный комментарий. Не следует получать данные ввода от пользователя, если они вам действительно не нужны. Процедура SaveActiveBook2 могла бы быть записана с оператором InputBox для получения имени файла вместо генерации этого имени автоматически. Автоматическое генерирование обеспечивает то, что резервные файлы, создаваемые этой процедурой, легко идентифицируются и пользователю не приходится выполнять ввод имени файла. Генерирование нового имени файла в процедуре устраняет также потенциальные проблемы, связанные с вводом неверного имени файла пользователем. Очевидно, что набор кода листинга 10.6 требует меньших усилий, чем набор кода листинга 10.5; такой код к тому же легче читать и понимать. Упрощайте свой код, используя структуру With...End With всякий раз, когда у вас несколько программных операторов используют свойства или методы одной объектной ссылки. Работа с коллекциями объектов и контейнерами объектов Коллекция (collection) объектов — это группа связанных объектов, таких как все рабочие листы в рабочей книге или все символы в параграфе. Объект в коллекции называется элементом (element) этой коллекции. 242 Глава 10 Сама коллекция является объектом; коллекции имеют собственные свойства и методы. Каждая коллекция, например, имеет свойство Count, которое возвращает число элементов в коллекции. Если в активной рабочей книге имеется 16 рабочих листов, то следующее выражение вычисляется до числа 16: Application.ActiveWorkbook.Worksheets Count В этом выражении Worksheets — коллекция всех рабочих листов в рабочей книге, ActiveWorkbook — свойство Excel-объекта Application, возвращающее активную рабочую книгу, a Count — свойство коллекции Worksheets, возвращающее общее число рабочих листов в коллекции. Это простое выражение помогает проиллюстрировать то, что одни объекты содержат другие объекты. Контейнер (container) — это любой объект, содержащий один или несколько других объектов. В данном примере Application содержит объект, на который ссылается ActiveWorkbook, содержащий в свою очередь, коллекцию объектов Worksheets. Все контейнерные объектные ссылки соединяются вместе с помощью точки-разделителя (.) для образования одного объектного выражения. Многие объекты содержат другие объекты различных типов: рабочая книга содержит объекты Module, Chart и Worksheets; рабочий лист может содержать объекты DrawingObjects, ChartObjects или OLEObjects. На рис. 10.9 в окне справочной системы показана диаграмма объектов Excel 2000/2002 — коллекция Рис. 10.9 Excel-коллекция Application в справочной системе VBA [Application ^Workbooks (Workbook) Microsoft Excel Objects “[Addins (Addin) •[ Worksheets (Worksheet) } -[Charts (Chart) [^ -[Answer ~j AutoCorrect -|DocumentProperties (DocumentProperty)l -[Assistant -jVBProject | -[CustomViews (CustomView) | -[CommandBars (CommandBar) [ jHTMLProject [ -[ptvotCaches (PivotCache) | -[Styles (Style) | -[Borders (Border) “{Font Hlnterror -[Windows (Window) | Црапез (Pane) ~ -[Names (Name) | -[RoutingShp I -[PublishObjects (PubllshObject) | -[SmartTagOptions | -[WebOpbons | -[AutoRecover -[CellFormat | •jCOMAddlns (COMAddln) | -[Debug | -[Dialogs (Dialog) | -[commandBars (CommandBar) ] -jErrorCheckingOptions ~[LanguageSettings -[Names (Name) “[Windows (Window) Црапе! (Pane) ~ ~~|WorksheetFunction -[RecentFiles (RecentFile) -[SmartTaqRecognizers ^-jSmartTagRecognizer Legend О Object and collection D Object only )► Click arrow to expand chart “[Speech -jSpellingOptlons -[FileSearch ~~|V8E -[ODBCErrors (ODBCError) -[OLEDBErrors (OLEDBError) -[DefaultWehOptions -[UsedObjects -[Watches l~jWatch [iRtdServer [iRTDUpdateEvent ~ J Объекты и коллекции, введение 243 Application, из которой видно, что одни объекты этой коллекции содержат другие. На рис. 10.10 показана диаграмма объектов коллекции Application.Worksheets. Подобную иерархию имеет и коллекция Application.Charts. На рис. 10.11 (также в окне справочной системы) показана диаграмма объектов Word 2000/2002 — коллекция Application, а на рис. 10.12 — коллекция Documents. Иерархия объектов и контейнеров, показанная на рис. 10.9-10.12, называется объектной моделью (object model). Как вы уже могли заметить, стрелки на диаграмме рядом с некоторой коллекцией (например, Worksheets рис. 10.9) указывают на то, что данная коллекция имеет в справочной системе подобную диаграмму (рис. 10.10), которую также можно вывести на экран. Коллекции, содержащие не только объекты, но и коллекции, окрашены желтым цветом, а содержащие только объекты — синим. Рис. 10.10 Excel-коллекция Application.Worksheets в справочной системе VBA Справка .Microsoft Visual Basic Contents; Мастер ответов Укй-jjH Microsoft Excel Objects (Worksheet) I-Г® 1 Введите кгкчееые слова jObject model Очистить [ Нацти | 2 Или выберите ключевые слова [add m ^automate automate automation chart COM component 3 Выберите раздел (найдено 6) Mcrosoft Excel Objects Microsoft Excel Objects (ChartGroups Microsoft Excel Objects (Charts) Microsoft Excel Objects (Shapes) Understanding Automation [Worksheets (Worksheet) •{Names (Name) 4'Ranqe •{Areas ~ •{Borders (Border) ~ •{Errors ЧЁггоГ •{Font ~ 4intenoF •{Characters LjFont ' ilMame -iStyle ___ _ •{Borders (Border) •{Font M Interior -(FormatConditions (FormatCondition)l •{HypaUrfe (Hyperlink) I -(Validation ~ I •{Comment 1 {Comments (Comment) I •fQjstomProperBes П ^CustoinProperty I •iHPaqeBreaks (HPaqeBreakTI •{VPaqeBreaks (VPageBreak)! •{Hyperlinks (Hyperlink)" "1 •{Scenarios (Scenario) I -jQLEObiects (OLEObiectFI -{Outline , , jPageSetup I ^Graphic ~~I •{QueryTabies (QueryTable)l ^Parameters (Parameter) ! •{PivotTables (PivotTable)! HCalculatedFields I ~{CalculatedMembers~~ I Ц C akutafedMernber -jCubeFields I ^CubeField ~ Объект Application и в Excel, и в Word называется внешним контейнером и содержит все другие объекты и коллекции. Например, Excel-объект Application (рис. 10.9) содержит коллекции Workbooks, Addins и другие; Workbooks — это коллекция всех открытых рабочих книг, a Addins — коллекция всех инсталлированных приложений-надстроек (Add-ins). Excel-коллекция Workbooks, в свою очередь, содержит коллекции Worksheets, Charts и т.д. Коллекция Worksheets содержит отдельные листы (рис. 10.10). На рис. 10.11 можно видеть, что объект Word Application содержит коллекции Documents — документы, Addins — надстройки, Dialogs — диалоги, Dictionaries — словари и много других коллекций. Некоторые коллекции Word Application сами содержат коллекции, например, коллекция Documents — это коллекция всех открытых документов (рис. 10.12). Рис. 10.9-10.12 дают представление о том, как определять сложные объектные ссылки. Чтобы указать VBA, на какой объект необходима ссылка, может понадобиться определить контейнер объекта. Для ссылки на определенный лист рабочей книги Excel, например, может быть необходимо включить ссылку на рабочую книгу, которая содержит этот рабочий лист: Workbook("Sales.xls").Worksheets("Отчет") 244 Глава 10 Microsoft Word Objects Рис. 10.11 Word-коллекция Application в справочной системе VBA •jEmailOption» | ] Z] zzj -iFtfeConverters | ^FJeConverter ] •jFHeDlalog | -fFHeSearch ~~] -jForrtNamei | HHangutHanjaConversionDictionartes] ^Dictionary | -jKeyBlndingt | LfreyBmtfafig I "[KeysBoundTo | ЦкеуВшЛпд ~~""П -jLanguages | i~|l.M>guage ~~ " | 4Dktionary j •jLanguageSettings j -jLfotGallerte» | LjlbtbJIery | nlistTemplates | Legend □ object and collection □ object only Click red arrow to expand chart Рис. 10.12 Word-коллекция Application.Documents в справочной системе VBA ;^Слраяка Microsoft Visual Basic Contents j Мастер ответов Як.«]Л 1 ^ведите ключевые слова pbject. Очистить Найти I 2. Или выберите ключевые слова Э-D л | abbreviation ' Accelerator ( accent > AccentedLetters accept AcceptAll v » 3. Выберите раздел (найдено 599) , Documents Collection Object (Application I ^Documents (Document) I Acofe : open I. Bookmarks Collection Object Characters CoSecoon Object ComrrandBars Collection Object Comments Collection Object Documentproperties Collection Object Usln< Use th Emad Object collect] Endnotes Collector । Ofrect open Envelope Object -e currently •cuments imes of the Ш ® ® йг- Object Property KeysBoundTo Collection Object Interaction (Object Browser) Set Reference to a Type Lbran * For Each aDoc In Documents aName = aName & aDoc.Name & vbCiv В данном объектном выражении используется Excel-коллекция Workbooks для ссылки на рабочую книгу Sales.xls, а затем используется коллекция Worksheets, содержащаяся в объекте рабочей книги Sales.xls, для ссылки на конкретный лист. (Как обозначаются отдельные элементы в коллекции, описывается немного дальше в этой главе.) Следующий пример выражения показывает еще более сложную объектную ссылку: Application.Workbooks("Sales.xls").Worksheets("Отчет").Range("Al") Здесь объектное выражение ссылается на ячейку А1 в листе Отчет рабочей книги Sales.xls. Как видно из этих двух примеров, определение полной объектной ссылки посредством всех контейнеров объекта может быть довольно утомительным. К счастью, VBA позволяет опускать объектную ссылку Application почти Объекты и коллекции, введение 245 для всех объектов, которые содержит объект Application. Если опускается объектная ссылка Application, VBA «полагает», что имеется в виду host-приложение, и подставляет ссылку автоматически. Следующее объектное выражение ссылается на тот же объект, что и предыдущее выражение (ячейка А1 в листе Отчет рабочей книги Sales.xls): Workbooks ("Sales . xls") .Worksheets ("Отчет") .RangefAl") Вам необходимо определять Excel-объектную ссылку Workbooks только тогда, когда ссылка может быть неоднозначной или при использовании встроенных функций рабочих листов Excel. Если Excel-объектная ссылка Workbooks (или объектная ссылка Documents в Word) опускается, VBA обычно (но не всегда) «полагает», что имеется в виду текущая активная рабочая книга или документ. Следующее объектное выражение эквивалентно предыдущему при условии, что рабочая книга Sales.xls является активной: Worksheets("Отчет").Range("Al") Если Sales.xls — активная рабочая книга, а Отчет — активный лист, то следующее объектное выражение также эквивалентно предыдущему: Range("Al") Однако во многих процедурах невозможно определить с уверенностью, что какая-либо отдельная рабочая книга (рабочий лист или документ) является активной, во время выполнения процедуры, поэтому, вероятно, потребуется определить, по крайней мере, некоторые из контейнеров для объекта, на который необходима ссылка. Не забывайте использовать методы и свойства, возвращающие объекты (такие как ActiveWorkbook и ActiveDocument ), чтобы делать контейнерные объектные ссылки короче. Использование структуры With...End With является идеальным способом избежать записи длинных объектных ссылок более одного или двух раз в одной процедуре. Чтобы лучше понять контейнерные объекты и коллекции, необходимо помнить, что программный объект не является физическим предметом, находящимся в другом физическом предмете. Помните, что объект, содержащий другой объект, на самом деле просто имеет адрес памяти другого объекта. Контейнеры ссылаются на объекты, которые они «содержат», посредством их адресов. Точно так, как многие различные люди могут иметь ваш почтовый адрес, но вы не присутствуете физически в их доме, на любой отдельный программный объект могут ссылаться несколько других объектов через его адрес. При необходимости ссылаться на контейнер какого-либо объекта используйте свойство Parent этого объекта. Все объекты имеют свойство Parent, которое возвращает объектную ссылку на контейнер объекта. Например, следующее объектное выражение ссылается на Excel-объект Application, содержащий коллекцию Workbooks: Workbooks.Parent В табл. 10.7 перечислены несколько наиболее часто используемых коллекций объектов в Excel 2000/2002 версии Visual Basic for Applications. В таблице приводится имя коллекции и краткое описание ее назначения. Таблица 10.7. Общие коллекции Excel 2000/2002 Коллекция Назначение Addins Коллекция надстроек приложения. Charts Коллекция всех таблиц (Chart sheets) в рабочей книге. 246 Глава 10 Коллекция Назначение Chartobjects Коллекция всех объектов Chart в рабочем листе. Dialogs Коллекция всех диалогов в приложении. Windows Коллекция всех окон в приложении, независимо от того, отображается ли окно на экране. Workbooks Коллекция всех открытых в данных момент рабочих книг в приложении. Worksheets Коллекция всех рабочих листов в рабочей книге. В табл. 10.8 перечислены некоторые наиболее часто используемые коллекции объектов в Word 2000/2002 версии VBA. В таблице приводится имя коллекции и краткое описание ее назначения. Таблица 10.8. Общие коллекции Word 2000/2002 Коллекция Назначение Addins Коллекция надстроек приложения. Bookmarks Коллекция всех закладок в документе, разделе или диапазоне (в зависимости от контейнера). Characters Коллекция всех символов в документе, разделе или диапазоне (в зависимости от контейнера). Каждый элемент в коллекции Characters является объектом Range, содержащим один символ. Comments Коллекция всех комментариев документа. Dialogs Коллекция диалогов приложения. Documents Коллекция всех открытых в данный момент документов. Paragraphs Коллекция объектов Paragraph в документе, разделе или диапазоне (в зависимости от контейнера). Sections Коллекция разделов в документе, разделе или диапазоне (в зависимости от контейнера). Styles Коллекция описаний стилей в документе для встроенных и определенных пользователем стилей. Templates Коллекция всех шаблонов приложения. Windows Коллекция всех окон в приложении или коллекция всех окон (отображающих документ в зависимости от контейнера). Добавление к коллекциям Большую часть времени вы будете работать с элементами, уже существующими в коллекции. Время от времени будет необходимо добавить какой-либо элемент в коллекцию. В Excel вы, вероятно, захотите создать новую рабочую книгу или добавить новый рабочий лист в рабочую книгу; в Word нужно будет создать новый документ или добавить новую закладку в документ. В этих случаях необходимо добавлять новый элемент в соответствующую коллекцию объектов. Каждая коллекция имеет метод Add (это один из базовых методов коллекции), который добавляет новый элемент в эту коллекцию. Многие из методов Add имеют один или несколько аргументов, которые позволяют задавать различные начальные значения или условия для свойств новых объектов. Следующий опера Объекты и коллекции, введение 247 тор показывает метод Add коллекции Workbooks, используемый для создания новой рабочей книги Excel: Workbooks.Add Этот оператор создает новую рабочую книгу и делает ее активной. Следующий оператор показывает метод Add коллекции Documents, используемой для создания нового документа Word: . Documents.Add Этот оператор создает новый документ и делает его активным. Ссылка на конкретные объекты в коллекции или контейнере Для задания отдельного элемента в коллекции используйте следующий синтаксис: СИНТАКСИС Collection (Index) Collection — любое допустимое объектное выражение, ссылающееся на коллекцию. Index может быть либо строкой, либо целым, обозначающим конкретный необходимый элемент. Если аргумент Index является строкой, строка должна содержать текстовое имя объекта. Например, в Excel можно использовать имя рабочего листа (показано на ярлычке листа), именованного диапазона в рабочем листе, файла рабочей книги, кнопки панели инструментов или команды меню и так далее в качестве Index для соответствующей коллекции. Например, для ссылки на рабочий лист с именем Данные июля в активной рабочей книге следует использовать такой оператор: Worksheets("Данные июля") В Word можно использовать имя файла документа, закладки, стиля и так далее в качестве аргумента Index для коллекции. Например, для ссылки на закладку с именем Последняя закладка в документе Отчет за июль нужно использовать следующий оператор: Documents("Отчет за июль").Bookmarks("Последняя закладка") Когда Index — целое, оно является номером элемента в коллекции. Каждый элемент нумеруется в том порядке, в котором он добавляется в коллекцию. Поэтому не существует легкого способа определения индексного номера любого данного элемента коллекции. Обычно следует использовать текстовое имя для ссылки на элемент в коллекции; это не только позволяет точно определить, на какой элемент необходима ссылка, но и делает код более читабельным. Worksheets("OT4eT”) гораздо понятнее, чем Worksheets(5). Для ссылки на все элементы в коллекции не включайте никакого индекса. Следующий оператор закрывает все видимые открытые рабочие книги в Excel: Workbooks.Close Следует помнить о том, что методы и свойства в объекте Application принадлежат host-приложению, а не VBA. Когда вы работаете с различными host-прило-жениями VBA, некоторые из методов и свойств в объекте Application могут варьироваться в зависимости от конкретного host-приложения: Excel 2000/2002, Word 2000/20 02 и т.д. Не забывайте, что объект Application предоставляет много полезных методов и свойств, а также предоставляет контейнер для объектов host-приложения. Например, помните, что Excel-функции рабочего листа, такие как SUM, MIN, MAX 248 Глава 10 и так далее, доступны через объект Application. Word-объект Application содержит методы для преобразования дюймов в точки, точек в дюймы и другие. Как уже отмечалось, объект Application может содержать методы с именами, дублирующими имена процедур или функций VBA. При использовании метода host-приложения, дублирующего имя процедуры или функции VBA, необходимо задавать объект Application, иначе VBA «полагает», что вы хотите использовать процедуру или функцию VBA. Например, Excel-объект Application содержит метод InputBox. Excel-метод InputBox — это не то же самое, что VBA-функция InputBox: Excel-метод Application.InputBox имеет на один аргумент больше (подробно описано в конце главы 6), чем VBA-метод InputBox; этот дополнительный аргумент позволяет ограничивать тип данных (численный, даты, текстовый), вводимый пользователем в диалоговое окно. Чтобы использовать Excel-метод InputBox, необходимо задать объект Application: Application.InputBox В противном случае VBA «полагает», что вы хотите использовать VBA-функ-цию InputBox. Фигуры в слое векторной графики VBA поддерживает общую модель объектов слоя векторной графики в Microsoft Word, Microsoft Excel и Microsoft PowerPoint. Верхним уровнем этой модели является коллекция Shapes, содержащая все графические объекты (Shape-объекты), которые включаются в слой векторной графики. Кроме коллекции Shapes, можно в качестве коллекции нескольких Shape-объектов использовать коллекцию ShapeRange, объединяющую некоторое подмножество фигур в векторном слое (часть коллекции Shapes). Добавление к коллекции Shapes «автофигур» Прежде чем работать с Shape-объектом, необходимо добавить его к (быть может, пока еще пустой) коллекции Shapes, используя ее метод AddShapes: СИНТАКСИС expression.AddShape(Type, Left, Top, Width, Height) Здесь expression — любое Shapes-выражение; Type — константа (тип Long), определяющая тип фигуры и принимающая одно из msoAutoShapeType-зна-чений (например, msoShapeFlowchartData, msoShapeFlowchartMerge, msoS-hapeLeftBracket, msoShapcRectangle, msoShapeHeart, msoShapeRightTri-angle, msoShapeHexagon, msoShapeHorizontalScroll, msoShapeWave — всего около 140 констант); Left — положение (тип Single) левого угла автофигуры (измеряется в «пойнтах»); Тор — положение (тип Single) верхнего угла автофигуры; Width— ширина (тип Single) автофигуры; Height — высота (тип Single) автофигуры. При добавлении в коллекцию Shapes фигура получает имя (свойство Name) по умолчанию, но его можно указать, используя следующий синтаксис: expression.AddShape(Type, Left, Top, Width, Height) .Ыате=<и^1я фигуры> Для получения ссылки на всю коллекцию объектов в слое векторной графики необходимо использовать следующий синтаксис: СИНТАКСИС mDocument.Shapes.SelectAll Объекты и коллекции, введение 249 В листинге 10.7 приведен код, использующий метод AddShape для добавления фигур к коллекции Shapes текущего документа Word. На рис. 10.13 добавленные фигуры отображены в текущем документе. Листинг 10.7. Добавление фигур к документу 1 Sub ActDocumShapes() ♦ 2 ' добавление фигур к документу 3 4 ' добавить к коллекции Shapes прямоугольник: 5 ActiveDocument.Shapes.AddShape(msoShapeRectangle, _ 6 150, 150, 70, 70).Name = "Rectangle" 7 8 ' добавить к коллекции Shapes правый треугольник: 9 ActiveDocument.Shapes.AddShape(msoShapeRightTriangle, _ 10 300, 150, 70, 40).Name = "RightTriangle" 11 12 ' добавить "горизонтально ракручивающийся лист": 13 ActiveDocument.Shapes.AddShape(msoShapeHorizontalScroll, 14 450, 150, 70, 90).Name = "Horizontalscroll" 15 16 ' выделить все фигуры коллекции: 17 ActiveDocument.Shapes.SelectAll 18 19 End Sub Рис. 10.13 Добавленные к коллекции Shapes фигуры отображены в текущем документе В листинге 10.8 приведен код, использующий метод AddShape для добавления фигур к коллекции Shapes первого слайда1 текущей презентации. На рис. 10.14 добавленные фигуры отображены на слайде 1 текущей презентации. Листинг 10.8. Добавление фигур к презентации 1 2 3 4 5 6 1 Sub ActPreShapes() 2 ' добавление фигур к первому слайду текущей презентации 3 4 ' добавить фигуру к коллекции Shapes: 5 ActivePresentation.Slides(1).Shapes.AddShape( _ 6 msoShape24pointStar, 150, 150, 70, 70).Name = "pointStar24" 1 Подобно листам в Excel в PowerPoint имеется коллекция слайдов. 250 Глава 10 7 8 ' добавить фигуру к коллекции Shapes: 9 ActivePresentation.Slides(1).Shapes.AddShape( _ 10 msoShape32pointStar, 250, 150, 200, 120).Name = "pointSta32" 11 End Sub Рис. 10.14 Добавленные к коллекции Shapes фигуры отображены на первом слайде текущей презентации ^Microsoft PowerPoint - [Презентация 11 ; гл -spj Файл Ставка Вид Вставка Формат Сервис Показ слайдов Окно £гравка Действия ” । tfr Автофис/ры» u J [ 1 4 t ’ 2 ’ 4 • ” Слайд 1 из 1 кормление по умолчана русский (Россия) Чтобы получить коллекцию ShapeRange, являющуюся подмножеством коллекции Shapes, необходимо использовать следующий синтаксис: СИНТАКСИС Shapes.Range(index) Здесь index — имя/индекс фигуры или массив имен/индексов фигур. Чтобы получить коллекцию ShapeRange, представляющую все фигуры коллекции Shapes, необходимо использовать следующий синтаксис: СИНТАКСИС Selection ShapeRange Чтобы получить коллекцию ShapeRange, представляющую все фигуры коллекции Shapes, необходимо использовать следующий синтаксис: СИНТАКСИС Selection.ShapeRange(index) Здесь index — имя/индекс фигуры или массив имен/индексов фигур. Например, при помощи кода листинга 10.9 можно «закрасить» фигуры, созданные кодом листинга 10.7. На рис. 10.15 отображены закрашенные фигуры. Листинг 10.9. Использование коллекции ShapeRange 1 Sub ActDocumShapeRange() 2 ' Использование коллекции ShapeRange 3 Объекты и коллекции, введение 251 4 ' "закрасить" первые две фигуры в коллекции Shapes: 5 ActiveDocument.Shapes.Range(Array(1, 2)).Fill.PresetGradient 6 msoGradientHorizontal, 1, msoGradientLateSunset 1 8 ' выделить все фигуры коллекции: 9 ActiveDocument.Shapes.SelectAll 10 11 ' "закрасить" третью фигуру коллекции ShapeRange: 12 ActiveWindow.Selection.ShapeRange(3).Fill.PresetGradient _ 13 msoGradientVertical, 1, msoGradientLateSunset 14 15 End Sub Рис. 10.15 Добавленные к коллекции Shapes фигуры закрашены кодом листинга 10.9 ц! Chapter 10 - Microsoft Word файл фавка &дд Встдоа Формат Сервис Таблица фно Оправка 51 115% * * Listing top + Times N - Исправления в измененном документе - Показать* р . L. il>-2»3'-4-i5i6'7i8'9il0<llil2 Например, при помощи кода пистннга 10 9 можно '<закрэ«лпы> фигуры созданные кодом лисп Листинг 10.9. Использование коллекцип 1 1 2 3 4 5 б 7 8 9 ' 'закг Аспу nys< фигуры в коллекци ^ng^(Arr%v(l,2))Fjl 1. rnsoQfgdienii^Sunset 'выдедр ^*1ллекции 'Исполь^МвНм* ShapesRange 10 11 ' 'закрасить' третью фигуру коллекции ЗДареКадде 12 УШ PresetGradient 13 (Ti50Gr?dierity ?rti?al, 1, rn$o<ftadientMHSunset Стр 23 Разд 1 23/24 На S Зсм Ст 6 Кол 1 Добавление к коллекции Shapes специальных фигур Кроме добавления к коллекции Shapes документа (листа, презентации) «автофигуры» (методом AddShape), можно также добавлять специальные элементы оформления, используя такие методы, как AddCallout, AddComment и другие (см. таблицу 10.9). Таблица 10.9. Методы для добавления фигур в документы, листы или слайды Метод Синтаксис Назначение Word: AddCallout AddCallout( Type As MsoCalloutType, Left As Single, Top As Single, Width As Single, Height As Single, [Anchor]) As Shape Добавляет в документ не имеющую границ выноску. Возвращает Shape-объект, представляющий эту выноску, и добавляет его в коллекцию Shapes. AddCanvas AddCanvas( Left As Single, Top As Single, Width As Single, Height As Single, [Anchor]) As Shape Добавляет в документ «полотно» для рисования (drawing canvas). Возвращает Shape-объект, представляющий «полотно» для рисования, и добавляет его в коллекцию Shapes. 252 Глава 10 Метод Синтаксис Назначение AddCurve AddCurve( SafeArrayOfPoints, [Anchor]) As Shape Возвращает в документ Shape-объект, который представляет кривую Безье. AddDiagram AddDiagram( Type As MsoDiagramType, Left As Single, Top As Single, Width As Single, Height As Single, [Anchor]) As Shape Возвращает в документ Shape-объект, который представляет только что созданную диаграмму. AddLabel AddLabel(Orientation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single, [Anchor]) As Shape Добавляет в документ надпись в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет эту надпись, и добавляет его в коллекцию Shapes. AddLine AddLine(BeginX As Single, BeginY As Single, EndX As Single, EndY As Single, [Anchor]) As Shape Добавляет линию в документ. Возвращает Shape-объект, который представляет эту строку, и добавляет его в коллекцию Shapes. AddOLE-Control AddOLEControl([C/assTi/pe], [Left], [Top], [Width], [Height], [Anchor]) As Shape Создает элемент управления ActiveX (ранее известный как OLE-элемент управления). (Только в Word; в Excel и PowerPoint используйте AddOLEObject) Возвращает Shape-объект, который представляет новый элемент управления ActiveX. AddOLE-Object AddOLEObject([CZassTi/pe], [FileName], [LinkToFile], [DisplayAsIcon], [IconFileNante], [Iconindex], [IconLabel], [Left], [Top], [Width], [Height], [Anchor]) As Shape Создает OLE-объект. Возвращает Shape-объект который представляет новый OLE-объект. AddPicture AddPicture(FiZeName As String, [LinkToFile], [SaveWithDocument], [Left], [Top], [Width], [Height], [Anchor]) As Shape Добавляет картинку в документ. Возвращает Shape-объект, который представляет эту картинку, и добавляет его в коллекцию Shapes. AddPolyline AddPolyline(SafeAzrai/OfPoints, [Anchor]) As Shape Добавляет ломаную линию или многоугольйик в документ. Возвращает Shape-объект, который представляет эту ломаную линию или многоугольник, и добавляет его в коллекцию Shapes. Объекты и коллекции, введение 253 Метод Синтаксис Назначение AddTextbox AddTextbox(Onentation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single, [Anchor}) As Shape * Добавляет в документ прикрепленную текстовую рамку в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет эту текстовую рамку, и добавляет его в коллекцию Shapes. AddText-Effect AddTextEffec^PresetTextEffect As MsoPresetTextEffect, Text As String, FontName As String, FontSize As Single, FontBold As MsoTriState, Fontltalic As MsoTriState, Left As Single, Top As Single, [Anchor]) As Shape Добавляет WordArt-объект в документ. Возвращает Shape-объект, который представляет этот WordArt-объект и добавляет его в коллекцию Shapes. Excel: AddCallout AddCallout(Ti/pe As MsoCalloutType, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Добавляет в документ не имеющую границ выноску. Возвращает Shape-объект, представляющий эту выноску. Add-Connector AddConnector(Tz/pe As MsoConnectorType, BeginX As Single, BeginY As Single, EndX As Single, EndY As Single) As Shape Создает соединительную линию. Возвращает Shape-объект, который представляет новую соединительную линию. Когда добавляется соединительная линия,она не соединена ни с чем. AddCurve AddCurNe(SafeArrayOfPoints) As Shape Когда применяется к объекту коллекции Shapes, возвращает Shape-объект, который представляет кривую Безье в электронной таблице. AddDiagram AddDiagramCType As MsoDiagramType, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает диаграмму. Возвращает Shape-объект, который представляет новую диаграмму. AddForm AddFormControl(Ti/pe As XlFormControl, Left As Long, Top As Long, Width As Long, Height As Long) As Shape Создает элемент управления Microsoft Excel. Возвращает Shape-объект, который представляет новый элемент управления. AddLabel AddLabel(Orientation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Добавляет в документ надпись в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет эту новую надпись. 254 Глава 10 Метод Синтаксис Назначение AddLine AddLine(BeginX As Single, BeginY As Single, EndX As Single, EndY As Single) As Shape Когда применяется к объекту коллекции Shapes, возвращает Shape-объект, который представляет новую линию в электронной таблице. AddOLE- Object AddOLEObj ect([ClassType], [Filename], [Link], [DisplayAslcon], [IconFileName], [Iconindex], [IconLabel], [Left], [Top], [Width], [Height]) As Shape Создает OLE-объект. Возвращает Shape объект, который представляет этот новый OLE-объект. AddPicture AddPicture(Fi/ename As String, LinkToFile As MsoTriState, SaveWithDocument As MsoTriState, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает картинку из существующего файла. Возвращает Shape-объект, который представляет новую картинку. AddPolyline AddPolyline(SafeArrayOfPoints) As Shape Создает ломаную линию или многоугольник. Возвращает Shape-объект, который представляет новую ломаную линию или многоугольник. AddTextbox AddTextbox(Orientation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает прикрепленную текстовую рамку в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет новую текстовую рамку. AddText-Effect AddTextEffect(PresetTextEffect As MsoPresetTextEffect, Text As String, FontName As String, FontSize As Single, FontBold As MsoTriState, Fontltalic As MsoTriState, Left As Single, Top As Single) As Shape Создает WordArt-объект. Возвращает Shape-объект, который представляет новый WordArt-объект. PowerPoint: AddCallout AddCallout(Type As MsoCalloutType, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает не имеющую границ выноску. Возвращает Shape-объект, представляющий эту новую выноску Add- Comment AddComment([Left As Single = 1], [Top As Single = 1], [Width As Single = 145], [Height As Single = 145]) As Shape Добавляет комментарий. Возвращает Shape-объект, который представляет новый комментарий. Add-Connector 1 AddConnector(Type As MsoConnectorType, BeginX As Single, BeginY As Single, EndX As Single, EndY As Single) As Shape Создает соединительную линию. Возвращает Shape-объект, который представляет новую соединительную линию. Когда добавляется соединительная линия,она не соединена ни с чем. Объекты и коллекции, введение 255 Метод Синтаксис Назначение AddCurve AddCurve(SafeArrayOfPoints) As Shape Создает кривую Безье. Возвращает Shape-объект, который представляет новую кривую. AddDiagram AddDiagram(Type As MsoDiagramType, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Возвращает Shape-объект, который представляет диаграмму, вставленную в слайд, master-слайд или slide range-слайд. AddLabel AddLabel(Orientation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает надпись в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет эту новую надпись. AddLine AddLine(BeginX As Single, BeginY As Single, EndX As Single, EndY As Single) As Shape Создает линию. Возвращает Shape-объект, который представляет эту новую линию. AddMedia-Ob ject AddMediaObject(FileName As String, [Left As Single], [Top As Single], [Width As Single = -1], [Height As Single = -1]) As Shape Создает media-объект. Возвращает Shape-объект, который представляет новый media-объект. AddOLE- Ob ject AddOLEObject([Left As Single], [Top As Single], [Width As Single = -1], [Height As Single = -1], [ClassName As String], [FileName As String], [DisplayAslcon As MsoTriState], [IconFileName As String], [Iconindex As Long], [IconLabel As String], [Link As MsoTriState]) As Shape Создает OLE-объект. Возвращает Shape-объект, который представляет новый OLE-объект. AddPicture AddPicture(FileName As String, LinkToFile As MsoTriState, SaveWithDocument As MsoTriState, Left As Single, Top As Single, [Width As Single = -1], [Height As Single = -1]) As Shape Создает картинку из существующего файла. Возвращает Shape-объект, который представляет новую картинку. AddPlace-holder AddPlaceholder(Type As PpPlaceholderType, [Left As Single = -1], [Top As Single = -1], [Width As Single = -1], [Height As Single = -1]) As Shape Восстанавливает ранее удаленное поле для текста или графического объекта на слайде. Возвращает Shape-объект, который представляет это восстановленное поле. AddPolyline AddPolyline(SafeArrayOfPoints) As Shape Создает ломаную линию или многоугольник. Возвращает Shape-объект, который представляет новую ломаную линию или многоугольник. 256 Глава 10 Метод Синтаксис Назначение AddShape AddShape(Type As MsoAutoShapeType, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает автофигуру (AutoShape). Возвращает Shape-объект, который представляет эту новую автофигуру. AddTable AddTable(NumRows As Long, NumColumns As Long, [Left As Single = -1], [Top As Single = -1], [Width As Single = -1], [Height As Single = -1]) As Shape Добавляет объект-таблицу в слайд. AddTextbox AddTextbox(Orientation As MsoTextOrientation, Left As Single, Top As Single, Width As Single, Height As Single) As Shape Создает прикрепленную текстовую рамку в виде прямоугольника с невидимыми границами и без заливки. Возвращает Shape-объект, который представляет новую текстовую рамку. AddText-Effect AddTextEffect(PresetTextEffect As MsoPresetTextEffect, Text As String, FontName As String, FontSize As Single, FontBold As MsoTriState, Fontltalic As MsoTriState, Left As Single, Top As Single) As Shape Создает WordArt-объект. Возвращает Shape-объект, который представляет новый WordArt-объект. AddTitle AddTitle() As Shape Восстанавливает ранее удаленное заглавие слайда. Возвращает Shape-объект, который представляет восстановленное заглавие. Фигуры коллекции Shapes после их добавления в коллекцию можно редактировать: перемещать, удалять, изменять размеры, изменять внешний вид (как это, например, делается в коде листинга 10.9), добавлять в них текст. Редактирование фигур осуществляется изменением их свойств. Объекты коллекции Shapes обладают как общими (Left, Top, Height и Width), так и специфическими (зависящими от типа объекта) свойствами. Например, код листинга 10.10 сначала добавляет объект clock.avi к первому слайду презентации, а затем (строки 12-15) изменяет его высоту (свойство Height) и ширину (свойство Width). Результат работы кода листинга 10.10 представлен на рис. 10.16. Листинг 10.10. Изменение свойств фигуры коллекции Shapes 1 Sub PropertyChangingl() 2 ' добавление объекта к коллекции Shapes 3 ' и изменение его размеров 4 5 Set myDocument = ActivePresentation.Slides(1) 6 7 ' добавить объект к коллекции Shapes: 8 myDocument.Shapes.AddMediaOb^ect FileName:= _ 9 "e:\win_xp\clock.avi", Left:=5, Top:=5, _ 10 Width:=100, Height:=100 11 Объекты и коллекции, введение 257 12 ' изменение размеров объекта: 13 With myDocument.Shapes(3) 14 Height = 200 15 .Width = 200 16 End With 17 18 End Sub Рис. 10.16 Изменение размеров объекта коллекции Shapes кодом листинга 10 10 Код листинга 10.11 при добавлении к коллекции Shapes прямоугольника помещает в него текст. Результат работы кода листинга 10.11 (в Excel) представлен на рис. 10.17. Рис. 10.17 Ввод текста для объекта коллекции Shapes кодом листинга 10 11 Листинг 10.11. Изменение свойств фигуры коллекции Shapes 1 Sub PropertyChanging2() 2 ' добавление прямоугольника к коллекции Shapes 3 ' и занесение в него текста 4 5 Set myDocument = Worksheets(1) 6 7 9 Программирование на VBA 2002 258 Глава 10 8 With myDocument.Shapes.AddShape(msoShapeRectangle, _ 9 0, 0, 100, 40).TextFrame 10 .Characters.Text = "Пример текста внутри прямоугольника" 11 .MarginBottom = 10 12 .MarginLeft = 10 13 .MarginRight = 10 14 .MarginTop =10 15 End With 16 * 17 End Sub Использование Object Browser с объектами, методами и свойствами Вы уже знаете, как использовать Object Browser для нахождения и получения справки VBA и функций host-приложений, процедур и констант. Подобным образом Object Browser используется с объектами, методами и свойствами; в действительности, основное назначение инструмента Object Browser (как предполагает его имя) — это обеспечивать возможность просмотра всех доступных объектов (с их различными методами и свойствами) в VBA и host-приложении. Вы уже знаете, как запустить Object Browser: щелкните на кнопке Object Browser на панели инструментов Visual Basic или выберите команду View | Object Browser (Вид | Просмотр объектов) для отображения окна Object Browser (рис. 10.18). Рис. 10.18 Используйте Object Browser для определения того, какие объекты доступны и какие свойства и методы принадлежат определенному объекту Members of 'Documents' Classes «3 DiagramNode * <3 DiagramNodeCh <3 DiagramNodes 3 Dialog 3 Dialogs 3 Dictionaries 3 Dictionary 3 Document 3 Documents 3 DropCap 3 DropDown <Л| Prnsil v Й? Application CanCheckOut Checkout Close Й? Count Й* Creator Item Open & Parent * Save Function Add([7empjlate]4 [NewTempiate] [DocumentType], [Vte/bte]) As Dyurnent Member of Л i I P vtiti^iit Чтобы просмотреть список доступных объектов host-приложения и просмотреть список свойств и методов для каждого заданного объекта, выполните следующие шаги: 1. Выберите библиотеку host-приложения в раскрывающемся списке Project/Lib-rary (Проект | Библиотека) в верхней части окна Object Browser. На рис. 10.18 показано открытое окно Object Browser в сеансе работы Редактора VB в Word; библиотека Word уже выбрана в раскрывающемся списке Project/Library. После выбора host-приложения в списке Project/Library список Classes (Классы) содержит все доступные для VBA объекты host-приложения. 2. В списке Classes выберите объект, методы и свойства которого вас интересуют. На рис. 10.18 показана коллекция Documents. Объекты и коллекции, введение 259 3. Чтобы получить более подробную информацию об объекте, выбранном вами в списке Classes, щелкните на кнопке со знаком вопроса (?) (в верхней правой части окна Object Browser) для доступа к справочной системе VBA. После выбора объекта в списке Classes список Members of <class> (Компонент <класс>) в окне Object Browser отображает все методы и свойства для этого объекта. 4. В списке Members of<class> выберите нужный вам метод или свойство. Object Browser теперь отображает имя метода или свойства в нижней части окна; при выборе метода, имеющего аргументы, Object Browser перечисляет также все аргументы метода. На рис. 10.18 показан выбранный метод Add коллекции Documents. 5. Щелкните на кнопке с вопросительным знаком в окне Object Browser для доступа к справочной системе VBA с целью получения подробной информации о методе или свойстве, выбранном в списке Members of<class>. Чтобы вы могли различать методы и свойства в списке Members of <class>, Object Browser отображает особые значки слева от каждого элемента в списке. Свойства обозначаются значком с изображением руки, указывающей на индексную карту. Методы обозначаются значком, похожим на зеленый прямоугольник. Синий мячик (видимый как часть значка метода Item на рис. 10.18) обозначает, что свойство или метод является глобально доступным. Используйте Object Browser для ознакомления с различными доступными объектами, методами и свойствами и для ускорения написания программного кода. 9* Fnaea 11 Повторение действий в Visual Basic: циклы У нас осталась, пожалуй, последняя тема (если не рассматривать работу с массивами, о которых вы узнаете из следующей главы), без которой пока еще невозможно писать хорошие программы на языке VBA. Теперь, когда вы научились выбирать различные действия на основе предопределенных условий, вы узнаете, что необходимо делать, чтобы процедуры VBA повторяли действия заданное количество раз или пока выполняется (или не выполняется) некоторое условие. Команды организации циклов Как уже вам стало ясно, макрорекордер позволяет записывать не все необходимые пользователю действия. Особенно это наглядно показано на примере операторов, изменяющих порядок выполнения кода процедур и функций. То же самое относится и к таким операторам, которые позволяют организовать циклическое повторение выполнения некоторых частей кода VBA. Для организации циклов VBA предоставляет несколько мощных и гибких структур, позволяющих легко повторять различные действия. Программные структуры, приводящие к неоднократному повторению одного или нескольких операторов, называются структурами организации циклов, потому что поток выполнения операторов процедуры проходит циклично по одним и тем же операторам неоднократно. Процесс выполнения всех операторов, заключенных в структуру цикла, один раз называется итерацией (iteration) цикла. Некоторые структуры цикла организуются так, что они всегда выполняются заданное количество раз. Структуры цикла, всегда выполняющиеся заданное количество раз, называются циклами с фиксированным числом итераций (fixed iteration). Другие типы структур цикла повторяются переменное количество раз в зависимости от некоторого набора условий. Поскольку количество раз повторений этих гибких структур цикла является неопределенным, такие циклы называются неопределенными циклами (indefinite loops). Существуют два основных способа создания неопределенного цикла. Можно построить цикл так, что VBA будет тестировать некоторое условие (детерминант цикла) перед выполнением цикла: если условие для повторения цикла не равно True, VBA пропускает все операторы в цикле. Можно также построить цикл таким образом, что VBA будет тестировать услове детерминанта цикла после выполнения операторов в цикле. Для цикла, в котором детерминант проверяется перед выполнением операторов внутри цикла, VBA определяет следующую последовательность действий: В верхней части цикла тестируется условие детерминанта. Если условия для выполнения цикла удовлетворяются, выполняются операторы внутри цикла. После выполнения последнего оператора внутри цикла VBA возвращается к началу цикла и снова оценивает условие детерминанта цикла. Повторение действий в Visual Basic: циклы 261 Если условия для выполнения цикла все еще удовлетворяются, VBA повторяет операторы внутри цикла и снова возвращается к началу цикла для тестирования детерминанта. Как только условия для выполнения цикла перестанут удовлетворяться, VBA останавливает выполнение цикла и начинает выполнение операторов после цикла. Заметьте, что если условия для выполнения цикла не удовлетворяются, когда VBA тестирует условие детерминанта цикла в первый раз, VBA не выполняет операторы внутри цикла ни разу; при этом тело цикла пропускается (не выполняется). Тело (body) цикла — зто блок операторов VBA, находящийся между началом и концом цикла. Для цикла, в котором детерминант проверяется после выполнения операторов в теле цикла, VBA определяет следующую последовательность действий: Выполняются все операторы в теле цикла. При достижении конца тела цикла, VBA оценивает условие детерминанта цикла. Если условия для выполнения цикла удовлетворяются, VBA возвращается к началу цикла и повторяет инструкции в теле цикла. В конце цикла VBA снова тестирует условие детерминанта цикла. Как только условия для выполнения цикла больше не удовлетворяются, VBA прекращает выполнение цикла и начинает выполнение операторов после цикла. Заметьте, что VBA всегда выполняет операторы в таком цикле, по крайней мере, один раз. Можно также создать неопределенный цикл таким образом, чтобы он не имел условия детерминанта вообще; циклы, не имеющие условия детерминанта, повторяются бесконечно и называются бесконечными циклами (infinite loops). Бесконечный цикл не заканчивается никогда; большинство бесконечных циклов являются результатом ошибок программирования, хотя имеется несколько случаев, когда удобно использовать бесконечные циклы. Повторение цикла фиксированное число раз: циклы For Самой простой структурой цикла является фиксированный цикл. VBA предоставляет две различные структуры фиксированного цикла: For ...Next и For Each... Next. Обе структуры фиксированного цикла называются циклами For, потому что они всегда выполняются для (for) заданного количества раз. Использование цикла For...Next Первый из VBA-циклов For — это цикл For...Next. Используйте цикл For ...Next, когда вам необходимо повторить действие или ряд действий заданное количество раз, известное до начала выполнения цикла. Цикл For...Next имеет следующий синтаксис: СИНТАКСИС а For counter = Start То End [Step Stepsize] Statements Next [counter] Здесь counter — любая численная переменная VBA, обычно — переменная типа Integer или Long; Start — любое численное выражение и определяет начальное значение для переменной counter; End — зто также численное выражение, определяет конечное значение для переменной counter (см. следующую диаграмму). 262 Глава 11 По умолчанию VBA увеличивает переменную counter на 1 каждый раз при выполнении операторов в цикле (считает количество циклов). Можно задавать другое значение (StepSize), на которое будет изменяться counter, включая необязательное ключевое слово Step. При включении ключевого слова Step необходимо задавать значение для изменения переменной counter. В указанной синтаксической конструкции StepSize представляет любое численное выражение и определяет значение для изменения переменной counter. Statements представляет один, несколько или ни одного оператора VBA. Эти операторы составляют тело цикла For; VBA выполняет каждый из этих операторов при каждом выполнении цикла. Ключевое слово Next сообщает VBA о том, что достигнут конец цикла; необязательная переменная counter после ключевого слова Next должна быть той же самой переменной counter, которая была задана после ключевого слова For в начале структуры цикла. Включайте необязательную переменную counter после ключевого слова Next для улучшения читабельности программного кода (особенно при использовании вложенных циклов For ...Next) и для повышения скорости выполнения кода (иначе VBA придется потратить время на определение того, какая переменная counter является правильной, для ее изменения после достижения ключевого слова Next). При выполнении цикла For ...Next VBA поступает следующим образом: Присваивает значение, представленное Star, переменной counter. Выполняет все операторы, представленные с помощью Statements, пока не достигнет ключевого слова Next. Ключевое слово Next указывает VBA на то, что достигнут конец тела цикла. Изменяет переменную counter на величину StepSize (если включается необязательное ключевое слово Step). Если Step не определено, то VBA увеличивает переменную counter на 1. Возвращается к началу цикла и сравнивает текущее значение переменной counter со значением, представленным с помощью End. Если значение counter меньше или равно End, VBA выполняет цикл снова. Если значение counter больше End, VBA продолжает выполнение кода с первого оператора после ключевого слова Next. Использование For...Next с возрастающим счетчиком В листинге 11.1 демонстрируется использование цикла For ...Next. Эта процедура получает два числа от пользователя, складывает все числа в диапазоне, заданном этими двумя числами, а затем отображает результирующую сумму. Повторение действий в Visual Basic: циклы 263 Листинг 11.1. Демонстрация цикла For...Next с возрастающим счетчиком 1 Sub Demo_ForNext() 2 3 Dim k As Integer 4 Dim sStart As String 5 Dim sEnd As String 6 Dim ISum As Long 7 8 sStart = InputBox("Введите целое число:") 9 sEnd = InputBox ("Введите другое целое число:") 10 11 ISum = 0 12 For i = CInt(sStart) To Clnt(sEnd) 13 ISum = ISum + i 14 Next i 15 16 MsgBox "Сумма чисел от " & sStart & _ 17 " до " & sEnd & " равна: " & ISum 18 End Sub Переменная i используется как счетчик цикла For ...Next (буквы i, j, k, 1, m, n чаще всего используются программистами в качестве счетчиков цикла, видимо, они больше других напоминают переменные целых типов); другие переменные используются для сохранения начального (sStart) и конечного значений (sEnd), полученных от пользователя, и для сохранения суммы чисел (ISum). Обратите внимание на типы этих переменных. Переменные sStart и sEnd в этой процедуре чаще всего используются для работы со строками (строки 8, 9, 16-17) и только в одном операторе (строка 12) нам понадобилось преобразовать их в числа. Переменная ISum, по существу, должна иметь тип числовой, причем как можно больший, потому что неизвестно, насколько большой диапазон будет вводиться пользователем, который будет испытывать этот код. В процедуре предполагается, что первое вводимое число меньше, чем второе. Иначе тело цикла не выполнится ни разу и значение переменной ISum будет равно 0, так как она инициализируется этим значением в строке 11. Со строки 12 начинается описание цикла For...Next. При обработке этой строки VBA сначала выполняет вызов функции CInt, которая преобразует пользовательский строковый ввод в числа типа Integer, а затем вставляет результирующие целые значения в оператор. VBA присваивает целый эквивалент значения, хранимого в sStart, переменной счетчика i. Затем значение в i сравнивается с целым эквивалентом числа, сохраненного в sEnd. Если i меньше или равно значению в sEnd, VBA выполняет тело цикла. Этот цикл имеет только один оператор в своем теле: выражение сложения и присваивания (в строке 13). В строке складывается текущее значение i с текущим содержимым переменной ISum, а затем результат сложения присваивается переменной ISum. Далее VBA переходит к оператору Next (в строке 14), который указывает на конец тела цикла For; VBA увеличивает переменную счетчика на 1 (по умолчанию) и возвращается к началу цикла (строка 12) и снова сравнивает значение в переменной счетчика i с числом, хранимым в переменной sEnd. Как только значение в счетчике цикла превысит значение, определенное для конечного значения счетчика (а это зависит от вводимых данных), VBA прекращает выполнение цикла. Теперь, когда цикл закончился, VBA продолжает выполнение кода с оператора MsgBox в строке 16, который отображает два введенных числа и сумму всех целых в этом диапазоне. 264 Глава 11 Рис. 11.1 Результирующее окно кода листинга 11.1 Сумма чисел от 10 до 20 равна: 165 | ОК Если вы хорошо разобрались с циклом For...Next, то, наверное, заметили, что этот цикл (как, впрочем, и рассматриваемые далее) можно реализовать оператором If...Then...Else. Чтобы зто понять, достаточно сравнить диаграммы, спровож-дающие синтаксис этих операторов. Дело только в том, что оператор For...Next и короче в записи, и быстрее при выполнении кода. Использование For...Next с убывающим счетчиком Не всегда бывает нужно записывать циклы For...Next с возрастающим счетчиком. Иногда легче или полезнее писать цикл For с убывающим счетчиком. Чтобы цикл For...Next имел убывающий счетчик, используйте ключевое слово Step и отрицательное число (в синтаксической конструкции StepSize может иметь любой знак) для значения шага. В листинге 11.2 показана процедура, полученная из предыдущего кода, но здесь добавлена возможность вводить значения шага цикла. Если при тестировании сначала ввести большее число, затем — меньшее и -1, то мы получим цикл For...Next с убывающим счетчиком. Понятно, что при вводе сначала меньшего числа, затем — большего и +1, мы получим обычный цикл с возрастающим счетчиком. Листинг 11.2. Цикл For...Next с использованием шага изменения счетчика цикла 1 Sub Demo_ForNext() 2 3 Dim i As Integer 4 Dim sStart As String ' 5 Dim sEnd As String 6 Dim sStep As String 7 Dim uSum As Long 8 9 uStart = InputBox("Введите целое число:") 10 uEnd = InputBox("Введите другое целое число:") 11 sStep = InputBox ("Введите шаг цикла (целое число):") 12 13 uSum = О 14 For i = CInt(uStart) To CInt(uEnd) Step CInt(sStep) 15 uSum = uSum + i 16 Next i , 17 18 MsgBox "Сумма чисел от " & uStart & _ 19 " до " & uEnd & " шагом " & sStep & " равна: " & uSum 20 End Sub Просматривая код листинга 11.2, помните, что при уменьшении счетчика цикла For...Next цикл выполняется, пока переменная счетчика больше или равна конечному значению, а когда счетчик цикла увеличивается, цикл выполняется, пока переменная счетчика меньше или равна конечному значению. Приведем еще один пример с использованием цикла For...Next и обработки строковых переменных. Довольно часто в различных приложениях приходится создавать уникальные строки для использования их в качестве кодов некоторых объектов (например, в базах данных). Обычно для этих целей используют генераторы случайных (чаще всего — псевдослучайных) чисел и (при необходимости) пе Повторение действий в Visual Basic: циклы 265 реводят их в строки. Если получаемые строки используются и создаются в течение долгого времени, существует вероятность совпадения новых строк со старыми. Если уникальные строки (и соответствующие им другие данные) располагать в порядке возрастания (строки ведь тоже можно сравнивать), то их можно создавать так, что следующая создаваемая строка должна быть больше последней имеющейся в наборе, отличаясь только «на один символ». Например, для строк из четырех символов можно записать неравенства: "АООХ" < "A00Y" < "A00Z" < "А0010" ... Код листинга 11.3 является примером функции, которая создает строку, отличающуюся от аргумента так, как отличаются друг от друга строки, приведенные выше. Листинг 11.3. Использование For...Next - пример в Excel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1Э 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 Function NextCode(PrevCode As String) As String ' функция возвращает код такой же длины, что и входной параметр ' первый символ строки выбирается из диапазона символов, ' отличающегося от диапазона для остальных символов Dim masl As String, masi As String, s4 As String, s3 As String Dim s2 As String, si As String, lenmasl As Integer Dim lenmas2 As Integer, lenmasNewCode As Integer Dim masNewCodeO As String ' массив с новыми значениями ' символов кода ' строки для выбора символов masl = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ' для первого символа masi = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ' для остальных lenmasl = Len(masl) ' длина строки masl lenmasi = Len(masi) ' длина строки masi lenmasNewCode == Len(PrevCode) ' длина входной строки ' заполнение массива символами входной строки: For i = 1 То lenmasNewCode ReDim Preserve masNewCode(i) masNewCode(i - 1) = Mid(PrevCode, i, 1) Next ' замена символов входной строки на новые, ' начиная с последнего символа: For i = lenmasNewCode - 1 То 0 Step -1 If i > 0 Then ' положение i-го символа в заданном диапазоне: posi = InStr (1, masi, masNewCode(i)) If posi = lenmasi Then 1 символ последний в диапазоне: masNewCode(i) = Mid(masi, 1, 1) Else ' выбор следующего символа из диапазона: masNewCode(i) = Mid(masi, posi + 1, 1) Exit For End If Else ' изменение первого символа в строке: posi = InStr(1, masl, masNewCode(i)) If posi = lenmasl Then ' аварийный, но вряд ли достижимый случай: MsgBox "Первый символ вышел из своего диапазона!" Else masNewCode(i) = Mid(masl, posi + 1, 1) 266 Глава 11 47 End If 48 End If 49 50 Next 51 52 ' формирование результата функции: 53 NextCode = 54 For i = 0 Io lenmasNewCode - 1 55 NextCode = NextCode & masNewCode(i) 56 Next 57 58 End Function * 1 2 3 4 5 Основная идея алгоритма, реализованного этим кодом, заключается в следующем. Каждая позиция в генерируемой строке может содержать символы из некоторого диапазона символов1, который можно задавать произвольным образом, но символы диапазона должны быть упорядочены по возрастанию. С использованием цикла с отрицательным шагом (строки 27-50) входная строка просматривается, начиная с последнего символа; определяется позиция последнего символа в заданном для него диапазоне. Если текущий рассматриваемый символ не совпадает с последним символом допустимого диапазона (находится в середине диапазона), то в выходной строке только этот символ заменяется на следующий символ из диапазона; на этом работа алгоритма заканчивается. Если же рассматриваемый символ совпадает с последним символом заданного диапазона, то он в выходной строке заменяется на первый символ диапазона, а символом, стоящим во входной строке слева от рассматриваемого, производятся те же действия, т.е. он становится текущим рассматриваемым символом. Для задания диапазона допустимых символов используются строки символов: masl — допустимый диапазон начала строки (первый символ), masi — допустимый диапазон для остальных символов. Для положения текущего символа в диапазоне (в подстроке) используется функция InStr, позволяющая найти положение одной строки в другой строке. Функция Mid используется для выделения указанного (индексом) символа из строки. На рис. 11.2 приведен пример использования функции: в колонке А помещены заданные строки (различной длины), а в колонке В — формулы NextCode(Ai). Обратите внимание на то, что результирующие строки отличаются от исходных на один или два символа (в конце). Рис. 11.2 Использование функции листинга 11 4 Е) Microsoft Excel - Книга! , ЙГ] Файл Правка Вид вставка Формат Сервис Данные Окно Справка -Эх 100% - ” Anal Суг - 10 - Ж /< Д В4 -г ft =NetxCode(A4) 1 AXXXY AX.XXZ 2 AZZ04 AZZ05 3 BZZZZZ С00000 4 iDCDFHZYIDCDFHZZ | 5 ’ К < ► и\Лист1/ Лист 2 / Л11 < | И] В общем случае для каждой позиции в строке можно задавать свой диапазон допустимых символов. В рассматриваемом коде только первый символ выходной строки имеет диапазон символов, отличный от диапазона для остальных символов, что определялось спецификой реальной задачи, которая послужила поводом для включения этого кода в книгу. Повторение действий в Visual Basic: циклы 267 Цикл For Each...Next Второй цикл For, который имеется в VBA — это цикл For Each...Next. В отличие от цикла For...Next цикл For Each...Next не использует счетчик цикла. Циклы For Each...Next выполняются столько раз, сколько имеется элементов в определенной группе, такой как коллекция объектов или массив. (Коллекции объектов описываются в предыдущей, а массивы — в следующей главе.) Другими словами, цикл For Each-Next выполняется один раз для каждого элемента в группе. Цикл For Each—Next имеет следующий синтаксис: СИНТАКСИС » г*, For Each Element In Group Statements Next (Element] Element — это переменная, используемая для итерации по всем элементам в определенной группе. Group — это объект коллекции или массив. Если Group — это объект коллекции, то Element должен быть переменной типа Variant, Object или заданным объектным типом, таким как Range, Worksheet, Document, Paragraph и так далее. Если Group — это массив, то Element должен быть переменной типа Variant; Statements — один, несколько или ни одного оператора VBA, составляющих тело цикла. Цикл For Each—Next имеет меньше опций, чем цикл For...Next. Цикл For Each—Next всегда выполняется столько раз, сколько имеется элементов в определенной группе. В листинге 11.4 показана функция с именем SheetExists, использующая цикл For Each—Next для определения того, существует ли определенный лист в рабочей книге Excel. Листинг 11.4. Использование For Each—Next — пример в Excel 1 Function SheetExists(sName As String) As Boolean 2 1 11 Возвращает True, если лист sName в активной книге 3 4 Dim aSheet As Object 5 SheetExists = False 6 7 ' цикл по всем листам co сравнением имен c sName, 8 ' сравнение текстовое 9 For Each aSheet In ActiveWorkbook.Sheets 10 If (StrComp(aSheet.Name, sName, 1) = 0) Then 11 SheetExists = True ' найдено имя 12 Exit For ' выход из цикла 13 End If 14 Next aSheet 15 End Function 16 17 Sub Test_SheetExists () 18 ' тестирует функцию SheetExists 19 20 Dim uStr As String 21 22 uStr = InputBox("Введите имя листа " & _ 23 "текущей книги:") 24 If SheetExists (uStr) Then 25 MsgBox "Лист 1" & uStr & _ 26 в текущей книге." 27 Else 268 Глава 11 28 MsgBox "Листа '" & uStr & _ 29 НЕТ в текущей книге." 30 End If 31 End Sub Функция SheetExists имеет один обязательный аргумент sName, в котором функции передается строка, содержащая имя искомого листа.'SheetExists возвращает значения типа Boolean: True, если лист с именем в sName, существует в текущей рабочей книге, иначе — False. Можно использовать подобную функцию в одной из процедур, чтобы убедиться в том, что рабочий лист (или диаграмма) существует, перед тем, как процедура выполнит команду обращения к этому листу. Если этого не предусмотреть, а лист действительно отсутствует, такая команда вызовет сообщение о runtime-ошибке и VBA прекратит выполнение программы. Функция, подобная SheetExists, позволяет писать процедуры так, чтобы они могли обнаруживать и исключать ошибки, которые могут возникнуть, например, когда пользователь вводит имя несуществующего рабочего листа. В строке 4 объявляется объектная переменная aSheet для использования в цикле For Each...Next. В строке 5 результату функции SheetExists присваивается значение False. Теперь функция должна только установить, существует ли лист, и присвоить True результату функции в случае положительного результата. Если результату функции SheetExists не удалось присвоить значение True, значит лист не найден или случилось что-то еще, что подразумевает отсутствие листа. В строке 9 начинается цикл For Each...Next, использующий объектную переменную aSheet как переменную Element для цикла. В качестве Group здесь выступает коллекция ActiveWorkbook.Sheets. Свойство Active Workbook — это свойство объекта Application и оно возвращает объектную ссылку на текущую активную рабочую книгу. Sheets — зто метод рабочей книги, который возвращает коллекцию всех листов в рабочей книге, включая рабочие листы и диаграммы. В строке 10 начинается тело цикла, которое состоит из одного оператора If...Then. При выполнении строки 10 VBA сначала вызывает StrComp для сравнения строки в sName со строкой, сохраненной в свойстве Name листа, на который в данный момент ссылается aSheet. Этот вызов функции StrComp определяет, что сравнение должно быть текстовым, и, следовательно, на него не оказывают влияние различия в регистре строки в sName и строки в свойстве Name листа. Если строка в sName совпадает со строкой в свойстве Name листа, VBA выполняет оператор в строке 11, который присваивает значение True результату функции. В строке 12 располагается оператор Exit For. Если вы еще не догадались, к чему приводит этот оператор, значит, вы еще не задумывались над тем, сколько же раз будет выполняться цикл в данном примере, даже если необходимый лист найдется в первой же итерации. На самом деле Exit For — это оператор немедленного выхода из цикла. Он не зависит от текущей итерации. Данный пример, как никакой другой, подходит для демонстрации этого оператора. Как только строка в sName совпадет со строкой в свойстве Name листа, VBA выполнит операторы в строках 11-12 и дальнейшая необходимость в цикле отпадет, хотя его можно было бы без вреда для программы выполнять и далее. В данной функции досрочный выход из цикла экономит только время (слово «только» использовано здесь не том смысле, что об этом не стоит беспокоиться; чаще всего в программах с хорошим пользовательским интерфейсом время — основная характеристика системы после надежности). Когда заканчивается (или прерывается) выполнение цикла, VBA продолжает выполнение кода со строки 15, которой заканчивается функция SheetExists, и возвращает результат функции. В строках 17-30 описана процедура Test_SheetExists для тестирования функции SheetExist. Процедура использует только уже изученные вами операторы, и, видимо, нет необходимости в ее подробном разборе. Повторение действий в Visual Basic: циклы 269 На рис. 11.3 приведен фрагмент работы тестовой процедуры, которая обнаружила лист, имя которого было введено пользователем. Перед тестированием этого кода не забудьте создать лист с необходимым именем, чтобы не получать одни только сообщения об отсутствии листа. Рис. 11.3 Результат поиска листа в рабочей книге кодом листинга 11.4 В листинге 11.5 показан еще один пример использования For Each...Next: на этот раз — для Word. Функция BookmarkExists из листинга 11.5 проверяет, существует ли определенная закладка в активном в данный момент документе, и если существует, переводит курсор к этой закладке. Листинг 11.5. Поиск закладки в документе Word 1 Function BookmarkExists(BkMark As String) As Boolean 2 ' Возвращает True, если закладка BkMark существует 3 ' в активном документе 4 5 Dim InstBkMark As Object 6 7 BookmarkExists = False ' предположим, закладка не найдена 8 9 ' цикл по всем закладкам; сравнение имени каждой 10 ' закладки с BkMark; сравнение текстовое 11 For Each InstBkMark In ActiveDocument.Bookmarks 12 If (StrComp(InstBkMark.Name, BkMark, vbTextCompare) = 0) Then 13 ' перейти к закладке: 14 Selection.GoTo What:=wdGoToBookmark, Name:=BkMark 15 BookmarkExists = True 16 Exit For 17 End If . . 18 Next InstBkMark 19 End Function 20 21 22 Sub Test_BookmarkExists() 23 ' тестирует функцию BookmarkExists 24 25 Dim uStr As String 26 27 uStr = InputBox("Введите имя закладки " & _ 28 "в текущем документе:") 29 If BookmarkExists(uStr) Then 30 MsgBox "Закладка '" & uStr & _ 270 Глава 11 31 "1 НАХОДИТСЯ в этом документе" 32 Else 33 MsgBox "Закладки '" & uStr & _ 34 "' НЕТ в этом документе" 35 End If , ’ ’ 36 End Sub Функция BookmarkExists работает в основном так же, как и функция Sheet-Exists. BookmarkExists имеет один обязательный аргумент BkMark, который содержит строку, представляющую имя закладки, поиск которой выполняется. BookmarkExists возвращает значение типа Boolean: True, если закладка, определяемая с помощью BkMark, находится в текущем документе, иначе — False. В строке 5 объявляется объектная переменная InstBkMark для использования в цикле For Each...Next. В строке 11 начинается цикл For Each...Next, использующий объектную переменную InstBkMark как переменную Element для цикла. В качестве Group выступает коллекция ActiveDocument.Bookmarks: ActiveDocument — это свойство объекта Word Application, которое возвращает объектную ссылку на активный в текущий момент документ. Bookmarks — это метод документа, возвращающий коллекцию всех закладок в документе. В строке 12 начинается тело цикла, которое состоит из одного оператора If...Then. При выполнении строки 12 VBA сначала вызывает функцию StrComp для сравнения строки в BkMark со строкой, сохраненной в свойстве Name закладки, на которую в данный момент ссылается InstBkMark. При сравнении строк используется функция StrComp для текстового сравнения строк независимо от установок Option Compare. Если строка в BkMark совпадает со строкой в свойстве Name закладки, VBA выполняет код в строках 14-15. В строке 15 присваивается значение True результату функции. С этим вы уже встречались в предыдущем листинге. В 14 строке располагается оператор перехода к найденной закладке. Этот оператор был получен из макроса, записанного рекордером, и состоит из вызова метода GoTO объекта Selection. Метод имеет два аргумента: What, которому присваивается значение встроенной константы wdGoToBookmark (выделенный фрагмент — закладка), и Name (наименование закладки), которому присваивается значение найденной метки. Как и в предыдущем листинге, здесь используется «досрочный» выход из цикла, если закладка найдена. Когда выполнение цикла для всех объектов в коллекции ActiveDocument.Bookmarks заканчивается, VBA продолжает выполнение кода со строки 19, которая заканчивает функцию BookmarkExists и возвращает результат функции. В строках 22-36 объявляется процедура Test_BookmarkExists для тестирования функции BookmarkExists. I Циклы Do VBA имеет чрезвычайно мощный оператор цикла для создания неопределенных структур цикла в процедурах и функциях. Обычно все VBA-неопределенные циклы строятся с помощью одного оператора неопределенного цикла: оператора Do. Оператор Do имеет так много опций и является настолько гибким, что в действительности он предоставляет четыре различных конструкции цикла в двух базовых категориях. Две базовые категории конструкций цикла Do — это циклы, которые тестируют условие детерминанта до выполнения тела цикла, и циклы, которые тестируют условие детерминанта после выполнения тела цикла. Условие детерминанта для неопределенного цикла задается с помощью логического выражения таким же образом, каким создаются логические выражения для использования с операторами If...Then. Повторение действий в Visual Basic: циклы 271 VBA предоставляет два различных способа тестирования условия детерминанта для цикла. Можно построить цикл так, чтобы он выполнялся, пока условие детерминанта цикла будет равно True, и прекращал выполнение, когда это условие становится равным False. Можно также создать цикл так, чтобы он выполнялся, пока условие детерминанта цикла будет равно False, и прекращал выполнение, когда это условие станет равным True. Чтобы цикл выполнялся, пока его условие детерминанта равно True, используйте в операторе цикла Do необязательное ключевое слово While. В этом случае VBA выполняет цикл, пока (while) условие детерминанта равно True, и прекращает выполнение цикла, как только это условие становится равным False. Предположим, вам необходимо написать процедуру, помогающую пользователю вводить данные в рабочий лист. Для процедуры ввода данных обычно желательно, чтобы процедура повторяла некоторые операторы, получающие информацию от пользователя, пока еще есть данные для ввода, и прекращала повторение этих операторов, когда данных больше нет. Можно написать цикл Do, неоднократно получающий данные от пользователя, продолжающийся, пока пользователь вводит непустые строки, и прекращающий выполнение, как только пользователь вводит пустую строку. Условие детерминанта для этого цикла записывается так, чтобы логическое выражение было равно True (и поэтому цикл продолжал выполняться), пока пользовательский ввод не является пустой строкой. Если пользовательский ввод сохраняется в переменной с именем uStr, логическое выражение для детерминанта цикла может быть любым из следующих (оба логических выражения равны True, когда строка в uStr имеет ненулевую длину): uStr о "" Len(Trim(uStr)) о О Для того чтобы цикл выполнялся пока его условие детерминанта равно False, используйте в операторе цикла Do необязательное ключевое слово Until. VBA выполняет такой цикл до тех пор, пока (until) условие не будет равно True, то есть цикл продолжает выполняться, пока условие детерминанта равно False, и прекращает выполнение, как только это условие становится равным True. Например, может понадобиться написать процедуру, продвигающуюся по столбцам рабочего листа, применяя определенное форматирование текста, и останавливающуюся в первом пустом столбце. Можно написать цикл Do, который повторяет операторы для форматирования заголовка столбца по достижении пустой ячейки. Условие детерминанта для этого цикла записывается так, что соответствующее логическое выражение равно False, пока текущая ячейка не является пустой, и равно True, когда текущая ячейка пустая. При использовании свойства ActiveCell объекта Application для возврата текущей активной ячейки и при использовании свойства Value для получения содержимого ячейки это логическое выражение для детерминанта может быть любым из следующих (оба выражения равны True, если текущая ячейка пустая): ActiveCell. Value .= "" Len(Trim(ActiveCell.Value)) = 0 Используется ли ключевое слово While или Until — зависит в основном от того, как вы представляете условие, определяющее, должен ли цикл выполняться, и от вашего умения строить логическое выражение для условия детерминанта цикла: используйте While, если хотите, чтобы цикл продолжал выполняться, пока заданное условие равно True. используйте Until, если хотите, чтобы цикл продолжал выполняться, пока заданное условие равно False. 272 Глава 11 Как прервать выполнение макроса или процедуры Поскольку одной из наиболее распространенных проблем, возникающих при работе с неопределенными циклами, является нечаянное создание бесконечного цикла, важно знать, как прерывать работу VBA, когда выполняются макросы и процедуры. Используйте один и тот же метод для прерывания записанных рекордером макросов или для прерывания процедур и функций, написанных вами самостоятельно. Для прерывания выполнения VBA нажмите клавишу Esc или комбинацию клавиш Ctrl+Break. VBA заканчивает выполнение текущего оператора, переходит в состояние ожидания и отображает окно сообщения о runtime-ошибке, показанное на рис. 11.4. Командные кнопки в этом окне сообщения те же и имеют то же назначение, что и в любом другом окне сообщения о runtime-ошибке: Continue. Возобновляет VBA-выполнение программных операторов. Обычно не следует выбирать эту кнопку после прерывания бесконечного цикла, поскольку она просто запустит бесконечный цикл снова. End. Заканчивает программу. Все переменные и их содержимое теряются. Это командная кнопка, которую обычно следует выбирать после прерывания бесконечного цикла. Debug. Активизирует VBA-режим Break (режим прерывания), чтобы вы могли проверить содержимое переменных и по шагам пройти выполнение цикла для определения причины зацикливания. Help. Активизирует справочную систему VBA для отображения информации о том, почему было прервано выполнение кода. Кнопка Help не очень полезна, если вы прервали выполнение кода нажатием на клавишу Esc или на Ctrl+Break; раздел справки констатирует, что выполнение кода было прекращено в результате нажатия на Esc или Ctrl+Break, и дает инструкции, как ввести режим Break или закончить выполнение кода. Не следует прерывать VBA во время отображения диалогового окна; необходимо закрыть все окна ввода, окна сообщения или другие до того, как вы прервете процедуру. В зависимости от конкретного цикла и операторов, которые в нем содержатся, VBA может не реагировать на одно нажатие на Esc или Ctrl+Break. В действительности, обычно необходимо нажимать и удерживать нажатой клавишу Esc для прерывания выполняющейся процедуры. Если вы удерживаете нажатой клавишу Esc, вы можете нечаянно закрыть окно сообщения о runtime-ошибке. В результате этого окно сообщения об ошибке может промелькнуть на экране слишком быстро, и вы не сможете его прочитать. Если такое случится, не стоит беспокоиться, вы можете понять, какой цикл был заблокирован, зная, насколько была выполнена процедура перед сбоем. Рис. 11.4 VBA отображает это окно, когда вы нажимаете Esc или Ctrl+Break для прерывания выполняющейся процедуры (или макроса) Microsoft Visual Basic Code execution has been interrupted Continue j End Debug Help Повторение действий в Visual Basic: циклы 273 Использование циклов, тестирующих условия до выполнения тела цикла Для VBA-тестирования условия детерминанта цикла до выполнения тела цикла следует помещать логическое выражение для детерминанта цикла в начало блока операторов, составляющего тело цикла. * Циклы Do While Первой конструкцией цикла, тестирующей свое условие детерминанта до выполнения цикла, является Do While со следующим синтаксисом: СИНТАКСИС i Do While Condition Statements Loop Condition — логическое выражение для детерминанта цикла; Statements — один, ни одного или несколько операторов, которые составляют тело цикла. Ключевое слово Loop после Statements указывает на окончание тела цикла и обозначает место, из которого VBA возвращается в начало цикла для проверки условия детерминанта (см. диаграмму ниже). В операторе Do While выражение Condition находится в начале цикла, поэтому VBA проверяет условие детерминанта до выполнения цикла. Поскольку в этой форме используется ключевое слово While, VBA выполняет цикл, пока логическое выражение, представленное с помощью Condition, равно True. При выполнении цикла Do While VBA сначала тестирует логическое выраже-' нйе, представленное с помощью Condition; если оно равно True, VBA выполняет операторы, представленные с помощью Statements. При достижении ключевого слова Loop VBA возвращается в начало цикла и снова проверяет, равно ли True логическое выражение Condition. Если Condition равно True, VBA выполняет цикл снова; если выражение Condition равно False, VBA продолжает выполнение кода с любых операторов после ключевого слова Loop, т.е. прекращает работу цикла. Заметьте, что если логическое выражение, представленное с помощью Condition, равно False, когда VBA выполняет оператор Do While в первый раз, VBA просто пропускает цикл, не выполняя его ни одного раза. Т.е. цикл Do While позволяет ни разу не выполнять операторы внутри него. В листинге 11.6 показан простой пример цикла Do While, который неоднократно получает некоторое число от пользователя, останавливаясь только после того, как пользователь введет столько нечетных чисел, что их сумма превысит число 100. 1 274 Глава 11 Л Листинг 11.6. Демонстрация цикла Do While 1 Sub Test_DoWhile() 2 ' считает нечетные числа, вводимые пользователем; 3 ' запоминает строку с нечетными числами; 4 1 останавливается, когда их сумма нечетных чисел превысит 100; 5 ' выводит строку с нечетными числами в диалоговом окне 6 * 7 Const ocTitle - "Сумматор нечетных чисел" 8 9 Dim OddSum As Integer ' сумма нечетных чисел 10 Dim OddStr As String ' строка с нечетными числами 11 Dim Num ’ для приема данных пользователя 12 о 13 OddStr = "" ' инициализация выходной строки 14 OddSum = 0 ’ инициализация суммы OddSum 15 16 Do While OddSum < 100 ' начало цикла 17 Num = InputBox("Введите число:", ocTitle) 18 If (Num Mod 2) <> 0 Then ' проверка на четность 19 OddSum = OddSum + Num ' изменение суммы OddSum 20 OddStr = OddStr & Num & " " 21 End If 22 Loop 23 24 ' вывод строки с нечетными числами: 25 MsgBox prompt:“"Вы ввели следующие нечетные " & _ 26 "числа: " & Chr(13) & OddStr, _ 27 Title:=ocTitle 28 End Sub Процедура Test_DoWhile демонстрирует использование цикла Do While. Цикл в процедуре выполняется, пока сумма введенных пользователем нечетных чисел (нечетное (odd) число — это число, которое нельзя разделить на 2 без остатка) меньше 100. Очевидно, что эту задачу нельзя выполнить с помощью цикла For...Next (без дополнительного использования условного оператора). Заметьте, что переменная OddSum, которая входит в условие детерминанта, изменяется только, когда пользователь вводит нечетное число. Поэтому цикл Do While в этой процедуре всегда будет выполняться различное количество раз: все зависит от пользовательского ввода. Если вы не раз запустите эту процедуру, то, вероятно, обратите внимание, что в диалоговом окне ввода, кроме кнопки ОК, находится кнопка Cancel. Чем меньшие нечетные числа вы будете вводить для тестирования процедуры, тем чаще (так как сумма будет расти медленно) будете видеть, эти две кнопки. Когда-нибудь вы поддадитесь соблазну нажать на кнопку Cancel, и увидите, что программа прекратит работу с выдачей окна runtime-ошибки. Это обстоятельство не является таким уж неожиданным: программа рассчитана на «правильного» пользователя, который дол-, жен вводить четные и нечетные числа и не «капризничать». Конечно, если бы мы могли убрать из диалогового окна кнопку Cancel, то все проблемы были бы решены. Выход из этой ситуации может быть один — проверять, не была ли нажата кнопка Cancel во время ввода чисел. В листинге 11.7 содержится код, который учитывает возможность отказа от ввода данных. Листинг 11.7. Демонстрация цикла Do While 1 2 3 4 1 Sub Test_DoWhile2() 2 ' считает нечетные числа, вводимые пользователем; 3 ' запоминает строку с нечетными числами; 4 ' останавливается, когда их сумма нечетных чисел превысит число, Повторение действий в Visual Basic: циклы 275 5 ' вводимое в диалоговом окне первым; 6 ' выводит строку с нечетными числами в диалоговом окне 7 8 Const ocTitle = "Сумматор нечетных чисел" 9 10 Dim Limit ' предел суммы нечетных чисел 11 Dim OddSum As Integer ' сумма нечетных чисел 12 Dim OddStr As String ' строка с нечетными числами 13 Dim Num ' для приема данных пользователя 14 15 OddStr = "" ' инициализация выходной строки 16 OddSum = 0 ' инициализация суммы OddSum 17 18 Limit = InputBox("Введите максимальную сумму:", ocTitle) 19 If Len(Limit) = 0 Then Exit Sub 20 21 Do While OddSum < Limit ' начало цикла 22 Num = InputBox("Введите число:", ocTitle) 23 If Len(Num) = 0 Then Exit Do 24 If (Num Mod 2) <> 0 Then ' проверка на четность 25 OddSum = OddSum + Num ' изменение суммы OddSum 26 OddStr = OddStr & Num & " " 27 End If 28 Loop 29 30 ' вывод строки с нечетными числами: 31 MsgBox prompt:="Вы ввели следующие нечетные " & _ 32 "числа: " & Chr(13) & OddStr, _ 33 Title:=ocTitle 34 End Sub Программа Test_DoWhile2 немного продвинута относительно своей предшественницы. Во-первых, она позволяет вводить в диалоге предел суммы нечетных чисел, после которого происходит выход из цикла (строка 18), во-вторых, в окне ввода можно использовать все (две) кнопки, так как операторы в строках 19 и 23 проверяют, не была ли нажата кнопка Cancel, и в первом случае (строка 19) прекращают выполнение процедуры, а во втором (строка 23) — цикла Do While. Во всяком случае, если вы пишете тестовый код не для себя, следует учитывать даже такие мелочи. Иначе пользователей ваших тестов будут больше занимать проблемы неработоспособности кода, чем его алгоритмическая сущность. Циклы Do Until Вариант Do While оператора Do — это один из способов создания оператора Do, тестирующего условие детерминанта до выполнения тела цикла. Можно также использовать форму Do Until оператора Do для создания цикла, тестирующего условие детерминанта до выполнения тела цикла. Оператор Do Until имеет следующий общий синтаксис: СИНТАКСИС Do Until Condition Statements Loop Condition — логическое выражение для детерминанта цикла, a Statements — это операторы VBA, составляющие тело цикла. Ключевое слово Loop после Statements указывает на конец тела цикла и также обозначает место, из которого VBA возвращается в начало цикла для проверки условия детерминанта (см. диаграмму синтаксиса цикла Do While). 276 Глава 11 VBA тестирует условие детерминанта цикла Do Until до выполнения операторов цикла. Поскольку эта форма включает ключевое слово Until, VBA выполняет цикл пока логическое выражение, представленное выражением Condition, равно значению False. При выполнении цикла Do Until VBA сначала тестирует логическое выражение, представленное с помощью Condition; если оно равно False, VBA выполняет операторы, представленные с помощью Statements. После достижения ключевого слова Loop VBA возвращается в начало цикла и снова проверяет, равно ли логическое выражение Condition значению False. Если Condition равно False, VBA выполняет цикл снова; если же оно равно True, VBA продолжает выполнение кода с операторов после ключевого слова Loop, т.е. прекращает работу цикла. Если Condition равно True, когда VBA встречает оператор Do Until в первый раз, VBA пропускает цикл без его выполнения. Т.е. цикл Do Until позволяет ни разу не выполнять операторы внутри него. В листинге 11.8 показан простой пример цикла Do Until, который неоднократно получает число от пользователя, прекращаясь, когда пользователь вводит четное число, большее 10. Листинг 11.8. Демонстрация цикла Do Until 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Sub Test_DoUntil() ' принимает от пользователя числа, пока не будет ' введено четное число, большее десяти Const evTitle = "Останов при четном, большем десяти" Dim EvenFlag As Boolean Dim Num EvenFlag = False Do Until EvenFlag Num = InputBox("Введите число:", evTitle) If Len(Num) = 0 Or TypeName(Num) <> "Integer" Then Exit Do If ((Num Mod 2) = 0) Then If Num > 10 Then MsgBox prompt:="Вы ввели четное число, " & "большее, чем 10 - Цикл заканчивается", _ Title:=evTitle EvenFlag = True Else MsgBox prompt:="Вы ввели четное число, " & "меньшее, чем (или равное) 10", _ Title:=evTitle ,, End If Else MsgBox prompt:="Bbi ввели нечетное число", _ Title:=evTitle End If Loop MsgBox prompt:^"Выполнение цикла прекращено", Title:=evTitle End Sub Процедура Test_DoUntil показывает, как построить цикл Do Until. Цикл в этой процедуре демонстрирует управляемый условием цикл и выполняется до тех пор, пока пользователь не введет четное число, большее 10. Условие, заканчивающее выполнение цикла — это ввод пользователем четного числа. На самом деле этим условием является получение значения True переменной EvenFlag, что про- Повторение действий в Visual Basic: циклы 277 исходит (в строке 19), когда код обнаруживает с помощью вложенных операторов If (в строках 14-15) факт введения пользователем четного числа, большего 10. Перед выполнением цикла переменной EvenFlag присваивается значение False, чем и обеспечивается, по крайней мере, первое выполнение цикла. Внутри цикла организуется прием числа, и анализ его на предмет четности и превышения 10. Если эти последние проверки дают положительный результат, выводится сообщение (строки 16-17) об окончании цикла и переменная EvenFlag получает значение True, что приводит к окончанию цикла. В строке 13 находится оператор, предупреждающий возникновение runtime-ошибок при работе с программой пользователей, склонных к экспериментам. Использование циклов, тестирующих условия после выполнения тела цикла Для VBA-тестирования условий после выполнения тела цикла необходимо поместить логическое выражение для детерминанта цикла в конец блока операторов, составляющих тело цикла, после ключевого слова Loop, которое сообщает о конце цикла. Циклы Do...Loop While Первая рассматриваемая нами конструкция цикла, тестирующая условие детерминанта после выполнения тела цикла, — это Do...Loop While. Оператор Do...Loop While имеет следующий синтаксис: СИНТАКСИС Do Statements Loop While Condition Statements — один, ни одного или несколько операторов VBA, составляющих тело цикла. Ключевое слово Loop после Statements обозначает конец тела цикла и также указывает место, из которого VBA возвращается в начало цикла; Condition представляет логическое выражение для детерминанта цикла (см. диаграмму ниже). В этой форме синтаксиса оператора Do...Loop While VBA проверяет условие детерминанта после выполнения операторов цикла. Поскольку эта форма оператора Do использует ключевое слово While, VBA выполняет цикл, пока логическое выражение, представленное с помощью Condition, равно True. 278 Глава 11 При выполнении оператора Do...Loop While VBA сначала выполняет операторы, представленные с помощью Statements. Когда VBA достигает ключевых слов Loop While, выполняется тестирование логического выражения, представленного с помощью Condition; если это выражение равно True, VBA возвращается в начало цикла и снова выполняет тело цикла. Когда VBA снова достигает ключевых слов Loop While в конце цикла, снова выполняется проверка, является ли логическое выражение Condition все еще равным True. Если Condition равно True, VBA выполняет цикл снова; если — нет, VBA продолжает выполнение кода с любых операторов после строки, содержащей ключевое слово Loop, т.е. прекращает работу цикла. Заметьте, что независимо от значения логического выражения, представленного с помощью Condition, этот цикл всегда выполняется, по крайней мере, один раз. (Сравните с циклами, проверяющими условие детерминанта до выполнения тела цикла.) Процедура Test_DoLoopWhile в листинге 11.9 использует конструкцию цикла Do...Loop While для получения в диалоговом окне данных от пользователя до тех пор, пока пользователь не введет слово "exit", указывая на то, что ввод данных завершен. Листинг 11.9. Пример использования структуры Do...Loop While 1 Sub Test_DoLoopWhile() 2 1 демонстрирует структуру Do...Loop While. 3 ' Цикл повторяется, пока не будет введено слово "exit" 4 5 Const iTitle = "Ввод данных" 6 Dim uStr As String 7 8 Do 9 uStr = InputBox(prompt:="Введите строку " & _ 10 "('exit' для окончания):", _ 11 Title:=ilitle, 12 Default:="exit") 13 ' операторы обработки или проверки вводимых данных 14 ' или сохранения данных в ячейках рабочего листа и т.д. 15 MsgBox prompt:="Bbi ввели: " & uStr, Title:=iTitle 16 Loop While uStr <> "exit" 17 18 MsgBox prompt:="Ввод данных завершен.", _ 19 Title:=iTitle, buttons:=vbExclamation 20 End Sub По-видимому, комментировать здесь нечего. К моменту рассмотрения этого листинга вы должны иметь знания, достаточные для того, чтобы понять представленный код. Циклы Do...Loop Until Для построения Do-цикла, тестирующего свое условие детерминанта после выполнения тела цикла можно также использовать форму Do...Loop Until оператора Do. Оператор Do...Loop Until имеет следующий синтаксис: СИНТАКСИС Do Statements ' ‘ Loop Until Condition Statements представляет операторы VBA, составляющие тело цикла; Condition — логическое выражение для детерминанта цикла (см. диаграмму синтаксиса цикла Do...Loop While). Повторение действий в Visual Basic: циклы 279 VBA проверяет условие детерминанта цикла Do...Loop Until после выполнения тела цикла. Поскольку эта форма Do-оператора использует ключевое слово Until, VBA выполняет цикл, пока логическое выражение, представленное с помощью Condition, равно False. При выполнении оператора Do...Loop Until VBA сначала выполняет операторы, представленные с помощью Statements. Когда VBA достигает ключевого слова Loop, выполняется тестирование логического выражения, представленного с помощью Condition", если логическое выражение равно False, VBA возвращается в начало цикла и снова выполняет тело цикла. Когда VBA снова достигает ключевого слова Loop в конце цикла, снова выполняется проверка, является ли логическое выражение Condition равным False. Если Condition равно False, VBA выполняет цикл снова; если оно равно True, VBA продолжает выполнение кода с любых операторов после строки, содержащей ключевое слово Loop, т.е. прекращает работу цикла. Заметьте, что этот цикл всегда выполняется, по крайней мере, один раз, независимо от значения логического выражения, представленного с помощью Condition. (Сравните с циклами, проверяющими условие детерминанта до выполнения тела цикла.) Процедура Test_DoLoopWhile в листинге 11.10 использует конструкцию цикла Do...Loop While для получения данных ввода от пользователя до тех пор, пока пользователь не введет слово "exit", указывая на то, что ввод данных завершен. Листинг 11.10. Пример использования структуры Do...Loop Until 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Sub Test_DoLoopUntil() ' демонстрирует структуру Do...Loop Until. ' Цикл повторяется, пока не будет введено слово "exit" Const iTitle = "Ввод данных" Dim uStr As String Do uStr - InputBox(prompt:“"Введите строку " & _ "('exit' для окончания):", _ Title:“iTitle, _ Default:“"exit") ' операторы обработки или проверки вводимых данных ' или сохранения данных в ячейках рабочего листа и т.д. MsgBox prompt:="BH ввели: " & uStr, Title:=iTitle Loop Until uStr = "exit" MsgBox prompt:="Ввод данных завершен.", _ Title:“iTitle, buttons:=vbExclamation End Sub Код этого листинга практически ни чем не отличается от кода предыдущего листинга, кроме того, что здесь используется структура Do...Loop Until, а не Do...Loop While (строка 16). Вложенные циклы Можно помещать циклы внутрь других циклов, аналогично тому, как можно помещать операторы If ...Then один в другой. Помещение одной структуры цикла в другую называют вложением (nesting) циклов. Можно помещать структуры циклов любого типа (смешанные For и Do циклы) в любой уровень. 280 Глава 11 При вложении циклов необходимо соблюдать следующие правила: При вложении циклов For...Next каждый цикл должен иметь свою уникальную переменную счетчика. При вложении циклов For Each...Next каждый цикл должен иметь свою уникальную е/етеп<-переменную. Если вы используете оператор Exit For или Exit Do во вложенном цикле, этим оператором заканчивается только выполняемый в данный момент цикл; VBA продолжает выполнение следующего цикла более высокого уровня. Вложение циклов For В листинге 11.11 показана простая процедура, которая использует вложенные циклы For ...Next. Процедура Test_ForNext предназначена для использования в Excel и применяет полужирный шрифт к первым п (вводится пользователем) строкам первых m (вводится пользователем) столбцов активного в данный момент рабочего листа. Внешний цикл в процедуре считает строки, а внутренний — столбцы. Листинг 11.11. Вложенные циклы For...Next 1 Sub Test ForNext() 2 3 ' Применяет шрифт Arial, полужирный ' к первым п строкам и m столбцам активной рабочей книги 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 End Dim sTitle As String Dim Rnum As Integer, Cnum As Integer Dim n As Integer, m As Integer sTitle = "Форматирование ячеек листа" n = Application.InputBox(prompt:“"Введите число строк", _ Title:“"Форматирование ячеек", Туре:=1) If п = 0 Then Exit Sub m - Application.InputBox(prompt:“"Введите число столбцов", Title-.“"Форматирование ячеек", Туре:=1) If m = 0 Then Exit Sub Worksheets("Sheetl").Activate For Rnum = 1 To n For Cnum = 1 To m Cells(Rnum, Cnum).Select * With Selection.Font ’ .Name = "Arial" .Fontstyle = "Bold" .Strikethrough = False .Superscript “ False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlNone » .Colorindex = xlAutomatic End With Next Cnum Next Rnum , Sub Повторение действий в Visual Basic: циклы 281 Процедура Test_ForNext использует циклы For ...Next, один, вложенный в другой, для применения полужирного шрифта Arial к ячейкам листа, начиная с первой и заканчивая в строке п и столбце ш. Значения пит вводятся в строках 10-11, 14-15 при помощи метода Application.InputBox, который, как уже отмечалось, позволяет сократить проверочный код пользователя использованием необязательного аргумента Туре. При значении Туре, равном 1, пользователь не сможет ввести в окне ввода ничего, кроме числа. Вы можете сами в этом убедиться. Набор чего-либо, не похожего на число, приведет к выдаче окна сообщения, подобного приведенному на рис. 11.5. Кроме контроля За вводом, в процедуре проверяется, не введены ли нулевые или отрицательные значения для пит (строки 12, 16). Работа процедуры продолжается только при введении положительных значений этих переменных. Рис. 11.5 Excel-метод Application.InputBox не позволяет вводить ничего, кроме того, что определено его необязательным аргументом Туре Счетчик внешнего цикла For...Next изменяется от 1 до п, и процедура использует переменную счетчика внешнего цикла для предоставления координат строки каждый раз при выполнении цикла. Следовательно, внешний цикл обрабатывает п строк от начала рабочего листа. Счетчик внутреннего цикла For...Next изменяется от 1 до т, и процедура использует переменную счетчика внутреннего цикла для предоставления координат столбца каждый раз при выполнении цикла. Следовательно, внутренний цикл обрабатывает в рабочем листе m столбцов слева направо. В строке 22 используется метод Cells объекта Application Excel для возвращения объекта Range, определенного с использованием Rnum и Спит в качестве координат строки и столбца. Оператор использует также метод Select объекта Range для выбора заданной ячейки в активном рабочем листе. Оператор Cells был скопирован из записанного рекордером макроса, который содержал только два действия: выбор ячейки и применение нужного форматирования. Оператор выбора ячейки был скопирован в эту процедуру, а литеральные значения из записанного рекордером оператора были заменены переменными Rnum и Спит. В строках 24-34 расположен оператор With, используемый для текущего выделенного фрагмента (ячейки). Объект Selection.Font содержит все установки шрифта для текущего выбора. Операторы внутри With (в строках 25-33) изменяют свойства объекта Selection.Font так, чтобы выбор имел нужный полужирный шрифт Arial. Эти операторы были также скопированы из записанного рекордером макроса. Вложенные циклы Do В листинге 11.9 показана процедура, использующая вложенные циклы Do, чтобы пользователь мог выполнить ввод данных, необходимых для получения накладной. Внешний цикл в процедуре Makelnv получает номера накладных от пользователя до тех пор, пока пользователь не отменит окно ввода. Внутренний цикл в процедуре Makelnv получает элементы записей накладной до тех пор, пока пользователь не отменит окно ввода. Когда вы будете изучать эту процедуру, помните, что 282 Глава 11 это просто эскизная процедура. На самом деле вам, вероятно, потребуется получить гораздо больше информации, чем используется здесь. Вам, конечно, предстоит также самим писать код для занесения вводимой информации в какие-либо хранилища данных. (Листинг 11.12 будет выполняться и в Excel, и в Word). Листинг 11.12. Вложенные циклы Do 1 Sub Makelnv() 2 ' обеспечивает ввод данных для накладных и элементы 3 ' записей для каждой накладной. Внешний цикл получает 4 ' информацию об отдельной накладной, внутренний - 5 ' о записях этой накладной (наименование и количество 6 ' товара) 7 8 Const miTitle = "" 9 10 Dim InvcNum As String * 5 1 номер накладной 11 Dim ItemNuml As String * 16 12 Dim ItemNum2 As String * 16 13 Dim ItemDone As Boolean 14 Dim InvcDone As Boolean 15 Dim pos As Integer 16 17 18 InvcDone = False 19 Do Until False 20 InvcNum = InputBox(prompt:="Введите номер накладной:", 21 Title:=miTitle) 22 If Trim(InvcNum) = "" Then 23 MsgBox prompt:="0тмена ввода накладной.", _ 24 Title:="Ввод накладных", Buttons:=vbExclamation 25 Exit Do 26 27 28 29 30 31 32 33 34 35 36 37 38 39' 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 End If pos = 1 Do Until False ' цикл для получения элемента строки ' Ввод наименования товара ItemNuml = InputBox(prompt:= _ "Введите наименование товара", _ Title:="Накладная №" & InvcNum & "Позиция N’" & pos) If Trim(ItemNuml) = "" Then MsgBox prompt:="Ввод позиций для накладной №" & _ InvcNum & " завершен.", _ Title:=miTitle Exit Do End If , \ 1 ввод количества товара ItemNum? = InputBox(prompt:= _ "Введите количество товара", _ Title:“"Накладная №" & InvcNum & "Позиция N‘" & pos) If Trim(ItemNum2) = "" Then MsgBox prompt:="Ввод позиций для накладной №" & _ InvcNum & " завершен.", _ Title:=miTitle Exit Do End If ’ операторы для сохранения вводимых данных, получения ' большей информации об элементе записи и т.д. MsgBox prompt:“"Введенный элемент N’" & pos & " " & Повторение действий в Visual Basic: циклы 283 56 ItemNuml & " кол-во " & ItemNum2 & _ 57 " в накладной №" & InvcNum, _ 58 Title:“"Контрольная выдача " 59 60 роз - роз + 1 61 Loop 62 Loop 63 64 MsgBox prompt:="Ввод накладной завершен", Title:=miTitle 65 End Sub Процедура Makelnv демонстрирует применение вложенных Do-циклов на примере имитации ввода накладных. В процедуре использованы бесконечные циклы (строки 19, 29), выход из которых осуществляется оператором Exit Do (строки 25, 50). Накладная имеет номер и записи, включающие наименование товара и количество. Номера накладных вводятся во внешнем цикле (начинается в строке 19). Сразу после ввода накладной производится проверка необходимости выхода из цикла (строки 22-26). Если пользователь не ввел номер или нажал кнопку Cancel, внешний цикл прекращается с предварительным сообщением об отмене ввода накладной (строки 23-24 ). Перед началом выполнения внутреннего цикла переменной pos (счетчик количества позиций в накладной) присваивается значение 1 (строка 28). В конце внутреннего цикла (строка 60) значение счетчика увеличивается на единицу. В теле внутреннего цикла вводятся наименования (строки 32-34) и количества (строки 43-45) товаров. После ввода каждого из этих элементов производится проверка ввода (строки 35-40, 46-50), после которой выполнение внутреннего цикла может быть завершено операторами Exit Do (строки 39, 50). Если наименование и количество товаров введены успешно, в конце внутреннего цикла (строки 55-58) производится контрольная выдача введенных данных на экран. Вот и все, что можно было рассказать в рамках этой главы о циклах, применяемых в VBA для выполнения различных повторяющихся действий. Гя@зо 12 Массивы В этой главе описываются массивы. Массивы являются распространенным и полезным способом сохранения многих различных частей связанных данных. Массивы полезны при создании отсортированных и неотсортированных списков данных, при сохранении таблиц данных и для выполнения многих других задач. Информация, сохраненная в массиве, может быть доступна в любом порядке. Массив (array) — это коллекция переменных, которые имеют общие имя и базовый тип. Массив является удобным способом хранения нескольких связанных элементов данных в едином контейнере для большего удобства и эффективности программирования. Все элементы данных, сохраняемых в массиве, должны иметь один и тот же тип; например, при создании массива для сохранения типов Integer (Double, String, Currency и т.д.) все элементы данных, сохраненных в этом массиве, должны быть числами Integer (Double, String, Currency и т.д.). Массив позволяет сохранять и манипулировать многими элементами данных посредством единственной переменной. Кроме уменьшения общего числа различных имен переменных, которые необходимо отслеживать, другим основным преимуществом использования массивов является то, что можно использовать циклы для легкой обработки различных элементов массивов. Объединяя массивы и структуры цикла (обычно For ...Next или For ...Each), можно написать небольшое число операторов, которые обрабатывают большой объем данных. Выполнение тех же задач с использованием отдельных переменных может потребовать написания сотен операторов. Размерность массива В языках программирования обычно используются одномерные и многомерные массивы, одни из которых описывают относительно простые, а другие — более сложные объекты. Одномерные массивы Наименее сложный массив — это просто список элементов данных; такого рода массив называется простым (simple) или одномерным (single-dimensional) массивом. Такой массив можно представить в виде таблицы (рис. 12.1). Каждый элемент данных, хранимых в массиве, называется элементом (element) массива. Массив на рис. 12.1 имеет 8 элементов; каждый элемент сохраняет число типа Double. Заметьте, что элементы в массиве пронумерованы от 0 до 7, что составляет 8 элементов. Такая система нумерации довольно распространена в программировании и называется нумерацией с нулевой базой (zero-based). Для доступа к данным, хранящимся в определенном элементе массива, следует указывать имя массива с последующим числом, называемым индексом (subscript или index) элемента. Индекс всегда заключается в круглые скобки. Например, если массив на рис. 12.1 имеет имя DoubleArray, то следующий оператор присваивает число 0.11 переменной Double Any: DoubleAny = DoubleArray (6) В этом операторе число 6 является индексом массива; заметьте, что он заключен в круглые скобки и не отделяется пробелами от имени массива. Поскольку ну Массивы 285 мерация элементов начинается с нуля, элемент, на который ссылается этот оператор, является, фактически, седьмым элементом массива DoubleArray. 10.2 11.2 22.1 1.1 21.3 123.0 0.11 1.1 0-й 1-й 2-й 3-й 4-й 5-й 6-й 7-й элемент элемент элемент элемент элемент элемент элемент элемент Рис. 12.1. Одномерный числовой массив; одномерные массивы - это, в основном, просто списки данных одного и того же типа Посмотрите снова на рис. 12.1 и обратите внимание, что элемент массива с номером 6 содержит значение 0.11. При выполнении приведенного выше оператора VBA выбирает значение 0.11 из указанного элемента массива и сохраняет это значение в переменной DoubleAny — точно так же, как в любом другом присваивании переменной. Можно также использовать индекс всякий раз, когда необходимо сохранить данные в отдельном элементе массива. Например, следующий оператор сохраняет число 12.3 в восьмом элементе массива, показанном на рис. 12.1: DoubleArray (7) =12.3 При выполнении этого оператора VBA помещает значение 12.3 в указанный элемент массива, заменяя предыдущее содержимое этого элемента — точно так же, как в любом другом присваивании переменной. Можно использовать элемент массива в любом выражении VBA — точно так же, как используется значение константы или переменной в каком-либо выражении. Одномерные массивы обычно используются для представления различных списков данных. Многомерные массивы Одномерные массивы хорошо подходят для представления простых списков данных. Однако часто бывает необходимо представить таблицы данных в программах с организацией данных в формате строк и столбцов, подобно ячейкам в рабочих листах Excel. Для этого необходимо использовать многомерные (multi-dimensional) массивы. Поскольку вы уже имеете опыт работы с ячейками Excel, то нет необходимости в подробном разъяснении сущности двумерного массива. Адрес каждой ячейки листа состоит из двух чисел (измерений), одно из которых (номер строки) является первым индексом, а второе (номер столбца) — вторым индексом массива. На примере организации листов Excel можно представить и трехмерные массивы. Здесь третьим индексом массива может быть номер листа. В VBA можно также создавать массивы, имеющие более трех измерений; фактически, VBA позволяет создавать массивы, имеющие до 60 измерений. Работа с массивами, имеющими 4 или более измерений, быстро становится запутанной; к счастью, вам, вероятно, не придется работать с такими массивами. Чаще всего в программировании используются одно- и двумерные массивы. Статические и динамические массивы В следующем разделе вы узнаете, что число элементов в массиве обычно задается во время объявления массива. Объявление массива указывает VBA величину различных измерений массива (диапазон изменения каждого индекса). После того как массив объявлен, VBA выделяет достаточный объем памяти для всех элементов массива. Например, для массива на рис. 12.1 VBA выделит объем памяти, достаточный для 8 чисел типа Double. I лава *Q Переменные типа массив подчиняются тем же правилам области действия, что и любые другие переменные. VBA сохраняет зарезервированной область памяти для всех элементов в массиве, пока существует переменная типа массив. Подобные массивы называются статическими (static), потому что число элементов в массиве не меняется. Выбор размера массива может быть затруднен, если неизвестно, сколько данных будет введено в массив, или если объем данных, собираемых для массива, значительно меняется. Если вам иногда приходится сохранять 100 значений, а иногда — только 10 значений, то потенциально напрасно расходуется область памяти, необходимая для сохранения 90 значений. Для подобных ситуаций VBA поддерживает особый тип массивов, называемый динамическим (dynamic) массивом. Динамические массивы получили свое название, потому что можно изменять число элементов в массиве при выполнении VBA-программы. Динамический массив (в сочетании с правильным программированием) может увеличиваться или сжиматься (уменьшаться в размере), чтобы вмещать точно необходимое число элементов без напрасного расходования памяти. Для изменения размера динамического массива используйте оператор ReDim, описываемый далее в этой главе. Оператор Option Base Обычно в VBA используются массивы с нулевой базой. В системе нумерации с нулевой базой индекс для первого элемента в любом измерении массива является равным 0; массив с 10 элементами имеет индексы от 0 до 9. Очевидно, что система нумерации с нулевой базой может быть непонятной, потому что индекс 0, в действительности, обозначает 1-й элемент массива, индекс 5 обозначает 6-й элемент массива и так далее. Было бы гораздо удобнее, если бы элементы массива нумеровались, начиная с 1, а не с 0. Если бы нумерация элементов начиналась с 1, то индекс 1 обозначал бы 1-й элемент массива, индекс 5 — 5-ый и так далее. VBA позволяет задавать начальное число для элементов массива. Можно задавать нижнее число для индексов массива при объявлении массива (описывается далее в этой главе), или использовать директиву компилятора Option Base для указания того, должна ли нумерация индексов начинаться с 0 или с 1. Директива компилятора Option Base имеет следующий синтаксис: СИНТАКСИС Option Base 0 | 1 Оператор Option Base позволяет задавать 0 или 1 как начальное число по умолчанию для индексов массива. Если оператор Option Base не используется, VBA начинает нумерацию индексов массива с 0 (по умолчанию). Необходимо помещать оператор Option Base в область объявлений модуля перед объявлениями любых переменных, констант или процедур. Нельзя помещать оператор Option Base внутри процедуры. Можно иметь только один оператор Option Base в модуле. Оператор Option Base влияет на все массивы, объявляемые в модуле, независимо от того, являются ли они локальными в процедуре или объявляются 'на модульном уровне. Следующие два оператора являются примерами директивы компилятора Option Base: Option Base 0 1 установка по умолчанию Option Base 1 1 индексы массивов начинаются с 1 Массивы 287 Объявление массивов Вы уже знакомы с оператором Dim, используемым для объявления переменных. Этот же оператор используется и для объявления массивов. В действительности, ключевое слово Dim является сокращением слова dimension (измерение). В оригинальном языке программирования BASIC ключевое слово Dim использовалось исключительно для изменения размеров массивов (dimensioning), отсюда и сокращение Dim. Однако современный язык VBA расширил использование ключевого слова Dim до использования со всеми переменными. С помощью Dim можно объявлять как одномерные, так и многомерные массивы. Объявление массива с помощью оператора Dim имеет следующий синтаксис: СИНТАКСИС Dim VarName ( [Subscripts'] ) [As Туре] ' VarName — любое имя для массива, удовлетворяющее VBA-правилам для имен идентификаторов. Subscripts — измерение (измерения) массива. Можно объявлять массивы, имеющие до 60 измерений. Для одномерного массива включается один Subscripts-, для двумерного массива — два (отделенные друг от друга запятой) и так далее. Каждый Subscripts добавляет новое измерение в массив. Можно также объявлять статические и динамические массивы, используя ключевые слова Public, Private и Static — точно так же, как для любой другой переменной и с тем же влиянием на область действия. Используйте показанный здесь синтаксис объявления массива и просто подставляйте ключевое слово Public, Private или Static вместо ключевого слова Dim, если необходимо. Оператор Subscripts имеет следующий синтаксис: СИНТАКСИС [lower То] upper [,[lower То] upper]... Здесь lower определяет нижний диапазон допустимых индексов для массива; upper — верхний предел. Заметьте, что только верхний предел является обязательным; часть lower То оператора Subscripts является необязательной. При определении только предела upper VBA нумерует элементы массива в зависимости от установки Option Base. Если действует установка Option Base 1, VBA нумерует элементы в массиве от 1 до upper, иначе — от 0 до upper. Включение части lower То оператора Subscripts помогает сделать код более легким и понятным, а также выявить ошибки программирования. Это также позволяет определять иной начальный индекс для массива, чем 0 или 1. Например, можно создать массив с элементами, имеющими номера от 5 до 10 или от -5 до 0, в зависимости от конкретной выполняемой задачи. Подобно обычным объявлениям переменных, можно объявлять определенный тип данных для массива, включая в объявление оператор As type. При этом type представляет любой допустимый тип VBA — Currency, Double, String и так далее. Можно также объявлять массивы, имеющие определенный пользователем тип (создание пользовательских типов в книге не рассматривается). Если опустить type, все элементы в массиве имеют тип Variant. VBA инициализирует элементы числовых массивов нулями и элементы строковых массивов пустыми строками. Заметьте, что оператор Subscripts является необязательным. Для создания динамического массива не используйте оператор Subscripts (необходимо включать круглые скобки в объявление массива, независимо от того, определяется ли Subscripts). 288 Глава 12 Следующие примеры являются допустимыми объявлениями массива: Dim strarray(l То 100) As String Dim variant_array() Dim str_Multiplication(0 To 15, 0 To 15) As String При объявлении массивов следует помнить, что включение оператора Subscripts в объявление массива создает статический массив с фиксированным числом элементов, пропуск оператора Subscripts в объявлении массива создает динамический массив, а установка Option Base может повлиять на общее число элементов в массиве. Использование массивов После объявления массива использовать его в коде VBA довольно просто. Как уже объяснялось в начале этой главы, для доступа к элементу массива необходимо указать имя массива, за которым следует значение индекса, заключенное в круглые скобки. Обращение к элементу массива имеет следующий синтаксис: СИНТАКСИС arrayName(validlndexl, [validlndex2]...) Здесь arrayName — имя массива; validlndexl — допустимое значение индекса для первого измерения массива; validlndex2 — допустимое значение индекса для второго измерения массива, если таковое имеется. Необходимо предоставлять значение индекса для каждого измерения массива при каждом обращении к какому-либо элементу в массиве. Например, для двумерного массива необходимо всегда определять два индекса. Допустимым индексом является любая переменная VBA или выражение, имеющее результатом целое число в диапазоне объявленных измерений массива. Например, допустимым значением индекса для одномерного массива, объявленного с индексами 1-10, может быть любое выражение VBA, имеющее результатом целое число в диапазоне от 1 до 10. Использование меньшего или большего индекса, чем диапазон для определенного измерения в массиве, приводит к тому, что VBA отображает runtime-ошибку. Следующий фрагмент кода показывает типичное объявление и использование массива. . Dim Factorial(0 То 30) As Double ' объявление массива из 31 элемента Factorial(0) = 1 ' инициализировать 1-й элемент For i = 1 То 30 ' начало цикла для работы с массивом Factorial(i) = i* Factorial(i - 1) ' изменить i-й элемент Next i Рассмотрим простой пример работы с одномерным массивом, представленный кодом листинга 12.1. Процедура в первом цикле For...Next принимает в диалоговом окне целые числа (для простоты без всякой проверки) и заносит их в элементы массива. Во втором цикле значения элементов массива заносятся в строку и выводятся на экран в диалоговом окне оператора MsgBox. Листинг 12.1. Работа со статическим одномерным массивом 1 Sub DemoStatArray() 2 Dim Int_Array(5) As Integer 3 Dim str_msg As String 4 Массивы 289 5 str_msg = "" 6 7 For i = 1 To 5 8 Int_Array(i) = InputBox("Введите целое число для " 9 & i & "-го элемента массива", _ 10 "Ввод элементов массива") 11 Next 12 13 For ] = 1 То 5 * 14 str_msg = str_msg & Int_Array(j) & ", " 15 Next 16 17 MsgBox "Введено: " & str_msg, _ 18 , "Вывод ранее введенного массива" 19 20 End Sub В строке 2 объявляется одномерный массив Int_Array (размерностью 5 элементов) целых чисел Int_Array. Далее (строка 3) объявлена рабочая переменная str_msg для завершающего вывода данных из массива в диалоговом окне (строка 19). В первом цикле For...Next (строки 7-11) в массив Int_Array записываются значения из окна ввода. Обратите внимание, как формируется значение аргумента Prompt функции InputBox. На рис. 12.2 приведен фрагмент ввода 3-го элемента массива. Рис. 12.2 Фрагмент ввода 3-го элемента массива Ввод элементов массива Введите целое число для 3-го элемента массива ОК Cancel В строках 13-15 располагается второй цикл, который формирует строку из значений элементов массива для выдачи ее в диалоговом окне (рис. 12.3). Рис. 12.3 Результат работы кода листинга 12 1 Процедура DemoStatАггау2 в листинге 12.2 предназначена для демонстрации работы с двумерным массивом. Листинг 12.2. Работа со статическим двумерным массивом 1 Sub DemoStatArray2() 2 Dim Int_Array(3, 6) As Integer 3 Dim str_msg As String 4 5 str_msg = "" 6 7 For i = 1 To 3 8 For ] = 1 To 6 9 Int_Array(i,j)“InputBox("Введите целое число для " 10 Программирование на VBA 2002 290 Глава 12 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 & " элемента (" & i & & j & _ "Ввод элементов массива; строка " & i) Next j Next i For i = 1 To 3 For j = 1 To 6 str_msg = str_msg & Int_Array(i, j) & ", " Next ] ' str_msg = str_msg & Chr(13) 'перевод строки Next i MsgBox "Введено: " 4 Chr(13) & str_msg, _ , "Вывод ранее введенного массива" 26 End Sub Для инициализации массива используется вложенный цикл в строках 7-13. Обратите внимание на строки 12-13. Здесь, как ранее отмечалось, указывается, по какой переменной заканчивается цикл. Это необязательно, но лучше привыкнуть к такому стилю программирования с самого начала. В окне ввода теперь для указания, какой элемент вводится в конкретный момент времени, выводятся оба индекса (рис. 12.4). Это уже довольно дружественный интерфейс для ввода двумерного массива: пользователю трудно не догадаться, чего от него добивается программа. Чтобы понять, как это достигается, внимательно проанализируйте оператор в строках 9-11. Рис. 12.4 Дружественный интерфейс для ввода элемента двумерного массива • । Ввод элементов массива, строка 2 Введите целое число для элемента (2,6) ОК Cancel |26f Вторая часть процедуры DemoStatArray2 также состоит из вложенных циклов и, как и в предыдущем листинге, эта часть предназначена для выдачи инициализированного массива в окне MsgBox при помощи переменной str_msg. Для осуществления этой задачи во внутреннем цикле (строки 16-18) формируется строка из элементов массива при постоянном первом индексе (переменная i). При этом меняется только второй индекс (переменная j). После заполнения строки, но перед изменением первого индекса к переменной str_msg добавляется символ перехода на другую строку (строка 20). Результат работы кода листинга 12.2 приведен на рис. 12.5. Рис. 12.5 В результате работы кода листинга 12.2 инициализирован массив размерностью 3x6 Массивы 291 М Процедуры листингов 12.1 и 12.2 работают при наличии в модуле, где они описаны, директивы компилятора Option Base 1. Использование ReDim с динамическими массивами Как упоминалось ранее Н” этой главе, могут сложиться обстоятельства, при которых точно не известно, сколько элементов потребуется в массиве. В VBA имеется возможность переопределять размерность массивов, а во время объявления не указывать размерность. Используя динамический массив, можно создавать массив такой большой или такой маленький, какой необходимо. Динамические массивы создаются с помощью оператора Dim, затем их размер устанавливается с помощью оператора ReDim во время выполнения процедуры. Оператор ReDim имеет следующий синтаксис: СИНТАКСИС а-- Л-.'W ReDim [Preserve] varname (subscripts') [As type] [, _ varname(subscripts) [As type]] Необязательное ключевое слово Preserve, как предполагает его имя, приводит к тому, что VBA сохраняет данные в имеющемся массиве, когда изменяется размер массива с помощью ReDim; varname — имя существующего массива; subscripts — это измерения массива (синтаксис для оператора subscripts в операторе ReDim такой же, как для оператора Dim); type — любой тип VBA или определенный пользователем тип. Необходимо использовать отдельный оператор As type для каждого массива, который вы определяете. Далее следуют допустимые примеры объявлений динамических массивов и возможные операторы ReDim, используемые с этими динамическими массивами: Dim aMonth() As String 1 объявляет динамический массив aMonth ReDim aMonth(l To 30) ’ изменяет размер массива до 30 элементов ReDim aMonth(31) ' изменяет размер массива до 31 элемента ReDim Preserve aMonth(l To 31) ' изменяет размер массива до 31 ' элемента, сохраняя содержимое Dim Table()As Integer ' объявляет динамический массив ReDim Table(3, 15) 1 делает массив двумерным ReDim Table (4, 20) ' изменяет размер двумерного массива ReDim Preserve Table (4, 25) ' только изменяет последний размер ' массива Dim Mas as Variant ' объявляет переменную типа Variant ReDim Mas(20) As Integer ' создает массив 20 целых в Variant Предыдущие примеры иллюстрируют некоторые важные моменты, относящиеся к динамическим массивам. Во-первых, можно изменять только последнее измерение многомерного массива, когда используется ключевое слово Preserve. Во-вторых, можно использовать ReDim для создания типизированного массива внутри переменной типа Variant. Поскольку переменные типа Variant могут содержать данные любого типа, можно использовать переменную типа Variant для сохранения динамического массива! (Использование переменной типа Variant для сохранения динамического массива дает возможность изменять размер массива с помощью ReDim и изменять тип данных массива.) Обычно оператор ReDim используется для изменения размера динамического массива, который уже был объявлен ранее с помощью операторов Dim, Private, Public или Static. Можно использовать оператор ReDim для изменения числа элементов и измерений в динамическом массиве столько раз, сколько необходимо. Однако нельзя использовать оператор ReDim для изменения типа данных массива, 10' 292 Глава 12 если только массив не содержится в переменной типа Variant или сами элементы массива не имеют тип Variant. Если динамический массив сохраняется в переменной типа Variant, можно изменять тип данных, используя оператор As type в операторе ReDim. Попытка использовать ReDim для статического массива (массив, измерения которого были явно определены в объявлении Dim, Public, Private или Static) приводит к тому, что VBA отображает runtime-ошибку. Код листинга 12.3 является примером использования динамического одномерного массива и выполняет задачу ввода данных в массив, подобную решаемой в листинге 12.1. Это делается для того, чтобы концентрировать внимание читателя на отличиях использования разных типов массивов, а не деталях различных задач. Листинг 12.3. Работа с динамическим одномерным массивом 1 Option Base 1 2 Sub DemoDinArray() 3 Dim Int_Array() As Integer 4 Dim str_msg As String, i As Integer 5 Dim Num 6 7 strmsg = "" 8 i = 0 ' 9 10 Do 11 i = i + 1 12 Num = InputBox("Введите целое число для " _ 13 & i & "-го элемента массива", _ 14 "Ввод элементов массива") 15 If Len(Num) = 0 Then Exit Do ’ выход из цикла 16 17 1 изменение размера массива 18 ' с сохранением элементов 19 ReDim Preserve Int_Array(i) 2° 21 ' ввод данных в i-й элемент массива 22 Int_Array(i) = Num 23 Loop 24 25 For j = 1 To i - 1 26 str_msg = str_msg & Int_Array(j) & ", " 27 Next 28 29 MsgBox "Введено: " & str_msg, _ «, 30 , "Вывод ранее введенного массива" 31 32 End Sub В строке 3 объявлен массив Int_Array без указания размерности. Это подразумевает, что где-то в коде при помощи оператора ReDim размерность будет указана. Для ввода данных в массив используется бесконечный цикл Do (строки 10-23), так как количество вводимых данных заранее неизвестно. В цикле в диалоговом окне функции InputBox (строки 12-14) вводятся значения для элементов массива. Если значение введено (пользователь не отказался от ввода посредством кнопки Cancel), размерность массива увеличивается (строка 19) с сохранением предыдущих значений элементов массива и очередному (новому) элементу массива присваивается введенное значение (строка 22). За количеством элементов в массиве «следит» целая переменная i, значение которой увеличивается в начале цикла. Массивы 293 Если пользователь отказывается от ввода, оператор Exit Do (строка 15) прекращает работу цикла Do. При этом значение переменной i в этот момент оказывается на единицу больше размерности массива: оператор в строке 11 выполнился (увеличение i), а в строке 19 — нет (увеличение размерности массива). Во второй части процедуры размерность массива уже известна (i— 1), поэтому можно для формирования строки выдачи на экран использовать цикл с определенным количеством итераций, т.е. цикл For...Next (строки 25-27). Остальное по причине сходства с предыдущими двумя листингами должно быть понятно без комментариев. В листинге 12.4 приведен код, который демонстрирует один из возможных способов работы с динамическим массивом. Листинг 12.4. Работа с динамическим двумерным массивом 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 Option Base 1 Sub DemoDinArray2() Dim Int_ArraylO As Integer Dim Int_Array() As Integer Dim str_msg As String Dim i As Integer, m As Integer, n As Integer Dim Num str msg = "" i = 0 Do i = i + 1 Num = InputBox("Введите целое число для " _ & i & "-го элемента массива", _ "Ввод элементов массива") If Len(Num) = 0 Then Exit Do ' выход из цикла ' изменение размера массива ' с сохранением элементов ReDim Preserve Int_Arrayl(i) ' ввод данных в i-й элемент массива Int_Arrayl(i) = Num Loop m = i - 1 ’ вторая размерность массива ' ввести первую размерность: п = InputBox("Введите количество строк массива ") ReDim Int_Array(n, m) ' запись в выходной массив уже введенной строки: For j = 1 То m Int_Array(l, j) = Int_Arrayl(j) Next ' теперь работаем с обычным двумерным массивом, ' только первую строку не заполняем: For i = 2 То п For j = 1 То m Int_Array(i, j) = InputBox("Введите целое число для " _ & " элемента (" & i & & j & ")", _ "Ввод элементов массива; строка " & i) Next j Next i 294 Глава 12 48 49 ' подготовка строки выдачи 50 For i = 1 То п 51 For j = 1 То m 52 str_msg = str_msg & Int_Array(i, j) & ", " t 53 Next j 54 55 str_msg = str_msg & Chr(13) 'перевод строки 56 Next i * 57 58 MsgBox "Введено: " & Chr (13) & str_msg, _ 59 , "Вывод ранее введенного массива" 60 61 End Sub В первой части процедуры DemoDinArray2 (строки 9-27) в динамический массив Int_Arrayl записывается первая строка будущего многомерного массива и определяется его вторая (количество столбцов) размерность. Как только пользователь во время ввода первой строки отказался от ввода, формирование первой строки заканчивается. В этот момент программе известна вторая размерность будущего двумерного массива: m=i—1. В строке 30 функция InputBox запрашивает ввести первую размерность массива Int_Array, а в строке 31 объявляется этот двумерный массив. В строках 33-36 данные из одномерного массива Int_Arrayl переписываются в первую строку двумерного массива Int_Array. Со строки 41 программа почти ничем не отличается от кода листинга 12.2, начиная со строки 7. Отличие состоит только в том, что в последнем коде заполнение двумерного массива во вложенном цикле осуществляется со второй строки и пределы цикла заданы не литерами, а переменными. В качестве еще одного примера использования динамического массива рассмотрим программу, при помощи которой можно пронумеровать выделенное количество строк. При этом эта нумерация будет отличаться от автонумерации Word тем, что строки, пронумерованные таким образом, ничем не отличаются от обычного текста и могут быть восприняты другими редакторами при передаче в них данного текста. Листинг 12.5. Нумерация строк 1 ' НумерацияСтрок Macro 2 1 11 Macro recorded 28.04.01 by Владимир Кузьменко 3 ' 4 ' Нумерует строки выделенного текста 5 ' Вызов: Ctrl+Alt+N 6 ' • 7 ' количество выделенных строк: 8 ii = Selection.Paragraphs.Count() 9 10 ' объявление массива для хранения строк: 11 Dim mas() As String 12 13 1 цикл считывания строк и добавления нумерации: 14 For i = 1 То ii 15 ReDim Preserve mas(i) 16 tt = Selection.Paragraphs(i) » 17 mas(i) = Str(i) & & vbTab & tt ' 18 Next 19 20 ' удаление выделенного фрагмента: 21 Selection.Cut 22 23 1 цикл печати массива: Массивы 295 24 For i = 1 То ii 25 Selection.TypeText Text:=mas(i) 26 Next 27 Если вам необходимо начинать нумерацию с некоторого числа и вместо символа использовать какой-либо другой, макрос можно переписать, например, так, как это сделано в следующем листинге. Листинг 12.6. Работа с динамическим одномерным массивом 1 Sub НумерацияСтрок() 2 ' 3 1 НумерацияСтрок Macro 4 ' Macro recorded 28.04.01 by Владимир Кузьменко 5 ' 6 ' Нумерует строки выделенного текста 7 ' Вызов: Ctrl+Alt+N 8 ' 9 10 BeginNumber = CInt(InputBox("Введите начальный номер строки", _ 11 "Ввод номера первой строки", 1)) 12 13 NumberChar = InputBox("Введите символ разделения", _ 14 "Ввод символа разделения", 15 16 ' количество выделенных строк: 17 ii = Selection.Paragraphs.Count() 18 19 ' объявление массива для хранения строк: 20 Dim mas() As String 21 22 ' цикл считывания строк и добавления нумерации: 23 For i - 1 То ii 24 ReDim Preserve mas(i) 25 tt = Selection.Paragraphs(i) 26 mas(i) - Str(i + BeginNumber - 1) & NumberChar & vbTab & tt 27 Next 28 29 1 удаление выделенного фрагмента: 30 Selection.Cut 31 32 ' цикл печати массива: 33 For i = 1 To ii 34 Selection.TypeText Text:=mas(i) 35 Next 36 End Sub Как и в предыдущем макросе, в строке 26, кроме вводимого символа разделения номера и кода, используется символ табуляции (его роль играет константа vbTab). Это необходимо для того, чтобы строки кода были выровнены слева. Заметьте, что для нумерации последнего макроса в качестве символа разделения использовался символ функции LBound и UBound Для контроля за размерами как статических, так и динамических массивов можно использовать одну или пару переменных для сохранения минимального и максимального индекса массива, как это делается в ранее рассмотренных лис 296 Глава 12 тингах. Если для отслеживания верхнего и нижнего пределов индексов массива пользователь полагается на собственные переменные, то он полностью отвечает за обновление и точность этих переменных. В противном случае процедуры не будут работать правильно — будет обрабатываться меньше элементов, чем в действительности содержит массив, или будет получено сообщение об ошибке при попытке доступа к массиву с индексами, выходящими за фактический размер массива. Такие программные ошибки бывает трудно отслеживать. VBA имеет пару функций, которые освобождают пользователя от необходимости вручную отслеживать верхний и нижний пределы массива — функции LBound и UBound. Эти функции возвращают нижнее и верхнее граничные значения индексов статического или динамического массива. Функции LBound и UBound имеют следующий синтаксис: СИНТАКСИС - « LBound(arrayName [, dimension]) UBound(arrayName [, dimension]) Функция LBound возвращает первый индекс массива, представленного с помощью arrayName. Функция UBound возвращает наибольший индекс массива, представленного с помощью arrayName. Можно использовать эти две функции как со статическими, так и с динамическими массивами. Аргумент dimension представляет целое число, определяющее измерение массива, для которого необходимо получить нижний или верхний предел. Если опустить dimension, VBA возвращает предел для первого измерения массива. Следующие фрагменты кода являются примерами использования функций LBound и UBound: Dim А(3 То 9) As String For i = LBound(A) To UBound(A) A(i) = String(10, 65 + 1) Next i Dim aMatrix(l To 365, 1990 To 1999) For i = LBound(aMatrix, 1) To UBound(aMatrix, 1) For j = LBound(aMatrix, 2) To UBound(aMatrix, 2) Matrix(i, j) = Rnd Next j Next i Заметьте, что во втором примере функции LBound и UBound используют необязательный аргумент dimension. Внешний цикл For...Next выполняется столько раз, сколько элементов имеется в первом измерении массива aMatrix, тогда как внутренний цикл For ...Next выполняется столько раз, сколько элементов имеется во втором измерении массива aMatrix. Использование Erase для очистки или удаления массивов VBA имеет особый оператор Erase, позволяющий выполнять одну из двух за- -дач в зависимости от того, каким массивом манипулирует пользователь — статическим или динамическим. В случае статических массивов Erase позволяет очищать все элементы массива, в основном переустанавливая массив в то же самое состояние, какое он имел, когда VBA создавал его в оперативной памяти. В случае динамических массивов Erase позволяет полностью удалять массив и его содержимое из оперативной памяти. Массивы 297 Когда элементы массива заполнены, данные в массиве остаются (независимо от того, является данный массив статическим или динамическим) до тех пор, пока пользователь не присвоит новые значения элементам массива или пока VBA не освободится от массива. (Массивы следуют тем же правилам области действия и персистенции, что и любая другая переменная в VBA, как описывается в главе 4.) При некоторых обстоятельствах может понадобиться очистить все значения в массиве, устанавливая числовые значения на 0, строковые значения на пустые строки и так далее. Обычно следует использовать цикл For...Next или For...Each для установки всех элементов в массиве на определенное значение. Следующие фрагменты кода показывают оба цикла For...Next и For ...Each, используемые для инициализации всех значений в числовом массиве на 0: For k = LBound(NumArray) То UBound(NumArray) NumArray(к) - О Next к For Each Num In NumArray Num = 0 Next Num Первый фрагмент кода использует цикл For ...Next и функции LBound и UBound для прохождения в цикле по всем элементам массива; второй фрагмент кода использует For...Each для прохождения в цикле по каждому элементу массива, также устанавливая каждый элемент на 0. Хотя эти циклы довольно короткие, можно выполнить ту же самую задачу для статического массива даже более эффективно с помощью единственного оператора Erase: Erase NumArray Массивы «имеют тенденцию» занимать относительно большой объем оперативной памяти — например, массив из 20 элементов занимает такой же объем памяти, как 20 отдельных переменных одного и того же типа. Поскольку массивам требуется так много памяти, следует удалять динамические массивы из оперативной памяти, когда они фактически не используются. (Статические массивы не могут удаляться из оперативной памяти до тех пор, пока VBA автоматически не освобождается от массива.) VBA удаляет из памяти массивы, объявляемые локально в процедуре (так же, как и любые другие локальные переменные), каждый раз, когда процедура прекращает выполняться. Однако массивы, объявляемые на модульном уровне, существуют пока любая процедура в этом модуле выполняется. Если программа большая, вам может понадобиться восстановить ресурс памяти, используемой динамическими массивами модульного уровня. Оператор Erase позволяет делать именно это. Оператор Erase имеет следующий синтаксис: СИНТАКСИС Erase arrayI [, array2, . ] Здесь arrayl и аггау2 представляют любое допустимое имя массива VBA. Можно перечислить столько массивов в операторе Erase, сколько хотите, отделяя каждое имя массива запятой. Оператор Erase удаляет из памяти динамические массивы, освобождая область памяти, ранее используемую этим массивом. При удалении динамического массива с помощью оператора Erase необходимо повторно создать массив с помощью оператора ReDim перед тем, как можно будет использовать этот определенный динамический массив снова. При попытке доступа к элементам в динамическом массиве, для которого был использован оператор Erase, без его переопределения VBA отображает сообщение о runtime-ошибке. 298 Глава 12 Поведение оператора Erase для статических массивов немного сложнее и зависит от конкретного типа элементов массива. В следующей таблице описывается действие оператора Erase со статическими массивами различных типов: Тип статического массива Действие оператора Erase Любой числовой тип Устанавливает элементы массива на 0. Любой строковый тип Устанавливает элементы массива на строку нулевой длины (""); устанавливает строки фиксированной длины как все символы пробелов. Variant Устанавливает элементы массива на Empty. Object Устанавливает элементы массива на Nothing. Любой пользовательский тип Устанавливает каждую переменную в пользовательском типе индивидуально: численные типы устанавливаются на 0, строковые — на строки нулевой длины, Variant — на Empty, Object — на Nothing. Использование массивов в качестве аргументов процедур и функций VBA дает возможность передавать массивы в качестве аргументов процедур и функций. Эта возможность может быть очень полезной; поскольку нет необходимости задавать размер массива, который передается как аргумент, можно писать универсальные процедуры или функции обработки массива. Например, можно написать функцию, получающую числовой массив в качестве аргумента и возвращающую среднее значение всех чисел в массиве как результат функции. Еще один пример: можно написать процедуру, получающую массив в качестве аргумента, передаваемого по ссылке, и сортирующую этот массив. И в одном, и в другом примерах можно написать процедуру или функцию для работы с массивом любого размера — пять элементов, 10 элементов, 100 элементов и так далее. Общий синтаксис для аргументов-массивов для процедур или функций такой же, как для любых аргументов процедур или функций: * СИНТАКСИС [ByVai I ByRef] arrayname() As type Как в случае аргументов процедур и функций, о которых вы уже знаете, ключевое слово ByVai указывает VBA передать аргумент-массив по значению, а ключевое слово ByRef указывает VBA, что следует передавать аргумент-массив по ссылке. Если ByVai и ByRef пропущены, VBA передает аргумент-массив по ссылке. В этой синтаксической конструкции аггаупате() представляет аргумент-массив; можно использовать любой допустимый идентификатор VBA в качестве имени аргумента-массива. Необходимо всегда включать пустые круглые скобки после arrayname', круглые скобки указывают VBA, что этот аргумент является массивом. Параметр type представляет любой допустимый тип VBA или определенный пользователем тип. Следующий фрагмент кода показывает, как включать массивы в качестве аргументов для процедур и функций: Массивы 299 Sub ShowText(Lines(), NumLines As Integer) 1 получает массив типа Variant, передаваемый по ссылке End Sub Sub SortList(ByRef List() As String, NumLines As Integer) 1 получает массив типа String, передаваемый по ссылке End Sub Если вы помните, передача аргументов по значению (с помощью ключевого слова By Vai) приводит к тому, что VBA передает копию данных функции или процедуре. Не передавайте массивы по значению, если в этом нет особой необходимости — передача больших массивов по значению может быстро исчерпать ресурсы памяти вашего компьютера, приводя к runtime-ошибкам из-за нехватки памяти. Если вы обратили внимание, в двух из трех последних примерах вместе с именами массивов в качестве параметров передаются целые переменные NumLines. Здесь подразумевается передача вместе с ссылкой на массив его размерности. Однако замечательным свойством VBA является то, что он позволяет посредством ранее рассмотренных нами функций Lbound и Ubound внутри процедуры, которая принимает массив в качестве аргумента, определить размерность переданного ей массива. Отметим, что далеко не все системы программирования обладают такой возможностью. Ниже (листинг 12.7) приведен пример передачи массива в качестве параметра процедуре, единственный оператор которой выдает в диалоговом окне размерность переданного ей массива. Листинг 12.7. Определение размерности массива-аргумента 1 Sub TestUBoundLBound(mas()) 2 MsgBox "размерность массива " & "(" & _ 3 UBound(mas, 1) & & UBound(mas, 2) & ")" . 4 End Sub 5 6 Sub a () 7 Dim arr(9, 7) 8 Call TestUBoundLBound(arr) 9 End Sub В результате работы этого кода на экране появляется диалоговое окно, представленное на рис. 12.6. Рис. 12.6 Размерность массива, передаваемого в качестве аргумента, легко определяется в вызывающей процедуре размерность массива (9,7) Microsoft Word иинажоигис!и oxxogodEOj II «UWh Глава 13 Управление файлами с помощью VBA Управление файлами — это одна из интереснейших задач для программиста в любой системе программирования. Когда-нибудь вы, вероятно, захотите (по всей видимости, вы уже захотели), чтобы ваши процедуры были способны копировать или удалять документ, рабочую книгу или другой файл. Visual Basic for Applications предоставляет различные операторы, функции и методы для выполнения общих задач управления файлами. Управление файлами В этом разделе описывается, что такое управление файлами, обсуждаются некоторые из типичных действий, которые можно выполнять как часть задач управления файлами, а также описываются VBA-функции, операторы и методы управления файлами. Что такое управление файлами Управление файлами (file management) — термин, используемый для описания действий, которые выполняются с файлами, сохраненными на дисковых драйверах. Управление файлами включает действия, такие как копирование файлов, удаление неиспользуемых файлов для освобождения области дисковой памяти, перемещение файлов с одного диска (или папки) на другие и создание или удаление каталогов диска. Управление файлами включает также такие виды обработки, как просмотр списка файлов в папке для определения размера файла или даты и времени, когда этот файл был модифицирован в последний раз. VBA позволяет выполнять наиболее общие задачи управления файлами под контролем процедуры или функции, которую вы можете написать. Windows Desktop и справочная система используют термин папка (folder) для обозначения того, что опытные пользователи Windows или DOS знают как каталоги (directories). В этой книге используется термин папка для согласованности с терминологией Windows; в некоторых случаях также используется термин каталог. Возможности VBA по управлению файлами В табл. 13.1 приведены VBA-функции, операторы и методы управления файлами. В первом столбце таблицы находится ключевое слово VBA, во втором — указывается, предназначено ли ключевое слово для функции, оператора или объектного метода. Наконец, в третьем столбце содержится краткое описание назначения каждой функции, оператора или метода. Таблица 13.1. Функции, методы и операторы управления файлами I Имя Категория Назначение ChDir Оператор Изменяет текущий каталог (папку). ChDrive Оператор Изменяет текущий драйвер диска. Управление файлами с помощью VBA 303 Имя Категория Назначение CurDir Функция Возвращает текущий каталог (папку). Dir Функция Возвращает имя каталога или файла, совпадающее с определенным именем файла (включая символы универсального сопоставления), передаваемым как строковый аргумент. Предназначена для нахождения одного или нескольких файлов на диске. FileCopy Оператор Копирует файл. FileDateTime Функция Возвращает значение типа Date, содержащее дату и время, когда этот файл был изменен последний раз. FileLen Функция Возвращает длину файла в байтах. GetAttr Функция Возвращает число, представляющее объединенные атрибуты файла или каталога диска, такие как System, Hidden и так далее. GetOpen-FileName Метод Отображает Excel-диалоговое окно Open и возвращает имя файла, выбранное пользователем. В Word не имеется. GetSave-AsFileName Метод Отображает Excel-диалоговое окно (Save As) и возвращает имя файла, выбранное пользователем. В Word не имеется. Kill Оператор Удаляет файлы с драйвера диска. MkDir Оператор Создает каталог диска (папку). Name Оператор Переименовывает или перемещает файл. RmDir Оператор Удаляет каталог диска (папку). SetAttr Оператор Устанавливает атрибуты файла. Вы могли заметить, что в табл. 13.1 не приводятся аргументы ни для каких элементов (функций, методов, операторов). Несколько из этих функций, операторов и методов имеют довольно сложные списки аргументов и опций. Начиная со следующего раздела в этой главе, каждая VBA-функция, оператор или метод управления файлами описывается полностью со всеми аргументами и опциями. Операторы, функции и объектные методы, имеющиеся в VBA, делятся на шесть различных функциональных частей: Получение или изменение атрибутов файла. Выборка или нахождение имен файлов. Получение или изменение текущего драйвера диска и папки или создание и удаление папок диска. Копирование или удаление файлов. ' Переименование или перемещение файлов. Получение информации о файлах, такой как длина файла, дата и время, когда этот файл был модифицирован последний раз. Атрибуты файла Каждый файл, сохраненный на любом диске Windows (или более ранней версии DOS), имеет атрибуты (attributes). Независимо от конкретного типа драйвера 304 Глава 13 диска (жесткий диск, гибкий диск, RAM-drive, ZLP-drive, Syquest-drive и так далее) Windows и DOS используют атрибуты файла для определения того, какие действия по управлению файлами допускаются для этого файла. Например, Windows (или DOS) запрещает вам (и любым программам приложений) удалять, модифицировать или переименовывать файлы с атрибутом read-only. Windows создает информацию об атрибутах файла, когда вы или программа приложения, работающая на вашем компьютере, создает новЬш файл. В каком-то смысле, атрибуты файла подобны свойствам объекта: атрибуты файла дают файлу некоторую характеристику в зависимости от конкретных атрибутов, которые он имеет. Атрибуты файла являются частью информации файла, которую Windows сохраняет на драйвере диска. Windows сохраняет информацию об атрибутах файла вместе с информацией об имени файла, размере, дате и времени. Windows автоматически обновляет и сопровождает информацию об атрибутах файла. Чаще всего вы не знаете об атрибутах файла, и обычно нет причины, по которой вам было бы необходимо знать, что такое атрибуты. В некоторых же случаях бывает полезно понимать и использовать атрибуты файла. В частности, необходимо понимать атрибуты файла и их значение для того, чтобы использовать все преимущества VBA-функции Dir. Windows (и DOS) использует всего семь атрибутов файла для определения различных характеристик файла. Каждый отдельный атрибут может объединяться с другими атрибутами, кроме атрибута Volume Label, например, файл может иметь одновременно атрибуты Hidden, System, Directory, Archive и Read-Only. В следующем списке содержится имя каждого атрибута файла и описывается его значение. Archive. Атрибут Archive указывает, изменялся ли файл со времени, когда его резервировали последний раз с помощью backup-программы, такой как BACKUP Windows, или backup-программы других поставщиков, таких как Fastback!, Backlt, Norton Backup и других. Если файл имеет атрибут Archive, это означает, что для этого файла необходимо резервирование. Если файл не имеет атрибута Archive, то этот файл не изменялся со времени, когда он был резервирован последний раз. Directory. Если файл имеет атрибут Directory, это означает, что файл в действительности является каталогом или подкаталогом (папкой — в терминологии Windows 95). Каталог диска — это файл, который содержит информацию о других файлах; когда вы создаете каталог, Windows создает специальный файл каталога и дает ему атрибут Directory. Атрибут Directory сообщает Windows о том, что этот файл содержит информацию о других файлах и препятствует переименованию, копированию или удалению каталога. Hidden. Если файл имеет атрибут Hidden, Windows «скрывает» файл, не показывая его в большинстве случаев при отображении каталога, хотя Windows имеет опцию просмотра, которая отображает имена скрытых файлов. Normal. Атрибут файла Normal является на самом деле отсутствием каких-либо специальных атрибутов. Так называемый Normal-атрибут (иногда называемый general) файла просто означает, что файл не имеет никаких других атрибутов, кроме, возможно, атрибута Archive для указания, необходимо ли резервирование для этого файла. Read-Only. Атрибут Read-Only означает, что вы можете только читать из файла, но не можете изменять его. Windows 95/98 препятствует изменению, удалению или переименованию файла, который имеет атрибут Read-Only. System. Атрибут System указывает Windows, что файл является частью операционной системы компьютера. Как в случае с файлами Read-Only, Windows препятствует изменению файла, имеющего атрибут System. Кроме того, если вы создаете диск автозапуска DOS-командой SYS (или с Windows Control Управление файлами с помощью VBA 305 Panel), любые файлы, имеющие атрибут System, переносятся на новый диск автозагрузки. Volume Label. Атрибут Volume Label информирует Windows о том, что файл является меткой тома диска. (Метка тома (volume label) — это имя, которое вы даете жесткому диску (или дискете) при форматировании, использовании DOS-команды LABEL или изменении свойства Label в листе свойств диска.) Диск может иметь только одну метку тома одновременно. Windows представляет каждый отдельный атрибут файла уникальным числом и сохраняет это число с информацией об имени и размере файла. Если файл имеет несколько атрибутов, Windows складывает кодовые числа для каждого атрибута и сохраняет их сумму. В следующем разделе описывается, как можно найти и интерпретировать кодовое число для атрибутов файла. В табл. 13.2 перечисляются коды атрибутов файлов, которые использует Windows, и внутренние константы VBA для этих кодов атрибутов. Как и в случае с другими Числовыми кодами, для которых VBA определяет константу, следует использовать VBA-константу для кодового числа вместо самого кодового числа. Таблица 13.2. Константы атрибутов файла Visual Basic for Applications Константа VBA Значение Что означает vbNormal 0 Normal vbReadOnly 1 Read-Only vbHidden 2 Hidden | vbSystem 4 System vb Volume 8 Volume Label vbDirectory 16 Каталог или подкаталог диска. vb Archive 32 Archive. Если установлен, указывает, что этот файл был изменен со времени последнего резервирования. vb Alias 64 Указанное имя файла является алиасным. Доступна только в Macintosh. Получение атрибутов файла Для того чтобы определить, какие атрибуты имеет определенный файл, используйте VBA-функцию GetAttr. Функция GetAttr возвращает число, содержащее сумму всех числовых кодов для атрибутов файла, и имеет следующий синтаксис: СИНТАКСИС GetAttr(pathname) Аргумент pathname — любое строковое выражение VBA, представляющее допустимое имя файла; pathname может включать буквенную метку диска и полный путь папки; если вы не включаете буквенную метку, GetAttr ищет указанный файл на текущем драйвере диска; если вы не включаете путь папки, функция GetAttr выполняет поиск в текущей папке. В листинге 13.1 содержится пример, в котором используется функция GetAttr и показывается, как интерпретировать результат функции. 306 Глава 13 Листинг 13.1. Использование функции GetAttr и интерпретация результата 1 Sub ShowFA(fName As String) 2 ' отображает окно с сообщением об атрибутах 3 ' файла, имя которого передается как аргумент 4 5 Dim fAttr As Integer 6 Dim mStr As String • 7 8 fAttr = GetAttr(fName) 9 mStr = UCase(fName) 10 mStr = mStr & " has these attributes: " & vbCr 11 If (fAttr And vbReadOnly) Then 12 mStr = mStr & "Read-Only" & vbCr 13 If (fAttr And vbHidden) Then _ 14 mStr = mStr & "Hidden" & vbCr 15 If (fAttr And vbSystem) Then __ 16 mStr = mStr & "System" & vbCr 17 If (fAttr And vbVolume) Then _ 18 mStr = mStr & "Volume" & vbCr 19 If (fAttr And vbDirectory) Then 20 mStr = mStr & "Directory" & vbCr * 21 If (fAttr And vbArchive) Then _ 22 mStr = mStr & "Archive" & vbCr 23 MsgBox mStr 24 End Sub ' 25 26 Sub ListFileAttr() 27 28 Dim strPath As String 29 30 ShowFA fName:="c:\io.sys" 31 ShowFA fName:="c:\msdos.sys" 32 33 strPath = "C:\Program Files\Microsoft Office\Office\XlStart" 34 ShowFA fName:=strPath 35 36 End Sub В листинге 13.1 содержатся две процедуры. Процедура ShowFA занимает строки 1-24, а процедура ListFileAttr — строки 26-36. ListFileAttr просто вызывает ShowFA несколько раз, передавая каждый раз другое имя файла. Процедура ShowFA имеет один обязательный аргумент с именем fName и типом String. В строке 5 объявляется переменная fAttr типа Integer для сохранения значения, возвращаемого функцией GetAttr. В строке 6 объявляется переменная mStr типа String для сохранения сообщения, формируемого этой процедурой. При выполнении оператора в строке 8 VBA вызывает GetAttr, передавая строку fName в качестве аргумента и сохраняя результат функции в переменной fAttr. Если строка в fName не содержит допустимого имени файла, VBA отображает сообщение о runtime-ошибке (рис. 13.1). Рис. 13.1 Сообщения VBA при ошибке в аргументе функции GetAttr Microtoft Visual Satie . RurPtime error 53 File not found OK [ Help Управление файлами с помощью VBA 307 Строки 9 и 10 формируют первую часть сообщения, которое отображает процедура ShowFA. В строке 9 используется VBA-функция UCase для преобразования имени файла в fName в верхний регистр по «косметическим» причинам. В строках 11-22 находится ряд операторов If...Then оценивающих число, сохраненное в fAttr, которое содержит сумму всех кодовых чисел для атрибутов этого файла. Заметьте, что эти операторы If...Then не являются вложенными. Значение в fAttr тестируется шесть раз — один раз для каждого возможного значения атрибута. Помните, что значение атрибута, которое Windows 95/98 сохраняет с файлом, является суммой всех кодовых чисел для каждого из атрибутов, которые имеет файл. Если атрибут, наличие которого проверяет определенный оператор If...Then, присутствует, то строка, содержащая соответствующее имя атрибута, добавляется в строку сообщения, сохраняемую в mStr. Оператор MsgBox в строке 23 отображает строку сообщения, которую формируют предыдущие операторы. В строке 26 содержится объявление процедуры ListFileAttr, которая просто вызывает процедуру ShowFA несколько раз, передавая ей различные имена файлов. Выполнение строки 30 приводит к тому, что ShowFA отображает атрибуты файла для файла IO.Sys. Этот файл является частью операционной системы Windows и всегда находится в корневом каталоге диска автозагрузки. Поскольку IO.SYS является частью операционной системы Windows, он имеет атрибут файла System; он имеет также атрибут Read-Only для предотвращения нечаянного удаления этого важного файла; кроме того, этот файл имеет атрибут Hidden, чтобы он обычно не появлялся в папке рабочего стола Windows или в списках каталога Проводника. При выполнении процедуры ListFileAttr последовательно отображаются диалоговые окна, показанные на рис. 13.2. Рис. 13.2 Такие окна последовательно отображаются кодом листинга 13 1 В процедуре ShowFA нет тестирования для атрибута файла Normal, потому что атрибут файла Normal — это просто отсутствие любых других атрибутов. Объявляйте все переменные, которые используете для сохранения кодов атрибутов файла, как переменные типа Integer, так кодовое число атрибута файла всегда находится в допустимом диапазоне типа Integer. Не следует также забывать, что коды атрибутов всегда обрабатываются как одно число, содержащее сумму всех отдельных кодовых чисел для атрибутов данного файла. Изменение атрибутов файла Атрибуты файлов можно устанавливать из кода VBA. Например, можно изменить атрибуты файла шаблонного документа, чтобы включить атрибут Read-Only для предотвращения нечаянного удаления этого шаблонного документа. 308 Глава 13 Для изменения атрибутов файла предназначен оператор SetAttr, выполняет ту же самую задачу, что и команда Файл | Свойства (доступная в любых окнах каталога Windows или с помощью щелчка правой кнопкой мыши на значке файла), а также DOS-команда ATTRIB. 1 Оператор SetAttr имеет следующий синтаксис: СИНТАКСИС SetAttr pathname, attributes Здесь pathname — любое строковое выражение, содержащее допустимую спецификацию файла Windows (имя файла и (необязательно) полный путь к каталогу, и буквенную метку диска); attributes — это численное выражение. Численное выражение для attributes должно быть числом между 1 и 255 и состоять из одного из кодовых чисел атрибута файла или суммы кодовых чисел атрибутов. В листинге 13.2 показан пример того, как можно использовать оператор SetAttr. Листинг 13.2. Использование оператора SetAttr для изменения атрибутов файла 1 Sub SetReadOnly(fName As String) 2 1 устанавливает атрибут только на чтение , 3 4 Dim fAttr As Integer 5 6 fAttr = GetAttr(fName) 7 8 ' не устанавливать атрибут, если он уже установлен 9 If Not CBool(fAttr And vbReadOnly) Then 10 SetAttr fName, fAttr + vbReadOnly 11 End If 12 13 MsgBox prompt:="Атрибут Read-only для " & _ 14 fName & " установлен.", _ 15 Title:-"Delete Protection" 16 End Sub 17 18 19 Sub Test_SetReadOnly() 20 Dim iName As String 21 iName = Application.GetOpenFilename 22 SetReadOnly iName 23 ShowFA iName 24 End Sub Процедура SetReadOnly защищает файлы от случайного удаления тем, что присваивает файлу атрибут Read-Only, не влияя на другие атрибуты. SetReadOnly имеет один обязательный аргумент типа String с именем fName, который используется для передачи имени файла в процедуру. В строке 4 объявляется переменная fAttr; процедура использует эту переменную для сохранения числа для атрибутов файла. В строке 6 используется функция GetAttr для получения атрибутов файла, определенного с помощью fName. В строках 9-11 содержится оператор If, выполняющий оператор SetAttr, если только этой файл не имеет уже атрибут Read-Only. В строке 10 содержится фактический вызов оператора SetAttr. Заметьте, что старые атрибуты файла арифметически складываются с константой vbReadOnly для задания новых атрибутов. Таким образом, оригинальные атрибуты файла сохраняются. Управление файлами с помощью VBA 309 Наконец, в строках 13-15 содержится оператор MsgBox, отображающий сообщение для пользователя о том, что атрибут Read-Only для файла установлен. Процедура Test_SetReadOnly тестирует процедуру SetReadOnly. В строке 21 используется Excel-метод GetOpenFileName (который будет описан в следующем разделе) для получения имени файла от пользователя. В строке 23 вызывается процедура SetReadOnly для задания атрибутов файла с целью включения атрибута Read-Only. Наконец, в стро"Ке 24 вызывается процедура ShowFA (приведенная в листинге 13.1) для отображения окна сообщения с новыми атрибутами файла. Для добавления нового атрибута файла к имеющемуся набору атрибутов используйте оператор Ог. Использование оператора Ог для объединения атрибутов файла в побитовой операции исключает любые возможные проблемы, которые могут возникнуть при использовании арифметического сложения для объединения новых атрибутов с уже имеющимися. Результатом выражения 0 Or 1 является 1; результатом выражения 1 Or 1 является также 1. Поэтому можно объединять новый атрибут файла с имеющимся числом атрибута файла, используя выражение, подобное OldAttr Or vbArchive. Если атрибут Archive не задан в OldAttr, он будет задан как результат операции Ог. Если атрибут Archive уже задан, он останется неизменным. Как находить файлы В этом разделе сначала будет показано, как использовать VBA-функцию Dir для поиска в папке одного или нескольких файлов, совпадающих с определенным именем файла. Затем вы узнаете, как использовать VBA для включения Word- или Excel-собственных диалоговых окон Open (Открытие документа) и Save As (Сохранение документа) в ваши процедуры. Можно использовать Word и Excel-встроенные диалоговые окна Open и Save As для предоставления возможности пользователю легко и правильно передавать имена файлов процедурам. Использование функции Dir для нахождения файлов Иногда может быть необходимо проверить, содержит ли каталог диска один или несколько файлов, совпадающих с определенной спецификацией имени файла, такой как \Му Documents\*.xls или \Му Documents\*.doc. Для этого можно использовать VBA-функцию Dir. Функция Dir выполняет в VBA те же задачи, что и список файлов в окне папки Windows или DOS-команда DIR — дает возможность посмотреть, какие файлы сохранены в определенной папке и какие имеются другие папки. Функция Dir имеет следующий общий синтаксис: СИНТАКСИС Dir(pathname[, attributes]) Здесь pathname представляет любое выражение String, имеющее результатом допустимое имя файла. Имя файла может содержать буквенную метку драйвера и полный путь папки. Имя папки может также включать символы универсального сопоставления файлов. Необязательный аргумент attributes является числом, представляющим атрибуты тех файлов, которые необходимо найти. При использовании attributes Dir выполняет поиск файлов, имеющих эти атрибуты. Если опустить аргумент attributes, функция Dir выполняет поиск обычных файлов, то есть любых файлов, кроме имеющих атрибуты Hidden, Volume Label, Directory или System. При вызове функции Dir с аргументом pathname она возвращает строку, содержащую имя первого найденного ею файла, совпадающее с именем файла 310 Глава 13 в аргументе pathname. Если имя файла содержит символы универсального сопоставления (* или ?), то для того, чтобы найти все файлы в каталоге, совпадающие с этим именем файла, необходимо использовать функцию Dir в два этапа. Во-первых, вызывать Dir с аргументом pathname для получения первого совпадающего файла, затем вызывать Dir неоднократно без аргументов до тех пор, пока Dir не возвратит пустую строку. Как только Dir возвращает пустую строку, значит, больше не остается файлов, совпадающйх с этим именем файла. При вызове Dir без указания имени файла, VBA выдает сообщение о runtime-ошибке. В листинге 13.3 показан пример использования Dir для нахождения только одного файла. Листинг 13.3. Использование Dir для нахождения одного файла 1 Function IsFile(fName As String) As Boolean 2 ' возвращает Истина (True), если файл на диске найден, 3 ' иначе - Ложь (False) 4 If (Dir(fName) О "") Then 5 IsFile = True 6 Else 7 IsFile = False 8 End If 9 End Function 12 Sub Test_IsFile() 13 Diq iName As String 14 Dim str_msg As String 15 16 iName = InputBox(prompt:“"Введите имя файла:", _ 17 Title:“"Тестирование функции IsFile") 18 19 str_msg = "Файл " S iName S результат поиска: 20 If IsFile(iName) Then 21 str_msg = str_msg S " найден" 22 Else 23 str_msg = str_msg & " не найден" ' 24 End If 25 26 MsgBox str_msg 27 End Sub В строках 1-9 содержится функция IsFile, имеющая один обязательный аргумент fName типа String. IsFile возвращает результат с типом Boolean: True, если имя файла в fName находится на драйвере диска, иначе — False. Работа функции IsFile очень проста. В строке 4 содержится оператор If... Then...Else, который (как часть его логического выражения) вызывает функцию Dir, передавая содержимое fName в качестве имени файла, поиск которого необходимо выполнить. В этом обращении к функции Dir никакой аргумент для атрибутов не определяется, поэтому она будет находить любой файл, кроме файлов, имеющих атрибуты Hidden, System, Directory или Volume Label. Поскольку назначением функции IsFile является просто определение тогр, существует ли определенный файл, возвращаемый результат функции Dir не используется, кроме сравнения его с пустой строкой. Если результат функции Dir не является пустой строкой, то Dir нашла указанный файл и VBA выполняет строку 5, которая присваивает результату функции значение True. Если результат функции Управление файлами с помощью VBA 311 Dir является пустой строкой, то никакого совпадающего файла не было найдено и VBA выполняет строку 7, которая присваивает False результату функции. В строках 12-27 объявляется процедура для тестирования функции IsFile. Учитывая номер текущей главы, не будем подробно останавливаться на разборе этого кода. Если в таком простом коде что-то неясно, следует прочитать внимательнее предыдущие главы. Функцию Dir можно также использовать для нахождения в папке всех файлов, совпадающих с определенным именем файла. Эта возможность функции Dir наиболее полезна, когда имя файла содержит символы универсального сопоставления. Можно использовать функцию Dir таким образом, если необходимо, скажем, найти все файлы шаблонов в определенной папке. В листинге 13.4 показан пример того, как функция Dir используется для нахождения нескольких файлов. Листинг 13.4. Использование функции Dir для нахождения нескольких файлов 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 Sub ShowFA(fName As String, Number As Integer) ' отображает окно с сообщением об атрибутах ' файла, имя которого передается как аргумент Dim fAttr As Integer Dim mStr As String fAttr = GetAttr(fName) mStr = UCase(fName) mStr = mStr & " has these attributes: " & vbCr If (fAttr And vbReadOnly) Then _ mStr = mStr & "Read-Only" & vbCr If (fAttr And vbHidden) Then _ mStr = mStr & "Hidden" & vbCr If (fAttr And vbSystem) Then _ mStr = mStr & "System" & vbCr If (fAttr And vbVolume) Then _ mStr = mStr & "Volume" & vbCr I If (fAttr And vbDirectory) Then _ mStr = mStr & "Directory" & vbCr If (fAttr And' vbArchive) Then _ mStr = mStr & "Archive" & vbCr ' запись в лист Excel: Cells(Number, 1).Value = mStr End Sub Sub ShowAllFiles() ' отображает имена и атрибуты всех файлов ' в указанном каталоге Введите имя каталога: Dim sAttr As Integer Dim fName As String Dim pName As String Dim fCount As Integer pName = InputBox("Введите имя каталога:") If Trim(pName) = "" Then Exit Sub If Right(pName, 1) <> "\" Then pName = pName & "\" sAttr = vbDirectory + vbArchive + vbReadOnly + _ vbHidden + vbSystem ' получить первое имя файла и атрибуты fName = Dir(pName & sAttr) 312 Глава 13 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 ' 61 62 63 If (fName о "") And _ ((fName <> ".") And (fName <> Then fCount = 1 ShowFA pName & fName, fCount End If Do While (fName <> "") fName = Dir() • If (fName <> "") And _ ((fName <> ".") And (fName <> Then fCount = fCount + 1 ShowFA pName & fName, fCount End If Loop MsgBox "Найдено файлов " & fCount End Sub В этом листинге сначала (строки 1-26) описана процедура ShowFA, которая уже встречалась в листинге 13.1. Здесь были внесены небольшие изменения: теперь процедура имеет еще один параметр Number типа Integer и результирующая строка выдается не в окне оператора MsgBox (при длинном списке файлов это будет утомлять пользователя даже в процессе тестирования кода), а записывается в Excel-лист, причем Number указывает номер строки, в которую будет записываться результирующая строка. Процедура ShowAllFiles запрашивает пользователя ввести имя папки (каталога), а затем использует функцию Dir для нахождения всех файлов в этом каталоге. В строках 32-35 объявляются несколько переменных. Переменная sAttr используется для сохранения числа атрибутов файла, fName — для временного хранения имен файлов, возвращаемых функцией Dir, pName — для сохранения пути каталога, который ищет эта процедура, fCount — для сохранения счетчика всех найденных файлов и в качестве параметра функции ShowFA для записи данных о файле в очередную строку листа. В строке 39 проверяется, имеет ли путь (введенный пользователем в строке 37) каталога в конце строки символ разделителя пути (\), и добавляет его в конец пути, сохраненного в pName, если символ пропущен. В строках 41-42 задается переменная sAttr, которая должна содержать атрибуты файлов, поиск которых будет выполнять функция Dir. Заметьте, что sAttr задается так, чтобы содержать все возможные атрибуты файла, кроме Volume Label. При таких атрибутах Dir будет находить любой файл в заданном каталоге, включая любые подкаталоги в нем. В строке 45 выполняется первый вызов функции Dir с использованием пути каталога в pName с добавленной в него строкой (для нахождения всех файлов) и переменной sAttr (с атрибутами файлов). Результат функции Dir присваивается переменной fName. В строках 46-50 содержится оператор If...Then, который оценивает строку, возвращаемую функцией Dir и сохраненную в переменной fName. Оператор проверяет: 1) является ли переменная fName пустой строкой, 2) не содержит ли fName строку, состоящую из одной точки (.), 3) не содержит ли fName строку, состоящую из двух точек (..). Эти особые строки используются системой файлов Windows 95/98 для обозначения текущего (.) и родительского каталога (..). Хотя такие особые имена файлов являются каталогами и функция Dir будет сообщать об их существовании с таким атрибутом и спецификацией универсального сопоставления, какие используются в данном примере, они на самом деле не существуют на диске, и любая попытка получить их атрибуты с помощью GetAttr приведет к возникновению runtime-ошибки. Управление файлами с помощью VBA 313 Если fName не является пустой строкой и не содержит специальных элементов (. или VBA выполняет оператор в строке 48, который устанавливает счетчик найденных файлов в 1 (переменная fCount), и выполняет оператор в строке 49, который вызывает процедуру ShowFA для записи в очередную ячейку текущего листа открытой рабочей книги имени файла и его фактических атрибутов. Теперь, когда первый совпадающий файл найден, необходимо использовать формат второй ступени функции Dir, чтобы найти остальные файлы в каталоге. В строках 52-60 содержится цикл Do, который выполняется, пока fName не является пустой строкой. Если хотя бы один совпадающий файл был найден в вызове функции Dir (в строке 45), то этот цикл будет выполняться, по крайней мере, один раз. Обратите особое внимание на строку 53. Этот оператор снова вызывает функцию Dir без аргументов. При таком вызове функции Dir VBA «полагает», что пользователь хочет найти больше файлов, совпадающих со спецификацией для аргументов пути и атрибутов, которые использовались в последнем вызове Dir. Функция Dir возвращает следующий файл в каталоге, совпадающий с предыдущими спецификациями имени и атрибутов. Если файлов больше нет, Dir возвращает пустую строку. Когда все совпадающие файлы в каталоге будут найдены, Dir возвращает пустую строку и цикл прекращает выполняться. Оператор в строке 62 отображает окно сообщения, указывающее, сколько совпадающих файлов было найдено. На рис. 13.3 представлен результат работы кода этого листинга при введенной в окне InputBox строки "C:\WIN98\" (конечно, на каком-то случайном компьютере). Рис. 13.3 Один из возможных результатов работы кода из листинга 13 4 Файл Главка Вид Вставка Формат Сдэвис Данные Окно Справка - S х Microsoft Excel А В С D Е F 1 С \WIN98\SYSTEM has these attributes □Directory^ 2 С \WIN98\WINSOCK DLL has these attributes □ArchiveO 3 C \WIN98\COMMAND has these attributes □Directory’^ 4 C \WIN98\WIN INI has these attributes j 5 C \WIN98\INF has these attributes DHiJ 6 C \WIN98\HWINFO EXE has these attnt 7 C \WIN98\NETDET INI has these attnbu Найден0 399 8 C \WIN98\PIDGEN DLL has these attrib i------1 9 C \WIN98\SUBACK BIN has these attnb I .У....ll 10 C \WIN98\W98SETUP BIN has these aH.uuiv..и,..ии 11 C \WIN98\HELP has these attributes □ Directory^ 12 C\WIN98\LICENSE TXT has these attributes DArchiveD •IQ Г 11Л/1К1ЛО1СТ innnDT ТУТ к-Л И.ЛЛЛ AHr К ПЛглк «ЧП К < ► н \ Sheetl / Sheet2 \Видеокарты/ ]< NUM Использование встроенных диалоговых окон Excel для получения имен файлов Excel-объект Application имеет два метода — GetOpenFilename и GetSave-AsFilename, которые можно использовать в Excel-коде VBA для упрощения задачи получения имени файла от пользователя. В следующих двух разделах описывается, как использовать эти два метода в процедурах. Использование метода GetOpenFilename Во многих примерах в этой книге использовалась функция InputBox для получения имен файлов от пользователя процедуры. Хотя получение имени файла 314 Глава 13 с помощью InputBox является нормальным, при этом не используются преимущества ориентированного на файл диалогового окна, такого как Excel-окно Open, которое фактически позволяет увидеть, какие файлы имеются на диске, и просматривать списки файлов различных драйверов диска и каталогов. Можно использовать Excel-метод GetOpenFilename в Excel-коде VBA для отображения диалогового окна, которое выглядит и работает так же, как диалоговое окно, отображаемое Excel при выборе команды File | Open (файл | Открыть). Метод GetOpenFilename возвращает строку, которая содержит имя файла, выбранного пользователем, включая буквенную метку диска и полный путь папки. Если пользователь отменяет диалоговое окно, GetOpenFilename возвращает Boolean-значение False в качестве ее результата. Excel-метод GetOpenFilename имеет следующий синтаксис: СИНТАКСИС <•, ...... object.GetOpenFilename(fileFilter, filterindex, title, _ buttonText, multiSelect) Здесь object — это ссылка на Excel-объект Application. Хотя ссылка object на Excel-объект Application является обязательной, все аргументы GetOpenFilename являются необязательными. Аргумент fileFilter представляет любое допустимое выражение String, специально форматированное для задания фильтров файла, перечисленных в окне раскрывающегося списка Files of type в диалоговом окне Open. Если аргумент fileFilter опущен, фильтр файла для раскрывающегося списка Files of type — это All Files (*.*). Аргумент filterindex представляет любое численное выражение и указывает, какой фильтр файла должен использовать VBA как фильтр по умолчанию для раскрывающегося списка Files of type (Тип файлов). Если этот аргумент опустить или указать число, большее, чем фактическое количество фильтров файла, то первый фильтр файла становится фильтром по умолчанию. Аргумент title представляет любое выражение типа String и является заголовком, отображаемым VBA в диалоговом окне Open. Если опустить title, VBA отображает диалоговое окно с обычным Open-заголовком. Аргумент buttonText — необязательный параметр типа Variant. Используется только в Macintosh. Аргумент multiSelect представляет любое выражение или значение Boolean. Если multiSelect равно True, то диалоговое окно Open дает возможность пользователю выбирать множество имен файлов. Когда multiSelect равно True, GetOpenFilename возвращает массив, содержащий имена всех выбранных файлов. Для определения строки фильтра файла форматируйте строку следующим образом: "FilterNamel,filespecl,FilterName2,filespec2,FilterNameN, filespecN" Аргумент filterName представляет текст, который VBA отображает в окне раскрывающегося списка Files of type. Аргумент filespec представляет спецификацию файла, которую Windows использует для ограничения файлов, приводимых в окне Open. Можно вносить в список сколь угодно много фильтров файла. В следующей строке показан пример строки фильтра файла: "Templates (*.xlt), *.xlt, Workbooks (*.xls), *.xls" Эта строка фильтра приводит к появлению двух опций (Templates и Workbooks) в окне раскрывающегося списка Files of type. В листинге 13.5 показан пример, использующий метод GetOpenFilename. Управление файлами с помощью VBA 315 Листинг 13.5. Использование метода GetOpenFilename для получения имени файла от пользователя процедуры 1 Sub TestGetOpenFilename() 2 ' открывает указанную рабочую книгу и выбирает 3 ' лист, указываемый пользователем в окне функции InputBox 4 5 Const iTitle = "Ввод имени рабочей книги" 6 Dim ShtName As String 7 8 Const FilterList = _ 9 "Templates (*.xlt),*.xlt,Workbooks (*.xls),*.xls" 10 11 Dim fName As String 12 13 14 fName = Application.GetOpenFilename(Title:=iTitle, _ 15 filefilter:=FilterList, _ 16 filterindex:=2) 17 18 19 If fName = "False" Then 'для русской версии "Ложь" 20 MsgBox prompt:“"Операция отменена!", _ 21 Title:=iTitle 22 Exit Sub 23 End If 24 25 Workbooks.Open Filename:=fName 26 27 ShtName = InputBox("Введите наименование листа") 28 ActiveWorkbook.Sheets(ShtName).Select 29 MsgBox prompt:“"Книга " & fName S _ 30 " открыта, лист 11 & ShtName & _ 31 " выбран ", _ 32 Title:“iTitle S " (Завершение)" 33 End Sub Процедура TestGetOpenFilename открывает рабочую книгу, выбранную пользователем в диалоговом окне с заголовком, определяемым константой iTitle, а затем выбирает рабочий лист с именем, указываемым в окне функции InputBox, в открытой рабочей книге. В строках 8-9 объявляется константа FilterList, в дальнейшем передаваемая в качестве фильтра файла при обращении к методу GetOpenfilename. В строках 14-16 содержится один оператор, вызывающий метод GetOpen-Filename и присваивающий его результат переменной fName. При выполнении этого оператора VBA отображает диалоговое окно, показанное на рис. 13.4. На этом рисунке показано открытое окно списка Files of type, чтобы можно было видеть действие аргумента fileFilter. Заметьте, что диалоговое окно на рисунке идентично Excel-окну Open, за исключением заголовка окна и содержимого окна списка Files of type. Поскольку аргумент filterindex (строка 16) установлен на 2, фильтром по умолчанию является фильтр Workbooks (*.xls), а не Templates (*.xlt). Имя в диалоговом окне можно выбрать точно так же, как в Excel-окне Open. Когда вы выбираете кнопку Open, метод GetOpenFilename возвращает строку, содержащую имя файла, буквенную метку диска и полный путь каталога (аргумент multiSelect не был использован, поэтому можно выбрать только одно имя файла). Если вы выберите Cancel, GetOpenfilename возвращает Boolean-значение False. Поскольку в данном случае fName является переменной String, VBA автоматически преобразует False в строку "False". 316 Глава 13 Рис. 13.4 Процедура TestGetOpenFilename использует метод GetOpenFilename для отображения этого диалогового окна Обратите внимание на фильтры в окне списка Тип файлов Если операторы в строках 19-23 не обнаружат факт отказа от ввода имени файла, то в строке 25 вызывается метод Workbooks.Open, открывающий выбранную пользователем рабочую книгу. В строке 27 с помощью функции InputBox пользователь может ввести наименование листа уже открытой рабочей книги. В это время ярлычки с именами листов будут видны пользователю (рис. 13.5). Рис. 13.5 В момент ввода наименования необходимого листа ярлычки листов видны пользователю Завершается процедура, как обычно, оператором MsgBox с сообщением об успешном выполнении задачи процедуры. Не следует забывать, что GetOpenFilename возвращает строку, когда пользователь выбирает имя файла, и Boolean-значение False — при отмене диалогового окна. Если вы присваиваете результат метода GetOpenFilename переменной типа Variant, необходимо выполнять тестирование для значения False, а не строки "False". Метод GetOpenFilename возвращает массив строк, если используется значение True для необязательного аргумента multiSelect, даже если пользователь выбирает только один файл. Управление файлами с помощью VBA 317 Использование метода GetSaveAsFilename Вы можете также использовать Excel-метод GetSaveAsFilename для отображения диалогового окна, которое выглядит и работает так же, как окно, отображаемое Excel, йогда пользователь выбирает команду File | Save As.... Метод GetSaveAsFilename также возвращает строку, содержащую имя файла, которое выбирает пользователь, включая буквенную метку диска и полный путь каталога. Если пользователь отменяет диалоговое окно, GetSaveAsFilename возвращает Boolean-значение False. Метод GetSaveAsFilename имеет следующий синтаксис: СИНТАКСИС object.GetSaveAsFilename(initialFilename, fileFilter, _ filterindex, title,buttonText) Метод GetSaveAsFilename имеет почти такие же аргументы и синтаксис, как метод GetOpenFilename. В этой синтаксической конструкции object — это ссылка на объект Application, fileFilter — выражение String, форматированное для задания фильтров файла, перечисленных в раскрывающемся списке Save as type; filterindex — численное выражение, указывающее, какой фильтр файла должен использовать VBA в качестве фильтра по умолчанию, a title — выражение String для строки заголовка диалогового окна. Если пропускается аргумент title, VBA отображает диалоговое окно с обычным заголовком SaveAs. Аргумент buttonText — необязательный параметр типа Variant. Используется только в Macintosh. Метод GetSaveAsFilename имеет еще один аргумент — initialFilename, который представляет любое допустимое имя файла. Если указать этот необязательный аргумент, имя файла, которое задается для initialFilename, появляется в текстовом окне File Name, когда диалоговое окно SaveAs отображается первый раз. Строки фильтра файла для метода GetSaveAsFilename определяйте таким же образом, каким форматируете их для GetOpenFilename. В листинге 13.6 показан пример, использующий метод GetSaveAsFilename. Листинг 13.6. Использование GetSaveAsFilename для получения имени файла от пользователя 1 Sub ConvTemplate() 2 ' сохраняет текущую книгу как файл шаблона 3 4 Const FilterList = "Templates (*.xlt),*.xlt" 5 Const iTitle = "Преобразование рабочей книги в шаблон" 6 Static sN As String 7 Static TCount As Variant 8 ' Dim iName As String 9 10 If IsEmpty(TCount) Then 11 TCount = 1 12 Else 13 TCount = TCount + 1 14 End If 15 16 sN = "Temp" & CStr(TCount) & ".xlt" 17 iName = Application.GetSaveAsFilename(initialfilename:=sN, 18 filefilter:=FilterList, _ 19 Title:=iTitle) 318 Глава 13 20 21 If iName = "False" Then 22 MsgBox prompt:^"Преобразование в шаблон отменено", 23 Title:=iTitle 24 Else 25 Activeworkbook.SaveAs Filename:=iName, _ 26 FileFormat:=xlTemplate 27 End If 28 End Sub • Процедура ConvTemplate сохраняет текущую рабочую книгу как Excel-шаблонный файл и использует метод GetSaveAsFilename для получения имени для нового шаблонного файла. В строке 4 объявляется константа для фильтра файла; в строке 5 — константа для заголовков диалоговых окон, отображаемых этой процедурой. В строках 6 и 7 объявляются Static-переменные: sN используется для имени нового шаблонного файла, a TCount — для нумерации шаблонных имен по умолчанию. Переменная iName используется для сохранения выбираемого пользователем имени файла. В строках 10-16 устанавливается счетчик шаблонных файлов и формируется предлагаемое имя шаблонного файла. В строках 17-19 содержится один оператор, который вызывает метод GetSaveAsFilename и присваивает его результат переменной iName. При вызове этого метода VBA отображает диалоговое окно, показанное на рис. 13.6. Заметьте, что это окно точно такое же, как Excel-окно SaveAs (Сохранение документа), за исключением заголовка диалогового окна (поскольку он формируется процедурой и является аргументом метода GetSaveAsFilename) и содержимого списка Тип файла (Save as type). В строке 21 с помощью оператора If...Then...Else проверяется, не отменил ли пользователь диалоговое окно метода GetSaveAsFilename. Если пользователь выбрал кнопку Cancel (или нажал Esc), то выполняется оператор в строках 22-23, отображая окно сообщения, информирующее пользователя о том, что преобразование в шаблон было отменено. Иначе — оператор в строках 25-26 вызывает метод SaveAs, сохраняя активную рабочую книгу как Excel-шаблонный файл. Необходимо помнить, что и GetOpenFilename, и GetSaveAsFilename могут изменять текущий диск и папку. Можно использовать функцию CurDir для получения текущего диска и папки и сохранять результат в переменной, чтобы можно было переключаться снова на текущий диск и папку с помощью ChDrive и ChDir (описываются далее в этой главе). Рис. 13.6 Процедура / ConvTemplate использует метод GetSaveAsFilename для отображения этого диалогового окна Управление файлами с помощью VBA 319 Использование встроенных диалоговых окон Word для получения имен файлов Word не имеет тех же самых методов GetOpenFilename и GetSaveAsFilename, которые предоставляет Excel. Однако Word позволяет использовать VBA для отображения любых встроенных диалоговых окон — это те же самые диалоговые окна, которые отображаются, когда Word используется интерактивно. Можно, следовательно, применять собственные окна Word Открытие документа и Сохранение документа (Save As) в коде VBA для получения имен файлов от пользователя. Использование встроенных диалоговых окон Word для получения имени файла от пользователя немного сложнее, чем использование Excel-методов GetOpenFilename и GetSaveAsFilename. Встроенные диалоговые окна Word доступны посредством свойства Dialogs Word-объекта Application. Свойство Dialogs возвращает коллекцию встроенных диалоговых окон Word. Для указания необходимого диалогового окна используются различные предопределенные константы Word (каждая из которых обозначается как wdDialog с последующим именем диалогового окна). Предопределенная Word-константа wdDialogFileopen определяет Word-диалоговое окно Open, а константа wdDialogFileSaveAs — диалоговое окно Сохранение документа. Для ссылки на одно из встроенных окон Word необходимо использовать следующий синтаксис: СИНТАКСИС Object.Dialogs(wdDialogConstant) Здесь object — объектная ссылка на Word-объект Application, которая является обязательной; wdDialogConstant — любая из предопределенных констант Word, которые определяют конкретное встроенное диалоговое окно. Для просмотра списка констант, предопределенных для Word, и разделов справочной системы для этих констант используйте окно Object Browser. Word предоставляет более сотни констант — слишком много для подробного обсуждения в этой книге. Для управления встроенными окнами Word необходимо сначала сослаться на конкретное диалоговое окно, которое будет использоваться, а затем вывести его на экран с помощью метода Display объекта Dialog. Метод Display отображает диалоговое окно; когда пользователь закрывает диалоговое окно, можно находить выбор пользователя из свойств объекта Dialog. При желании можно также задавать значения по умолчанию для установок диалогового окна, задавая свойства объекта Dialog перед отображением этого окна на экране. Два наиболее важных свойства для диалоговых окон, определяемых константами wdDialogFileOpen и wdDialogFileSaveAs, являются также единственными общими для этих окон свойствами: Name и Format. Свойство Name — это строка, сохраняющая имя файла, которое пользователь выбрал в окне Открытие документа или в окне Сохранение документа. Можно также предлагать имя файла в текстовом окне File Name (Имя файла) диалоговых окон Открытие документа и Сохранение документа, присваивая значение свойству Name перед отображением этих диалоговых окон. Свойство Format указывает, какой тип документа открывается или сохраняется: документ или шаблон. Свойство Format может содержать значение одной из двух Word-констант типа файла: wdTypeDo-cument и wdTypeTemplate. В целях сбора информации от пользователя для процедур VBA используйте метод Display объекта Dialog. Метод Display возвращает значение, указывающее, 320 Глава 13 закрыл ли пользователь диалоговое окно щелчком кнопки Открыть, кнопки Отмена. В табл. 13.3 приведены возвращаемые значения метода Display и поясняется их смысл. , , > Таблица 13.3. Возвращаемые значения метода Display Числовое значение Что означает -2 Диалоговое окно было закрыто с помощью кнопки Отмена. -1 Диалоговое окно было закрыто щелчком кнопки Открыть в диалоговых окнах wdDialogFileOpen и wdDialogFileSaveAs). 0 Диалоговое окно было отменено. > 0 Командная кнопка; 1 — для первой командной кнопки, 2 — для второй и так далее. Теперь, когда вы понимаете основы использования Word-встроенных диалоговых окон Открытие документа и Сохранение документа, можно рассмотреть некоторые конкретные примеры работы этих окон. Использование Word-диалогового окна Открытие документа В листинге 13.7 показана процедура, использующая Word-встроенное диалоговое окно Открытие документа для получения имени файла документа от пользователя. Процедура открывает документ и помещает курсор в конец документа. Листинг 13.7. Использование Word-встроенного диалогового окна wdDialogFileOpen для получения имени файла 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Sub OpenWordFile() ' открывает указанный документ и перемещает ' указатель вставки в конец документа Const iTitle = "Открытие файла" Dim fName As String Dim IRetVal As Long With Application.Dialogs(wdDialogFileOpen) IRetVal = .Display , fName = .Name End With " * If IRetVal <> -1 Then MsgBox prompt:^"Операция отменена", _ Title:=iTitle Exit Sub End If Documents.Open FileName:=fName Selection.EndKey unit:=wdStory MsgBox prompt:="Документ & fName & _ открыт", _ ; Title:=iTitle & " завершено" End Sub Управление файлами с помощью VBA 321 Процедура OpenWordFile использует только одну константу — iTitle — в качестве заголовков диалоговых окон, отображаемых этой процедурой (заголовок диалогового окна Open изменить невозможно). В строках 7 и 8 объявляются переменные, используемые процедурой: fName используется для сохранения имени файла, введенного пользователем, a IRetVal — для сохранения результата метода Display, чтобы процедура могла определить, отменил пользователь или закрыл диалоговое окно Word, не делая выбора. В строке 10 производится ссылка на диалоговое окно Открытие документа, а строке 11 используется метод Display объекта Dialog для вывода на экран этого окна. В результате отображается диалоговое окно, показанное на рис. 13.7. Это окно идентично во всех отношениях окну, отображаемому Word, когда выбирается команда Файл | Открыть (File | Open). Рис. 13.7 Word-диалоговое окно Открытие документа, отображаемое оператором в строке 11 листинга 13 7 Выполнение процедуры OpenWordFile приостанавливается на то время, пока открыто диалоговое окно; после закрытия окна Открытие документа (пользователем) значение, возвращаемое методом Display, сохраняется в IRetVal и выполнение кода возобновляется со строки 12. В этот момент свойство Name диалогового окна содержит имя файла, выбранное пользователем (или строку нулевой длины, если пользователь не выбрал имя файла). В строке 12 значение свойства Name диалогового окна сохраняется в fName. В строках 15-19 оператор If оценивает возвращаемый методом Display результат, который был сохранен в переменной IRetVal. Значение —1 указывает, что диалоговое окно было закрыто щелчком на кнопке Открыть (или эквивалентным действием, таким как двойной щелчок на имени файла). Если окно не было закрыто щелчком на кнопке Открыть или ее эквиваленте, то отображается сообщение о том, что операция была отменена, иначе — выполнение кода продолжается со строки 21. В строке 21 выбранный файл открывается, а в строке 22 курсор помещается в конец документа. Наконец, в строках 24-26 отображается сообщение об успешном завершении операции. Использование Word-диалогового окна Сохранение документа В листинге 13.8 показана процедура, использующая Word-встроенное диалоговое окно Сохранение документа (Save As) для получения имени файла документа от пользователя, предлагающее формат шаблона документа для файла, который должен быть сохранен. Затем процедура сохраняет документ как .dot-шаблон. 11 Программирование на VBA 2002 322 Глава 13 Листинг 13.8. Использование Word-встроенного диалогового окна wdDialogFileSaveAs для получения имени файла 1 Sub ConvWordTemplate() 2 ' сохраняет текущий документ как файл шаблона 3 4 Const iTitle = "Преобразовать документ в шаблон" 5 Static sName As String • 6 Static TCount As Variant 7 8 Dim iNameas As String 9 Dim IRetVal As Long 10 11 If IsEmpty(TCount) Then 12 TCount = 1 ' 13 Else 14 TCount = TCount + 1 15 End If 16 17 sName = "Temp" & CStr(TCount) & ".dot" 18 ж With Application.Dialogs(WdDialogFileSaveAs) 19 .Name = sName 20 .Format = wdTypeTemplate 21 IRetVal = .Display 22 iName = .Name 23 End With 24 25 If IRetVal о -1 Then 26 MsgBox prompt:“"Преобразование отменено", _ 27 Title:“iTitle 28 Else f 29 ActiveDocument.SaveAs FileName:“iName, _ 30 fileformat:“wdTypeTemplate 31 End If 32 End Sub Процедура ConvWordTemplate сохраняет текущий документ как шаблонный Word-файл и использует диалоговое окно Сохранение документа для получения имени нового шаблонного файла. В строках 11-17 устанавливается счетчик шаблонных файлов и формируется предлагаемое имя файла. В строке 18 начинается оператор With, который ссылается на диалоговый объект Application.Dialogs(wdDialogFileSaveAs), то есть диалоговое окно, отображаемое Word, когда выбирается команда Файл | Сохранить как (File | Save As). В строках 19 и 20 устанавливаются некоторые предлагаемые умолчания для окна Сохранение документа. В строке 19 задается свойство Name диалогового окна, чтобы оно содержало предлагаемое имя файла шаблона (в sName). В строке 20 устанавливается свойство Format диалогового окна на wdTypeTemplate, это приводит к тому, что в диалоговом окне Сохранение документа в списке Тип файла (Save as type) выбирается тип файла Шаблон документа (Document Template) в качестве типа по умолчанию. При выполнении оператора в строке 21 VBA отображает диалоговое окно, показанное на рис. 13.8. Заметьте, что это окно точно такое же, как Word-диалоговое окно Сохранение документа. Как только пользователь делает выбор в окне Сохранение документа, возвращаемое значение метода Display сохраняется в IRetVal и выполнение кода продолжается со строки 22, где выбранное пользователем имя файла (из свойства Name диалогового окна) помещается в iName. В строках 29-30 документ сохраняется с использованием имени файла (в iName) и формата файла (wdTypeTemplate). Управление файлами с помощью VBA 323 Рис. 13.8 Word-диалоговое окно, отображаемое оператором в строке 21 листинге 13 8 Работа с дисками и папками В этом разделе рассматривается, как использовать функции и операторы VBA • для нахождения текущего диска и папки, как изменять текущий диск или папку и как создавать или удалять подпапки. Помните, текущий диск (current drive) — это диск, который использует Word или Excel, когда не указывается определенная буквенная метка диска. Аналогично, текущая папка (current folder) — это папка диска, которую Excel (или Word) использует, если не указывается определенная папка. Получение пути текущей папки и буквенной метки диска Выборка текущего диска и пути папки довольно проста. Обе части информации можно получить, используя функцию CurDir. CurDir возвращает строку, которая содержит полный путь текущей папки, включая буквенную метку диска. (CurDir является аббревиатурой слов current directory, помните, что папка и каталог — это одно и то же.) Функция CurDir имеет следующий синтаксис: СИНТАКСИС CurDir[(drive)] Здесь drive представляет любое выражение типа String и указывает функции CurDir, текущая папка какого диска необходима пользователю. Если аргумент drive опущен, CurDir возвращает текущую папку текущего диска. Обычно drive содержит только одну букву; если пользователь передает строку с несколькими символами, CurDir использует первый символ строки как буквенную метку диска. В листинге 13.9 показан пример использования функции CurDir. Листинг 13.9. Использование функции CurDir для получения текущего каталога и диска 1 Sub ShowCurDriveDir() 2 ' отображает текущий драйвер и каталог 3 4 Dim DirName As String 'для имени каталога 5 Dim DirLetter As String 'для буквы диска 6 и* 324 Глава 13 7 DirName = CurDir() 'получить текущую папку диска 8 9 ' взять первый символ из DirName - буква диска: 10 DirLetter = Left(DirName, 1) 11 12 ' вывод на экран: 13 MsgBox "Текущий драйвер: " & DirLetter & _ 14 Chr(13) & "Текущий каталог: " & DirName » 15 16 ' получить текущий каталог на драйвере С: 17 DirName = CurDir("C") ' 18 MsgBox "Текущий каталог на драйвере С: " & _ 19 DirName 20 End Sub Наличие большого количества комментариев и простота синтаксиса функции CurDir, видимо, не требуют анализа данного листинга. В дополнение можно предложить один из возможных результатов работы процедуры на рис. 13.9. Рис. 13.9 Такие окна могут получиться в результате работы кода из листинга 13.9 Microsoft Word Текущий драйвер1 F Текущий каталог: F \VB_books\VBA\Bce о УВА\Часть II Разработка приложенийVлава 13 Управление файлами с помощью VBA Изменение текущей папки Если вам необходимо, чтобы процедура VBA изменила текущую папку на какую-либо другую, используйте оператор ChDir. Если у вас есть опыт работы с DOS, вы поймете, что ChDir в VBA выполняет ту же задачу, что DOS-команды CHDIR и CD. (ChDir — это аббревиатура слов change directory). Оператор ChDir имеет следующий синтаксис: СИНТАКСИС ChDir path Аргумент path представляет любое выражение типа String, имеющее результатом допустимый путь папки; path может (необязательно) содержать буквенную метку диска. Если пользователь включает буквенную метку в аргумент path, ChDir изменяет текущую папку диска на указанную в path без изменения текущего диска. В листинге 13.10 показан пример использования оператора ChDir. Листинг 13.10. Использование ChDir 1 2 3 1 Sub Test_ChDir() 2 ’ демонстрирует оператор ChDir 3 Управление файлами с помощью VBA 325 4 Dim oldDir As String ' для текущего каталога 5 6 MsgBox "Текущий каталог: " & CurDir() 7 8 ' сохранить текущий (старый) каталог: 9 oldDir = CurDirO 10 11 ' изменить каталог: 12 ChDir "\Мои документы" 13 14 ' вывести на экран новый каталог: 15 MsgBox "Новый каталог: " & CurDirO 16 17 1 вернуться к старому каталогу 18 ChDir oldDir 19 MsgBox "Текущий каталог: " & CurDirO 20 21 End Sub Эта процедура, по всей видимости, также не нуждается в комментариях. Изменение текущего диска Для изменения текущего диска необходимо использовать оператор ChDrive. (ChDrive — это аббревиатура слов change drive.) Оператор ChDrive имеет следующий синтаксис: СИНТАКСИС ChDrive drive Аргумент drive — это любое выражение типа String, представляющее буквенную метку диска. Если drive содержит более одного символа, ChDrive использует только первый символ в строке для буквенной метки. Если для аргумента drive задается пустая строка, то текущий диск не изменяется. Если задается символ, не являющийся одной из букв от А до Z, VBA отображает runtime-ошибку. VBA отображает также runtime-ошибку, если задается буквенная метка для диска, которого фактически нет в данной компьютерной системе, хотя вы можете использовать буквенные метки дисков, соединенных с вашим компьютером через сеть. В листинге 13.11 демонстрируется использование оператора ChDrive. Листинг 13.11. Использование ChDrive для изменения текущего диска 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Sub Test_ChDrive() Dim oldDir As String ' запомнить текущий (старый) каталог: oldDir = CurDirO ' выдать на экран текущий каталог: MsgBox "Текущий каталог: " & oldDir ' изменить драйвер на А: ChDrive "D" ' выдать на экран новый драйвер и каталог: MsgBox "Новый драйвер и каталог: " & CurDir 326 Глава 13 16 ' восстановить старый драйвер (используется 17 ' только первый символ строки, содержащий драйвер): 18 ChDrive oldDir 19 20 ' восстановить старый каталог: 21 ChDir oldDir 22 23 MsgBox "Текущий каталог: " & CurDir () . 24 End Sub Создание дисковых папок Вам может понадобиться, чтобы одна из процедур создавала новую дисковую подпапку для сохранения в ней новых файлов рабочей книги или документа или по каким-либо другим причинам. Для создания дисковой папки используйте оператор MkDir. Оператор MkDir выполняет ту же задачу, что DOS-команды MKDIR или MD или команда WINDOWS File | New | Folder (Файл | Создать | Папка). (MkDir — это аббревиатура слов make directory.) Оператор MkDir имеет следующий синтаксис: СИНТАКСИС MkDir path Аргумент path представляет любое выражение типа String, которое имеет результатом допустимый путь папки; path может (необязательно) содержать буквенную метку диска. Если буквенная метка диска не включена в аргумент path, MkDir создает новую папку на текущем диске. Если path указывает имеющуюся уже папку или включает недопустимые символы имени файла, VBA отображает сообщение о runtime-ошибке. При попытке создать подпапку в папке, которой не существует, VBA также отображает сообщение о runtime-ошибке. Использование MkDir не изменяет текущего диска или папки. В листинге 13.12 показан пример использования оператора MkDir, не требующий никакого анализа. Листинг 13.12. Использование MkDir для создания нового дискового каталога 1 Sub Test_MkDir() 2 ' демонстрирует оператор MkDir 3 4 Dim newDir As String 5 .6 ' новый (будущий) каталог: 7 newDir = "A:\testl" 8 9 ' создать новый каталог: 10 MkDir newDir 11 12 ' перейти к новому (только что созданному) каталогу: 13 ChDir newDir 14 15 ' проверить результат перехода к новому каталогу: 16 MsgBox "Текущий каталог драйвера А: " & CurDir("А") 17 End Sub Перед запуском этой процедуры убедитесь, что в дисководе А: имеется диск, иначе VBA отобразит сообщение о runtime-ошибке. Управление файлами с помощью VBA 327 Удаление дисковых папок Вам может понадобиться также, чтобы одна из процедур удаляла дисковую подпапку. Для удаления дисковой папки используйте оператор RmDir. Оператор RmDir выполняет ту же задачу, что и DOS-команды RMDIR или RD; в Windows используется команда File | Delete (Файл | Удалить) для удаления как файлов, так и папок. (RmDir — это аббревиатура слов remove directory.) Оператор RmDir имеет следующий синтаксис: СИНТАКСИС RmDir path Аргумент path представляет любое выражение String, имеющее результатом допустимый путь папки; path может (необязательно) содержать буквенную метку диска. Если буквенная метка не включена в аргумент path, RmDir удаляет папку на текущем диске. Если path определяет папку, которая еще не существует, или включает недопустимые символы имени файла, то VBA отображает сообщение о runtime-ошибке. В листинге 13.13 показан простой пример использования оператора RmDir. Листинг 13.13. Использование RmDir для удаления папки 1 Sub Test_RmDir() 2 ' демонстрирует оператор RmDir 3 4 Dim delDir As String 5 6 ' имя удаляемой папки: l 7 delDir = "A:\testl" 8 9 ' если удаляемая папка - текущая, перейти 10 ' в корневую; НЕЛЬЗЯ УДАЛЯТЬ ТЕКУЩУЮ ПАПКУ 11 If CurDir("A") = delDir Then ChDir "A:\" 12 13 ' удалить папку A:\testl 14 RmDir delDir 15 16 End Sub Предполагается, что была выполнена процедура в листинге 13.12 для создания папки Testi для диска А:. Если текущая папка диска А: является той же папкой, которая должна быть удалена, то в строке 11 вызывается функция ChDir для изменения текущей папки диска А: на корневую папку. Нельзя удалять дисковую папку, если она является текущей или непустой. Копирование и удаление файлов Копирование и удаление файлов — это, вероятно, две наиболее часто выполняемые операции по управлению файлами. В этом разделе описывается, как можно копировать или удалять файлы под контролем процедур VBA. Копирование файлов Для копирования файла используйте оператор FileCopy. Этот оператор VBA эквивалентен DOS-команде COPY или команде File | Сору (Файл | Копировать) в Windows. 328 Глава 13 Оператор FileCopy имеет следующий синтаксис: СИНТАКСИС FileCopy source, destination Как source, так и destination являются выражениями типа String, имеющие результатом допустимые имена файла. Они могут (необязательно) включать полный путь папки и буквенную метку диска. При попытке копировать файл в самого себя VBA выдает runtime-ошибку. VBA также выдает runtime-ошибку при попытке копировать файл, когда нет достаточного дискового пространства для сохранения копируемого файла. В листинге 13.14 используется оператор FileCopy. Процедуру следует тестировать в Excel, так как она использует методы GetOpenFilename и GetSaveAsFilename. Листинг 13.14. Процедура, использующая оператор FileCopy 1 Sub TestCopyFiles() 2 ' копирует файл, указанный пользователем, в файл 3 ' с новым именем, драйвером или каталогом 4 / 5 Dim sName As String 6 Dim dName As String 7 8 Do 9 With Application 10 sName = .GetOpenFilename(Title:= _ 11 ' "File Copy - Source") 12 13 If sName = "False" Then Exit Sub 14 15 dName = .GetSaveAsFilename(Title:= _ 16 "File Copy - Destination") 17 18 If dName = "False" Then Exit Sub 19 20 End With 21 22 FileCopy Source:=sName, Destination:=dName 23 24 Loop 25 26 End Sub Эта процедура дает возможность пользователю выбирать файл-источник, диск, папку и имя файла-приемника, в который будет осуществляться копирование (иногда называют целевым). В строках 5 и 6 объявляются две переменные типа String для имен исходного и целевого файлов. В строке 8 начинается бесконечный цикл Do (цикл без детерминантного условия). Цикл в строках 8-24 выполняется до тех пор, пока пользователь не отменит одно из двух файловых диалоговых окон. В строке 9 начинается оператор With. В строках 10-11 содержится один оператор, вызывающий метод GetOpenFilename для отображения диалогового окна открытия файла и присваивающий имя файла (результат метода) переменной sName. В строке 13 оператор проверяет, отменил ли пользователь диалоговое окно открытия файла. Если — да, процедура заканчивается. Иначе VBA выполняет оператор в строках 15 и 16, который использует метод GetSaveAsFilename, чтобы дать возможность пользователю выбрать имя файла, диск и папку для копируемо Управление файлами с помощью VBA 329 го файла. В строке 18 проверяется, отменил ли пользователь диалоговое окно открытия файла. Если — да, выполнение процедуры прекращается. Иначе VBA продолжает выполнять код с оператора FileCopy в строке 22. Когда VBA выполняет оператор FileCopy в строке 22, файл (имя которого сохранено в sName) копируется с новым именем на новый диск и в новую папку, сохраненные в dName. После копирования файла цикл Do повторяется. Удаление файла Для удаления файла используйте оператор с драматическим именем Kill. Оператор Kill выполняет ту же задачу, что DOS-команда DEL или команда File | Delete (Файл | Удалить) в Windows. Оператор Kill имеет следующий синтаксис: СИНТАКСИС Kill pathname Аргумент pathname — это любое выражение типа String, имеющее результатом допустимую спецификацию имени файла; pathname может включать буквенную метку диска, полный путь папки и символы универсального сопоставления (* и ?). Если pathname включает символы универсального сопоставления, Kill удаляет все файлы, совпадающие со спецификацией в pathname. В листинге 13.15 показан пример оператора Kill. Листинг 13.15. Использование Kill для удаления файлов 1 Sub Test_KillFiles() 2 ' удаляет файлы, пока пользователь не отменит диалог 3 4 Dim fName As String 5 Dim Ans As Integer 6 1 Do 8 9 fName = Application.GetOpenFilename(Title:= _ 10 "Delete File") 11 12 If fName = "False" Then Exit Sub 13 14 Ans = MsgBox(prompt:="Delete " & fName & "?", 15 Title:="Delete File", _ 16 Buttons:=vbQuestion + vbYesNo) 17 18 If Ans = vbYes Then 19 Kill fName 20 End If 21 22 Loop 23 End Sub Эта процедура использует метод GetOpenFilename, дающий возможность пользователю выбрать имя файла, подтверждает удаление, удаляет файл. Эти действия повторяются в цикле. В строке 7 начинается бесконечный цикл Do, который выполняется до тех пор, пока пользователь не отменит файловое диалоговое окно. В строке 9 вызывается метод GetOpenFilename и его результат присваивается переменной fName. 330 Глава 13 В строке 12 проверяется, отменил ли пользователь файловое диалоговое окно, и процедура завершается, если пользователь его отменил. В строках 14-16 содержится оператор MsgBox, запрашивающий пользователя подтвердить удаление выбранного файла. Если пользователь подтверждает удаление, VBA выполняет оператор Kill (в строке 19), который удаляет файл. Не следует пытаться удалить файл открытой рабочей книги или документа, в таком случае VBA выдает runtime-ошибку. Проверяйте атрибуты файла перед попыткой удалить его. При попытке удалить файл, имеющий какой-либо из атрибутов Hidden, System или Read-Only VBA выдает runtime-ошибку. Используйте функцию GetAttr для выборки атрибутов файла и оператор SetAttr — для их изменения при необходимости удалять файлы с атрибутами Hidden, System или Read-Only. Переименование или перемещение файлов Вам может понадобиться изменить имя файла или переместить файл в другую папку на том же диске. Для переименования файла или перемещения его в другую папку используйте оператор Name. Оператор Name имеет следующий синтаксис: СИНТАКСИС Name oldpathname As newpathame Аргументы oldpathname и newpathname — это выражения типа String, имеющие результатом допустимые имена файлов. Оба могут (необязательно) содержать полный путь папки, включая буквенную метку диска. Если пользователь включает буквенную метку, оба выражения oldpathname и newpathname должны включать одну и ту же буквенную метку диска, иначе VBA выдает runtime-ошибку. Если oldpathname и newpathname ссылаются на разные папки, VBA перемещает файл в новую папку и изменяет его имя. В листинге 13.16 показана процедура, использующая оператор Name для переименования файлов. Листинг 13.16. Использование Name для переименования или перемещения файлов 1 Sub Test_RenameOrMoveFile() 2 ' переименовывает или перемещает файл 3 4 Const iTitle = "Переименовать или удалить - " 5 Dim oldName As String 6 Dim newName As String 1 Dim oldDir As String 8 9 oldDir = CurDir() 10 With Application 11 oldName = .GetOpenFilename(Title:=iTitle & "Источник") 12 If oldName = "False" Then Exit Sub 13 14 newName = .GetSaveAsFilename(InitialFilename:=oldName, 15 Title:=iTitle & "Новое имя") 16 If newName = "False" Then Exit Sub 17 End With 18 19 If Left(oldName, 1) = Left(newName, 1) Then 20 Name oldName As newName Управление файлами с помощью VBA 331 21 Else 22 FileCopy oldName, newName 23 Kill oldName 24 End If 25 26 ChDrive oldDir 27 ChDir oldDir 28 End Sub Эта процедура переименовывает или перемещает файлы. Пользователь процедуры выбирает имя файла, папку и диск для оригинального файла и для нового имени и/или местоположения. В строке 9 вызывается функция CurDir, результат которой сохраняется в переменной oldDir. В строке 10 начинается оператор With для объекта Application. В строке 11 используется метод GetOpenFilename для того, чтобы пользователь мог выбрать файл, который будет переименован или перемещен. В строке 12 используется оператор If для проверки того, отменил ли пользователь диалоговое окно GetOpenFilename; если — да, то процедура прекращается. В строке 14 вызывается метод GetSaveAsFilename для того, чтобы пользователь мог выбрать новое имя файла, диск и папку. Заметьте, что этот вызов GetSaveasFilename использует аргумент InitialFilename для заполнения предлагаемого нового имени файла. В строке 16 проверяется, отменил ли пользователь это диалоговое окно, и, если отменил, процедура заканчивается. В строке 19 начинается оператор If...Then...Else, который проверяет, выбрал ли пользователь другой диск для перемещения на него файла. Логическое выражение для оператора If в строке 19 использует функцию Left для возвращения первой буквы строк oldName и newName. Если эти две буквы одинаковые, то пользователь переименовывает или перемещает файл на том же самом диске и VBA выполняет оператор Name в строке 20 для переименования файла. Если пути папок в oldName и newName различны, Name перемещает файл в новую папку. Если первые буквы oldName и newName различные, то пользователь выбрал перемещение файла на другой диск. Нельзя использовать Name для перемещения файлов на другой диск, поэтому процедура использует FileCopy для копирования файла на другой диск и затем использует Kill для удаления оригинального файла. Наконец, операторы ChDrive и ChDir восстанавливают оригинальный диск и папку, которые были текущими при запуске процедуры. (Помните, методы GetOpenFilename Get Save AsFilename могут'изменить текущий диск и папку.) Получение информации о файлах Иногда бывает важно знать размер файла или дату и время, когда файл был модифицирован последний раз. Например, имея процедуру, резервирующую файлы рабочей книги, можно написать ее так, чтобы она проверяла, не заменяет ли она более недавний файл более старой версией. Получение времени и даты создания/модификации файла Всякий раз, когда одна из программ приложения, такая как Word или Excel, изменяет дисковый файл, файловая система Windows записывает дату и время (в соответствии с часами данной компьютерной системы) с файлом, чтобы можно было определить, когда этот файл был модифицирован последний раз. Чтобы сделать эту информацию доступной в процедурах VBA, используйте функцию File-DateTime. Эта функция возвращает информацию о дате и времени из файла как VBA-значение типа Date. 332 Глава 13 Функция FileDateTime имеет следующий синтаксис: СИНТАКСИС FiledateTime (pathname1 11) Аргумент pathname — это любое выражение типа String, имеющее результатом допустимую спецификацию файла; pathname может цеобязательно включать буквенную метку диска и полный путь папки, но не может содержать символы универсального сопоставления (* или ?). В листинге 13.17 в следующем разделе показан пример, использующий функцию FileDateTime. Получение длины файла Для того чтобы определить длину файла, используйте функцию FileLen. FileLen возвращает длину файла в байтах. Функция FileLen имеет следующий синтаксис: СИНТАКСИС FileLen(pathname) Аргумент pathname — это выражение типа String, имеющее результатом допустимую спецификацию имени файла; pathname может (необязательно) включать буквенную метку диска и полный путь папки, но не может включать символы универсального сопоставления. Если pathname определяет открытый файл, FileLen возвращает размер файла, каким он был, когда файл был сохранен на диске последний раз. В листинге 13.17 показан пример, использующий функцию FileLen, а на рис. 13.10 — один из возможных результатов работы кода этого листинга. Листинг 13.17. Использование функций FileDateTime и FileLen 1 Sub ShowFDS(sName As String) 2 ' отображает размер и дату последней модификации файла 3 4 Dim msgl As String 5 Dim msg2 As String 6 Dim fDate As Date ‘ , 7 Dim fLen As Long 8 9 fDate = FileDateTime(sName) 10 fLen = FileLen(sName) 11 msgl = "Размер: " & Format(fLen, "###,###,###") & 12 "байт." 13 msg2 = "Последняя модификация: " & _ 14 Format(fDate, "long date") & _ 15 " в " & Format(fDate, "long time") 16 MsgBox Т1Д1е:="Дата и размер файла", _ 17 prompt:=sName & Chr(13) & _ 18 msgl & Chr(13) & msg2 19 End Sub 20 21 Sub Test_ShowFDS() 22 Dim sName As String 23 24 Do Управление файлами с помощью VBA 333 25 With Application 26 sName = .GetOpenFilename(Title:="Дата/Размер файла") 27 End With 28 If sName <> "False" Then ShowFDS sName 29 Loop Until sName = "False" 30 End Sub Процедура ShowFDS использует функции FileLen и FileDateTime для отображения окна сообщения, показывающего текущий размер файла и дату и время, когда этот файл модифицировался последний раз. ShowFDS имеет единственный аргумент fName типа String, используемый для указания процедуре ShowFDS., информация о каком файле должна быть отображена. Рис. 13.10 Процедура ShowFDS использует функции FileLen и FileDateTime для сбора информации о размере файла и о том, когда он был модифицирован последний раз Дата и размер файла E:\Documents and Settings'Ll ладимир\Му Documents\Chapterl0.doc Размер: 987,1366айт. Последняя модификация: Sunday, January 26, 2003 в 12:45:10 РМ I 6k В строках 4-7 объявляется несколько переменных этой процедуры. Первые две переменные (msgl и msg2) используются для формирования текста сообщения, отображаемого процедурой. Переменные fDate и fLen используются для сохранения информации о дате и времени и информации о размере файла, соответственно. Заметьте, что fLen имеет тип Long, потому что длина файла может исчисляться миллионами байт. В строке 9 вызывается функция FileDateTime с аргументом sName в качестве имени файла, а результат функции сохраняется в fDate. В строке 10 вызывается функция FileLen также с использованием sName для определения аргумента имени файла, а результат этой функции сохраняется в fLen. В строках 11 и 12 содержится один оператор, который формирует первую часть сообщения, отображаемого этой процедурой, и сохраняет ее в msgl. В строках 13-15 содержится также один оператор, который формирует вторую часть сообщения, отображаемого этой процедурой, и сохраняет ее в msg2. Наконец, оператор MsgBox в строках 16-18 отображает имя файла, его размер и дату и время, когда этот файл модифицировался последний раз. В строках 21-30 содержится процедура, тестирующая процедуру ShowFDS. Эта процедура использует метод GetOpenFilename, чтобы пользователь мог выбрать файл, а затем вызывает процедуру ShowFDS. Глава 14 Элементы диалоговых окон До сих пор вы учились использовать диалоговые окна, которые встроены в VBA, а именно, функции MsgBox и InputBox. Хотя MsgBox и InputBox придают вашим программам гибкость, которой могут обладать только интерактивные программы, их возможности в известной степени ограничены. При разработке более сложных программ вы захотите выводить диалоговые окна, которые дают возможность пользователям ваших программ задавать при помощи одного диалогового окна сразу несколько опций, выбирать пункты из списка или вводить в одном окне несколько значений подобно тому, как это можно делать с помощью диалоговых окон, выводимых Word, Excel и другими приложениями Windows. Часто у вас будет возникать необходимость вместо встроенных окон, принадлежащих Word или Excel, использовать диалоговые окна, созданные специально для вашей программы. VBA позволяет создавать и применять пользовательские1 диалоговые окна в написанных вами программах и процедурах при помощи добавления в проект объекта UserForm. Используя VBA-формы пользователя (VBA User Forms), вы можете создавать диалоговые окна для вывода данных или получения значений от пользователя вашей программы именно в том виде, который требуется вашей программе. Например, вы можете вывести на экран диалоговое окно со списком различных вариантов формата даты и предоставить пользователю возможность выбрать из списка один из форматов. Диалоговые окна позволяют вашей программе общаться с пользователем наиболее удобным образом, обеспечивая гибкую форму ввода и вывода данных. Из этой главы вы узнаете об основных элементах диалоговых окон и их свойствах, научитесь создавать простые диалоговые окна. Формы пользователя Диалоговое окно в VBA создается добавлением в проект объекта UserForm. Объект UserForm — это пустое диалоговое окно. Настройку диалогового окна можно выполнить добавлением к объекту UserForm (обычно называют просто фор ма) элементов управления. Каждому объекту UserForm присущи определенные свойства, методы и события, которые он наследует от класса объектов UserForm. Каждый объект UserForm включает в себя также модуль класса, в который вы можете добавлять собственные методы и свойства или код обработки событий формы. Первый шаг в создании пользовательского диалогового окна состоит в добавлении к проекту новой формы (объекта UserForm). Форма содержит рабочую область, в которую вы можете поместить элементы, необходимые для выполнения некоторого диалога пользователя с приложением. Поскольку объекты UserForm хранятся в коллекции UserForms проекта, они являются частью проекта. Для добавления к проекту новой формы используйте команду VB-редактора Insert | UserForm (Вставка | UserForm). Редактор VB добавляет к текущему проекту новую форму, присваивая ей по умолчанию имя UserFormN и используя ту же систему нумерации, что и для модулей. Редактор VB выводит новую форму в режи ме разработки, как показано на рис. 14.1. [В режиме разработки вы можете добавлять (или удалять) элементы управления к форме, устанавливать свойства формы 1 В переводной литературе встречается термин «настраиваемые) (от анг custom) Элементы диалоговых окон 335 или ее элементов управления и выполнять другие манипуляции с внешним видом формы в интерактивном режиме. Когда форма выведена и используется как часть выполняющейся программы, она находится в режиме выполнения.] На рис. 14.1 показана добавленная в проект форма UserForml. Заметим, что широкая рамка вокруг формы указывает на то, что форма выделена. Обратите внимание на сетку из точек на поверхности формы и панель элементов (Toolbox). Сетка из точек помогает выравнивать и контролировать размеры элементов управления, помещаемых на форму, и появляется только в режиме разработки. Панель элементов является «палитрой», с помощью которой вы можете выбирать элементы управления и добавлять их к форме. Панель, как правило, появляется только в том случае, если выбрана форма и ни один из ее элементов управления. Вы можете переименовать объект UserForm так же, как стандартный модуль или модуль класса. Для этого отредактируйте в Properties Window (окно свойств) свойство Name этого объекта. Не оставляйте вновь созданной форме имя, присвоенное ей по умолчанию, например UserForml или UserForm2. Напротив, переименовывайте новую форму сразу, как только ее создали. Когда форма выводится на экран в режиме разработки, вы можете протестировать ее поведение, используя команду Run | Run Sub/UserForm (Запуск | Запуск под-программы/UserForm). После этого редактор VB выведет форму в режиме выполнения и все ее элементы управления будут активными. Однако следует помнить, что любой код, используемый формой, хранящийся не в модуле класса формы, не может быть инициализирован. При запуске формы инициализируется только код, находящийся в модуле класса формы. Переменные в стандартных модулях необязательно будут инициализироваться. В результате этого, если форма не является полностью независимой, некоторые из программ связанных с ней, могут не выполняться, выдавая сообщения о различных runtime-ошибках. Рис 141 Новая UserForm в режиме разработки Свойства объекта UserForm Форма как объект имеет некоторые встроенные свойства, и вы можете устанавливать эти свойства или программным образом, или в Properties Window (окне свойств) редактора VB. Строго говоря, данные способы изменения свойств форм не являются эквивалентными. Некоторые из свойств могут быть установлены только посредством Properties Window. Программным способом свойства форм устанавливаются таким же образом, как и свойства других объектов: путем присвоения 336 Глава 14 свойству нового значения. В Таблице 14.1 перечислены свойства UserForm, на которые вам, скорее всего, придется ссылаться или изменять их. Таблица 14.1. Наиболее часто используемые свойства объектов UserForm I Свойство Описание | ActiveControl Возвращает объектную ссылку на элемент управления, находящийся в фокусе в данный момент. Только для чтения. BackColor Целое типа Long определяет цвет фона формы. Самый простой способ установить это свойство — использовать Properties Window; чтобы выбрать желаемый цвет (если необходимо), можно скопировать номер цвета из Properties Window в свою программу. Caption Текст, выводимый в качестве заголовка формы. Запись/Чтение. Controls Возвращает коллекцию всех элементов управления формы. Только для чтения. Cycle Определяет, должно ли нажатие клавиши табуляции вызывать последовательный выбор всех элементов управления во всех группах и на каждой странице многостраничных элементов управления или только в пределах текущей группы или страницы. Может содержать одну из двух встроенных констант: fmCycleAUForms или fmCycleCurrentForm. Чтение/Запись. Enabled Содержит значение типа Boolean, указывающее, доступна ли форма. Если его значение равно False, ни один из элементов управления формы не доступен. Чтение/Запись. Font Возвращает ссылку на объект Font, посредством которого вы можете выбрать параметры шрифта формы или элемента управления. ForeColor То же самое, что и свойство BackColor, но устанавливает цвет используемый для переднего плана (обычно — это цвет текста) объекта формы. Методы объекта UserForm Всякий раз создавая в проекте новый объект UserForm, вы создаете новый подкласс объекта UserForm. Любые процедуры или функции, написанные вами в разделе General (общий) модуля класса, относящегося к форме, становятся дополнительными методами для отдельного подкласса объекта. Вы также можете создать для формы новые свойства, добавив в ее модуль класса процедуры Property Get и Property Let. Вы можете создавать экземпляры подкласса вашей UserForm с помощью оператора Dim и ключевого слова New. Однако чаще всего вы будете манипулировать объектом формы при помощи стандартных методов и свойств класса UserForm и при помощи собственных процедур обработки событий для определенной вами формы и ее элементов управления. В табл. 14.2 перечислены наиболее часто используемые методы для объектов UserForm, которыми вы можете воспользоваться, и кратко изложены их свойства. Эти методы будут доступны для каждой формы, которую вы добавляете в свой проект. Элементы диалоговых окон 337 Таблица 14.2. Наиболее часто используемые методы для объектов UserForm Метод Назначение Сору Копирует выделенный в элементе управления текст в буфер обмена Windows. . Cut Вырезает выделенный в элементе управления текст и помещает его в буфер обмена Windows. Hide Скрывает UserForm, не выгружая ее из памяти, сохраняя значения элементов управления формы и всех переменных, объявленных в модуле класса формы. Paste Вставляет содержимое буфера обмена Windows в текущий элемент управления. PrintForm Выводит на используемый в Windows по умолчанию принтер изображение формы, включая все данные, введенные в элементы управления. Repaint Перерисовывает форму, выведенную на экран. Используйте этот метод, если хотите перерисовать форму, не ожидая, когда она будет перерисована через обычный период времени. Show Выводит форму на экран. Если форма еще не загружена в память, то данный метод сначала ее загружает. В этой главе при написании примеров процедур обработки событий нам понадобится метод Show. Поэтому рассмотрим его подробнее. Синтаксис метода Show: СИНТАКСИС FormName.Show В данной синтаксической конструкции FormName может быть любым объектом UserForm текущего проекта. FormName — имя формы в том виде, как оно отображается в Project Explorer. Например, если у вас есть форма frminsert Figure, вывести ее на экран можно с помощью оператора: frmlnsertFigure.Show Если форма в данный момент не загружена в память, метод Show загрузит ее и выведет на экран. Если форма уже загружена, метод Show просто выведет ее на экран. В любом случае метод Show выводит форму и затем передает ей управление. Форма будет оставаться на экране до тех пор, пока или не будет выполнен метод Hide объекта UserForm, или форма не будет выгружена при помощи оператора Unload. Все формы VBA являются модальными (modal) приложениями, это означает, что вы не сможете выполнить какое-либо другое действие в приложении до тех пор, пока форма диалога не будет закрыта или скрыта. Когда VBA выполняет метод Show для отображения формы диалогового окна, процедура, содержащая вызов метода Show, приостанавливается до тех пор, пока выведенная форма не будет закрыта пользователем. Однако VBA будет выполнять программу для любых событийных процедур в модуле класса формы. 338 Глава 14 События и событийные процедуры Событие (event) — это что-то, что может произойти с диалоговым окном или элементом управления диалогового окна. Типичные примеры событий: щелчок на кнопке, переключателе и т.д. Другие примеры событий: изменение содержимого окна редактирования или выбор элемента списка. Щелчок мышью, нажатие клавиши и действия внутренние для вашего компьютера, — все они запускают или, иными словами, влекут за собой события. Использование событий позволяет создавать действительно диалоговые приложения. В таких приложениях все действия пользователя приводят к определенной реакции приложения, если эти действия предусмотрены и не заблокированы. Если вы хотите, чтобы ваши пользователи чувствовали себя комфортно при работе с вашими программами, начинайте создавать свои диалоговые окна с разработки событийных процедур. Такие объекты, как формы и элементы управления приводят в действие, то есть делают доступными, некоторые события. Вы можете написать собственные VBA-процедуры, реагирующие на события. Такие процедуры, называются событийными процедурами (event procedures) или процедурами обработки событий. Событийные процедуры следует записывать в модуль класса, который является частью UserForm. При этом такие процедуры должны иметь имена в виде ObjectName_EventName, где ObjectName — имя формы или элемента управления, a EventName — имя события, с которым вы хотите работать. Такой формат имени, позволяет VBA сопоставлять заданному событию требуемую процедуру. Большая часть программы, которую вы записываете в модуль класса формы, будет связана с обработкой событий. В таблице 14.3 перечислены события, для которых вы можете написать процедуры обработки. Таблица 14.3. События объектов UserForm Событие Синтаксис заголовка процедуры обработки события Описание Activate Private Sub object _Activate() Инициируется всякий раз, когда окно формы становится активным. Используйте это событие для обновления содержимого диалоговых элементов управления, чтобы отразить любые изменения, которые произошли, пока окно формы было неактивным. Click Private Sub object_C].ick(index As Long) Инициируется всякий раз, когда по форме (любой ее части, не занятой элементами управления) щелкают мышью. DblClick Private Sub ofeject_DblClick(index As Long, By Vai Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда по форме (любой ее части, не занятой элементами управления) дважды щелкают мышью. * Deactivate Private Sub ob/ect_Deactivate() Инициируется всякий раз, когда форма перестает быть активной. Элементы диалоговых окон 339 Событие Синтаксис заголовка процедуры обработки события Описание Initialize Private Sub ofe/ect_Initialize() » Инициируется всякий раз, когда форма впервые загружается в память посредством выполнения оператора Load или с помощью метода Show. Используйте это событие для инициализации элементов управления формы при ее появлении на экране. Resize Private Sub U serForm_Resiz e() Инициируется при изменении размеров формы. Terminate Private Sub ofe/ect_Terminate() Инициируется всякий раз, когда форма выгружается из памяти. Используйте это событие для осуществления любых специальных служебных задач, которые необходимо выполнить прежде, чем переменные формы будут выгружены. В дополнение к методам, свойствам и событиям, встроенным в объект User-Form, VBA предоставляет два оператора, которые особенно полезны при работе с объектами форм: Load и Unload. Вы можете использовать эти операторы для того, чтобы или загрузить форму в память, или же удалить ее оттуда. Синтаксис Load/Unload Синтаксические конструкции для использования операторов Load и Unload выглядят следующим образом: СИНТАКСИС Load Object Unload Object Здесь Object представляет любую допустимую ссылку на объект UserForm. Оператор Load загружает в память объект UserForm и запускает метод формы Initialize, но не выводит форму на экран. Когда форма загружена, вы можете использовать написанную на VBA программу для работы с объектом UserForm. Оператор Unload удаляет из памяти UserForm, а также все переменные формы. После того как форма выгружена, она перестает быть доступной для VBA-кода. Примеры программ модуля класса формы Рассмотрим несколько простых примеров использования свойств и методов формы с помощью процедур обработки событий. Будем инициировать события, описанные в табл. 14.3, а в ответ на них с помощью окна функции MsgBox будем сообщать о типе события или менять видимые свойства формы. Начнем с события Click, так как процедуру обработки этого события легче всего создать: достаточно дважды щелкнуть на форме (используем созданную в начале главы форму) в режиме разработки, и вам будет предоставлен шаблон процедуры в виде: Private Sub UserForm_Click() End Sub 340 Глава 14 Запишите после заголовка процедуры следующий оператор MsgBox("Событие: Click") Запустите форму на выполнение командой Run | Run Sub/UserForm. После появления формы на экране щелкните на ней мышью, на экране появится сообщение, подобное приведенному на рис. 14.2. Рис. 14.2 Выполнение процедуры обработки события Click Если даже вам не часто будет нужно использовать подобное событие для формы, не забывайте о такой возможности. А еще лучше поступайте следующим образом. Всегда используйте это событие на случай, когда пользователь ваших форм при попытке щелкнуть на каком либо элементе управления не совсем точно позиционирует курсор мыши. Если при этом будет выполняться процедура обработки события Click для формы с выводом шутливого сообщения о недостаточной уверенности в действиях пользователя, с вашим приложением станет приятно работать. Вы также никогда не забудете о возможности использовать это событие, когда для этого появятся серьезные причины. Продолжим рассмотрение событий и протестируем событие Activate. Запишите в модуле рассматриваемой формы следующую процедуру: Private Sub UserForm_Activate() MsgBox ("Событие: Activate") End Sub Снова запустите форму на выполнение командой Run | Run Sub/UserForm. После появления формы на экране вы увидите сообщение о том, что произошло событие Activate (рис. 14.3). Рис. 14.3 Сразу после загрузки формы произошло событие Activate Рассмотрим события Deactivate и Terminate. Первое из них инициируется всякий раз, когда форма перестает быть активной, а второе — когда форма выгружается из памяти. Процедура обработки события Terminate просто добавляется Элементы диалоговых окон 341 к имеющейся коллекции программ формы UserForml и выполняется при завершении работы с формой. Для демонстрации же события Deactivate необходимо, не выходя из приложения, сделать форму UserForml неактивной. Это можно осуществить, если активной станет другая форма. И ее надо создать. Создайте новую форму либо при помощи кнопки Insert UserForm, либо — командой Insert | UserForm. Пусть она имеет имя, которое ей присваивается по умолчанию: UserForm2. Помните, что следует всегда переименовывать формы для удобства сопровождения разработки, но для нашего тестирования событий мы этого делать не будем. Наметим план тестирования: 1. Загружаем форму UserForml. 2. Событие Click формы UserForml вызывает метод Show для загрузки формы UserForm2. 3. Загрузка/выгрузка формы UserForm2 не сопровождаются никакими событиями. 4. Форма UserForml имеет процедуры обработки событий: Click, Activate, Deactivate, Terminate. Для выполнения поставленной задачи в модуль формы UserForml необходимо поместить код листинга 14.1. Листинг 14.1. Процедуры событий UserForml 1 ' Обработчик события Click формы UserForml 2 Private Sub UserForm_Click() 3 ' Вывод окна сообщения на экран: 4 MsgBox ("Событие: Click. Выводим UserForm2") 5 1 Загрузка формы UserForm2: 6 UserForm2.Show 7 End Sub 8 9 ' Обработчик события Activate формы UserForml 10 Private Sub UserForm Activated 11 1 Вывод окна сообщения на экран: 12 MsgBox ("Событие: Activate для формы UserForml") 13 End Sub 14 15 Private Sub UserForm Deactivated 16 ' Вывод окна сообщения на экран: 17 MsgBox ("Событие: Deactivate для формы UserForml") 18 End Sub 19 20 Private Sub UserForm Terminate() 21 ' Вывод окна сообщения на экран: 22 MsgBox ("Событие: Terminate для формы UserForml") 23 End Sub Следует отметить, что после создания новой формы, вы не сразу можете найти модуль формы UserForml. Ваш экран может быть похожим на тот, который приведен на рис. 14.4. Выберите команду Run | Run Sub/UserForm. Теперь вы имеете возможность проследить за инициализацией всех четырех событий. Сразу после загрузки UserForml выдается сообщение "Событие: Activate для формы UserForml" (процедура User-Form_Activate). Щелчок на форме приводит к выводу сообщения "Событие: Click. Выводим UserForm2" (процедура UserForm_Click), загрузке формы UserForm2 (процедура UserForm_Click) и выводу сообщения "Событие: Deactivate для формы UserForml" (процедура UserForm_Deactivate) в результате того, что форма UserForml становится неактивной. Если бы мы описали процедуру события Activate 342 Глава 14 и для формы UserForm2, то один щелчок мыши вызвал бы инициализацию трех событий. И, наконец, не забудьте обратить внимание на то, что при выгрузке из памяти формы UserForml на экран выдается сообщение процедуры UserForm_Ter-minate. Рис. 14.4 После создания новой формы очень легко «потерять» предыдущую Событие Initialize инициализируется при загрузке формы при помощи оператора Load или метода Show. При выполнении команды Run | Run Sub/UserForm это событие не инициализируется. Это событие следует использовать при первой загрузке формы для установки каких-либо свойств формы и ее элементов управления. В следующем примере (листинг 14.2) для этого события устанавливается свойство формы BackColor. Листинг 14.2. Процедуры событий UserForm2 1 Dim sRED, sGREEN, sBLUE 'переменные для задания цвета формы 2 3 ' Процедура обработки события Initialize 4 ' Инициализируется один раз: при загрузке 5 Private Sub UserForm_Initialize() 6 ' задаем начальный цвет формы 7 sRED = 100 8 sGREEN = 100 9 sBLUE = 200 10 UserForm2.BackColor = RGB(sRED, sGREEN, sBLUE) 11 End Sub 12 13 ' Процедура обработки события Click 14 ' При каждой инициализации меняет цвет формы. При недопустимых 15 1 11 значениях sRED, sGREEN, sBLUE выдает ошибку времени исполнения 16 Private Sub UserForm_Click() 17 Dim I 18 - ‘ 19 1 Меняем цвет формы: < 20 sRED = sRED + 20 21 sGREEN = sGREEN +10 ' , 22 SBLUE = SBLUE - 20 23 1 = RGB(SRED, SGREEN, SBLUE) 24 UserForm2.BackColor = I 25 Элементы диалоговых окон 343 26 ' Изменить заголовок формы: 27 UserForm2.Caption = "Цвет: " & Str(i) 28 End Sub Для загрузки формы UserForm2 используйте форму UserForml с программами обработки событий из листинга 14.1. В листинге 14.2 для установки свойства формы BackColor используется функция RGB, которая возвращает RGB-значение типа Long, используемое далее для присвоения свойству UserForm2.BackColor. Синтаксис функции RGB:' СИНТАКСИС RGB(red, green, blue) Именованные аргументы: Аргумент Описание Red Обязательный; тип: Variant (Integer). Число в диапазоне 0-255; представляет красный компонент цвета. Green Обязательный; тип: Variant (Integer). Число в диапазоне 0-255; представляет зеленый компонент цвета. Blue Обязательный; тип: Variant (Integer). Число в диапазоне 0-255; представляет синий компонент цвета. После вывода формы с именем UserForm2 на экран событие Click будет приводить к изменению цвета и заголовка формы. Мы не рассмотрели еще два события, связанные с формой: DblClick, которое является аналогом Click, и Resize — событие, которое инициализируется при изменении размеров формы. Рассмотрим последнее событие, так как первое должно быть понятным и в реализации похожим на ранее рассмотренные. Размеры формы могут изменяться как во время диалога (если это предусмотрено разработчиком формы), так и программным способом. Для иллюстрации программы обработки события изменения формы удобнее использовать программный способ. Листинг 14.3 содержит две процедуры: первая обрабатывает событие Click (при этом изменяется свойство формы Width), вторая — событие Resize. Листинг 14.3. Обработка событий Click и Resize 1 Private Sub UserForm_Click() 1 Можно UserForm_DblClick 2 MsgBox ("Событие: Click") 3 ' Меняем размер формы: 4 UserForml.Width = 400 5 End Sub 6 7 Private Sub UserForm_Resize() 8 MsgBox ("Событие: Resize") 9 End Sub Элементы управления Объект UserForm может содержать те же элементы управления, что и находящиеся в диалоговых окнах Word, Excel или других приложений Windows. Элементы управления (controls) — это элементы диалогового окна, которые дают возмож 344 Глава 14 ность пользователю взаимодействовать с программой. Они включают в себя кнопки-переключатели, текстовые поля, линейки прокрутки, командные кнопки и так далее. В этом разделе вы познакомитесь со стандартными элементами управления, включенными в VBA, которые сможете добавлять в свои формы. Многие производители программного обеспечения сделали доступными пакеты, расширяющие набор элементов управления. Вы можете добавлять элементы управления (известные как объекты ActiveX и Automation) к панели Toolbox (панели элементов), предварительно создавая ссылку из вашего проекта на библиотеку, содержащую расширенный набор элементов управления. После этого можно добавлять данные элементы управления на панель Toolbox. Каждый элемент управления — это объект с определенными свойствами, методами и событиями. Как и для формы, их содержащей, вы можете устанавливать свойства элементов управления программным путем или посредством Properties Window редактора VB. В программе вы можете присваивать или восстанавливать значения свойств элементов управления так же, как для любых других объектов. В табл. 14.4 перечислены стандартные элементы управления, включенные в VBA, и описано назначение каждого элемента. Как видно из этой таблицы, к стандартным относятся, практически, все элементы управления, которые вам встречались в приложениях Windows. (В зависимости от host-приложения VBA, в котором вы работаете, на панели Toolbox могут появляться дополнительные элементы управления, не перечисленные в табл. 14.4. Эти дополнительные элементы доступны через библиотеки элементов управления, поставляемые с каждым из host-приложений.) Таблица 14.4. Стандартные элементы управления, включенные в VBA Элемент управления Назначенне Label (надпись, метка) Позволяет создавать заголовки элементов управления, которые не имеют собственных встроенных заголовков. Используйте этот элемент для того, чтобы поместить на форму статический текст, например, инструкции, советы по заполнению других диалоговых элементов управления. TextBox (текстовое поле) Окно редактируемого текста свободной формы для ввода данных. Может быть одно- или многострочным. ComboBox (поле со списком) Этот элемент управления объединяет окно редактирования и окно списка. Используйте, когда хотите предложить пользователю выбрать значение, но при этом дать ему возможность ввести данные, отсутствующие в списке. Вы можете также ограничить выбор только теми значениями, которые появляются в ComboBox для эмуляции ниспадающего списка. ListBox (список) Отображает список значений, из которых пользователь может сделать выбор. Окна списка можно использовать, чтобы дать возможность пользователю выбрать только одно значение или же несколько. CheckBox (флажок) Стандартный флажок (квадратное окно, содержащее, если элемент выбран, «галочку»). Используйте флажки для выбора вариантов, которые не являются взаимоисключающими. OptionButton (переключатель) Стандартная кнопка-переключатель (круглое окно, при выборе в центре него находится черная точка). Используйте OptionButton, когда пользователю необходимо сделать выбор между «включено/выключено», «истина/ложь». Кнопки-переключатели, как правило, объединяются вместе при помощи рамки для создания группы переключателей. Элементы диалоговых окон 345 Элемент управления Назначение ToggleButton (выключатель) Выключатели служат для той же цели, что и флажки, но выводят установки в виде кнопки находящейся в «нажатом» или «отжатом» состоянии. Frame (рамка) Визуально и логически объединяет некоторые элементы управления (особенно флажки, переключатели и выключатели). Используйте Frame, чтобы показать пользователю, какие элементы управления в диалоговом окне связаны между собой, или чтобы выделить группу элементов управления, отделяя ее от остальных элементов управления, находящих- ся в диалоговом окне. CommandButton (кнопка) Используйте кнопки для выполнения таких действий, как Cancel (Отмена), Save (Сохранить), ОК и так далее. Когда пользователь щелкает по кнопке, выполняется VBA-процедура, закрепленная за данным элементом управления. TabStrip (набор вкладок) Этот элемент управления состоит из области, в которую следует помещать другие элементы управления (такие как текстовые поля, флажки и так далее) и полосы кнопок табуляции. Используйте элемент управления TabStrip для создания диалоговых вкладок, отображающих одни и те же данные в различных категориях. MultiPage (набор страниц) Этот элемент управления состоит из нескольких страниц. Вы можете выбрать любую из них, щелкнув по соответствующей-вкладке. Используйте элемент управления MultiPage для создания диалоговых окон с вкладками, такими, например, как диалоговое окно, появляющееся при выборе команды Tools | Options (панели инструментов | настройка). ScrollBar (полоса прокрутки) Элемент управления ScrollBar позволяет выбирать линейное значение, аналогично тому, как это можно сделать при помощи счетчика. SpinButton (счетчик) Элемент управления SpinButton является специальной разновидностью текстового поля. Обычно счетчики используются для того, чтобы ввести число, дату или какие-либо иные последовательные величины, которые заведомо находятся в определенном интервале значений. Щелчок по указывающей вверх стрелке счетчика увеличивает значение в окошке, а щелчок по стрелке, направленной вниз, соответственно, уменьшает его. Image (рисунок) Элемент управления Image позволяет вывести на форме графическое изображение. Используйте Image для вывода графических изображений в любом из следующих форматов: *.bmp, *.cur, *.gif, *.ico, *.jpg, или *.wmf. Вы можете обрезать и масштабировать графическое изображение, чтобы подобрать размер элемента Image, но только не редактировать графическое изображение. Можно даже написать специальную VBA-процедуру, выполняющуюся, если пользователь щелкнет по элементу управления Image. Обращение к элементам управления происходит, в основном, через их свойства и с помощью процедур обработки событий, написанных для каждого элемента. В табл. 14.5 перечислены наиболее часто используемые свойства элементов управле 346 Глава 14 ния, которые могут понадобиться для работы с вашими VBA-программами — свойства, которые позволяют изменять заголовок, определять состояние элемента управления (то есть обнаруживать установки, выполненные пользователем) и так далее. Таблица 14.5. Наиболее часто используемые свойства стандартных элементов управления Свойство Где применяется Описание Accelerator CheckBox, Tab, CommandButton, Label, Page, OptionButton, ToggleButton Содержит символ, используемый, в качестве быстрой клавиши вызова, элемента управления. При нажатии АИ+<клавиша быстрого вызова> происходит выбор элемента управления. BackColor Все элементы Число, представляющее определенный цвет фона элемента управления. Caption CheckBox, CommandButton, Frame, Label, OptionButton, ToggleButton, Page, Tab, UserForm Для надписи — текст, отображаемый, элементом управления. Для других элементов управления — надпись, которая появляется на кнопке или вкладке или рядом с рамкой, флажком или переключателем. Cancel CommandButton Задает кнопку отмены диалогового окна. При нажатии на эту кнопку или клавишу Esc диалоговое окно исчезает. Только одна кнопка формы может иметь данное свойство. ControlTipText Все элементы управления Устанавливает текст, который отображается в виде всплывающей подсказки (ControlTip, называемой также ToolTip), когда указатель мыши помещается на элемент управления. Default CommandButton Определяет заданную по умолчанию кнопку. Когда пользователь нажимает в процессе диалога клавишу Enter, эта кнопка ведет себя так, как если бы по ней щелкнули мышью. Enabled Все элементы управления Хранит значение типа Boolean, определяющее доступен или нет элемент управления. Если Enabled имеет значение False, то элемент управления продолжает отображаться в диалоговом окне, но не может быть выбран. ForeColor Все элементы управления То же самое, что и BackColor, но устанавливает цвет для переднего плана элемента управления, как правило, символов текста. Элементы диалоговых окон 347 Свойство Где применяется Описание List ComboBox * * 1 Массив типа Variant (одно- или многомерный), представляет список содержащийся в элементе управления. Используйте индекс Value как нижний индекс в коллекции List, чтобы получить текст для выбранного пункта списка. Используйте методы элемента управления Additem и Removeitem для добавления или удаления пунктов списка. Мах ScrollBar, SpinButton Переменная типа Long, определяющая максимальное значение счетчика или значение, при котором полоса прокрутки находится в самом верху (для вертикальной полосы) или справа (для горизонтальной). Min ScrollBar, SpinButton Переменная типа Long, определяющая минимальное значение счетчика или значение, при котором полоса прокрутки находится в самом низу (для вертикальной полосы) или слева (для горизонтальной). Name Все элементы управления Содержит имя элемента управления. Вы можете установить данное свойство толь- ко с помощью Properties Window. RowSource ComboBox Задает источник, из которого ListBox берет список объекта. В Excel VBA RowSource обычно использует диапазон рабочего листа. Selected ListBox Возвращает массив значений типа Boolean для списка, который допускает множественный выбор. Каждый элемент массива содержит по одному элементу, соответствующему каждому пункту списка. Если значение элемента в массиве Selected равно True, то соответствующий пункт списка выбран. Tabindex Все элементы управления Число, указывающее положение элемента управления в порядке табуляции (может иметь значение от 0 до значения, равного количеству элементов управления на форме). TabStop 1 Все элементы управления Значение типа Boolean, указывающее может ли элемент управления быть выбран клавишей Tab. Если значение TabStop равно False вы, тем не менее, можете щелкнуть на элементе и таким образом его выбрать. 348 Глава 14 Свойство Где применяется Описание Value Все элементы управления Значение текущих установок элемента управления: текст в текстовом поле, какие выбраны флажки и переключатели, индекс выбранного раздела списка или число, указывающеедекущее положение полосы прокрутки или счетчика. Visible Все элементы управления Значение типа Boolean, указывающее, является ли элемент управления видимым. В табл. 14.6 перечислены события элементов управления, для которых вы можете написать собственные процедуры обработки событий. Каждый элемент управления, который вы добавите в свою форму, будет иметь доступ к этим событиям. В частности, для кнопок используется событие Click, а для того, чтобы проверить данные или обновить другие элементы управления, — AfterUpdate или Change. Таблица 14.6. Наиболее часто используемые события объектов управления Событие Синтаксис процедуры обработки Описание AddControl См. Приложение А Инициируется всякий раз, когда к форме (или элементам Frame, Page, MultiPage) добавляется какой-либо элемент управления. AfterUpdate Private Sub object_AfterUpdate() Инициируется после обновления значения элемента управления. BeforeUpdate Private Sub object_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean) Инициируется после того, как было изменено значение элемента управления, но перед тем, как был обновлен сам элемент управления. Change Private Sub object_Change() Инициируется всякий раз, когда изменяется значение элемента управления. Click Private Sub object_Click() Инициируется всякий раз, когда по элементу управления щелкают мышью. Используйте данное событие для того, чтобы выполнить действие при помощи кнопки. DblClick Private Sub ob j ect_DblClick(By V al Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда по элементу управления дважды щелкают мышью. Используйте данное событие для вывода дополнительных форм. Enter Private Sub object_Enter() Инициируется всякий раз, когда выделяется элемент управления. Exit Private Sub object_Exit(ByVal Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда с элемента управления снимается выделение. Элементы диалоговых окон 349 Событие Синтаксис процедуры обработки Описание Error Private Sub object_Error(Index As Long, ByVai Number As integer, ByVai Description As MSForms.ReturnS tring) Инициируется всякий раз, когда элемент управления обнаруживает ошибку и не может возвратить информацию об ошибке в вызывающую программу. KeyDown Private Sub ob ject_KeyD own(By V al KeyCode As MSForms.Returninteger, ByVai Shift As fmShiftState) Инициируется при нажатии пользователем какой-либо клавиши в тот момент, когда форма выполняется и имеет фокус. KeyPress Private Sub object_Key-Press(ByVal KeyANSI As MSForms.Returninteger) Инициируется, когда пользователь нажимает алфавитно-цифровую клавишу. KeyUp Private Sub object_KeyUp(By V al KeyCode As MSForms.Returnlnteger, ByVai Shift As fmShiftState) Инициируется, когда пользователь отпускает клавишу. Layout Private Sub object_Layout() Инициируется, когда изменяются размеры элемента Frame (или MultiPage). MouseDown, MouseUp См. Приложение A Инициируются при щелчке мышью. MouseDown: когда пользователь нажимает на клавишу мыши; MouseUp: когда пользователь отпускает клавишу мыши. MouseMove См. Приложение A Инициируется, когда пользователь перемещает мышь. SpinDown, SpinUp Private Sub object_SpinDown() Private Sub object_SpinUp() Событие SpinDown инициируется, когда пользователь щелкает стрелку «вниз» (или «влево») кнопки счетчика. Событие SpinUp инициируется, когда пользователь щелкает стрелку «вверх» (или «вправо») кнопки счетчика. ' Zoom Private Sub object_Zoom(index As Long, Percent As Integer) Инициируется при изменении свойства Zoom. В приложении А приведено описание параметров, используемых в табл. 14.6. 350 Глава 14 Использование Toolbox (панели элементов) Прежде чем мы рассмотрим примеры обработки событий, связанных с элементами управления, вам следует научиться помещать элементы управления на форму и задавать им необходимые свойства. Редактор VB в режиме разработки вместе с формой выводит на экран Toolbox (панель элементов) (если вывод этой панели не отключен при помощи меню View | Toolbox). На рис. 14.5 Toolbox показана в виде плавающего окна. Кнопки на панели Toolbox активизируют различные инструменты, которые позволяют помещать на форму элементы управления. Toolbox (подобно всем другим панелям инструментов) можно настраивать. Если вы или другой пользователь установили дополнительные элементы управления независимых производителей или произвели настройку панели, она может выглядеть иначе, чем та, что показана на рис. 14.5. На рис. 14.5 присутствуют только стандартные элементы управления, поставляемые вместе с VBA. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Рис. 14.5. Используйте Toolbox для размещения на форме элементов управления 1 - Select Objects (выбор объектов), 2 - Label (надпись), 3 - TextBox (поле), 4 - ComboBox (поле со списком), 5 - ListBox (список), 6 - CheckBox (флажок), 7 - OptionButton (переключатель), 8 - ToggleButton (выключатель), 9 - Frame (рамка), 10 - CommandButton (кнопка), 11 - Tabstrip (набор вкладок), 12 - MultiPage (набор страниц), 13 - ScrollBar (полоса прокрутки), 14 - SpinButton (счетчик), 15 - Image (рисунок) Чтобы воспользоваться панелью Toolbox для добавления элементов управления к вашей форме, выполните следующие действия: 1. Щелкните на Toolbox по кнопке, соответствующей элементу управления, который вы хотите добавить к форме. Указатель мыши изменит форму на перекрестие, когда будет находиться на форме. 2. Установите перекрестие в то место формы, в котором хотите поместить верхний левый угол нового элемента управления. 3. Нажмите и удерживайте левую кнопку мыши. 4. Перемещайте мышь вниз и вправо, пока элемент управления не примет нужный размер, после чего отпустите кнопку мыши. Редактор VB вставит в форму элемент управления, и указатель мыши вновь примет форму стрелки. Вы можете изменить размер самой формы. Щелкните по строке заголовка формы для ее выделения и затем, перемещая один из маркеров изменения размеров, увеличьте или уменьшите размер формы до желаемого. Маркеры изменения размеров (sizing handles) — это маленькие квадратики, которые появляются в углах и на серединах сторон графического объекта (наряду с толстой серой границей) при выделении объекта. Добавление к форме элементов управления Когда вы создаете новую форму, редактор VB предоставляет чистую (без элементов управления) форму (смотри рис. 14.1). Вы можете добавить к форме элементы управления с использованием различных инструментов панели Toolbox. Элементы диалоговых окон 351 Чтобы добавить к форме элемент управления, используйте панель Toolbox, как описано в предыдущем параграфе этой главы. В качестве примера добавления к форме конкретного элемента добавьте на новую форму кнопку, выполнив следующие действия: 1. Выберите команду Insert | UserForm (Вставка | UserForm). Редактор VB добавит новую форму, отображая ее в режиме разработки, и, кроме того, на экране появится Toolbox. 2. Щелкните на элементе CommandButton панели Toolbox. Кнопка перейдет в «утопленное» состояние, указывая выбранный вами элемент. 3. Поместите курсор мыши на форму. Курсор при этом изменит свою форму на перекрестие с прикрепленным к нему символом выбранного элемента. 4. Поместите перекрестие в ту точку формы, в которой должен быть верхний левый угол кнопки. 5. Переместите курсор мыши вниз и вправо, чтобы нарисовать элемент управления CommandButton. В процессе перемещения курсора мыши редактор VB отображает прямоугольный контур, показывающий размер кнопки. 6. Отпустите кнопку мыши, когда решите, что CommandButton имеет необходимый размер. Редактор VB создаст элемент управления CommandButton и поместит его на форму. На рис. 14.6 показано, как выглядит кнопка, сразу же после того, как была помещена на форму. Рис. 14.6 UserForml сразу же после добавления элемента CommandButton Добавив к форме кнопку, вы можете заметить, что верхний левый угол кнопки (также как и сама граница кнопки) автоматически выравнивается по шаблону сетки на форме. Это действие, называемое привязка к сетке (snap to grid), поможет вам выровнять размещенные на форме элементы управления и текст. Вы можете включать и отключать привязку к сетке, настраивать шаг сетки или скрывать ее, изменяя установки в диалоговом окне Option (Параметры) редактора VB. Выберите Tools | Options (Сервис | Параметры) и щелкните по вкладке General (общие), чтобы вывести Form Grid Settings (Параметры сетки в форме). Выберите или сбросьте необходимые опции. Все элементы управления формы должны иметь уникальные имена. Эти имена следует использовать при ссылках на элемент управления в своей программе. Всякий раз, когда вы добавляете к форме новый элемент управления, VBA присваивает ему имя по умолчанию, состоящее из имени типа элемента и номера. VBA обеспечивает уникальность имени включением в имя элемента управления числа. Число в имени больше, чем число любого другого подобного элемента управления. Если кнопка, которую вы добавили в начале этого раздела, Является первой кнопкой, она получит имя CommandButtonl. Следующая добавленная вами кнопка будет CommandButton2 и так далее. Если после этого вы добавите поле, оно получит имя TextBoxl. 352 Глава 14 Перед тем как продолжить работу с формами, давайте договоримся о несложных правилах, которые помогут вам с первых шагов создавать диалоговые окна, почти похожие на профессиональные. Если вы до сих пор не обращали внимания на то, что все окна «солидных» разработчиков имеют общие черты, то сейчас как раз то время, когда это нужно сделать. На рис. 14.7 приведена схема, которой можно придерживаться при разработке своих первых форм. Рис. 14.7 Схема типичного диалогового Windows-окна Наименование окна, как вы уже знаете, задается свойством Caption формы. Кнопка закрытия окна, если ничего специально не предпринимать, по умолчанию всегда будет в окне приложения. Если она вам не нужна, то лучше от нее избавиться. В «полезной» части окна помещаются функционально необходимые элементы управления, которые определяются назначением окна. Здесь могут быть, например, элементы для ввода некоторой информации или изменения настроек приложения. С кнопкой ОК обычно связывают событие, которое подводит некоторый итог. Обычно в профессиональных приложениях все, что вводится в диалоговом окне, не сразу вступает в действие, а только после того, как пользователь щелкнет кнопку ОК. Это дает возможность отказаться от недостаточно обдуманных действий. Разработчику таких окон не очень трудно скопировать данные из диалогового окна в несколько переменных прежде, чем присвоить их каким-либо свойствам элементов управления, а пользователю удобнее работать с окном, из которого всегда можно выйти без последствий. Из предыдущего абзаца, видимо, понятно назначение кнопки Отмена. Дополнительной ее функцией является и выход из процедуры обработки событий формы. Кнопка же ОК может разрешить пользователю продолжить путешествие «внутрь» приложения, которое открылось данным окном (иногда говорят «панелью» или «диалогом»). Кнопка Справка знакома всем «с детства». К сожалению, не так просто организовать помощь, подобную обычной Windows-справке, но можно сначала использовать эту кнопку для простых подсказок, которые создаются простым помещением на пустую форму элемента Label с текстом подсказки. В дальнейшем, изучив способы построения сложных систем подсказок, можно создавать почти профессиональные диалоговые окна. Этих нехитрых правил, конечно же, вам хватит при проектировании несложных форм. При создании «хороших» форм следует ознакомиться с рекомендациями фирмы Microsoft. Эти рекомендации имеют отношение к следующим аспектам: Размещение элементов управления на форме (в том числе и установка интервалов между элементами). Выравнивание меток (метки должны быть хорошими путеводителями формы). Элементы диалоговых окон 353 Использование стандартных шрифтов (часто пользователи собирают по всему свету интересные шрифты и забывают о том, что такие шрифты могут отсутствовать у других). Использование цвета. При размещении на форме нескольких элементов управления, которые можно условно разделить на отдельные группы, следует использовать элемент frame (рамка). При этом желательно пользоваться свойством, определяющим заголовок рамки. Для более легкого чтения полей, расположенных друг под другом, необходимо выравнивать их по левому краю. Старайтесь поддерживать стандартными высоту и ширину элементов управления, а также расстояния между ними. Интервалы между элементами измеряются в твипах (один пиксел равен 15 твипам). Microsoft рекомендует для высоты элемента управления 300 твипов, для ширины командной кнопки — 1200 твипов, для расстояния по вертикали между элементами — 60 твипов между связанными (по смыслу) и 90 твипов между несвязанными элементами. Для всех элементов управления используйте в качестве шрифта нормальный Sans Serif 8-пунктов. Конечно, следует учитывать и запросы потенциального пользователя вашего продукта, но при подготовке тестового варианта для обсуждения сначала необходимо придерживаться рекомендаций Microsoft. Самые обычные серые цвета, которые вы можете видеть во всех известных продуктах Windows, рекомендуются и для ваших приложений. Хотя в вашем распоряжении имеется большое количество цветов, все равно без особой нужды не следует изменять цвета по умолчанию. Если же вы можете предоставить пользователю работающего приложения самому изменять цвета формы и элементов управления на ней, это будет опимальным вариантом. Итак, если вы согласны с предлагаемыми правилами, создайте свою первую форму в соответствии со схемой рис. 14.7. Рис. 14.8 Форма с самыми необходимыми кнопками В следующей таблице приведены значения свойств элементов управления, которые были изменены. Для своих приложений в качестве документации вы тоже можете создавать такие таблицы для облегчения сопровождения своего программного продукта. Тип элемента Свойство, которое изменено Значение Примечание UserForm Name Frmfirst Имя формы, на которое можно ссылаться в коде. Caption Тестирование кнопок Заголовок окна (формы) в верхней части. !2 Программирование на VBA 2002 354 Глава 14 Тип элемента Свойство, которое изменено Значение Примечание CommandButton Name CmdOK Имя кнопки, на которое можно ссылаться в коде. Caption OK Текст на кнопке. Default True При нажатии на клавишу Enter инициируется событие Click кнопки. CommandButton Name CmdCancel Имя кнопки, на которое можно ссылаться в коде. Caption Отмена Текст на кнопке. Cancel True При нажатии на клавишу Esc инициируется событие Click кнопки. CommandButton Name CmdHelp Имя кнопки, на которое можно ссылаться в коде. Caption Справка Текст на кнопке. В VBA (как и в Microsoft Visual Basic) кнопки (элементы CommandButton) имеют специальное свойство Cancel, которое определяет кнопку Отмена (независимо от того, называется ли эта кнопка Отмена). Только одна кнопка формы может иметь свойство Cancel, установленное равным True. Если задать это свойство для одной из кнопок, аналогичное свойство для всех остальных кнопок формы будет установлено равным False. Если форма содержит кнопку с установленным свойством Cancel, то нажатие клавиши Esc приводит к тому же результату, что и щелчок по кнопке. Если вы запустите форму на выполнение (командой Run | Run Sub/UserForm), то ни щелчок на кнопке, ни нажатие клавиши Esc не приведут ни к какому результату, так как с кнопкой не связано никакого события. Но диалоговое окно появится на экране в режиме выполнения и будет создавать впечатление чего-то работающего (рис. 14.9). Рис. 14.9 Такое окно тоже «имеет право» называться «диалоговым» Если вы будете щелкать кнопки этого окна, то убедитесь в том, что окно совершенно «нечувствительно» к вашим манипуляциям. Единственная кнопка, которая будет реагировать на ваши действия, находится вверху справа (с изображением перекрестия). Эта кнопка закроет окно. Чтобы кнопки, помещенные вами на диалоговой панели, «ожили», необходимо для каждой из них написать процедуры обработки событий Click (щелчок на Элементы диалоговых окон 355 кнопке). Начнем с кнопки Отмена, чтобы всегда иметь возможность выйти из приложения. Свяжем с щелчком на кнопке Отмена программу, которая выгрузит форму, что приведет к окончанию работы с диалоговым окном. Для создания процедуры обработки события дважды щелкните на кнопке Отмена в режиме разработки и в появившемся шаблоне процедуры обработки события введите оператор выгрузки формы, как это представлено в листинге 14.4. Листинг 14.4. Процедура обработки события - щелчок на кнопке Отмена 1 Private Sub CmdCancel _Click() 2 Unload Me ' Выгружаем форму, заканчивая приложение 3 End Sub Снова запустите форму на выполнение. Вы увидите то же диалоговое окно, что и на рис. 14.6, но теперь это окно — «настоящее» диалоговое, потому что при щелчке на кнопке Отмена выполняется программа обработки события и окно закрывается. Более того, при нажатии на клавишу Esc вы получаете точно тот же результат! Понятно, что процедура обработки события Click (именно это событие и связано с кнопкой) может выполнить и более серьезную работу, чем простая выгрузка формы. Чтобы это было действительно понятно, добавим к процедуре вывод сообщения о том, что возможен выход из диалога (см. листинг 14.5). Листинг 14.5. Более «продвинутая» процедура обработки события - щелчок на кнопке Отмена 1 Private Sub CmdCancel _Click() 2 ' объявление переменных 3 Dim Msg, Title, Response As String 4 5 ' выдаваемое в окне MsgBox сообщение -x 6 Msg = "Хотите закончить работу"’" 7 8 1 состав кнопок и тип значка 9 Style = vbYesNo + vbCritical + vbDefaultButton2 10 11 ' заголовок окна 12 Title = "Выход из программы" 13 14 ' вызов функции MsgBox с возвращаемым значением - 15 Response = MsgBox(Msg, Style, Title) 16 ' анализ возвращаемого значения 17 If Response = vbYes Then 18 Unload Me 'выгрузка формы 19 End If 20 21 End Sub Если вы запустите форму с такой процедурой обработки события Click и щелкните на кнопке Отмена или нажмете клавишу Esc, то на экран будет выдано сообщение, подобное приведенному на рис. 14.10. Эта процедура стала более дружественной, поскольку не сразу заканчивает работу окна диалога. Случайный щелчок на кнопке Отмена или нажатие на клавишу Esc не приведут к окончанию работы с диалогом. Теперь, когда у нас имеется возможность покинуть диалоговое окно, можно написать простые процедуры обработки событий для кнопок ОК и Справка. Кнопка ОК в начале разработки приложения может быть связана с процедурой, выдающей сообщение о том, что приложение пока не готово к эксплуатации. С кнопкой Справка 12* 356 Глава 14 Рис. 14.10 Процедура обработки сообщения от кнопки Отмена стала более дружественной для ваших первых приложений можно поступить по-разному: например, одним из решений может быть выдача длинного сообщения посредством функции MsgBox, а можно создать новое диалоговое окно с элементом Label, свойством Caption которого будет также длинное сообщение о полезности приложения. Далее будет рассмотрено создание и вызов дополнительного диалогового окна приложения. Очень полезной может оказаться процедура обработки события Change — при любом изменении свойств элементов управления (в конечном итоге, все, что происходит в диалоговом окне — это изменение тех или иных свойств) выполнять некоторые проверки на допустимость изменений и сообщать пользователю о возможных проблемах. Можно также использовать событие Change для подсказки пользователю о происходящих изменениях со свойствами элементов управления. В качестве примера создайте форму UserForml так, чтобы она была похожа на представленную на рис. 14.11. Чтобы соответствующее форме диалоговое окно позволило продолжить работу с приложением, в этом окне необходимо в одном из текстовых полей ввести либо фамилию, либо имя пользователя. При изменении со держимого любого поля (свойство Text) инициируется процедура обработки события Change, в которой свойству Enable кнопки OK_button (с заголовком ОК) присваивается значение True. Кнопка OK_button предназначена для изменения свойства Caption формы UserForm2 и вывода этой формы на экран. Кнопка с заголовком Отмена всегда доступна и предназначена для выхода из программы. Свойство Cancel этой кнопки имеет значение True. Рис. 14.11 Форма для тестирования события Change для TextBox Тестирование события Change Данные о пользователе Фамилия Имя i Для создания такой формы выполните следующее: 1. Создайте новую форму с именем по умолчанию UserForml. В Properties Window измените свойство Caption этого элемента на Тестирование события Change. 2. Поместите на форму UserForml элемент Frame. По умолчанию его имя будет Framel. Измените свойство Caption этого элемента на Данные о пользователе. (Размеры элемента не важны.) Элементы диалоговых окон 357 3. Поместите на форму в область Framel элемент TextBox (с именем по умолчанию TextBoxl) и элемент Label с заголовком (свойство Caption) Фамилия. Имя метки для данного случая не имеет значения. 4. Поместите на форму в область Framel элемент TextBox (с именем по умолчанию TextBox2) и элемент Label с заголовком Имя. 5. Поместите на форму (см. рис. 14.11) элемент CommandButton и измените его свойство Name на Cancel_button, а свойство Caption на Отмена. Установите свойство Cancel в True, чтобы при нажатии на клавишу Esc программа выполняла ту же процедуру, что и при щелчке на кнопку Отмена. 6. Поместите на форму элемент CommandButton и измените его свойство Name на OK_button, а свойство Caption на ОК. Измените свойство Enabled этой кнопки на False. Этим вы сделаете кнопку ОК недоступной для пользователя после выдачи диалогового окна на экран в режиме выполнения. Чтобы кнопка стала доступной и приложение могло выполнить какую-либо работу с использованием кнопки ОК, пользователь должен будет изменить содержимое одного из текстовых окон. 7. Откройте модуль класса формы UserForml и запишите в него код, представленный в листинге 14.6. 8. Создайте форму UserForm2 (без элементов управления) и запишите в модуль класса этой формы код из листинга 14.2. Тип элемента Свойство, которое изменено Значение Примечание UserForm Name UserForml Имя главной формы, на которое можно ссылаться в коде. Caption Тестирование события Change Заголовок окна (формы) в верхней части. Frame Name Framel Имя, на которое можно ссылаться в коде. Caption Данные о пользователе TextBox Name TextBoxl Имя, на которое можно ссылаться в коде. Label Name Label 1 Caption Фамилия Заголовок для текстового окна TextBoxl. TextBox Name TextBox2 Имя, на которое можно ссылаться в коде. Label Name LabeI2 Caption Имя Заголовок для текстового окна TextBox2. CommandButton Name Cancel_button Имя кнопки, на которое можно ссылаться в коде. Caption Отмена Текст на кнопке: кнопка для окончания работы приложения. CommandButton Name OK_button 358 Глава 14 Тип элемента Свойство, которое изменено Значение Примечание Caption OK Текст на кнопке: кнопка для продолжения работы приложения. Enabled False Кнопка недоступна для пользователя сразу после выдачи диалогового окна на экран. UserForm Name UserForm2 Имя формы, загружаемой из главной при щелчке на кнопке ОК. Выполните команду Run | Run Sub/UserForm. Если вы не будете редактировать (изменять) содержимое текстовых окон, вам будет доступна только кнопка Выход. Как только вы измените содержимое какого-либо текстового окна (Фамилия или Имя), инициируется событие Change и свойству Enabled кнопки ОК будет присвоено значения True (строка 17 Листинга 14.6). Так как с кнопкой ОК связана процедура обработки события Click, которая загружает форму UserForm2, пользователь получает возможность дальнейшей работы. При этом свойству Caption формы присваивается сумма содержимого полей TextBoxl и TextBox2. Листинг 14.6. Обработка события Change 1 ' Обработка события Click кнопки Выход 2 Private Sub Cancel_button_Click() 3 MsgBox ("Заканчиваем программу!") 4 Unload Me 5 End Sub 6 7 ' Обработка события Click кнопки OK 8 Private Sub OK. button.. Click () 9 10 ' Изменить заголовок диалогового < окна I JserForm2 11 UserForm2.Caption = TextBoxl.Text + TextBox2.Text 12 13 14 UserForm2.Show ' загрузка End Sub окна UserForm2 15 16 ' Обработка события Change текстового Private Sub TextBoxl Change () окна с меткой Фамилия 17 18 19 Next_button.Enabled = True End Sub 20 21 22 ' Обработка события Change текстового Private Sub TextBox2_Change() Next button.Enabled = True окна с меткой Имя 23 End Sub В следующей главе будут использованы и другие события, для которых вы можете сами написать код обработки. Редактирование элементов управления на форме Поместив на форму элемент управления, вы имеете возможность изменять его размеры, двигать, копировать, удалять, форматировать (изменять размер, стиль, гарнитуру шрифта) или изменять его свойства (такие как имя, заголовок и так далее). Элементы диалоговых окон 359 Чтобы открыть существующую форму для редактирования, щелкните по ней два раза в Project Explorer (Окне проекта). Кроме того, вы можете выбрать в Project Explorer форму, которую хотите отредактировать, и затем щелкнуть кнопкой Show Object (Просмотр объектов). Выбор элементов управления Чтобы отредактировать элемент управления, вы должны сначала выделить его щелчком мыши. Выделенный элемент имеет серую границу с маркерами изменения размеров, как показано для кнопки на рис. 14.5. Чтобы выделить несколько элементов управления сразу, удерживайте нажатой клавишу Shift, когда щелкаете по элементам управления, которые хотите выделить. Выделять сразу несколько элементов управления имеет смысл, если вы хотите выполнить форматирование, которое будет распространяться на все элементы формы. Это может быть, например, изменение размера шрифта, стиля или гарнитуры. Выбор нескольких элементов управления может также оказаться полезным, если вы хотите переместить эти элементы одновременно. Вы можете временно сгруппировать несколько элементов управления, воспользовавшись командой Format | Group (Формат | Группировать). Если элементы управления сгруппированы, они ведут себя как один объект, когда вы их выбираете, перемещаете, копируете или редактируете. Элементы управления остаются сгруппированными до тех пор, пока вы не примените к выделенной группе команду Format | Ungroup (Формат | Разделить). Перемещение элементов управления Чтобы переместить элемент управления на новое место в форме, сначала выделите его. После этого поместите указатель мыши поверх любой части серой границы, окружающей выбранный элемент управления, за исключением маркеров изменения размеров. Теперь щелкните и перетащите этот элемент на новое место. Изменение размеров элементов управления Чтобы изменить размер элемента управления, сначала выделите этот элемент. После этого поместите курсор мыши поверх любого из маркеров изменения размеров. Когда курсор находится на маркере изменения размера, он меняет свою форму на двойную стрелку, показывающую направление, в котором вы можете изменять размер выбранного элемента управления. Теперь нажмите (не отпуская) кнопку мыши и передвиньте маркер изменения размера на нужное место. В процессе перемещения редактор VB будет отображать контур, показывающий новые границы элемента управления. Когда элемент управления станет требуемого размера, отпустите кнопку мыши, редактор VB перерисует элемент управления в соответствии с вновь заданным размером. Копирование, вставка и удаление элементов управления Один из самых простых способов создать несколько одинаковых элементов управления, таких как несколько флажков или кнопок, состоит в том, чтобы сначала создать один элемент управления, скопировать его, после чего поместить скопированный элемент в форму столько раз, сколько необходимо. Чтобы скопировать элемент управления, просто выберите его и затем воспользуйтесь командой Edit | Сору (Правка | Копировать) или нажмите Ctrl+C. 360 Глава 14 После того как элемент управления скопирован, вы можете вставить его в ту же или другую форму, используя команду Edit | Paste (Правка | Вставить) или нажав Ctrl+V. После выполнения операции вставки переместите элемент управления в предназначенное для него место. Чтобы удалить элемент(ы) управления, выделите его (их), после чего нажмите клавишу Delete. Редактор VB удалит выделенный(-ные) элемент(-ы) управления. Редактирование или форматирование заголовков элементов управления Для редактирования текста заголовков таких элементов управления, как кнопка, переключатель или флажок, просто щелкните по этому тексту. Редактор VB поместит в текст заголовка курсор вставки. Теперь можно редактировать текст, используя любые стандартные команды редактирования текста Windows, с которыми вы уже знакомы. Однако для того, чтобы изменить гарнитуру, стиль или размер шрифта, необходимо вывести для соответствующего элемента управления Properties Window (окно свойств) и изменить свойство Font. Чтобы отредактировать текст заголовка формы, отредактируйте свойство формы Caption в Properties Window. А для форматирования текста заголовка формы воспользуйтесь свойством формы Font. Некоторые элементы управления, такие как поля (TextBox), списки (ListBox) и поля со списком (ComboBox) не имеют встроенной надписи (или заголовка). Чтобы пометить такие элементы на форме, используйте элемент Label. Управление последовательностью перехода В активном состоянии ваша форма будет вести себя подобно другим диалоговым окнам Windows. Пользователь вашего диалогового окна может переходить от одного элемента управления к другому вперед и назад, используя соответственно клавиши Tab или Shif+Tab. Порядок, в котором будут активизироваться элементы управления в ответ на нажатие пользователем клавиш Tab или Shif+Tab, называется последовательностью перехода (tab order) элементов управления. Обычно последовательность перехода для элементов управления выбирают так, чтобы она соответствовала (приблизительно) перемещению слева направо и сверху вниз. Вообще говоря, вы должны постараться так расположить элементы управления, чтобы последовательность перехода обеспечивала логическое перемещение от одного элемента управления диалогового окна к другому. Редактор VB по умолчанию устанавливает для элементов управления последовательность перехода, определяемую порядком, в котором они были добавлены на форму. Очень часто, после того, как вы разместили на форме все элементы управления и несколько раз их передвинули, чтобы добиться приемлемого вида формы, установленная по умолчанию последовательность перехода уже больше не обеспечивает логической последовательности перемещения по элементам управления диалогового окна. Для изменения последовательности перехода, выполните следующие действия: 1. Выберите команду View | Tab Order (Вид | Последовательность перехода); редактор VB отображает диалоговое окно Tab Order (Последовательность перехода), показанное на рис. 14.12. Список Tab Order выводит все элементы управления формы в существующей на данный момент последовательности. 2. В списке Tab Order выберите элементы, положение которых хотите изменить. (На рис. 14.12 выбран элемент управления с именем TextBoxl.) 3. Используя кнопки Move Up (вверх) и Move Down (вниз) измените положение выбранного элемента управления в последовательности перехода. Щелчок по Элементы диалоговых окон 361 Рис. 14.12 Использование диалогового окна Tab Order для изменения последовательности перехода к элементам управления формы t кнопке Move Up переместит элемент управления вверх по списку (то есть он будет активизироваться раньше), а щелчок по кнопке Move Down переместит этот элемент вниз по списку (то есть он будет активизироваться позже). 4. Повторите пункты 2 и 3 для каждого элемента управления, пока не получите удовлетворяющую вас последовательность перехода для элементов управления формы. 5. Выберите в диалоговом окне Tab Order кнопку ОК, чтобы подтвердить сделанные вами изменения, после чего закройте окно. Хотя элементы Label тоже появляются в диалоговом окне Tab Order и вы можете поменять их положение в списке, в VBA нельзя выбрать элемент управления Label. Этот элемент предназначен исключительно для вывода текста. Задание свойств формы и элементов управления в режиме разработки Каждая форма и каждый элемент управления формы имеют собственный набор свойств точно так же, как и другие объекты VBA или host-приложения. Некоторые свойства формы и элемента управления проще и практичнее задать в режиме разработки, а не в коде VBA. Установленные вами свойства формы или элемента управления становятся для них новыми свойствами по умолчанию. Например, хотя вы можете задать шрифт, цвет фона и цвет текста элемента управления с помощью VBA-кода, обычно нет необходимости изменять эти свойства в процессе выполнения кода. Вместо этого, гораздо проще установить данные свойства в процессе разработки. Вы также можете задать для формы значения по умолчанию, задавая свойство Value элемента управления. Например, чтобы создать на форме флажок, который установлен по умолчанию, вы должны в режиме разработки, установить свойство Value для этого флажка равным True. Каждый раз, когда в процессе выполнения программы форма будет загружаться в память, флажок будет уже установлен. Аналогично в процессе разработки, можно заполнить списки элементов управления, установив свойство RowSource списка элемента управления. В Excel вы можете с помощью свойства RowSource связать список с диапазоном ячеек листа и связать поле с ячейкой листа, установив свойство ControlSource. Вы также можете задать значение по умолчанию для поля, введя текст непосредственно в элемент управления TextBox на форме. После этого каждый раз при выводе формы поле будет содержать введенный вами текст. В режиме разработки свойства формы или элемента управления устанавливаются в Properties Window, где перечислены все свойства объекта, которые вы можете установить в этом режиме. Конкретные свойства, появляющиеся в этом окне, зависят от выбранного вами элемента управления. На рис. 14.13 показано Properties 362 Глава 14 Window для кнопки с именем (свойством Name) CmdOK и заголовком (Caption) Вычислить для некоторой формы. Properties Window имеет две страницы (вкладки). Первая — показана на рис. 14.13 и содержит список свойств объекта в алфавитном порядке. Вторая страница, показанная на рис. 14.14, содержит список свойств, разделенных на категории. Заметьте, что различные категории выделены в Properties Window жирным шрифтом: Appearance (Вид), Behavior (Поведение), Font (Шрифт) и так далее. Вы можете свернуть или развернуть список свойств конкретной категории, щелкнув по квадратику слева от заголовка каждой из категорий. Рис. 14.13 Properties Window для кнопки, показывающее список свойств в алфавитном порядке tef Properties - CmdOK CmdOK CommandButton jJ Alphabetic Categorized t I (Na me) CmdOK a ^Accelerator |AutoSize False If BadcCoiw О анвоооооога iBackStyle 1 - fmBackStyleOpaque Cancel False Caption Вычислить ControlTipText Default False Enabled True Font Tahoma ForeColor 8HB00000128 Height 18 HelpContextlD 0 Left 180 Locked False Mouseicon (None) iMousePomter 0 fmMousePointerDefau Picture (None) jPicturePosition 7 - fmPicturePositionAbov v la Properties - CmdOK Г„ I Рис. 14.14 Properties Window для кнопки, показывающее список свойств по категориям |CmdOK CommandButton Alphabetic 5 Categorized S Appearance (Name) CmdOK Bad-Cotor (□ 8H8000000F& * BackStyle Caption ControlTipText ForeColor 1 - fmBackStyleOpaqu Вычислить 84800000128 Visible True S Behavior AutoSize False Cancel False Default False Enabled True Locked Falsfi TakeFocusOnClick True Wordwrap S Font False Font Tahoma Misc Accelerator Элементы диалоговых окон 363 Чтобы задать свойство формы или элемента управления, щелкните в поле, соответствующем свойству, которое хотите изменить. Для большинства свойств появится раскрывающийся список. Щелкните по кнопке списка и выберите из списка нужное значение свойства. Другие свойства (такие как Name и Caption) дают возможность ввести любой необходимый текст. Некоторые свойства при их выборе выводят кнопку с многоточием (...). Щелчок по такой кнопке открывает дополнительные диалоговые окна, помогающие задать это свойство. Чтобы изменить свойства формы или элемента управления, выполните следующие действия: 1. Выберите элемент управления, свойства которого хотите изменить. Чтобы выделить форму, щелкните где-нибудь на поверхности формы, не занятой элементами управления. 2. Выберите команду View | Properties Window (Вид | Окно свойств) для отображения Properties Window. (Вы можете сделать это и щелчком на кнопке Properties Window на панели инструментов редактора VB или, нажав F4.) 3. Установите необходимое свойство для выбранного элемента управления. 4. Щелкните по кнопке Close (закрыть) в верхнем левом углу окна Properties Window, чтобы его закрыть. Итак, вы познакомились с основными положениями создания и управления диалоговыми окнами и их элементами. Более полную информацию о каждом элементе управления можно получить из справочной системы VBA. Пример разработки приложения с диалоговой формой У нас имеется файл некоторой базы данных в DBase-формате (dbf-файл). Этот файл содержит данные о кодах товаров, наименований и цен (оптовых, розничных, закупочных). Система, использующая базу данных с этим файлом, работает под DOS (таких систем пока еще очень много, и нет особых причин, по которым они должны были бы прекратить свое существование). Как известно, под DOS практически нет графических редакторов, с помощью которых можно было бы красиво подготовить прейскурант (или прайс-лист). Поэтому предлагается загрузить dbf-файл в Excel и напечатать прейскурант с минимальным участием пользователя. Если кому-то исходные посылки кажутся слишком искусственными, не обращайте на это внимания, сосредоточьтесь на самом процессе. Интерфейс Сначала следует продумать действия пользователя и будущего макроса от начала работы до получения результата. Что должен уметь пользователь? Пользователь должен уметь загружать Excel с рабочей книгой Прейскурант (это достаточно просто, если пользователь способен в Windows найти файл ПРЕЙСКУРАНТ.XLS и щелкнуть на нем мышью). Далее действия пользователя зависят от того, какой интерфейс для работы с макросом мы ему предложим. Чтобы максимально облегчить работу пользователя, будем при загрузке книги выдавать на экран диалоговое окно для работы с прейскурантом. Поместим также в меню Tools опцию Прейскурант, чтобы после того, как пользователь по тем или иным причинам уберет это диалоговое окно, его можно было бы снова выводить на экран. Тогда пользователь должен еще уметь работать с меню в Excel и с простым диалоговым окном. 364 Глава 14 Что поместить в диалоговое окно? В диалоговом окне будем помещать все необходимые для получения прейскуранта элементы управления: элементы настройки распечатываемых страниц; элементы выбора различных видов товара; кнопки запуска и выхода. * Данные для макроса Для работы макроса при построении прейскуранта необходимы числовые данные, которые будут использоваться по умолчанию и которые пользователь может изменять для своих нужд. Это могут быть такие параметры, как количество распечатываемых на листе строк (в зависимости от шрифта и параметров принтера), признак печати в одну/две колонки, признак вывода того или иного вида цен и т.д. Эти параметры необходимо где-то хранить, поэтому нам потребуется в Excel отдельный рабочий лист, который не очень часто будет изменяться и для макроса станет его источником данных. I Разработка приложения Создайте в Excel новую рабочую книгу. Сохраните эту книгу под именем Прейскурант в диалоговом окне SaveAs. Для работы нам нужны два рабочих листа. Если нужно, вставьте новый рабочий лист, выбирая Insert | Worksheet. (На самом деле, вам, скорее всего, придется избавиться от лишних листов.) Переименуйте рабочие листы: первый назовите Прейскурант, второй (здесь будет база данных макроса) — Настройки. ( Разработка диалогового окна Войдите в Visual Basic Editor и добавьте к проекту с помощью кнопки Insert UserForm новую форму и по своему вкусу (или по требованию потенциального пользователя) расположите на новой форме необходимые элементы управления, что на данном этапе чтения этой книги сделать не трудно. На рис. 14.15 представлен один из возможных вариантов такого окна в режиме разработки, а в следующей таблице приведены расположенные на форме элементы управления с измененными свойствами. Не указаны только размеры и шрифты. Не указаны также элементы управления типа Label, поскольку они не используются в коде модуля формы. Тип элемента Наименование свойства Значение свойства Frame Name Framel Caption Настройки прейскуранта TextBox Name НачальнаяСтрока Enable False TextBox Name ДлннаСтраницы Enable False SpinButton Name 8р1п_НачСтр SpinButton Name S рш_Д линаСтр Frame Name Frame2 Caption Колонки Элементы диалоговых окон 365 Тип элемента Наименование свойства Значение свойства OptionButton Name Кол_Одна Caption Одна OptionButton Name Кол_Две Caption Две Frame Name Frame3 Caption Цена OptionButton Name Цена_Опт Caption Оптовая OptionButton Name Цена_Розн Caption Розничная ComboBox Name Группа CommandButton Name Кн_Обновить Caption Обновить CommandButton Name Кн_Выход Caption Выход Рис. 14.15 Расположенные на форме элементы управления В листинге 14.15 приведен код, который обрабатывает события, связанные со всеми элементами управления, кроме кнопки Обновить. Некоторые из элементов этой формы только считывают данные листа Настройки (который представлен на рис. 14.16), а некоторые также изменяют эти данные. Листинг 14.7. Первичный код модуля формы Прейскурант 1 2 3 4 5 6 7 1 Public НачСтрокаЗнач As Integer 2 Public ДлинаСтраницыЗнач As Integer 3 Public dir_file As String ' путь файла с данными о товарах 4 Public ЧислоКолонок As Integer 5 Public ТипЦены As Integer ' оптовая/розничная 6 Public CustSheet As String 1 наименование листа настроек 7 Public ГруппаТовара As String 366 Глава 14 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 Public ИндексТекущейГруппы As Integer Private Sub UserForm_Initialize() , 1 процедура инициализации формы Dim КолГрупп As Integer 1 количество групп товаров CustSheet = "Настройки" 1 имя листа с настройками ' считывание параметров настройки из листа Настройки: НачСтрокаЗнач = _ Activeworkbook.Worksheets(CustSheet).Cells(2, 3) ДлинаСтраницыЗнач = _ Activeworkbook.Worksheets(CustSheet) .Cells (2, 4) ЧислоКолонок = _ Activeworkbook.Worksheets(CustSheet) .Cells(1, 4) ТипЦены = _ Activeworkbook.Worksheets(CustSheet) .Cells (3, 4) ' подготовка окна списка Группа КолГрупп = _ ActiveWorkbook.Worksheets(CustSheet).Cells(3, 3) For i = 1 To КолГрупп Группа.Additem _ (ActiveWorkbook.Worksheets(CustSheet) .Cells (i, 1) .Value) Next ' текущая группа: ИндексТекущейГруппы = _ ActiveWorkbook.Worksheets(CustSheet) .Cells (1, 3) ГруппаТовара = _ ActiveWorkbook.Worksheets(CustSheet) .Cells ( _ ИндексТекущейГруппы, 1) ' настройка элементов управления диалогового окна ' согласно листа Настройки НачальнаяСтрока.Value = НачСтрокаЗнач ДлинаСтраницы.Value = ДлинаСтраницыЗнач If ЧислоКолонок = 1 Then i Кол_Одна.Value = True Кол_Две.Value = False Else Кол_Одна.Value = False Кол_Две.Value = True End If If ТипЦены = 1 Then Цена_Опт.Value = True 'цена оптовая ' Цена_Розн.Value = False Else Цена_Опт.Value = False 'цена розничная Цена_Розн.Value = True End I f Группа.Value = ГруппаТовара Элементы диалоговых окон 367 71 1 72 End Sub 73 74 75 Private Sub Кн_Выход_С11ск() 76 ' выход из программы с подтверждением 77 78 Dim Msg, Title,* Response As String 79 Dim Style 80 81 Msg = "Хотите закончить работу?" 82 Style = vbYesNo + vbCritical + vbDefaultButton2 83 Title = "Выход из программы" 84 Responce = MsgBox(Msg, Style, Title) 85 86 If Responce = vbYes Then 87 Unload Me 88 End If 89 End Sub 90 91 Private Sub Кн_Обновить_С11ск() 92 ' событие - выбор кнопки Обновить 93 94 MsgBox ("Эта кнопка не работает") 95 96 End Sub 97 98 99 Private Sub Кол_Одна_С11ск() 100 ' событие - выбор переключателя Одна (колонка) 101 102 ЧислоКолонок = 1 , 103 104 ' запись в лист Настройка 105 ActiveWorkbook.Worksheets(CustSheet) .Cells (1, 4) = _ 106 ЧислоКолонок 107 End Sub 108 109 110 Private Sub Кол_две_СИск () 111 1 событие - выбор переключателя Две (колонки) 112 113 ЧислоКолонок = 2 114 115 ' запись в лист Настройка 116 ActiveWorkbook.Worksheets(CustSheet).Cells(1, 4) = ЧислоКолонок 117 End Sub 118 119 120 Private Sub Цена_Опт_С11ск() 121 ' событие - выбор переключателя Оптовая (цена) 122 123 ТипЦены = 1 124 125 ' запись в лист Настройка 126 ActiveWorkbook.Worksheets(CustSheet) .Cells (3, 4) = _ 127 ТипЦены 128 End Sub 129 130 131 Private Sub Цена_Розн_С11ск() 132 1 событие - выбор переключателя Розничная (цена) 133 368 Глава 14 134 ТипЦены = 2 135 136 ' запись в лист Настройка 137 ActiveWorkbook.Worksheets(CustSheet) .Cells (3, 4) = _ 138 ТипЦены 139 End Sub 140 141 • 142 Private Sub Framel_Click() 143 ' событие - неправильно выбран элемент управления 144 145 MsgBox ("У Вас сегодня не очень твердая рука1") 146 147 End Sub 148 149 150 Private Sub Зр1п_ДлинаСтр_Зр1пОс’л’п () 151 ' событие - выбор стрелки "Вниз" элемента управления SpinButton 152 153 ДлинаСтраницыЗнач = ДлинаСтраницыЗнач - 1 154 ДлинаСтраницы.Value = ДлинаСтраницыЗнач 155 156 ' запись в лист Настройки 157 ActiveWorkbook.Worksheets(CustSheet).Cells(2, 4) = _ 158 ДлинаСтраницыЗнач 159 End Sub 160 161 162 Private Sub Зр1п_ДлинаСтр_ЗргпОр() 163 ' событие - выбор стрелки "Вверх" элемента управления SpinButton 164 165 ДлинаСтраницыЗнач = ДлинаСтраницыЗнач + 1 166 ДлинаСтраницы.Value = ДлинаСтраницыЗнач 167 168 ' запись в лист Настройки 169 ActiveWorkbook.Worksheets(CustSheet) .Cells (2, 4) = _ 170 ДлинаСтраницыЗнач 171 End Sub 172 173 174 Private Sub Spin__Ha4CTp_SpinDown() 175 ' событие - выбор стрелки "Вниз” элемента управления SpinButton 176 177 НачСтрокаЗнач = НачСтрокаЗнач - 1 178 НачальнаяСтрока.Value = НачСтрокаЗнач 179 180 ' запись в лист Настройки 181 ActiveWorkbook.Worksheets(CustSheet).Cells(2, 3) = _ 182 НачСтрокаЗнач 183 End Sub 184 185 186 Private Sub Spin_Ha4CTp_SpinUp() 187 ' событие - выбор стрелки "Вверх" элемента управления SpinButton 188 189 НачСтрокаЗнач = НачСтрокаЗнач + 1 190 НачальнаяСтрока.Value = НачСтрокаЗнач 191 192 ' запись в лист Настройки 193 ActiveWorkbook.Worksheets(CustSheet).Cells(2, 3) = _ 194 НачСтрокаЗнач 195 End Sub 196 Элементы диалоговых окон 369 197 198 Private Sub rpynna_Change() 199 ' работа окна комбинированного списка 200 201 ГруппаТовара = Группа.Value 202 ИндексТекущейГруппы = Группа.Listindex 203 204 ' запись в лист» Настройки 205 ActiveWorkbook.Worksheets (CustSheet).Cells (1, 3) = 206 ИндексТекущейГруппы + 1 207 208 End Sub Рис. 14.16 Код, управляющий работой диалогового окна (рис 14 15), использует и изменяет данные листа Настройки Если вы введете в модуль формы представленный код и запустите форму на выполнение (Run | Run Macro), то увидите, что диалоговое окно выполняет все операции, предоставляемые элементами управления, кроме операции кнопки Обновить. Рассмотрим код подробно. В строках 10-72 записан код процедуры, которая выполняется при первой загрузке формы в память. Здесь из листа Прейскурант активной рабочей книги считываются данные из определенных ячеек (строки 20-44) и присваиваются свойству Value некоторых элементов управления (строки 51-68). Обратите внимание на подготовку данных для окна комбинированного списка Группа товара (строки 32-45). Здесь из ячейки СЗ листа Настройки считывается количество групп товаров (перечисленных в колонке А того же листа). Далее (строки 36-39) в цикле в коллекцию Группа комбинированного списка заносятся наименования групп из листа Настройки. В строках 42-43 из листа Настройки считывается индекс текущей группы, в строках 44-45 определяется текущая группа товара. В результате работы событийной процедуры UserForm_Initialize диалоговое окно появляется перед вами не с пустыми текстовыми окнами и переключателями. В строках 75-89 находится код событийной процедуры Кн_Выход_СИск, которая, как нетрудно догадаться, выполняется при нажатии на кнопку Выход. Процедура выполнена в «лучших интерфейсных традициях» и перед окончанием сеанса требует подтверждения об окончании работы с приложением. Далее по тексту (строки 91-96) следует «заглушка» процедуры Кн_Обно-вить_СИск, которая является единственной процедурой, выполняющей полезную работу, но пока не разработана. Прием использования программных «заглушек» пришел к нам из нисходящего проектирования при использовании идеологии структурного программирования. Идея нисходящего проектирования заключается в том, что сначала следует разработать код общей управляющей части про 370 Глава 14 граммного комплекса, без учета работы отдельных его элементов. Для отладки общего кода отдельные его элементы (подпрограммы) заменяются «заглушками», которые, например, только принимают данные и каким-либо образом сообщают о том, что им передано управление и данные. Когда верхний уровень программного комплекса отлажен, приступают разрабатывать код нижнего уровня, заменяя «заглушки» (которые, быть может, также вызывают «заглушки» более нижнего уровня) полезным кодом. При этом «заглушки», имеющие отлаженный с верхним уровнем комплекса интерфейс, могут кодировать разные группы программистов. Подобным образом вы можете разрабатывать код событийных процедур — сначала детально отладить работу с диалоговым окном, а затем — полезную часть кода. В нашем случае, конечно, единственная полезная кнопка — это Обновить. Она обновляет лист с прейскурантом. Все остальные элементы управления только настраивают параметры прейскуранта, взаимодействуя с листом настроек. Процедура Кол_Одна_СИск (строки 99-107) обрабатывает событие выбора переключателя Одна группы Колонки. При этом переменной ЧислоКолонок присваивается значение 1, которое также заносится в ячейку D1 листа Прейскурант. Процедура Кол_две_СПск (строки 111-119) обрабатывает событие выбора переключателя Две группы Колонки. При этом переменной ЧислоКолонок присваивается значение 1, которое также заносится в ячейку D1 листа Настройки. Аналогично предыдущим устроены процедуры Цена_Опт_СИск и Це-на_Розн_СИск (строки 120-139). Результат выбора переключателей Оптовая и Розничная записывается в ячейку D3 листа Настройки. Процедуры 8рш_ДлинаСтр_8ршВо\уп (строки 150-159) и 8рш_ДлинаСтр_ SpinUp (162-171) устроены одинаково и предназначены для уменьшения и увеличения, соответственно, значений переменной ДлинаСтраницыЗнач и записываются в текстовое поле ДлинаСтраницы диалогового окна и ячейку D2 листа Настройки. Процедуры Spin_Ha4CTp_SpinDown (строки 174-183) и Spin_Ha4CTp_Spin-Up (186-195) устроены одинаково и предназначены для уменьшения и увеличения, соответственно, значений переменной НачСтрокаЗнач и записываются в текстовое поле НачальнаяСтрока диалогового окна и ячейку С2 листа Настройки. И, наконец, завершает (строки 198-208) приведенный код процедура Груп-na_Change, обслуживающая окно комбинированного списка. Здесь переменной ГруппаТовара присваивается свойство Value, а переменной ИндексТекущейГруп-пы — свойство Listindex объекта Группа. Значение (ИндексТекущейГруппы + 1) сохраняется в листе Настройки. Для проверки работы рассматриваемого диалогового окна расположите окно в режиме выполнения так, как показано на рис. 14.17, и, манипулируя элементами управления, наблюдайте за изменениями, происходящими с данными на листе Настройки. Таким образом, предварительные действия, связанные с построением диалога, завершены. Остается написать программу, связанную с кнопкой Обновить и использующую всю вводимую в диалог информацию. Перед первым выводом диалогового окна на экран можно, используя лист Настройки, записать в лист Прейскурант данные из DBF-файла, Вывод диалогового окна на экран можно выполнять при помощи панели инструментов (добавив перед этим на панель новую кнопку) или посредством меню. Немного о способах попадания данных в лист Настройки. Их несколько. Начинающий программист-разработчик приложения может записать данные один раз вручную и объяснить пользователю важность правильного хранения этого листа. Можно при этом снабдить лист комментариями подобно тому, как показано на рис. 14.16. Достаточно подготовленный программист может предусмотреть кнопку настройки листа Настройки в режиме диалога с пользователем. В этом случае лист можно скрыть от пользователя и пользователь даже не будет знать о существовании листа. Элементы диалоговых окон 371 Рис. 14.17 Работу диалогового окна Прейскурант можно проверить без написания кода для кнопки Обновить 'Sp*] файл Правка Вид Вставка Формат Сервис Данные Окно Справка Щ 100% - 7 Arial Суг ’ 10 •» ж к ч — =g 8 9 10 (ЗХВ) Диски для X Box (DVS) Другие DVD (GA) Картриджи для GB (GBA) Картриджи для GB Advanc (MP4) Диски MP4 (R) (REK) Рекламные (TV) Телевизоры АМС РМ SRC (ЗХВ) (DVS) (GA) 20 9 40 Ндстроики npeitcKvp-»irra Начать со строки ДлинаСтраницы 2 53 12 Аккустика (АС) 13 Аксессуары (А) 14 Аксессуары к PC (PC) 15 Диски PC (PC CD) 16 ЗИП(З) 17 Игровые приставки (К) 18 Картридж Game boy (G) 19 Картридж Game boy (цвет)(ОС) 20 Картридж Nintendo 64 b t (N64) ► н\ Прейскурант \Настройки Цена Колонки • Оптовая Одна Розничная • Две Грута товара Обновить J Картридж Nintendo 64-bit (N64) Выход । 2 5 6 Стиль предыдущего абзаца, по крайней мере, должен был навести читателя на мысль о том, что работу над оставшейся частью программы ему предлагается выполнить самому. Это связано с тем, что далее решается очень специфическая задача, а знаний у читателя для ее решения уже должно хватать. 15 Отладка VB-кода. Поиск и устранение ошибок К сожалению, начинающие программировать недостаточно серьезно подходят к вопросам, о которых пойдет речь в этой главе. Даже некоторые опытные программисты утверждают, что в методах отладки нет необходимости — «нужно просто писать код без ошибок». На практике же получается, что отсутствие навыков в вопросах отладки приводит к большим потерям времени. Как бы вы ни старались, кода без ошибок не бывает. Каждая последняя найденная вами ошибка должна всего лишь придавать вам уверенности в том, что скоро вы найдете еще одну (снова «последнюю») ошибку. Процесс нахождения ошибок (bugs) в приложении называется отладкой (debugging). В этой главе рассматриваются средства отладки Visual Basic и вопросы «управления» ошибками времени исполнения. Типы ошибок Все ошибки, которые могут возникать при создании и эксплуатации приложения, можно разделить на: синтаксические ошибки (syntax errors), ошибки компи ляции (compile errors), ошибки времени исполнения или runtime-ошибки (runtime errors). Иногда говорят еще и о логических ошибках, которые связывают с тем, что программа выполняет не то, что хотел разработчик, но для системы программирования это не является ошибкой. Синтаксические ошибки возникают в результате неправильного ввода кода. Это самые простые ошибки: они обнаруживаются редактором кода Visual Basic сразу и являются результатом несоблюдения разработчиком синтаксиса языка или просто невнимательности при вводе кода. Например, можно случайно написать идентификатор для какой-либо переменной, совпадающий с ключевым словом, или неправильно указать аргументы для встроенной функции. К синтаксическим, например, относятся орфографические ошибки при вводе ключевого слова VBA, имени переменной или подпрограммы. Редактор VB «способен» распознавать большинство синтаксических ошибок по мере того, как вы редактируете или вводите текст программы. (VBA выполняет проверку синтаксиса, когда вы перемещаете курсор вставки с вновь отредактированной или набранной строки). Другие синтаксические ошибки могут проявляться как ошибки при трансляции. В общем, все, на что редактор кода Visual Basic (во время ввода кода) реагирует выводом окна сообщения (рис. 15.1), сопровождаемым звуковым сигналом, — это синтаксические ошибки. Обратите внимание на то, что сам редактор VB называет синтаксическую ошибку ошибкой компиляции (Compile error) — редактор VB проверяет синтаксис запуском компилятора, и ошибка происходит во время компиляции, хотя это не означает, что ошибка не синтаксическая. Ошибки компиляции возникают при попытке запустить подпрограмму, содержащую оператор, который VBA не в состоянии правильно откомпилировать. Если у VBA возникают какие-либо трудности в процессе компиляции написанного вами кода, то он выдает сообщение об ошибке и не создает оттранслированного кода. Например, если в вашем модуле содержится оператор Option Explicit и используется переменная без ее предварительного объявления (с помощью оператора Dim), VBA перемещает курсор вставки в точку, где обнаружена переменная, которую забыли Отладка VB-кода. Поиск и устранение ошибок 373 Рис. 15.1 Обычно так редактор VB сообщает об ошибках синтаксиса * ' «». cl ». [T FHe gdt View insert f й .у й * ем Pun look &dd-Ins Window Цф i 4.4 Й? Ч’ Л © Ln 15 Cd 26 ”3 !т«яР"1 Sub TestPut () ~ ip иле. I Din MyRecord As Record Rej End Sub Kill TESTFILE” Open "TESTFILE" Microsoft Visual Basic For Rardom a Compile error Expected var able Put #1 1 MyRecord Close #1 Sub TestTestPut () Help MyRecord FirstName 'Петр объявить, и выдает сообщение об ошибке компиляции (рис. 15.2) Заметьте, что в отличие от синтаксической ошибки эта ошибка обнаруживается при попытке вы полнить код процедуры. Рис 15.2 Эта ошибка была обнаружена при попытке выполнить код процедуры [j| Bte f-dtt tfew [nsert Format Debug Rin Tods Add-Ins ® J-И M ^ueneial) iyndow Ln 45 Col 4 I esi jet Close #1 End Sub sub TestGetO Mfcrasmft Visual Basie law - Tjima (гмппгэд] - Din MyRecord As Open "TESTFILE Rec For LOF(l) \ |\^ Compile error vanable not defined MyRecord) Help For RecordNumber -See) #1 Record Cet #1 MyRec Debug Print MyRecord FirstName i Next RecordNumber &. MyRecord ID Close #1 Ошибки времени исполнения или runtime-ошибки возникают, когда VBA встречает выражения или операторы, которые не удается вычислить или выполнить, например, содержащие недопустимые команды, недопустимые аргументы в процедурах и функциях, или недопустимые математические операции. Эти ошибки проявляются в процессе выполнения программного кода. Вот типичные примеры, приводящие к появлению runtime-ошибок: выражения, в результате которых происходит математическое переполнение, несоответствие типов переменных в выражениях присваивания или в аргументах подпрограммы; попытка открыть несуществующие файлы; попытка выполнить деление на ноль. На рис. 15.3 в строке кода для вызова процедуры записи массивов nFirst-Name, nLastName и nID в файл с произвольным доступом Call TestPut(nFirstName, nLastName, , nID) 374 Глава 15 оказалась лишняя запятая. VBA, как «мог», проанализировал строку и «решил», что мы хотели вызвать процедуру с пропущенным аргументом. На самом деле, никакая система не в состоянии абсолютно точно указать причину ошибки, поэтому не всегда можно понять из диагностики, какая же ошибка произошла в действительности. Рис. 15.3 Ошибка в вызове процедуры End sub * сдав» ti - р Bit tfew Insert Format Qebug Bun loots fcdd-lns « t * й Д/й ‘ > и «М Ln 3 Cd 25 pGiiiieral) sub TestPut (mFirstName, mLastName mID) Dim MyRecord As Record, RecordNumber, i Kill "TESTFILE" Open "TESTFILE' For Raroom As #1 Len = Len(MyRecord) RecordNumber = UBound(mFirstName) For i = 0 To RecordNumber - 1 MyRecord.FirgtN MyRecord LastNa MyRecord ID = m Put #1, i+l, Next Close #1 Sub TestTestPut () Dim nFirstName(2), nFirstName(0) = "Петр" nLastName(O) = 'Петров' nID(0) = 333 nFirstName(0) - "Сидор" nLastName(O) = "Сидоров nID(0) = 222 Конечно же, «классическим» примером ошибки времени исполнения является попытка деления на ноль, при возникновении которой выдается диалоговое окно, представленное на рис. 15.4. Следует отметить, что попытка разделить на ноль необязательно связана с невнимательным делением чего-либо на число ноль. Это может произойти (и чаще всего так и бывает) в результате того, что некоторая переменная (или выражение), являющаяся делителем, непосредственно перед делением будет оценена как нулевое значение. Рис. 15.4 Ошибка деления на ноль Средства отладки Рассмотрим средства отладки кода, предоставляемые системой VBA. Как и все современные системы, VBA имеет функции интерактивной отладки кода. Во-первых, это — панель Debug, которая представлена на рис. 15.5. Панель инструментов Debug не выводится на экран автоматически. Чтобы ее вывести, выберите в меню команду View | Toolbars | Debug (Вид | Панели инструментов | Отладка). (Когда панель инструментов выведена на экран, в меню слева от опции Debug появляется «галоч- Отладка VB-кода. Поиск и устранение ошибок 375 ка».) Панель инструментов Debug можно перемещать так же, как и любую другую панель инструментов и настраивать ее подобно панелям инструментов Windows-приложений. 9 11 13 Рис. 15.5. Панель Debug 1 - Exit Design Mode, 2 - Run Sub/UserForm, 3 - Break, 4 - Reset, 5 - Toggle Breakpoint, 6 - Step Into, 7 - Step Over, 8 - Step Out, 9 - Locals Window, 10 - Immediate Window, 11 - Watch Window, 12 - Quick Window, 13 - Call Stack Наименования кнопок, указанных на рисунке, появляются на экране рядом с панелью, когда курсор мыши на несколько секунд остается на соответствующей кнопке. Назначение кнопок приведено в следующей таблице. Кнопка Назначение Exit Design Mode Переводит design-режим в состояние off или on. Run Sub/UserForm Служит для переключения из режима разработки в режим выполнения (Run) или из режима прерывания в режим выполнения (Continue). В режиме прерывания название кнопки меняется на Continue. Break Останавливает выполнение приложения и переключает систему отладки в режим прерывания. Reset Очищает стек выполнения и переменные модульного уровня. Завершает выполнение кода. Toggle Breakpoint Устанавливает или отменяет в текущей строке точку останова. Здесь можно прервать программу, просмотреть некоторые данные и после продолжить выполнение кода. Step Into Выполняет следующую строку кода с заходом в процедуры. Код процедуры выполняется по шагам, как и до входа в процедуру. Step Over Выполняет следующую строку кода без захода в процедуры. Код процедуры выполняется как одна команда. Step Out Выполняет оставшуюся часть текущей процедуры и останавливает работу прРграммы на следующей строке вызывающей процедуры. Locals Window Отображает текущие значения локальных переменных в отдельном окне. Immediate Window Позволяет выполнить нужные операторы или просмотреть значения переменных в режиме прерывания. Watch Window Открывает окно с текущими значениями выбранных выражений. Quick Watch Отображает текущее значение выражения в режиме прерывания. Call Stack Отображает в режиме прерывания окно со списком вызванных, но еще не выполненных процедур (стек вызовов). 376 Глава 15 Замечание'. Эта панель по умолчанию не появляется на экране. Вы сами можете вызвать ее, выполнив команды: View, Toolbars, Debug. Режимы отладки Чтобы тестировать и отлаживать (находить ошибки) приложение, вам необходимо понять, какие режимы работы используются при создании нового приложения. Основная часть работы происходит в режиме разработки {design time). После того как разработчик приложения выбирает команды Run, Start, редактор VB переходит в режим исполнения {run time). Этот режим еще не является «боевым», поскольку поддерживается средой редактора VB и разработчик имеет возможность тем или иным способом приостановить выполнение кода в определенном месте для выполнения отладочных операций, т.е. перейти в режим прерывания. В режиме прерывания {break mode) программа не выполняется, но занимает память; здесь вы можете просматривать и изменять значения переменных и выражений и даже перемещаться по коду, выполняя один или группу операторов. Основное время при создании приложения занимает режим разработки. Здесь к приложению добавляются формы, элементы управления на формах, модули кода и так далее. В этом режиме используется только одно средство отладки — редактор кода, но, кроме того, вы можете расставить точки останова и определить контрольные выражения. В заголовке главного окна Visual Basic всегда отображается режим, в котором в данный момент времени находится система: в заголовке окна приложения после имени документа в квадратных скобках помещаются слова design, running, break. Для переключения режимов можно, кроме меню, использовать кнопки Start, Break и End панели Debug. Режим останова В процессе отладки программы у вас часто будет возникать потребность, проследить за тем, как именно VBA выполняет операторы вашей программы и какие значения принимают некоторые переменные на разных этапах ее выполнения. Режим останова редактора VB предоставляет возможность более близкого «взаимодействия» с написанным вами VBA-кодом по сравнению с обычным его выполнением (когда код выполняется от начала до конца с максимальной скоростью, которую может обеспечить VBA, и вы не в состоянии уследить ни за тем, какие части кода исполняются в данный конкретный момент, ни за тем, чему в этот момент равны значения интересующих вас переменных). В режиме же останова вы получаете возможность исполнения кода вашей программы или отдельных его частей построчно или по одной подпрограмме за шаг, как в замедленной съемке. Пооператорное выполнение программы называется пошаговым {single-stepping) проходом. В VBA перевести редактор VB в режим останова можно следующими способами: Щелчком на кнопке Debug (Отладка) в диалоговом окне runtime-ошибки. Задав одну или несколько точек останова. Вставив в текст программы оператор Stop. Воспользовавшись командой Debug | Step Into (Отладка | Шаг с заходом), кнопкой Break или Step Into на панели Debug (или нажав F8). Нажав Esc или Ctrl+Break, чтобы прервать выполнение программы. Переход в режим останова из окна сообщения об ошибке Всякий раз, когда в процессе выполнения одной из ваших VBA процедур или функций происходит runtime-ошибка, появляется диалоговое окно ошибки, подобное тому, что показано на рис. 15.4 (конкретное сообщение об ошибке может Отладка VB-кода. Поиск и устранение ошибок 377 быть другим, в зависимости от того, какая именно ошибка произошла). В диалоговом окне выводится номер ошибки и дается краткое пояснение характера ошибки. Кроме того, оно имеет несколько кнопок. В диалоговом окне, появляющемся при возникновении runtime-ошибки, имеются следующие кнопки: Continue (Продолжить) — продолжить выполнение прерванного VBA-кода. В случае возникновения runtime-ошибки управляющая кнопка Continue, как правило, отключена (см. рис. 15.4). End (Завершить) — завершить выполнение VBA-кода и выйти из режима останова. Debug (Отладка) — вывести оператор VBA, который привел к возникновению runtime-ошибки; в случае необходимости открываются соответствующие проект и модуль. VBA остается в режиме останова, позволяя разработчику VBA-приложения проверить значения переменных, проследить цепочку подпрограмм, приведшую к подпрограмме, исполняемой в данный момент, и ряд других параметров связанных с отладкой. Используйте кнопку Debug для быстрого перехода к оператору, выполнение которого привело к появлению ошибки. Help (Справка) — вывести диалоговое окно со справочной информацией, относящейся к возникшей runtime-ошибке. Для того чтобы перейти в режим останова из диалогового окна сообщения о runtime-ошибке, просто нажмите на кнопку Debug. Редактор VB откроет Code Window (окно кода), в котором появится выделенный желтым цветом оператор, приведший к появлению runtime-ошибки. Точки останова Для того чтобы обнаружить причину появления runtime- и логических ошибок, в большинстве случаев приходится прибегать к пошаговому выполнению операторов разрабатываемой программы. Пошаговый проход программы, позволяет либо точно узнать, какой оператор выполнялся в момент возникновения runtime-ошибки, либо дает возможность проконтролировать выполнение группы операторов, в корректности исполнения которых разработчик сомневается. Пошаговый проход всех операторов подпрограммы, а тем более программы в целом, может оказаться занятием довольно утомительным и требующим больших затрат времени. Желание или возможность выполнить пошаговый проход всех операторов программы возникает нечасто. Редактор VB позволяет выполнить большую часть кода с максимальной скоростью, переходя в режим останова только тогда, когда это необходимо для выполнения отдельных операторов кода. (Помните, чтобы выполнить пошаговый проход кода, необходимо находиться в режиме останова.) Точка останова (breakpoint) — это специально помеченная строка программы. Когда VBA доходит до точки останова, происходит его переключение из режима обычного выполнения программы в режим останова. Использование точек останова позволяет выполнить большую часть программы с полной скоростью с переходом в режим останова, только когда VBA достигает определенных операторов, выполнение которых вы хотите проверить более тщательно. Точка останова «действует» до тех пор, пока вы ее не удалите или не закроете проект, содержащий модуль, в котором она установлена. Точку останова можно поместить в любой строке исходного кода, содержащей исполняемый оператор. Обычно точка останова задается перед оператором, который, как вы знаете (или предполагаете), является причиной возникновения проблем. Для того чтобы задать точку останова, необходимо выполнить следующие шаги: 378 Глава 15 1. Выведите на экран VBA модуль и подпрограмму, содержащие операторы, для которых вы хотите задать пошаговое выполнение. 2. В Code Window (окне программы), поместите курсор вставки на строке, начиная с которой нужно, чтобы VBA переключился из обычного выполнения программы в режим останова. Эта строка станет новой точкой останова и должна содержать выполняемый оператор VBA. 3. Выберите команду Debug | Toggle Breakpoint (Отладка | Точка останова), чтобы вставить точку останова. [Вы также можете нажать клавишу F9 или воспользоваться кнопкой Toggle Breakpoint (Точка останова) на панели инструментов Debug (Отладка) редактора VB.] VBA выделяет выбранную в качестве точки останова строку (темно красным цветом), как показано на рис. 15.6; а рядом со строкой у левой границы Code Window появляется (темно-красная) точка. Рис. 15.6 VBA выделяет выбранную в качестве точки останова строку, а рядом со строкой у левой границы окна Code Window появляется точка Чтобы удалить точку останова, необходимо проделать те же самые действия, что и для ее вставки. Если применить команду Toggle Breakpoint к строке, содержащей точку останова, VBA удалит эту точку. Для того чтобы удалить все точки останова в модуле, необходимо выбрать команду Debug | Clear All Breakpoints (Отладка | Снять все точки останова) или нажать клавиши Ctrl+Shift+F9. Использование оператора Stop Точки останова, заданные при помощи команды Toggle Breakpoint, «действуют» только в течение текущего рабочего сеанса. Иногда, особенно в случае сложных программ, отладка может потребовать нескольких рабочих сеансов. Поэтому вы, возможно, захотите установить «многоразовые» точки останова. Именно для этой цели целесообразно использовать ключевое слово Stop. Когда VBA встречает оператор Stop, выполнение программы приостанавливается, отображаются модуль и процедура, содержащие выполняемый в данный момент оператор, и происходит переключение в режим останова. При использовании оператора Stop создается постоянная точка останова, то есть она, фактически, становится частью VBA-кода. Единственный способ удалить точку останова, созданную при помощи оператора Stop, — это удалить сам оператор Stop из исходного кода. Как правило, оператор Stop вставляют в текст программы в случаях, когда нужна постоянная точка останова. После завершения отладки программы необходимо отредактировать текст программы, удалив из него операторы Stop. Отладка VB-кода. Поиск и устранение ошибок 379 Переход в режим останова с помощью команды Step Into Вы уже знаете, что можете запустить выполнение процедуры непосредственно из исходного кода, используя команду Run | Run Sub/UserForm или нажав с помощью мыши кнопку Run Sub/UserForm на панели инструментов Debug. Подобным же образом можно запустить на выполнение любую процедуру в режиме останова. Просто поместите курсор вставки внутрь процедуры, которую хотите выполнить в режиме останова, и выберите команду Debug | Step Into (Отладка | Шаг с заходом). (Вы также можете нажать F8 или щелкнуть мышью по расположенной на панели инструментов Debug кнопке команды Step Into.) VBA перейдет в режим останова и покажет текущий исполняемый оператор подпрограммы. Как упоминалось выше, в режиме останова текущий исполняемый оператор выделяется в Code Window желтым цветом и стрелкой у левой границы текста кода (как показано на рис. 15.7). Рис. 15.7 В режиме останова текущий исполняемый оператор выделяется в Code Window желтым цветом и стрелкой у левой границы текста кода Переход в режим останова прерыванием исполнения кода Как вы уже знаете, VBA прерывает выполнение кода, когда пользователь нажимает клавишу Esc (или комбинацию Ctrl+Break). Когда вы прерываете исполнение кода, VBA выдает диалоговое окно ошибки с сообщением, что выполнение кода было прервано, и предлагает те же самые возможности выбора, что и диалоговое окно, появляющееся при возникновении runtime-ошибки: Continue, End, Debug и Help. Чтобы перейти к выполнению программы в режиме останова, нажмите на кнопку Debug. VBA перейдет в режим останова и укажет оператор, выполнявшийся в тот момент, когда вы прервали процедуру. Выход из режима останова Часто возникает необходимость «пройти» часть программы в пошаговом режиме, после чего завершить выполнение оставшейся части в обычном режиме. Возможно, в некоторых случаях вы также захотите как выйти из режима останова, так и завершить выполнение программы, чтобы получить возможность, внести исправления в текст программы для устранения выявленных в режиме останова ошибок. Для того чтобы выйти из режима останова и продолжить выполнение программы в обычном режиме, воспользуйтесь командой Run | Continue (Запуск | Продолжить). VBA выйдет из режима останова и продолжит выполнение программы до тех пор, пока не произойдет ее нормальное завершение. Если VBA встретится с точкой останова или оператором Stop, прежде чем достигнет конца программы, 380 Глава 15 то произойдет переход в режим останова. (Выйти из режима останова и продолжить выполнение программы, можно также нажатием F5 или щелчком мышы по кнопке Continue на панели инструментов Debug.) Для того чтобы выйти из режима останова и одновременно завершить выполнение всех программ, выберите команду Run | Reset (Запуск | Сброс). VBA выйдет из режима останова и прервет дальнейшее выполнение программы, все переменные потеряют свои значения, а все процедуры будут удалены из памяти. (Вы можете также выйти из режима останова и завершить выполнение программы, щелкнув мышью по кнопке Reset на панели Debug.) Использование команды Step Into Теперь, вы знаете, как перейти в режим останова и как из него выйти, поэтому можно приступить к изучению использования команды Step Into (шаг с заходом) г я я пошагового выполнения программы в режиме останова. Пошаговое выполне-ие операторов позволяет в процессе отладки проследить за исполнением отдельных процедур, функций или программы в целом. При пошаговом проходе исходного кода с использованием команды Step Into VBA входит в тело каждой вызываемой процедуры или функции, давая возможность выполнить в пошаговом режиме и их операторы тоже. Пошаговое выполнение программы с использованием команды Step Into позволяет проследить за выполнением всех операторов главной процедуры и всех операторов каждой функции или процедуры, вызываемых из основной программы. В Code Window операторы, которые будут выполняться следующими, выделены желтым цветом. Если код не такой простой, как в процедуре TestTestPut, име,-ет условные операторы или операторы циклов, то пошаговый проход программы, выполняемый таким образом, может в некоторых случаях помочь понять, правильно ли работают используемые разработчиком приложения программные структуры. Перед выполнением следующей команды можно, помещая курсор вставки на переменные или выражения, в окне ToolTip просмотреть значение переменной или выражения. Режим подсказки значений данных (позволяющий просматривать значения выражений в окне типа ToolTip) по умолчанию включен. Если по каким-то причинам на вашем компьютере подсказки не работают, выберите команду Tools | Options и на вкладке Editor окна Options выберите флажок Auto Data Tips. Наблюдение за значениями выражений Если в процессе пошагового выполнения операторов кода вас интересует не только последовательность выполнения операторов, но и изменение значений переменных, то вас вряд ли удовлетворит возможность просматривать значения переменных (и даже выражений) в окне ToolTip. Редактор VB имеет окно Watches, в котором можно просматривать значения выражений по мере пошагового выполнения кода. Например, на рис. 15.8 приведено окно Watches, в котором отображается значение переменной nFirstName(O) процедуры TestTestPut модуля Modulel. Рис. 15.8 В режиме пошагового выполнения кода в Watch Window можно наблюдать за изменением значений выражений (переменных) 3 Watches ИИ | Expression j Value |Type Jcpntext 1® nF'r ’’Петр’ / VananfzSinng Moduhl.lr.*: «и Отладка VB-кода. Поиск и устранение ошибок 381 Для просмотра значений выражений (переменных) процедуры необходимо занести (добавить) эти выражения в окно Watches. Это можно выполнить двумя способами, предварительно выделив выражение (для переменной можно просто поместить на ней курсор вставки): Из контекстного меню (правой кнопки мыши) выбрать опцию Add Watch. * Из меню Debug выбрать опцию Add Watch. В любом случае на экране появляется диалоговое окно (рис. 15.9) Add Watch, в котором в самом простом случае можно просто щелкнуть на кнопке ОК, после чего в окне Watches (если ранее его не было на экране, то оно выводится) появляется строка, содержимое которой соответствует содержимому окна Add Watch (рис. 15.10): совпадают поля Expression и Context. В поле Value окна Watches либо отображается значение выражения, либо указывается, что выражение находится «вне контекста» (<Out of context>), либо (для массивов) выводится сообщение о том, что ходит за пределы допустимого диапазона» (<subscript out of range>). «индекс вы- Рис. 15.9 диалоговое окно Add Watch, в котором в самом простом случае можно просто щелкнуть на кнопке ОК Add Watch Expression Context Procedure Cancel Module |TestTeslPut । Modulel Help Project Project Watch Type Watch Expression Break When Value Is True ? Break When Value Changes Рис. 15.10 В режиме пошагового выполнения кода • окне Watch можно наблюдать за изменением значений выражений (переменных) ДЗ Watches tression _ _ nFtrstNameflO) Value ................*Туре ______________ 1 Context^ <Out of context> Variant/Empty Modulel TestTestPut Вернемся к окну Add Watch. Как уже можно понять, в секции Expression указывается выражение (переменная), в секции Context — наименование процедуры и модуля, где находится выражение. Если перед вызовом окна Add Watch добавляемое выражение уже указано (выделено), то в секции Context ничего изменять не нужно. Если в момент вывода диалогового окна Add Watch курсор вставки не указывал ни на какую переменную, то в текстовом окне Expression необходимо будет ввести выражение (переменную). В любом случае окна комбинированных списков Procedure и Module в секции Context будут содержать имена текущих процедуры и модуля, на коде которых находится курсор вставки. Конечно, можно воспользоваться этими списками для выбора других доступных модулей и процедур. Секция Watch Туре окна Add Watch предоставляет дополнительные возможности для отладки. При помощи переключателя Break When Value Is True (останов, если значение выражения истинно) этой секции можно использовать окно Add Watch не в пошаговом режиме выполнения кода, а в обычном. Для подобной же цели можно 382 Глава 15 использовать и переключатель Break When Value Changes (останов при изменении значения выражения). Как уже должно быть понятно, режимом выполнения кода в этих случаях может быть обычный режим. При соответствующих изменениях указанных выражений произойдет переход в режим останова. Таким образом, если задать в окне интересующие разработчика выражения, можно попеременно задавая то пошаговый, то обычный режим выполнения приложения, просматривать изменения значений выражений. На рис. 15.11 показаны Code Window и окно Watches при пошаговом выполнении кода приведенного ниже листинга. Наблюдаемыми переменными являются два массива: nFirstName и nID. Оба массива уже получили значения для первых элементов, но nFirstName получил также значение для второго элемента, a nID — нет. Рис. 15.11 Окно Code и Watches при пошаговом выполнении кода приведенного ниже листинга Ibeneia!) End Sub ▼j sTe«iTesfPut Sub TestTestPut() Dim nFirstName(2), nLastName(2), nID(2) nFirstName(0) = "Петр" nLastName(Q) = "Петров" nID(0) = 333 nFirstName(1) = "Сидор" nLastName(1) = "Сидоров" nlD(l) = 222 Call TestPut(nFirstName, nLastName, nID) End Sub #1 Watches Expression [Value 64 R nFirstName T— nFir$lName(O) 1- nFirstName(l) L nFirstName(2) "Петр" 'Сидор Empty .ГТуре,,, .........___ VanantA/ariant(O to 2) Vanant/Stnng Vanant/Stnng Vanant/Empty I.Contgxt Modulel TestTestPut Modulel TestTestPut Modulel TestTestPut Modulel TestTestPut 333 Empty Empty Vanant/lnteger Vanant/Empty Vanant/Empty Modulel TestTestPut Modulet TestTestPut Modulel TestTestPut Листинг 15.1. Код для изучения работы с окном Watches 1 Option Explicit 2 Type Record ' Определенный пользователем тип 3 ID As Integer 4 FirstName As String * 20 5 LastName As String * 20 6 End Type 7 8 Sub TestPut(mFirstName, mLastName, mID) 9 ' Тестирование Put 10 Dim MyRecord As Record, RecordNumber, i 11 Kill "TESTFILE" 12 Open "TESTFILE" For Random As #1 Len = Len(MyRecord) 13 RecordNumber = UBound(mFirstName) 14 For i = 0 To RecordNumber - 1 15 MyRecord.FirstName = mFirstName(i) 16 MyRecord.LastName = mLastName(i) 17 MyRecord.ID = mID(i) 18 Put #1, i+l, MyRecord 19 Next 20 Close #1 21 Lnd Sub 22 Sub TestTestPut() 23 Dim nFirstName(2), nLastName(2), nID(2) 24 nFirstName(0) = "Петр" Отладка VB-кода. Поиск и устранение ошибок 383 25 nLastName(O) = "Петров" 26 nID(0) = 333 27 nFirstName(1) = "Сидор" 28 nLastName(l) = "Сидоров" 29 nID(l) = 222 30 Call TestPut(nFirstName, nLastName, nID) Редактирование наблюдаемого выражения Наблюдаемые в окне Watches выражения можно редактировать после того, как они уже добавлены в это окно. Чтобы отредактировать контрольное выражение, можно выполнить следующее: 1. В окне Watches выделите выражение, которое хотите отредактировать. 2. Выберите команду Debug | Edit Watch (Отладка | Изменить контрольное значение). Эта команда активизирует диалоговое окно Edit Watch, которое отличается от окна Add Watch только заголовком и дополнительной кнопкой Delete (Удалить). 3. Выполните необходимые исправления в выражении, а также, если необходимо, внесите изменения в разделы Context и Watch Туре. Заметьте, что выражение для контроля может вообще не встречаться в отлаживаемом коде. Важно только, чтобы оно содержало выражения, входящие в код. Например, вы можете остановить выполнение цикла за несколько итераций до указанной в качестве последней или наблюдать изменения не самой переменной некоторой программы, а результат ее деления по модулю на какое-либо число. 4. Нажав кнопку ОК, закройте диалоговое окно Edit Watch. VBA внесет в окно Watches соответствующие исправления. Рис. 15.12 Окно Edit Watch отличается от окна Add Watch только заголовком и дополнительной кнопкой Delete Edit Watch Expression Context Procedure ^TestTestPut Module Modulel Project Project Delete Cancel Help Watch Type (• Watch Expression Break When Value Is True ( Break When Value Changes Удаление наблюдаемого выражения По мере работы с наблюдаемыми переменными и выражениями вы можете обнаружить, что список в окне Watches имеет тенденцию разрастаться, и в какой-то момент поймете, что значения далеко не всех находящихся в нем выражений, действительно, необходимо контролировать. Поэтому вам может понадобиться удалить их из окна Watches. Удалить контрольное выражение можно одним из двух способов: 1. Выделите выражение, которое хотите удалить из окна Watches, и нажмите клавишу Del. VBA удалит выделенное выражение из окна без предупреждения. 2. Выделите выражение, которое хотите удалить, затем выберите команду Debug | Edit Watch. В появившемся окне Edit Watch щелкните кнопку Delete. VBA удалит выделенное выражение из окна Watches. 384 Глава 15 Использование команды Step Over Если код вашего приложения состоит из большого количества процедур, а предполагаемый характер ошибки — неправильный алгоритм вызова этих процедур, то пошаговое выполнение каждой вызываемой процедуры может оказаться достаточно утомительным. Во всяком случае, нет необходимости выполнять по шагам код процедуры, в которой вы абсолютно уверены (хотя, конечно, программист должен быть абсолютно уверен только в том, что в любой процедуре в любой момент времени содержится, по крайней мере, одна ошибка). Но даже, если вы «правильно» не уверены во всех процедурах, на каком-то этапе разработки приложения многие процедуры выполняют то, что от них требуется, и их пошаговое выполнение имеет мало смысла. Отладчик VBA предоставляет в дополнение к команде Step Into (шаг с заходом) команду Step Over (шаг с обходом). При использовании команды отладки Step Over, если встречается оператор, вызывающий процедуру или определенную пользователем функцию, VBA не переходит к пошаговому выполнению кода вызванной подпрограммы. Вместо этого он выполняет код вызванной подпрограммы с обычной скоростью и продолжает пошаговое выполнение с первого оператора, следующего за вызовом подпрограммы. Если вы уверены в нормальной работе процедур, вызываемых из некоторой управляющей процедуры, возможность избежать пошагового выполнения подпрограмм помогает сосредоточиться на отладке операторов текущей процедуры. Кроме того, за счет отказа от пошагового выполнения там, где в этом нет необходимости, можно сэкономить затрачиваемое на отладку время. Использование окна Locals Окно Locals (Локальные переменные), хотя и не связано с окном Watches, но выполняет похожую функцию (по умолчанию не появляется на экране и вызывается командой View | Locals Window). Оно выводит все локальные (или находящиеся в активной области видимости) переменные выполняемой в данный момент процедуры или функции. На рис. 15.14, например, показаны значения локальных переменных процедуры TestTestPut приведенного ранее листинга. Окно Locals содержит три колонки: Expression (Выражение) (имя переменной или объекта), Value (Значение) (текущее значение переменной или свойство объекта) и Туре (Тип) (тип данных или объекта). Обратите внимание на прямоугольники слева от элементов mFirstName, mLastName и mID в окне Locals на рис. 15.13. Они аналогичны прямоугольникам в других раскрывающихся древовидных списках Windows. Если в прямоугольнике содержится знак «плюс», это означает, что, щелкнув по нему мышью, можно открыть древовидную диаграмму со свойствами и значениями объекта. Значок «минус» показывает, что диаграмма уже раскрыта и, щелкнув по нему, вы можете ее свернуть. Если щелкнуть по значку «плюс» слева от элемента mFirstName, появится список всех элементов массива и значения, которые каждый из них имеет в настоящий момент. Окно Locals удобно использовать для наблюдения за текущими значениями и структурой переменных и объектов выполняемой в данный момент процедуры, функции или модуля. Трассировка вызовов процедур При отладке программ довольно часто возникает необходимость определить точную цепочку или последовательность процедур, приведшую к выполнению конкретного оператора, который порождает ошибки. Знание цепочки вызовов процедур может оказаться полезным, поскольку часто играет важную роль в определении причины ошибки. Например, вы можете обнаружить оператор, приводящий Отладка VB-кода. Поиск и устранение ошибок 385 Рис. 15.13 Окно Locals при пошаговом выполнении кода приведенного ранее листинга Sub TestPut(mFirstName, mLastName, mID) T* Up ~ > Г -~J Dim MyRecord As Record, RecordNumber, i Kill "TESTFILE" Open "TESTFILE" For Random As #1 Len = Len(MyRecorc___. RecordNumber = UBound(mFirstName) For i = 0 To RecordNumber - 1 MyRecord.FirstName = mFirstName(1) MyRecord.LastName = mLastName(i) MyRecord.ID = mID(i) Put #1, i+l, MyRecord fproject: Modutel TestPut Expression................... i Value[Type Щ Module! Щ mFirstName Modulet/Module! Щ mLastName ПВВВИ k- mlD(D) U mlD(1) ! L mID(2) Щ MyRecord RecordNumber 333 222 Empty 2 Vanant/Vanant(O to 2) Vanant/Vanant(D to 2) Vanant/lnteger Vanant/lnteger Vanant/Empty Record Vanant/Long Vanant/Long к ошибке деления на ноль, но не знаете, почему одна из переменных в операторе содержит ноль. Знание точной цепочки вызовов процедур поможет вам определить, что процедура была вызвана, например, с пропущенным необязательным параметром или просто с неверным значением требуемого аргумента. VBA позволяет просматривать цепочку вызовов процедур посредством диалогового окна Call Stack (Стек вызова). Чтобы вывести окно Call Stack на экран (в режиме останова), либо выберите команду View | Call Stack (Вид | Стек вызова), либо щелкните мышью по кнопке Call Stack на панели инструментов Debug, либо нажмите Ctrl+L. На экране появится диалоговое окно Call Stack, пример которого показан на рис. 15.14 (последовательность вызовов процедур может быть иной). Как видно из рис. 15.14, диалоговое окно Call Stack выводит список последовательности вызовов процедур, приводящей к выполняемой в данный момент процедуре или функции. Рис. 15.14 Окно Call Stack и код, посредством которого можно получить такое окно Sub b_sub(var As String) Call c_sub(var) End Sub String) 13 Программирование на VBA 2002 386 Глава 15 Вы, наверное, уже заметили, что диалоговое окно Call Stack содержит две кнопки — Show (Показать) и Close (Закрыть). Кнопка Close просто закрывает диалоговое окно. Кнопка Show выполняет очень полезную функцию и служит для того, чтобы можно было найти оператор, вызвавший исполняемую в данный момент подпрограмму. Кнопкой Show можно воспользоваться для проверки значений аргументов, переданных выполняемой процедуре. Для этого откройте диалоговое окно Call Stack, выберите имя процедуры, которая вызвала текущую процедуру, и щелкните командную кнопку Show. VBA закроет диалоговое окно Call Stack и отметит в окне Code оператор, содержащий вызов текущей процедуры. Используя кнопку Show и диалоговое окно Call Stack, можно пройти в обратном направлении вдоль всей цепочки вызовов подпрограмм. Использование окна Immediate Иногда даже сочетания пошагового выполнения программы с использованием наблюдаемых переменных и трассировки вызовов подпрограмм бывает недостаточно, чтобы найти содержащуюся в программе ошибку. В редакторе VB предусмотрено еще одно средство для нахождения ошибок в вашей программе — окно Immediate (Проверка) редактора VB является редактором свободного формата, позволяющим контролировать значения переменных и выражений, производить вычисления, изменять значения переменных и проверять результаты выполнения функций. Все эти функции поддерживаются, когда программа находится в режиме останова. Для того чтобы воспользоваться окном Immediate, выберите View | Immediate Window или введите с клавиатуры комбинацию Ctrl+G, или щелкните на кнопке Immediate Window на панели инструментов Debug. VBA выведет диалоговое окно Immediate. Чтобы вывести в окне Immediate интересующую вас информацию, используйте оператор Print (или ?). Оператор Print вводится в окне Immediate вместе со списком переменных или выражений. Достаточно набрать команду Print, перечислить интересующие вас переменные и выражения, а затем нажать клавишу Enter. VBA вычислит значения переменных, перечисленных после команды Print, и выведет результаты в строке следующей за командой Print. На рис. 15.15 показан пример работы в окне Immediate. Рис. 15.15 Просмотр данных в окне Immediate | (General) Next Close #1 1$ - (С<и End Sub sub TestTestPut () Dim nFicstName(2), nLastName(2) , nFirstName(0) = "Петр" nLastName(O) = "Петров" nlD(O) = 333 nFirstName(1) - "Сидор") nLastName(1) = "Сидоров" nID(l) = 222 Отладка VB-кода. Поиск и устранение ошибок 387 Оператор Debug.Print Объект VBA Debug имеет метод Print, позволяющий вывести информацию в окно Immediate в процессе выполнения программы. Для этого необходимо добавить в программу VBA операторы, вызывающие метод Debug.Print. Метод Debug.Print используется, как правило, в сочетании с уже изученным в этой главе оператором Stop. Сочетание этих двух элементов позволяет выполнять программы в обычном (неотладочном) режиме, получая при этом отладочную информацию аналогичную той, которую дает использование наблюдаемых переменных или выражений. Как правило, вы добавляете один или несколько операторов, вызывающих метод Debug.Print, выводящих значения определенных переменных или выражений в окно Immediate. Хотя при выполнении программы в нормальном режиме окно Immediate невидимо, как только VBA встретит оператор Stop и переключится в режим останова, оно сразу станет доступным и позволит вам просмотреть всю информацию, выведенную включенными в программу операторами Debug.Print. Используя этот технический прием, можно сэкономить массу отладочного времени за счет отказа от пошагового выполнения кода. Просмотрев информацию, содержащуюся в окне Immediate, вы можете возобновить выполнение программы в обычном режиме. Оператор Debug. Assert Объект VBA Debug имеет метод Assert, приостанавливающий выполнение кода на строке, содержащей этот метод, при выполнении некоторого условия. Синтаксис метода следующий: СИНТАКСИС Debug.Assert Bocleanexpression Аргумент Booleanexpression — логическое выражение, имеющее результатом значение True или False. Этот метод, практически, выполняет функции оператора Stop, но выполняется, когда его аргумент принимает значение False. Обработчик ошибок Обработчик ошибок — это код для перехвата и обработки ошибок в вашем приложении. Создание своего собственного обработчика ошибок состоит из следующих шагов: Установки ловушки прерываний (error trap) сообщением места кода, куда следует перейти при возникновении ошибки (адрес обработчика). Этот шаг осуществляется посредством оператора On Error, который делает доступным перехват прерываний и указывает метку, за которой начинается обработчик прерываний. Написания процедуры обработки прерываний, связанных с ошибками вашего приложения. Обеспечения выхода из процедуры обработки прерывания. Установка ловушки прерываний осуществляется при помощи оператора On Error, который при этом указывает на обработчик прерывания. Ловушка остается активной на время работы процедуры (функции), в которой она установлена, т.е. до того, как выполнится один из операторов Exit Sub, Exit Function, Exit Property, End Sub, End Function или End Property этой процедуры (функции). В любой момент времени может быть доступна только одна ловушка в данной процеду 13* 388 Глава 15 ре. Но вы можете создавать много ловушек и активизировать их в разное время. Ловушку можно сделать неактивной применением специального типа команды On Error — On Error GoTo 0. Простой синтаксис оператора On Error GoTo имеет следующий вид: СИНТАКСИС On Error GoTo label Здесь label — метка (отмечаемая в коде двоеточием за ней), за которой начинается обработчик. Итак, первым оператором блока кода обработки прерывания по ошибке является метка с двоеточием за ней. Далее без всяких ограничивающих блоки операторов следует писать код, который, кстати, необязательно должен обрабатывать ошибки: вы можете просто констатировать факт наличия ошибки. Во-первых, не всегда можно идентифицировать ошибку, а во-вторых, не всякую ошибку можно исправить. Вы можете, например, только предположить, что произошло, и попытаться дать рекомендации пользователю, как избежать повторения какой-либо ошибки. Для кодов-примеров мы, конечно, будем точно знать типы ошибок, потому что сами будем их инициировать. Перед меткой, задающей начало обработчика, должен находиться оператор выхода из процедуры (функции). Иначе даже при отсутствии ошибки код обработчика будет выполняться. В листинге 15.2 приведен пример обработчика, который выполняется в том случае, если пользователь введет в текстовом окне не число, а что-либо отличное от числа. Листинг 15.2. Пример обработчика ошибок 1 Private Sub Commandl_Click() 2 Dim z, у As Integer 3 On Error GoTo err 4 у - InputBox("Введите число") 5 z = у + 10 6 7 MsgBox z 8 MsgBox "Спасибо!" 9 Exit Sub 10 11 err: 12 MsgBox ("Просили же Вас ввести число!") 13 End Sub Как видно из этого примера, здесь никто не собирался идентифицировать ошибку: в таком простом коде можно было только предположить, что всему виной будет пользователь, который не может пользоваться окном ввода целого числа. Тем не менее, в Visual Basic есть возможность узнать тип ошибки (как ее «для себя» определяет Visual Basic) посредством объекта Err с несколькими свойствами, из которых для нас наиболее полезны Number — номер ошибки, и Description — описание ошибки. При этом в документации MSDN есть замечание с рекомендацией не очень доверять свойству Description, а использовать только свойство Number. Например, код листинга 15.2 можно дополнить анализом произошедшей ошибки (см. листинг 15.3). i Листинг 15.3. Анализ ошибки в обработчике 1 Private Sub Commandl_Click() 2 Dim z, у As Integer 3 On Error GoTo err Отладка VB-кода. Поиск и устранение ошибок 389 4 у = InputBox("Введите число") 5 z = у + 10 4 6 7 MsgBox z 8 MsgBox "Спасибо!" 9 Exit Sub 10 11 err: 12 If err.Number = 13 Then 13 MsgBox ("Просили же Вас ввести число!") 14 End If 15 End Sub Если вы предполагаете, что в течение работы с процедурой могут произойти самые разные ошибки, можно в коде обработчика использовать оператор Select Case для возможных действий, исправляющих ситуацию. Как вы могли уже заметить, в листингах 15.2-15.3 сразу после выполнения кода обработчика вся процедура завершается. Такой обработчик хорош только в качестве примера того, как не нужно поступать. Если мы по всяким пустякам будем завершать процедуры, то с таким приложением будет трудно работать. Итак, нам нужен способ обработать ошибку или, в крайнем случае, сообщить о ней, но обязательно как-то продолжить выполнение процедуры. Выход из блока обработки прерывания по ошибке Для выхода из блока обработки ошибки можно ничего не предпринимать, и работа функции будет завершена. Но поскольку с таким образом завершившей свою работу процедурой (или функцией) могут быть связаны другие части кода, видимо, не всегда будет правильно просто отказаться от дальнейшего выполнения процедуры. По крайней мере, надо как-то сообщить о том, что процедура завершилась из-за ошибки. Например, если функция должна была возвратить результат некоторых вычислений, используемый в дальнейших расчетах, то аварийный выход по ошибке дает мало пользы. Ошибка может произойти и при открытии файла. Если не сообщить об этом при выходе из блока обработки ошибки, то найдется такая функция, которая попытается считывать данные из неоткрытого файла. И так далее. Для выхода из блока обработки ошибок предназначен оператор Resume, функции которого приведены в следующей таблице. Оператор Описание Resume [0] Выполнение кода возобновляется с того оператора, который вызвал ошибку. Используйте этот оператор для повторения кода после исправления ошибки. Resume Next Возобновляет выполнение кода с оператора, следующего непосредственно за оператором, вызвавшим ошибку. Если ошибка произошла вне процедуры, содержащей блок обработки ошибок, выполнение кода возобновляется с оператора, находящегося за вызовом процедуры, вызвавшей ошибку, если в этой процедуре нет своего обработчика. Resume line Возобновляет выполнение кода с указанной метки line. Метка должна находиться в процедуре, содержащей обработчик ошибок. Err.Raise Number:= number Эмулирует ошибку времени исполнения. Когда этот оператор выполняется внутри блока обработки ошибок, Visual Basic обращается к списку вызовов (последовательность вызова процедур) для поиска другого обработчика. 390 Глава 15 Пример использования оператора Resume приведен в листинге 15.4. Это самая простая форма оператора, при которой происходит возврат к строке кода, где произошла ошибка. По крайней мере, в данном случае этого вполне достаточно, поскольку после правильного ввода числа программа будет работать нормально. Листинг 15.4. Использование в обработчике оператора Resume 1 Private Sub Commandl_Click() 2 Dim z, у As Integer 3 On Error GoTo err 4 у = InputBox("Введите число") 5 z = у + 10 6 7 MsgBox z 8 MsgBox "Спасибо!" t 9 Exit Sub 10 11 err: 12 If err.Number =13 Then 13 MsgBox ("Просили же Вас ввести число1") 14 Resume 15 End If 16 End Sub В листингах 15.5 и 15.6 приведены примеры использования оператора Resume Next. Причем в первом из них выполняется присвоение переменной числа 9999, если пользователь «забыл», как вводятся числа. Затем код продолжается со следующей строки (за оператором InputBox). В листинге 15.6 обработчик более «лоялен» к пользователю, давая ему три попытки для ввода числа. Поэтому здесь используется и оператор Resume, и Resume Next. Для этого в код введен счетчик со, который при загрузке формы (процедура Form_Load) инициализируется значением 1. В блоке обработки ошибок значение счетчика увеличивается на единицу. Как только пользователь использует три попытки ввода числа, но не введет число, оператор Resume Next прекратит пользовательские «мучения», как это делается (только гораздо раньше) в предыдущем листинге. Листинг 15.5. Использование в обработчике оператора Resume Next 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Private Sub Commandl_Click() Dim z, у As Integer On Error GoTo err у = InputBox("Введите число") z = у + 10 ' MsgBox z MsgBox "Спасибо!" Exit Sub err: If err.Number = 13 Then MsgBox ("С Вашего разрешения введем 9999") , у = 9999 Resume Next End I f End Sub Отладка VB-кода. Поиск и устранение ошибок 391 Листинг 15.6. Использование в обработчике оператора Resume Next 1 Public со As Integer 2 Private Sub Commandl_Click() 3 Dim z, у As Integer 4 On Error GoTo err 5 у = InputBox("Введите число") 6 z = у + 10 * 7 8 MsgBox z ‘ 9 MsgBox "Спасибо1" 10 Exit Sub 11 12 err: 13 If err.Number = 13 Then 14 If co = 2 Then 15 MsgBox ("С Вашего разрешения введем 9999") 16 у = 9999 17 Resume Next 18 Else 19 co = co + 1 20 MsgBox ("У Вас осталось " & _ 21 (3 - co) & " попытки") 22 Resume 23 End If 24 End If 25 End Sub 26 27 Private Sub Form_Load() 28 co = 0 29 End Sub Очень простой пример использования оператора Resume line приведен в следующем листинге. Листинг 15.7. Использование в обработчике оператора Resume line 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Public со As Integer Private Sub Commandl_Clrck() Dim z, у As Integer On Error GoTo err у = InputBox("Введите число") z = у + 10 MsgBox z MsgBox "Спасибо!" , . Exit Sub err_exit: MsgBox ("Что-то у Вас не получается") Exit Sub err: If err.Number = 13 Then If co = 2 Then Resume err_exit Else co = co + 1 MsgBox ("У Вас осталось " & _ (3 - co) & " попытки") Resume End If 392 Глава 15 26 End If 27 End Sub 28 29 Private Sub Form_Load() 30 co = 0 31 End Sub В листинге 15.8 блок кода обработки ошибок находится не в той процедуре, где происходит ошибка при делении числа на ноль. Visual Basic при помощи списка вызовов возвращается в процедуру А, поскольку именно там был активизирован обработчик ошибок. Оператор Resume Next инициировал переход к строке кода, которая находится за оператором вызова процедуры В. ' Листинг 15.8. Обработчик ошибок в одной из процедур 1 Private Sub Commandl_Click() 2 Call A 3 End Sub 4 5 Sub A() 6 On Error GoTo err 7 Call В 8 MsgBox ("В любом случае процедура а завершается") 9 Exit Sub 10 err: 11 MsgBox ("Где-то произошла ошибка!") 12 Resume Next 13 End Sub 14 15 Sub B() 16 Call C 17 End Sub *' 18 19 Sub C() 20 Dim d As Integer 21 d = 1 / 0 ’ 22 End Sub Программная обработка ошибок при помощи оператора On Error Оператор On Error позволяет обрабатывать ошибки, возникающие во время выполнения кода, программно. Синтаксис оператора On Error следующий: СИНТАКСИС On Error GoTo line On Error Resume Next On Error GoTo 0 Синтаксис оператора On Error имеет следующие формы: On Error GoTo line Делает доступным обработчик ошибок, который начинается со строки, определенной аргументом line. Аргумент line может быть меткой или числом. При возникновении ошибки управление выполнением программы передается на строку кода с меткой line.Таким образом происходит активизация обработчика ошибок. Метка line должна находиться в той же процедуре, что и оператор On Error. Отладка VB-кода. Поиск и устранение ошибок 393 On Error Resume Next Указывает на то, что при возникновении ошибки управление выполнением программы передается на оператор, следующий непосредственно за тем, в котором произошла ошибка. Этот оператор позволяет продолжить выполнение программы, несмотря на возникновение runtime-ошибки. Оператор On Error Resume Next становится неактивным при вызове другой процедуры. On Error GoTo 0 Отключает пользовательский обработчик ошибок в данной процедуре. Этот оператор не указывает метку 0 в качестве начала обработчика ошибки, даже если в процедуре действительно имеется такая метка. Без этого оператора обработчик ошибок «отключается» автоматически после окончания работы процедуры. Пользовательские обработчики ошибок являются составной частью «дружественного» интерфейса. Если во время работы пользователя с вашим приложением возникает не предусмотренная вами ситуация, то в любом случае не стоит оставлять пользователя «наедине» с системой VBA, не настолько дружественной, как хороший разработчик приложений. VBA «знает» очень мало о том, в каких местах вашего программного кода и какие могут возникать ошибки. Разработчик же приложения должен знать все «тонкие» места в коде и ожидать те или иные ошибки. Даже если приложение просто пытается открыть файл, который нечаянно «убили», VBA-сообщение об отсутствии файла не так информативно, как могло бы быть сообщение разработчика, которое не только должно сообщить об отсутствии файла, но и предложить возможные пути его восстановления или замены старой копией. Следует различать состояния «доступность» («enabled») и «активность» («active») обработчика ошибок. Обработчик доступен, если оператор On Error выполнен, но ошибка еще не возникла. Обработчик активен, когда им выполняется обработка некоторой возникшей ошибки. Если ошибка возникает, когда обработчик активен (обрабатывает ранее возникшую ошибку), эта ошибка не обрабатывается и управление передается в вызывающую процедуру. Если вызывающая процедура имеет обработчик ошибок, находящийся в состоянии «enabled», обработчик переходит в состояние «active» (т.е. обработки ошибки). Если обработчик вызывающей процедуры находится в состоянии «active», то управление передается предыдущей вызывающей процедуре с обработчиком в состоянии «enabled», но не «active». Т.е. в цепочке вызывающих процедур ищется обработчик ошибок в состоянии «enabled», готовый обработать ошибку. Обычно в процедурах обработки ошибок для определения причины ошибки используется свойство Number объекта Err. Сообщение об ошибке (довольно «скупое»), связанное с Err.Number, содержится в Err.Description. Поэтому обычно на стадии отладки после метки, на которую передается управление выполнением программы в случае возникновения (ожидаемой) ошибки, помещается следующий оператор: MsgBox "Error " & Err & & Err.Description В процедуре листинга 15.9 используется On Error Resume Next для того, чтобы при обнаружении отсутствия в системе экземпляра приложения Excel программа не завершалась с ошибкой. Листинг 15.9. Обработчик ошибок для защиты программы от прерывания 1 Sub TestErrorQ 2 Dim xlApp As Object 3 Dim xlSheet As Object 394 Глава 15 4 5 6 7 8 9 10 11 12 13 14 15 On Error Resume Next Set xlApp = Nothing Set xlApp = GetObject(, "Excel Application") If Err.Number 0 Then Set xlApp = CreateObject("Excel.Application") End If Err.Clear * Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook Worksheets(1) xlSheet.Application.Visible = True End Sub Управление другими приложениями ЕЪсизсз 16 Управление host-приложениями VBA Вы уже знаете, что Visual Basic for Applications — язык программирования, предназначенный в основном для работы с имеющимся программным обеспечением и для расширения его возможностей. Приложения Microsoft Office имеют множество различных объектов, доступных VBA. Свойства и методы этих объектов позволяют посредством VBA-кода управлять, практически, любым аспектом работы приложений Microsoft Office. Из этой главы вы узнаете, как посредством VBA-кода управлять основными операциями в Word и Excel, а именно: Как работать с объектами Excel: Workbook и Worksheet. Как использовать методы объекта Excel, возвращающие объекты Range, включая то, как задать и выделить диапазоны ячеек в листе Excel. Как ввести в ячейки листа Excel значения и формулы. Как работать с объектами Word: Document и Template. Как использовать методы объекта Word, возвращающие разделы документов^ включая объекты Paragraphs, Characters и Range. Как добавить, вырезать, скопировать или вставить данные в лист Excel или документ Word. Работа с Excel В первой части главы вы узнаете, как управлять наиболее важными и основными объектами Excel. Во-первых, вы узнаете об объектах Workbook и Worksheet, а затем научитесь управлять информацией, содержащейся в объекте Worksheet. Далее из этой же главы вы узнаете, как управлять аналогичными объектами в Word. Возвращение объекта книга В Excel каждая книга является объектом Workbook, a Workbooks — коллекцией всех открытых книг в текущем рабочем сеансе Excel. Для ссылок на конкретную книгу следует использовать коллекцию Workbook объекта Application: СИНТАКСИС Workbooks(Index) Index может быть: Численным выражением, представляющим книгу, которую необходимо использовать. Число 1 означает первую книгу, открытую в текущем рабочем сеансе, 2 — вторую и так далее. Строковым выражением, представляющим имя открытой книги, которую вы хотите использовать. Управление host-приложениями VBA 397 Более распространенный и обычно наиболее удобочитаемый способ — использование в качестве Index текстовой строки. Листинг 16.1 содержит соответствующий пример. Листинг 16.1. Использование коллекции Workbooks 1 Sub SetWorkbookProte'ction () 2 ' Установка защиты книги > , « 3 4 Workbooks("Книга17_01.XLS").Protect Structure:=True, Windows:=True 5 MsgBox "Защита для файла Книга17_01.XLS установлена", , _ 6 "Установка защиты книги" 7 End Sub Рис. 16.1 Результат выполнения кода листинга 16.1 Усыионна защит ы киши Защита для файла Книга 17_O1.XLS установлена Выражение в строке 4, Workbooks("KHHral7_01.XLS"), возвращает объектную ссылку на объект книга с именем KHHral7_01.xls. Метод Protect устанавливает защиту книги. Оператор MsgBox (в строках 5-6) выводит сообщение, информирующее о том, что для данной книги защита была установлена. (Предполагается, что книга с именем KHHral7_01.xls в данный момент открыта. Если это — не так, то вы получите сообщение о runtime-ошибке.) Как открыть книгу Если необходимая вам книга еще не открыта, воспользуйтесь методом Open для загрузки ее в память. СИНТАКСИС Workbooks.Open(Filename) Аргумент Filename — текстовая строка, представляющая полный путь к книге: диск, папка и имя файла. Если вы не зададите имя диска или папку, Excel будет искать файл на текущем диске и в той папке, которая открыта в данный момент. Пример использования'метода Open представлен в листинге 16.2. Листинг 16.2. Применение метода Open для открытия книги 1 Sub OpenWorkbook() 2 ' Предлагает открыть и затем открывает ее 3 4 Dim Workbookname As String 5 6 Workbookname = _ 7 InputBox("Введите полный путь к книге:") 8 If Workbookname О "" Then 9 Workbooks.Open FileName:=Workbookname 10 End If 11 End Sub 398 Глава 16 В этой процедуре переменная WorkbookName объявлена с типом .String (строка 4). Функция InputBox предлагает пользователю ввести имя файла книги (строки 6 и 7). Оператор If...Then (в строке 8) проверяет, не отменил ли пользователь диалог ввода. Если — нет, другими словами, если строка WorkbookName не пуста, метод Open использует WorkbookName для открытия файла (строка 9). Как создать новую книгу Если вашей процедуре требуется создать новую книгу, воспользуйтесь методом Add коллекции Workbooks. СИНТАКСИС Workbooks.Add([Template]) Необязательный аргумент Template определяет тип книги, создаваемой Excel. Если вы опустите Template, Excel создаст книгу, заданную по умолчанию и содержащую некоторое количество чистых листов. Количество чистых листов в новой книге задается на вкладке Общие (General) в диалоговом окне Параметры (Options) (вызвать данное диалоговое окно можно, выбрав команду Сервис | Параметры (Tools | Options)). Вы можете также задать количество чистых листов в новой книге при помощи свойства Application.SheetsInNewWorkBook. Для того чтобы создать новую книгу, основываясь на существующем шаблоне, подставьте в качестве аргумента Template строковое значение, определяющее имя шаблона. Если необходимый вам шаблон расположен не в загрузочной или не в альтернативной загрузочной папке, включайте в аргумент Template полный путь: имя диска, папку и имя шаблона. Чтобы создать книгу, содержащую только один лист, используйте одну из следующих встроенных констант аргумента Template (эти константы определены в классе xlWBATemplate): xlWBATWorksheet, xlWBATChart, x!WBATExce!4-MacroSheet или xlWBATExce!4IntlMacroSheet. Листинг 16.3 демонстрирует пример процедуры, создающей новую книгу. Листинг 16.3. Использование метода Add для создания новой книги 1 Sub CreateMonthlyReport() 2 ' Создание новой книги на основе шаблона "Балансовый отчет" 3 4 Dim dPath As String 5 6 dPath = "E:\Program Files\Microsoft Office" 7 dPath = dPath S "\Templates\1049\" 8 Workbooks-Add Template:=dPath & "Балансовый отчет" 9 With ActiveWorkbook 10 .Title = "Отчет компании" 11 .Subject - "Отчет за ДЕКАБРЬ 2002" 12 .Author = "Иван Петров" 13 End With 14 End Sub Код листинга 16.3 создает новую книгу на базе шаблона Балансовый отчет, поставляемого с Excel и Microsoft Office (строка 8). (Путь к шаблону книги, используемому в этом примере, дан из расчета, что установка Microsoft Office выполнялась в папку, предлагаемую по умолчанию; в вашем случае файл может находиться в другом месте.) Любая новая книга автоматически становится активной книгой. В строках с 9 по 13 для добавления в файл новой книги некоторой общей Управление host-приложениями VBA 399 информации — Title, Subject и Author — используется объект ActiveWorkbook. Для просмотра результатов работы кода строк 9-13 используйте или всплывающую Explorer-подсказку (см. рис. 16.2), или вкладку Summary диалогового окна Properties для данного файла. Рис. 16.2 Общую информацию о файле можно увидеть, если просто на некоторое время поместить на его значке курсор мыши Книга! г nt г Мт ’о > " е. Управление host-приложениями УВД JT \ Балансовый отчет 1202 ЙУ |Г 1СЛ ’ Туре Лист Microsoft Excel Author Иван Петров Title Отчет компании Subject Отчет за ДЕКАБРЬ 2002 Date Modified' 1/5/2003 11'33 AM Size 28 О KB Как сделать книгу активной Если ваша VBA-программа работает с несколькими одновременно открытыми книгами, вам может понадобиться переключаться из одной книги в другую для вывода на экран, например, отчета или введенных данных. Чтобы сделать открытый документ активным, используйте метод Activate: СИНТАКСИС Object.Activate В данном случае Object представляет любую допустимую объектную ссылку на лист, который необходимо сделать активным. В листинге 16.4 — пример процедуры, использующей метод Activate. Листинг 16.4. Использование метода Activate для переключения к книге 1 Sub ActivateTest() 2 ' Изменение активной книги без вывода на экран 3 4 Dim SaveBook As String 5 6 SaveBook = ActiveWorkbook.Name 7 8 Application.Screenupdating = False 9 Workbooks("Балансовый отчет 1202.XLS").Activate 10 11 ' код, выполняющий заполнение файла Балансовый отчет 1202.XLS 12 ' . . . 13 14 Workbooks(SaveBook).Activate 15 Application.Screenupdating = True 16 End Sub Эта простая процедура демонстрирует два принципа хорошего программирования. Во-первых, по возможности следует скрывать от пользователя промежуточные операции, выполняемые вашей программой. Например, если процедура содержит операторы, форматирующие диапазоны ячеек и введенные данные, выполняйте данные действия «за кулисами». Выводите для пользователя на экран лишь 400 Глава 16 конечный результат. Сделать это можно, задав свойство Screenupdating объекта Application равным False. Во-вторых, если вы устанавливаете книгу активной, потому, что это требуется вашей программе, а не для того, чтобы пользователь мог увидеть другой файл, ваша процедура должна по завершении «возвращать» пользователя в то же самое место, где он находился при ее старте. Особенно это относится к малоопытным пользователям, которые приходят в замешательство, обнаружив, что по выполнении процедуры, они оказываются совсем в другой книге, не имея, при этом, никаких разумных предположений для объяснения этого факта. Назначение представленной в листинге 16.4 процедуры — переключиться из текущей книги в другую книгу (Балансовый отчет 1202.XLS), произвести в ней программным образом некоторые изменения, а затем вернуться к первоначальной книге. Сначала (в строке 6) имя текущей активной книги сохраняется в строковой переменной SaveBook. Далее, чтобы избавить пользователя от наблюдения за деталями выполнения процедуры, в строке 8 свойство Screenupdating устанавливается равным False. В строке 9 книга Балансовый отчет 1202.XLS устанавливается активной. Строки, следующие далее, должны выполнять действия в книге Балансовый отчет 1202.XLS. Реальная программа, которая вносит изменения в Балансовый отчет 1202.XLS, в данном примере опущена. Для того чтобы «вернуть» пользователя в то же место, в котором он находился перед запуском процедуры, в строке 14 активной становится первоначальная книга. В строке 15 значение ScreenUpdating вновь устанавливается равным True. I Как сохранить книгу Если ваша VBA-программа вносит в книгу изменения, вы должны предло- ' жить пользователю сохранить их. Сделать это довольно просто, или включив встроенную команду Сохранить в меню вашей программы, или добавив кнопку Сохранить на панель инструментов программы, если программа имеет меню или панели инструментов. Хотя возможны случаи, когда у вас возникнет потребность сохранить книгу под управлением процедуры. Например, вы захотите создать собственную версию команды Файл | Сохранить. Более того, вы, возможно, попытаетесь предостеречь начинающего пользователя от выполнения неудачной последовательности команд, таких как закрытие книги, выход из программы или из Excel без сохранения результатов работы. Для сохранения книги следует пользоваться методом Save. СИНТАКСИС Object.Save В данном случае, Object — это объектная ссылка на открытый объект Workbook, который следует сохранить. Существует также очень удобный метод SaveCopyAs. Этот метод сохраняет копию заданной книги на диск, никак не влияя на эту книгу в памяти. Общий синтаксис метода SaveCopyAs выглядит следующим образом: СИНТАКСИС Object.SaveCopyAs(Filename) Object — это объектная ссылка на объект Workbook, который будет сохранен, a Filename — строковое выражение для имени, которое следует использовать при сохранении копии книги. Управление host-приложениями VBA 401 В листинге 16.5 приведен код, использующий методы Save и SaveCopyAs. Листинг 16.5. Использование методов Save и SaveCopyAs 1 Sub BackUpToZIP() 2 ' Сохраняет активную книгу и делает ее копию на ZIP-диске Н: 3 4 Const ZIPDrv = "Н:” 5 б With ActiveWorkbook 7 If Not .Saved Then .Save 8 .SaveCopyAs Filename:=ZIPDrv & .Name 9 End With 10 End Sub Эта процедура сохраняет активную книгу и создает резервную копию на ZIP-диске Н (рис. 16.3). Процедура начинается с объявления единственной константы для имени ZIP-диска. Оператор With выполняет несколько команд для объекта ActiveWorkbook. Рис. 16.3 Копия активной книги на ZIP-диске -дополнительная гарантия сохранения результатов вашей работы ZIP750 (Н:) Elie Edit View Favorites Tools Help Q Back - , * > Search «cdress Н \ „IMAC Format Options ©PC Users Click Here Щкнига17_О1 Тест If...Then (строка 7) проверяет свойство Saved книги. Если оно равно False, в книге имеются изменения, которые еще не были сохранены, поэтому процедура вызывает метод Save. Имя резервной копии файла создается конкатенацией значения константы ZIPDrv и свойства Name книги. Результат используется в качестве аргумента Name метода SaveCopyAs (строка 8), который сохраняет копию книги на гибком диске. Метод Save не следует использовать для новой книги (которая прежде ни разу не сохранялась). Если вы все же сделаете это, Excel сохранит новую книгу под ее текущим именем, например, KHHFAl.XLS. Чтобы при сохранении присвоить книге имя используйте метод SaveAs: СИНТАКСИС Object.SaveAs([FileName] [, FileFormat] [, Password] [, WriteResPassword] [, ReadOnlyRecommended] [, CreateBackup] [, AccessMode] [, ConflictResolution] [, AddToMru]) Object — это объектная ссылка на объект Workbook, a Filename — строковое выражение для имени, которое следует использовать при сохранении копии книги. FileFormat (тип Variant) — применяемый при сохранении файла формат. Для существующего на диске файла по умолчанию используется последний заданный формат, для нового файла — формат используемой версии Excel. Password (тип Variant) — строка (не более 15-ти символов), которая используется в качестве пароля при открытии файла. Пароль вводится в диалоговом окне, представленном на рис. 16.4. 402 Глава 16 Рис. 16.4 При открытии защищенного паролем файла пароль вводится в диалоговом окне Введите пароль Книга17_01 xls4 xls' защищен Пароль OK j Отмена j WriteResPassword (тип Variant) — строка, определяющая пароль, при помощи которого файл защищается от перезаписи. Рис. 16.5 Использование в методе SaveAs аргумента WriteResPassword позволяет закрыть файл на запись для пользователей, не знающих соответствующего пароля Пароль 'Книга17_01 xls4 xls зарезервирован Владимир Введите пароль разрешения записи или откроите файл в режиме Только для чтения' Пароль Отмена Только для чтения ReadOnlyRecommended (тип Variant) — аргумент, который при значении, равном True, приводит к появлению окна (рис. 16.6) с рекомендацией открывать файл только на чтение. | ) 'Книга17_01 xls рекомендуется открывать только для чтения, если изменения, внесенные в нГ'' этот файл, не обязательно должны быть записаны Открыть только для чтения’ Да Отмена Рис. 16.6. Использование в методе SaveAs аргумента ReadOnlyRecommended приводит к тому что при открытии файла пользователь уведомляется о том, что файл желательно не изменять CreateBackup (тип Variant) — аргумент, который при значении, равном True, приводит к созданию резервной копии сохраняемой книги (рис. 16.7). Рис. 16.7 Использование в методе SaveAs аргумента CreateBackup приводит к созданию резервной копии сохраняемого файла Управление host-приложениями VBA 403 AccessMode — значение одной из следующих констант: xlExclusive (монопольный доступ); xlNoChange (не менять режим доступа, действует по умолчанию); xlShared (многопользовательский доступ). При использовании константы xlExclusive файл может быть открыт для записи только одним пользователем. Другой пользователь получит сообщение о том, что файл уже открыт, в диалоговом окне, представленном на рис. 16.8. С другой стороны, константа xlShared дает возможность сразу нескольким пользователям работать с одним файлом (рис. 16.9). Редактирование 'Книга17_01 xls' запрещено пользователем 'Владимир' Откройте только для чтения или нажмите "Уведомить", чтобы открыть копию документа только для чтения и получить уведомление о его освобождении Тольго чтение Уведомить Отмена Рис. 16.9 Этот файл был сохранен с использованием константы xlShared Рис. 16.8. Если вы получите при открытии файла такое сообщение, значит, кто-то уже работает с файлом, сохраненным ранее с использованием константы xlExclusive При одновременной работе нескольких пользователей с одним файлом в любой момент времени любой пользователь может сохранять свои изменения в файле. При этом, если какой-либо другой пользователь уже сохранял данные на диске, эти данные попадают в файл того, кто делает в данный момент сохранение своих данных. На рис. 16.10 показано сообщение, выдаваемое пользователю, который сохраняет данные. Однако при такой совместной работе с одним файлом не всегда можно просто сохранить свои данные в файле на диске. На рис. 16.11 представлено окно Возник конфликт доступа, которое предупреждает о том, что вы пытаетесь одновременно с другим пользователем изменить содержимое одной и той же ячейки. ConfhctResolution — одна из следующих констант: xlUserResolution (отображать диалоговое окно разрешения конфликтов); xlLocalSessionChanges (автоматически принимать пользовательские изменения); xlOtherSessionChanges (принимать другие изменения вместо локальных пользовательских). 404 Глава 16 ©пил ]|_ ем f । д.Би Дчнные < гнп Справка В? ы 100% -г “ Anal Cyr V 10 -г ж /с ч s£ s $ •- АЗ ▼ А Изменения пользователя Владимир 4 „ _ _ .. __ _ ____ . - 1 Изменения пользователя Наталья • 2 3 4 5 6 7 8 Q Н Готово [Изменен^ пользователя Владимир н\л NUM Рис. 16.11 Если вы пытаетесь сохранить изменения в общем файле, с которым работает другой пользователь, то не всякие ваши изменения «легко» записать на диск Рис. 16.10. Сообщение, выдаваемое пользователю, который сохраняет данные в файле, записанном с использованием константы xIShared и открытом одновременно несколькими пользователями AddToMru (тип Variant) — аргумент, который (при равенстве значению True) указывает на то, что файл добавляется в список недавно используемых файлов. По умолчанию этот аргумент принимается равным значению False. Метод SaveAs имеет и другие параметры, о которых вы можете узнать из справочной системы. Как закрыть книгу После завершения работы с книгой, следует ее закрыть, чтобы высвободить память и избежать «засорения» экрана. Закрыть книгу можно, воспользовавшись одной из форм метода Close. СИНТАКСИС Workbooks.Close Object.Close(SaveChanges) При использовании первой синтаксической формы можно просто закрыть все открытые книги. Excel предлагает сохранить изменения в книгах перед тем, Управление host-приложениями VBA 405 как их закрыть, если это необходимо. Вторая синтаксическая форма позволяет закрыть конкретную книгу, на которую указывает Object. Аргумент SaveC-hanges используется следующим образом: Если SaveChanges равен True, Excel сохраняет книгу автоматически, перед тем как ее закрыть. Если SaveChanges равен False, Excel закрывает книгу без сохранения изменений. Если вы опустите аргумент SaveChanges, Excel предложит (в случае необходимости) выполнить сохранение. Листинг 16.6 демонстрирует использование метода Close. Листинг 16.6. Использование метода Close 1 Sub CloseAll() 2 ' Закрывает все открытые книги и предлагает сохранить сделанные 3 ' в них изменения 4 Const qButtons = vbYesNo + vbQuestion 5 6 Dim Book As Workbook 1 Dim Ans As Integer 8 Dim MsgPrompt As String 9 10 For Each Book In Workbooks 11 If Not (Book.Name = ThisWorkbook.Name) Then 12 If Not Book.Saved Then 13 MsgPrompt = "Сохранить изменения в " & Book.Name & "?" 14 , Ans = MsgBox(prompt:=MsgPrompt, Buttons:=qButtons) 15 If Ans = vbYes Then 16 *' Book.Close SaveChanges:=True 17 • ' Else 18 Book.Close SaveChanges:=False 19 End If 20 . ’ Else 21 Book.Close 22 End If 23 End If 24 Next Book 25 End Sub Данная процедура закрывает все открытые книги (за исключением книги, содержащей процедуру) и предлагает пользователю сохранить изменения для каждой книги, имеющей несохраненные изменения. Используйте процедуру, подобную этой, вместо метода Workbooks.Close, когда вам необходимо, чтобы пользователь не отменял операцию сохранения. Встроенная в Excel команда Сохранить имеет кнопку Отмена. После объявления константы и нескольких переменных (строки с 4 по 8) процедура начинает цикл For Each для обработки всех книг в коллекции Workbooks. Поскольку закрытие книги, содержащей выполняемую в данный момент процедуру, приведет к ее остановке, строка 11 содержит оператор If ...Then, который проверяет, не имеет ли книга, обрабатываемая в данный момент, то же самое имя, что и книга, содержащая процедуру CloseAll. Если — да, то часть кода, выполняющая закрытие книги пропускается; строки с 12 по 22 выполняются только в том случае, если книга не содержит процедуры CloseAll. (Свойство ThisWorkbook возвращает ссылку на книгу, содержащую выполняемый в данный момент код.) Если книга содержит изменения, которые не были сохранены (строка 12), функция MsgBox (строка 13) запрашивает пользователя, необходимо ли сохранять 406 Глава 16 изменения. Если пользователь выбирает Yes (то есть переменная Ans получит значение vbYes), процедура запускает метод Close с аргументом SaveChanges, равным True (строка 16). В противном случае процедура закрывает книгу с SaveChanges, равным значению False (строка 18). Если в книге отсутствуют несохраненные изменения, процедура запустит метод Close без аргументов (строка 21). Работа с объектами Worksheet Объекты Worksheet содержат набор свойств и методов, которые вы можете использовать в своей программе. Эти свойства и методы позволяют делать листы активными и скрывать их, добавлять в книгу новые листы, а также перемещать, копировать, переименовывать или удалять их. В следующих разделах описывается каждая из этих операций над листом. Возвращение значения объекта Worksheet Каждый лист является объектом Worksheet, а все листы данной книги образуют коллекцию Worksheets. Для ссылок на заданный лист используйте коллекцию Worksheets объекта Workbook: СИНТАКСИС Object.Worksheets(Index) Object представляет ссылку на объект Workbook, содержащий лист. Index может быть: Числом, представляющим лист, который следует использовать. Число 1 означает первый лист в книге, 2 — второй лист и так далее. Имя листа, который следует использовать, в виде строки. Это имя, которое появляется на вкладке листа. Листинг 16.7 представляет пример наиболее частого способа использования метода Worksheets — когда лист идентифицируется строкой текста. Листинг 16.7. Использование коллекции Worksheets 1 Sub SetWorksheetProtection() 2 ' Активизирует защиту листа 3 4 Workbooks("Балансовый отчет 1202.xls").Worksheets( 5 "Расходы").Protect Contents:=True, Scenarios:=True 6 MsgBox "Защита листа 'Расходы' активизирована." 7 End Sub ' Объект Workbooksf'BaaaHcoBbih отчет 1202.XLS").Worksheetsf'Pacxoabi") возвращает ссылку на лист с именем Расходы в книге Балансовый отчет 1202.XLS.xls. Метод Protect задает защиту для содержимого и сценария. Процедура MsgBox информирует пользователя о том, что защита листа активизирована (рис. 16.12). Рис. 16.12 Процедура MsgBox информирует пользователя о том, что защита листа активизирована Защита листа 'Расходы' активизирована Управление host-приложениями VBA 407 Для работы рассматриваемой программы необходимо, чтобы в коллекции Workbook имелась та книга, на которую выполняется ссылка — Балансовый отчет 1202.XLS.xls. Если это — не так, VBA выдаст сообщение об ошибке (рис. 16.13), которое вряд ли поможет вам сразу понять причину ошибки. Хорошим правилом при программировании является проверка наличия объекта в коллекции перед попыткой его использования. В следующем листинге защита листа книги Балансовый отчет 1202.XLS.xls выполняется в том случае, если эта книга находится в коллекции Workbooks. Наличие самого листа в книге не проверяется, хотя можно было бы и проверить. Рис. 16.13 Если в коллекции Workbook нет книги, на которую выполняется ссылка, VBA выдаст сообщение об ошибке, которое вряд ли поможет вам сразу понять причину ошибки Листинг 16.8. Использование коллекции Worksheets 1 Sub SetWorksheetProtection() 2 ' Активизирует защиту листа с проверкой 3 ' наличия книги в коллекции Workbooks 4 Dim ProtYes As Boolean 5 ProtYes = False 6 7 For Each Book In Workbooks 8 If (Book.Name = "Балансовый отчет 1202.xls") Then 9 Book.Worksheets("Расходы").Protect _ 10 Contents:=True, Scenarios:=True 11 MsgBox "Защита листа 'Расходы' активизирована " 12 ProtYes = True 13 Exit For 14 End If 15 Next Book 16 17 If Not ProtYes Then MsgBox "Книга не найдена!" 18 19 End Sub ' В строках 4 и 5 объявляется и инициализируется переменная ProtYes, которая используется в качестве индикатора наличия необходимой книги в коллекции Workbooks. В цикле For Each (строки 7-15) для каждой книги проверяется свойство Name. При совпадении этого свойства со строкой "Балансовый отчет 1202.xls” выполняется защита листа Расходы (строка 9), переменной ProtYes присваивается значение True (книга найдена), происходит выход из цикла при помощи оператора Exit For. В строке 17 выдается сообщение об отсутствии необходимой книги в коллекции Workbooks, если переменная ProtYes содержит значение False. Если вам необходимо сослаться на активный лист, используйте свойство книги ActiveSheet. Если вам нужно сослаться на все страницы книги (или вы не уверены, какой тип листа необходимо выбрать), используйте вместо коллекции Worksheets коллекцию Sheets. Коллекция Sheets содержит не только листы, но и диаграммы. 408 Глава 16 Как сделать лист активным Большинство книг содержат более одного листа, поэтому вашей программе может понадобиться переключаться с одного листа на другой. Например, отобразить один лист для ввода данных и затем переключиться на другой лист, чтобы просмотреть отчет или диаграмму. Выполнять переключение между листами можно при помощи метода Activate. СИНТАКСИС Object.Activate Object представляет ссылку на объект Worksheet, который следует сделать активным. Листинг 16.9 содержит пример использования метода Activate. Листинг 16.9. Использование метода Activate для перехода на заданный лист 1 Sub Displaysheet () 2 1 Устанавливает активным лист "Расходы" 3 4 Dim Ans As Integer, qBtns As Integer 5 Dim mPrompt As String 6 7 • mPrompt = "Хотите просмотреть ""Расходы""?" 8 qBtns = vbYesNo + vbQuestion + vbDefaultButton2 । 9 Ans = MsgBox(prompt:=mPrompt, Buttons:=qBtns) 10 If Ans = vbYes Then 11 Workbooks("Балансовый отчет 1202.xls").Worksheets( _ "Расходы").Activate 12 End If 13 End Sub В данной процедуре пользователю задается вопрос, хочет ли он просмотреть определенный лист, в данном случае — Расходы (строки 7-9 программы). Если пользователь выбирает кнопку Yes, то лист с именем Расходы становится активным (строка 11). Для выбора листа используйте метод Select: СИНТАКСИС Object.Select Данный метод полезен для создания трехмерных ссылок и определения листов, которые следует вывести на печать. Трехмерная ссылка (three-dimensional reference) — это ссылка на диапазон ячеек более чем одного листа. Не следует без необходимости делать лист активным. Для большинства свойств и методов объекта Worksheet вы можете просто воспользоваться методом Worksheets для ссылок на лист, который нужно использовать. Например, следующий оператор возвращает стандартную ширину листа График баланса, не делая его активным: StdWidth = Worksheets("График баланса").Standardwidth Как создать новый лист Коллекция Worksheets имеет метод Add, который вы можете использовать для добавления в книгу новых листов. Синтаксическая конструкция применения данного метода следующая: Управление host-приложениями VBA 409 СИНТАКСИС Object.Worksheets.Add([Before] [, Count] [, Type]) Object представляет ссылку на объект Workbook, в который добавляется новый лист. Аргумент Before, задает лист, перед которым добавляется новый лист, а аргумент After — лист, после которого добавится новый лист. (Нельзя использовать аргументы Before и After одновременно в одном и том же операторе.) Если опустить оба аргумента, как Before, так и After, VBA добавит новый лист перед активным листом. Count — количество вновь добавляемых листов. (Если опустить Count, метод Add добавит один лист.) Туре — тип добавляемого листа. Существуют следующие возможные варианты аргумента Туре (определенные в классе XlSheet-Туре): xlWorksheet (устанавливается по умолчанию), xlChart, х!Ехсе14Мас-roSheet или xlExce!4IntlMacroSheet. Как переименовать лист Имя листа — это текст, который появляется на закладке листа. В случае необходимости переименовать лист следует изменить свойство Name листа: СИНТАКСИС Object.Name Object — это лист, который будет переименован. Копирование и перемещение листа Если вам необходимо расположить листы книги в определенном порядке, используйте методы Сору и Move. Оба метода имеют одинаковый синтаксис. СИНТАКСИС Object.Сору([Before] [, After]) Object.Move([Before] [, After]) Object — объектная ссылка на лист, который необходимо скопировать или переместить. Before задает лист, перед которым, a After — лист, после которого будет помещен копируемый или перемещаемый лист. (Нельзя использовать аргументы Before и After одновременно в одном операторе.) Если опустить как Before, так и After, VBA создаст для копируемого или перемещаемого листа новую книгу. Листинг 16.10 содержит процедуру, использующую метод Move. Листинг 16.10. Использование метода Move для перемещения листа 1 Sub CreateWorksheet () 2 ' Создание нового листа и перемещение 3 ' его в конец книги 4 5 Dim NewSheet As String 6 7 Worksheets.Add before:“Worksheets(Worksheets.Count) 8 NewSheet = ActiveSheet.Name 9 With Worksheets(NewSheet) 10 .Move after:“Worksheets(Worksheets.Count) 11 .Activate 410 Глава 16, I 12 End With 13 14 End Sub С помощью метода Add в книгу добавляется лист (строка 7). В данном случае метод Add вызывается с необязательным аргументом Before для того, чтобы добавить новый лист непосредственно перед последним листом книги. Номер последнего листа книги определяется в строке 7 с помощью свойства Count, которое возвращает количество листов в книге. После чего новое название листа сохраняется в переменной NewSheet. В строке 10 с помощью метода Move, новый лист помещается за последним листом книги. Для того чтобы получить количество листов в книге, вновь используется свойство Count. После этого новый лист устанавливается активным (строка 11). Если вы разрабатываете приложение, в котором часто приходится создавать и перемещать листы, будет неплохой практикой устанавливать перед этими операциями команды отключения обновления экрана (Application.ScreenUpdating = False). При этом следует не забывать включать обновление экрана, если ваша процедура его отключала (Application.ScreenUpdating = True). Помните, что вы можете добавить лист и после любого заданного листа. Процедура в листинге 16.10 добавляет лист перед последним листом и затем перемещает его, поскольку Excel не позволяет добавлять листы в конец книги. Использование аргумента After, совместно с методом Add позволяет добавить новый лист после любого существующего листа, за исключением последнего. Как удалить лист В целях поддержания управляемости книгами и экономии места на диске ненужные листы следует удалять. Это особенно актуально в случаях, когда созданные вами приложения используют для хранения промежуточных результатов временные листы. Для удаления листа используйте метод Delete. СИНТАКСИС Object.Delete Object — ссылка на лист, который следует удалить. Листинг 16.11 демонстрирует пример использования метода Delete. Листинг 16.11. Использование метода Delete для удаления листа 1 Sub DeleteTemporarySheets() 2 ' Удаление всех временных листов * 3 4 Dim Sheet As Worksheet 5 6 Application.DisplayAlerts = False 7 8 For Each Sheet In Workbooks ( _ "Балансовый отчет 1202.XLS").Worksheets 9 If InStr(l, Sheet.Name, "Временный") Then 10 Sheet.Delete 11 End If 12 Next Sheet 13 14 Application.DisplayAlerts = True 15 End Sub Управление host-приложениями VBA 411 Эта процедура проверяет каждый лист книги и удаляет все ранее созданные временные листы. Процедура «полагает», что временные листы должны называться Временный!, Временный2 и так далее. Процедура объявляет объектную переменную Sheet (типа Worksheet) и задает свойство DisplayAlerts объекта Application равным False (строка 6). Таким образом подавляется обычное диалоговое Excel-окно подтверждения, которое появляется всякий раз, когда вы пытаетесь удалить лист. В строке 8 начинается цикл For Each, перебирающий все листы книги Балансовый отчет 1202.XLS. Функция InStr проверяет каждый лист на наличие в названии листа строки "Временный". Если такая строка обнаруживается, то (в строке 10 кода) этот лист удаляется. Когда данный процесс завершается, свойство DisplayAlerts вновь устанавливается равным True (строка 14). Процедура в листинге 16.11 будет работать правильно, если Option Compare Text является текущей глобальной установкой сравнения. Методы, возвращающие объекты Range Наибольшую долю при работе с листом составляют: ввод информации, копирование данных, а также использование опций форматирования, включая работу с ячейками, диапазонами ячеек и их именами. Нет ничего удивительного в том, что так много методов объекта Excel в VBA, в конечном счете, выполняют какие-либо действия с диапазоном ячеек. При обычной диалоговой работе с Excel прежде чем работать с диапазоном ячеек листа, диапазон необходимо выделить. Для процедуры VBA это означает, что вы должны сослаться на диапазон ячеек листа, перед тем как сможете что-нибудь с ним сделать. Наиболее распространенным из всех объектов Excel является объект Range. Объект Range может быть одной ячейкой, строкой, колонкой, набором ячеек и даже трехмерным диапазоном значений (то есть набором ячеек нескольких листов). Использование Range метода Наиболее легкий и прямой способ задать ячейку или диапазон ячеек состоит в использовании метода Range: СИНТАКСИС Object.Range(Name) Object — ссылка на объект Worksheet, который содержит диапазон ячеек. Если вы опустите Object, VBA будет «считать», что метод применяется к объекту ActiveSheet. Аргумент Name — ссылка на диапазон ячеек или имя диапазона, введенное как текст. Метод Range работает также с именованными диапазонами ячеек. Код листинга 16.12 демонстрирует пример использования метода Range. Листинг 16.12. Использование метода Range 1 2 3 4 5 6 7 8 9 1 Sub FormatRangeFont() 2 1 С помощью метода Range задается шрифт для диапазона ячеек 3 4 With Worksheets("Лист1") 5 .Range("Al:LI").Font.Size = 24 6 .Range("Al:LI").Font.Bold = True 7 .Range("Al:LI").Font.Name = "Times New Roman" 8 End With 9 End Sub 412 Глава 16 В этом примере все три оператора (строки с 5 по 7) возвращают диапазон ячеек А1:Ы листа Лист1. (Обратите внимание на то, что диапазон ячеек следует заключать в кавычки.) Процедура листинга 16.12 устанавливает некоторые атрибуты шрифта для заданного диапазона ячеек. Font — свойство объекта Range. Font возвращает ссылку на объект Font, связанный с заданным диапазоном значений. Свойства объекта Font — те же самые, что и атрибуты шрифта, которые можно задать при помощи диалогового окна Шрифт: полужирный, курсив, подчеркнутый и другие. Ниже, в качестве примера, представлено несколько1 свойств объекта Font (во всех случаях Object — объект типа Range): Object.Font.Bold: Устанавливает (или отменяет) полужирный стиль шрифта (True или False). Ob/ect.Font.Italic: Устанавливает (или отменяет) курсив (True или False). Ob/ect.Font.Underline: Устанавливает эффект подчеркивания включенным или выключенным. Значение свойства Underline может быть равно одной из встроенных констант, определенных в классе xlUnderlineStyle: xlUnderline-StyleNone, xlUnderlineStyleSingle, xlUnderlineStyleDouble, xlUnderlineSty-leSingleAccounting или xlUnderlineStyleDoubleAccounting. Ob/ect.Font.Name: Устанавливает наименование шрифта. Значение свойства Name определяется, например, в виде строки "Arial". Obyect.Font.Size: Устанавливает размер шрифта (в пунктах). В Excel имеется альтернативная синтаксическая конструкция для метода Range, применение которой требует двух аргументов: СИНТАКСИС Object.Range(Cell 1, Се112) Как обычно, Object — является объектом типа Worksheet, содержащим диапазон значений ячеек. Аргумент Celli определяет верхний левый «угол» диапазона, а Се112 — правый нижний «угол». Каждый аргумент может быть текстовым адресом ячейки, объектом Range, состоящим из одной ячейки, или же целым столбцом или строкой. Преимущество использования данной синтаксической конструкции заключается в разделении угловых значений в различных аргументах, что позволяет независимо изменять значение для каждого из «углов» под управлением процедуры. Например, вы можете задать имена переменных, таких как UpperLeft и Lower-Right, и возвращать объекты Range различных размеров в виде Range(UpperLeft, LowerRight) Не следует использовать в методе Range координаты диапазонов, если доступны их имена. Имена диапазонов облегчают восприятие и отладку программы. Использование метода Cells Хотя для того чтобы выполнить ссылку на одну ячейку, можно воспользоваться методом Range, такую же возможность дает и метод Cells, который является более гибким: Для того чтобы просмотреть полный список свойств Font, используйте инструмент Object Browser. Управление host-приложениями VBA 413 СИНТАКСИС Object.Cells(Rowindex, Columnindex) Object — ссылка или на Worksheet или на объект Range, содержащий ячейку, с которой необходимо работать. Если Object опущен, метод применяется к объекту ActiveSheet. Rowindex — номер строки, в которой находится ячейка. Если Object — лист, то Rowindex, равный 1, ссылается на строку 1 листа. Если Object — диапазон значений, то Rowindex, равный 1, ссылается на первую строку диапазона. Columnindex — номер столбца, в котором расположена ячейка. Вы можете ввести или букву (как буквенную константу или как строковую переменную), или число, задающее столбец. Если Object — лист, то Columnindex, равный "А" или 1, ссылается на столбец А листа. Если Object — диапазон значений, то Columnindex, равный "А" или 1, ссылается на первый столбец диапазона. В листинге 16.13 приведен пример использования метода Cells. Листинг 16.13. Использование метода Cells 1 Sub CmdWrite_Click() 2 ' Ввод данных из диалогового окна формы пользователя в лист 3 4 Dim I As Integer 5 Dim DBNewRow As Integer 6 Dim NewRange As String 7 8 With Range("База_данных") 9 ' находится новая строка данных 10 DBNewRow = .Row + .Rows.Count 11 12 ' ввод данных из диалогового окна в ячейки новой строки 13 For I = 1 То .Columns.Count 14 Cells(DBNewRow, (I + .Column) - 1).Value = _ 15 UserForml.Controls("TextBox" & CStr(I)).Text 16 Next I 17 18 ' расширение диапазона базы данных 19 NewRange = "=" & .Parentt.Name & "!" 20 NewRange = NewRange & Cells(.Row, .Column).Address & 21 NewRange = NewRange & Cells(DBNewRow, _ 22 (.Column + .Columns.Count) - 1).Address 23 Names("Базаданных").RefersTo = NewRange 24 End With 25 End Sub Эта процедура — часть приложения поддержки базы данных. Пользователь вводит в «базу данных» информацию при помощи настраиваемого диалогового окна (подобного тому, что показано на рис. 16.1). Процедура CmdWrite_CHck вызывается при нажатии кнопки Записать новые данные диалогового окна. Процедура Рис. 16.14 Диалоговое окно (в режиме разработки) для ввода данных 414 Глава 16 Cmd W rite_Click записывает новые данные в лист в конец диапазона ячеек базы данных и увеличивает диапазон ячеек базы данных для включения новой строки. Описание элементов управления, на которые ссылается код процедуры листинга 16.13, приведено в следующей таблице: Тип элемента Свойство Значение Примечание k UserForm Name UserForml Имя формы, на которое можно Ссылаться в коде. Caption Запись данных Заголовок окна (формы) в верхней части. Command-। Button Name Cmd Write Имя кнопки, на которое можно ссылаться в коде. Caption Запись Текст на кнопке. Default True При нажатии на клавишу Enter инициируется событие Click кнопки. Command-Button Name CmdExit Имя кнопки, на которое можно ссылаться в коде. Caption Выход Текст на кнопке. Cancel True При нажатии на клавишу Esc инициируется событие Click кнопки. Label Name Labell Имя метки, на которое можно ссылаться в коде. Caption Фамилия Текст на метке. Label Name Label2 Имя метки, на которое можно ссылаться в коде. Caption Имя Текст на метке. Label Name Label3 Имя метки, на которое можно ссылаться в коде. Caption Отчество Текст на метке. TextBox Name TextBoxl Имя поля, на которое можно ссылаться в коде. TextBox Name TextBox2 Имя поля, на которое можно ссылаться в коде. TextBox Name TextBox3 Имя поля, на которое можно ссылаться в коде. Пример работающего окна для ввода данных при помощи кода листинга 16.13 приведен на рис. 16.15. Рис. 16.15 Процедура CmdWrite_Click листинга 16 13 работает с данными, вводимыми с использованием диалогового окна, подобного этому Запись данных Фамилия j Петров ’ Запись Имя |~пётр~~ Отчество ВЫХОД Управление host-приложениями VBA 415 В строках с 4 по 6 объявляются переменные, используемые в процедуре. Строка 8 начинается оператором With, задающим диапазон ячеек, на которые ссылается имя База_данных. В строке 10 переменной DBNewRow присваивается значение, соответствующее строке, расположенной сразу же за диапазоном ячеек базы данных — это строка, в которой должны быть сохранены новые данные. Цикл For...Next (в строках с 13 по 16) записывает значения из диалогового окна формы пользователя в лист. Счетчик цикла (I) «пробегает» значения от 1 до числа столбцов диапазона ячеек, полученного при нахождении свойства Count коллекции Columns для объекта Range. (Коллекция Columns содержит все столбцы объекта Range, а его свойство Count возвращает число столбцов.) Внутри цикла метод Cells (строка 14) возвращает каждую ячейку в новой строке и свойство Value ячейки устанавливается равным соответствующему тексту в элементе управления окна редактирования. Предполагается, что каждый элемент управления окна редактирования в форме пользователя имеет имя (по умолчанию) TextBoxA, где N — номер текстового окна в последовательности помещения его на форму и соответствующего столбца в диапазоне ячеек базы данных. Таким образом, в строке 15 собирается имя элемента управления окна редактирования, из которого будет преобразовано значение данных посредством конкатенации строки, эквивалентной переменной текущего счетчика цикла, с буквенной константой "TextBox". [Вместо нескольких имен текстовых окон можно использовать один массив таких окон с одним именем и разными индексами. ] Чтобы включить новую строку в «базу данных», необходимо изменить диапазон ячеек «базы данных». Переопределить диапазон, на который ссылается конкретное имя, можно, изменив свойство RefersTo этого имени. (Именованные диапазоны ячеек листа, являются объектами типа Name и доступны через коллекцию Names листа.) Свойство RefersTo должно содержать строку вида "=sheet\refe гепсе", где sheet — имя листа, содержащего именованный диапазон, a reference — адрес в виде R1C1. В строках с 19 по 23 собирается соответствующим образом отформатированная строка, задающая новый диапазон «базы данных». В строке 19, чтобы получить имя листа, содержащего данный объект Range, к адресу диапазона с помощью свойства Parent объекта Range добавляется имя листа. Далее (в строке 20) с помощью свойства Address объекта Cells, возвращающего строку с адресом ячейки, на которую сделана ссылка, добавляются координаты верхнего левого «угла» нового диапазона ячеек (в данном случае это те же самые строка и столбец, на которые указывает текущая ссылка диапазона База_данных). В строках 21-22 вновь с использованием свойства Address (на этот раз — для ячейки, которая находится на пересечении новой строки и прежнего числа столбцов в диапазоне ячеек базы данных) добавляются координаты нижнего правого «угла» нового диапазона ячеек. Наконец, (в строке 23) свойству RefersTo присваивается новое значение диапазона База_данных, на который ссылаются посредством коллекции Names. Использование метода Offset При определении объектов Range конкретный диапазон адресов, который необходимо использовать, часто бывает неизвестен. Например, у вас может возникнуть необходимость сослаться на ячейку, которая расположена на две строки ниже и один столбец правее от активной ячейки. Хотя вы все-таки можете определить адрес активной ячейки и вычислить адрес ячейки, которая вам необходима, в Excel VBA предусмотрен более легкий и более гибкий путь — использование метода Offset. Offset возвращает объект типа Range, который смещен относительно заданного диапазона ячеек на заданное количество строк и столбцов. 416 Глава 16 СИНТАКСИС Object.Offset(IRowOffset] [, ColumnOffsetl ) Object является ссылкой на исходный объект Range. RowOffset — число строк, на которое смещается Object. Вы можете использовать положительное число (для смещения вниз), отрицательное число (для смещения вверх), или О (для использования той же строки). Если вы опустите RowOffset, будет использовано значение по умолчанию — 0. Листинг 16.14 демонстрирует процедуру, использующую метод Offset. Листинг 16.14. Использование метода Offset для ссылки на диапазон ячеек 1 Sub SelectData() 2 ' Выделяется область данных диапазона базы данных 3 4 Dim DBRows As Integer ' 5 ' , 6 Worksheets("Лист1").Select 7 With Range("База_данных") 8 DBRows = .Rows.Count 9 .Offset(l, 0).Resize(DBRows - 1, .Columns.Count).Select 10 End With 11 End Sub Данная процедура выделяет область данных диапазона ячеек с именем База_данных, то есть диапазон, в который предполагается включать только данные (без заголовков столбцов), опуская для этого из текущего выбора первую строку именованного диапазона. Выполнение данной процедуры полезно, если необходимо выполнить над данными в таблице глобальные операции, такие как сортировка или форматирование. В строке 6 выбирается лист с именем Лист1, а оператор With в строке 7 задает для этого листа объект Range с именем База^данных. В строке 8 с помощью свойства Rows.Count объект Range получает число строк диапазона ячеек, которое сохраняется в переменной DBRows. В строке 9, метод Offset (с аргументами 1 и 0) возвращает диапазон, который является смещением диапазона База_данных на одну строку вниз. Поскольку этот диапазон включает (предположительно) пустую строку, находящуюся за диапазоном База_данных, вы должны эту дополнительную строку удалить. Чтобы выполнить данную операцию, можете воспользоваться свойством Resize, изменяющим размер диапазона: СИНТАКСИС Object.Resize([KowSize] [,ColumnSize}) Object — объектная ссылка на диапазон, размер которого изменяется. RowSi-ге — число строк в возвращаемом диапазоне. ColumnSize — число столбцов в возвращаемом диапазоне. В строке 9 при помощи выражения Resize(DBRows—1, .Columns.Count) удаляется ненужная нижняя строка смещенного диапазона. Метод Select (в строке 9) выделяет новый диапазон ячеек. Другие методы и свойства, возвращающие диапазоны ячеек Методы Range, Cells и Offset являются наиболее часто используемыми методами для возвращения объектов Range, но они далеко не единственные. На приме- Управление host-приложениями VBA 417 ре кода листинга 16.14 вы познакомились с тем, как с помощью метода Resize можно возвратить диапазон заданного размера. Вот лишь некоторые методы и свойства, возвращающие объекты типа Range: • [cellRef]. Вы можете возвратить одну ячейку, поместив ссылку на нее в квадратные скобки. Например, [Al].Font.Size=16 устанавливает размер шрифта ячейки А1 равным 16 пунктам. Обратите внимание на то, что в данном случае для ссылки на ячейку не используется никаких кавычек. • Object .R<yws.(Index). Данный метод возвращает строку листа или диапазона ячеек, заданных при помощи Object. Если вы опустите Object, VBA использует ActiveSheet. Index — номер строки. Если Object является листом, Index, равный 1, ссылается на строку 1 листа. Если же Object является диапазоном, то Index, равный 1, ссылается на первую строку диапазона. • Object.EntireRow. Данное свойство возвращает целую строку или строки, содержащие диапазон ячеек, заданных при помощи Object. Object.Columns(/nciex). Данный метод возвращает столбец листа или диапазона ячеек, заданных при помощи Object. Если вы опускаете Object, VBA использует ActiveSheet. Index — буква или номер столбца. Если Object является листом, Index, равный "А" или 1, ссылается на столбец А листа. Если же Object является диапазоном ячеек, то Index, равный "А" или 1, ссылается на первый столбец диапазона. Object.EntireColumn. Данное свойство возвращает целый столбец или столбцы, содержащие диапазон ячеек, заданных при помощи Object. • Object.CurrentRegion. Данное свойство возвращает текущую область диапазона Object. Текущая область определяется как область, окружающая текущую ячейку или диапазон ячеек, ограниченный пустыми строками сверху и снизу и пустыми столбцами слева и справа. Работа с Cells и Ranges Теперь, когда вы знаете, как возвращать объект Range, вы можете использовать все преимущества применения многочисленных свойств и методов Range. В следующем разделе рассматриваются некоторые из этих свойств и методов. -Для того чтобы увидеть все методы и свойства объекта Range, пользуйтесь инструментом Object Browser и соответствующим данному объекту разделом справочной системы. Выделение ячейки или диапазона ячеек Для выделения ячейки или диапазона ячеек используйте метод Select: СИНТАКСИС Object.Select Object — ссылка на объект типа Range, который выделяется. Листинг 16.15 демонстрирует пример использования данного метода. Листинг 16.15. Использование метода Select для выделения диапазона ячеек 1 Sub CreateChart() 2 ' Создается диаграмма на основе данных диапазона Продажа 3 4 With Workbooks("Отчеты.XLS").Worksheets("Лист2") 5 .Activate 6 .Range("Продажа").Select 7 End With 4 Программирование на VBA 2002 f 418 Глава 16 8 9 Charts.Add 10 End Sub Данная процедура создает из выбранного диапазона ячеек новую диаграмму. В строке 5 активизируется лист Workbooks(”OT4eTbi.XLS ”).Worksheets(JlHCT2). В строке 6 на листе выделяется диапазон ячеек с именем Продажа. В строке 9 для создания диаграммы выполняется метод Add объекта Charts. Свойства Value и Formula Если вам необходимо получить содержимое ячейки или ввести данные в диапазон ячеек, VBA предлагает два свойства объекта Range: Value и Formula. Синтаксис для использования этих свойств следующий: СИНТАКСИС Object.Value Object.Formula Object — объектная ссылка на объект типа Range, с которым необходимо работать. Для того чтобы получить содержимое ячейки, руководствуйтесь следующими правилами: Если вам необходимо значение, содержащееся в ячейке, используйте свойство Value. Например, если ячейка А1 содержит формулу =2*2, то выражение Range("Al").Value возвращает значение 4. Если вам необходима формула, содержащаяся в ячейке, используйте свойство Formula. Например, если ячейка А1 содержит формулу =2*2, то выражение Range("Al").Formula возвращает текстовую строку "=2*2". Для того чтобы ввести ячейку или диапазон ячеек, вы можете применять как Value, так и Formula. Листинг 16.16 демонстрирует несколько примеров такого использования. Листинг 16.16. Использование методов Value и Formula для ввода данных 1 Sub CreateCalculator() 2 ' Выплаты по ссуде в листе с именем ЛистЗ 3 4 Worksheets("ЛистЗ").Select 5 6 With Range("Al") 7 ' введение заголовков: 8 .Value = "Расчет выплат по ссуде" „ 9 .Font.Bold = True \ 10 .Font.Italic = True 11 .Font.Size = 16 12 .Offset(1).Value = "Тариф" 13 .Offset (2) .Value = "Период" 14 .Offset(3).Value = "Количество" 15 .Offset(5).Value = "Платеж” 16 17 ' ввод формата чисел и формулы: 18 .Offset(l, 1).NumberFormat = "0.00%" 4 19 .Offset (3, 1) .NumberFormat = ,##0_); ($#,##0)" 20 .Offset(5, 1) .NumberFormat = "$#,##0.00_) ; [Red] ($#,##0.00)" 21 .Offset (5, 1).Formula = "=PMT($B$2/12, $B$3*12, $B$4)" 22 End With 23 24 End Sub Управление host-приложениями VBA 419 Данная процедура помещает на ЛистЗ активной книги простой калькулятор для расчета выплат по ссуде. Оператор With использует ячейку А1 как начальную. Свойство Value этой ячейки устанавливается содержащим текст "Расчет выплат по ссуде" (строка 8), кроме того, устанавливаются некоторые параметры шрифта (строки 9-11). В следующих четырех строках (12-15) используется свойство Value ячеек А2, АЗ, А4 и А6 для ввода заголовков. При работе с этими ячейками обратите внимание на использование метода Offset. Код строк 18-20 задает формат ячеек В2, В4 и В6. Выполняется данная операция при помощи свойства NumberFormat для диапазона ячеек, на который существует ссылка: Object.NumberFormat = FormatString Object — является объектной ссылкой на ячейку или диапазон, которые необходимо отформатировать, Formatstring — текстовая строка, определяющая форматирование. Наконец, код строки 21 использует свойство Formula для введения в ячейку В6 формулы платежа. Определение имени диапазона ячеек Имена диапазонов ячеек в VBA являются Name-объектами. Для того чтобы их задать, необходимо использовать метод Add коллекции Names, которая обычно является коллекцией имен, определенных в книге. Ниже представлена сокращенная синтаксическая конструкция использования метода Add коллекции Names. Всего данный метод имеет одиннадцать аргументов — все необязательные. Полный синтаксис метода следует смотреть в справочной системе, а легче всего получить доступ к нужному разделу справочной системы при помощи Object Browser. СИНТАКСИС Names.Add([Warne][, RefersTo} [, RefersToRlCl]) Аргумент Name — любое строковое выражение, задающее имя, которое вы хотите использовать для нового именованного диапазона. RefersTo и RefersToRlCl — аргументы, описывающие диапазон, на который ссылается имя. Аргументы используются следующим образом: • RefersTo: Используйте данный аргумент для ввода диапазона ячеек, описанного в Al-стиле, например: "=Sales!$A$l:$C$6". RefersToRlCl: Используйте данный аргумент, когда диапазон ячеек описывается или в стиле R1C1, например, "=Sales!RlCl:R6C3”, или когда описание диапазона является методом или свойством, возвращающим диапазон, например, Range("Al:C6") или Selection. Листинг 16.17 демонстрирует применение метода Add коллекции Names. Листинг 16.16. Задание имени диапазона при помощи метода Add коллекции Names 1 Sub CreateNameRange() 2 ' При помощи вводимых пользователем координат и имени, 3 ' создает именованный диапазон ячеек 4 5 Const strTaskName = "Имя диапазона" б 7 8 9 10 11 12 Dim strTopLeft As String Dim strBottomRight As String Dim RngName As String Worksheets("Лист1").Select 4* 420 Глава 16 13 ' принять диапазон и имя: 14 strTopLeft = InputBox(prompt:="Верхний левый угол " & _ 15 "в формате R1C1:", _ 16 Title:=strTaskName) 17 strBottomRight = InputBox(prompt:="Нижний правый угол " & 18 " в формате R1C1:", _ 19 Title:=strTaskName) 20 RngName = InputBox(prompt:="Имя для нового " & _ 21 "диапазона ячеек:", _ 22 Title:=strTaskName) 23 24 ' задать имя нового диапазона ячеек: 25 Names.Add Name:=RngName, RefersToRlCl:="=Лист1!" & _ 26 strTopLeft & & strBottomRight 27 28 ' выделить новый диапазон ячеек 29 Range(RngName).Select 30 31 End Sub Данная процедура не очень сложна — она(содержит всего лишь несколько операторов InputBox для того, чтобы получить координаты диапазона ячеек (верхний левый угол и нижний правый) и его имя. Затем, используя предложенные координаты и имя, процедура создает именованный диапазон ячеек. Как вырезать, скопировать и очистить данные Если ваша процедура должна выполнять некоторые основные, наиболее часто используемые операции редактирования листа, то это можно делать методами Cut, Сору и Clear. Синтаксис первых двух из них следующий: СИНТАКСИС Object.Cut([Destination]) Object.Copy([Destination]) Object — объектная ссылка на объект типа Range, который необходимо вырезать или скопировать. Destination — ячейка или диапазон, в который нужно поместить содержимое вырезанного или скопированного диапазона. Если вы опустите аргумент Destination, данные будут вырезаться или копироваться в буфер обмена Windows. Для очистки диапазона ячеек вы можете использовать метод Cut с аргументом назначения или без него или воспользоваться любым из следующих методов: СИНТАКСИС Object.Clear Object.СleaгContents Object.ClearFormats Object.ClearNotes В каждом случае Object является объектной ссылкой на диапазон ячеек, который следует очистить. Метод Clear очищает все — содержимое, форматирование и примечания. ClearContents очищает содержимое Object, ClearFormats — форматирование Object, ClearNotes удаляет из Object примечания. Листинг 16.18 демонстрирует пример применения методов Cut, Сору и Clear. Управление host-приложениями УВД 421 Листинг 16.18. Использование методов Cut, Сору и Clear 1 Sub CopyToTemp() 2 ' Копирует данные во временный лист 3 4 Dim Lastcell As Range 5 Dim oldSheet As String 6 7 Application.Screenupdating = False 8 9 oldSheet = Activesheet.Name ' имя текущего листа 10 Worksheets.Add ' создается временный лист 11 ActiveSheet.Name = "Временный" 12 Worksheets("Лист1").Select ' выбирается Лист1 13 14 Set Lastcell = Range("Al").Specialcells(xlLastCell) 15 With Worksheets("Временный") 16 .Cells.Clear 17 RangeCAl", Lastcell) .Copy Destination : = . Range ( "Al" ) 18 End With 19 20 Sheets(oldSheet).Select ' восстанавливается исходный лист 21 Application.Screenupdating = True 22 23 End Sub 24 25 26 Sub RestoreFromTemp() 27 ' Восстанавливаются данные из временного листа 28 29 Dim Lastcell As Range 30 Dim oldSheet As String 31 32 Application.Screenupdating = False 33 oldSheet - ActiveSheet.Name 34 35 Worksheets("Лист1").Select 36 With Worksheets("Временный") 37 Set Lastcell = .Range("Al").Specialcells(xlLastCell) 38 .Range("Al", Lastcell).Cut Destination:=Range("Al") 39 End With 40 41 Sheets(oldSheet).Select 42 Application.Screenupdating = True 43 44 End Sub Код состоит из двух процедур: CopyToTemp (строки 1-23) и RestoreFromTemp (строки 26-44). Процедура CopyToTemp добавляет лист с именем Временный и выбирает лист с именем Лист1. Далее она копирует все данные из активного листа и сохраняет их в листе Временный. Для возврата последней ячейки активного листа и сохранения объектной ссылки результирующего объекта Range в переменной LastCell данная процедура использует метод SpecialCells с аргументом xlLastCell (строка 14). Затем с использованием оператора With над листом Временный выполняются два действия: код строки 16 использует метод Clear для очистки всего листа (метод Cells без аргументов возвращает все ячейки листа), код строки 17 использует метод Сору для копирования диапазона, заданного с помощью А1 (верхний левый угол) и LastCell (нижний правый угол); «получателем» является ячейка А1 листа Временный. 422 Глава 16 Вторая процедура, RestoreFromTemp, выполняет обратные действия. На этот раз LastCell устанавливается на последнюю ячейку листа Временный (строка 37). Диапазон от А1 до LastCell вырезается и помещается в ячейку А1 активного листа (строка 38). Активным является лист Лист1, выбранный в строке 35. Для вставки данных из буфера обмена в лист используйте с объектами Worksheet или Range методы Paste или PasteSpecial. Синтаксис метода Paste следующий: СИНТАКСИС Object.Paste ([Destination], [Link]) Object — любая допустимая объектная ссылка на лист. Необязательный аргумент Destination — любой объект диапазона ячеек. Данные вставляются, начиная с верхнего левого угла диапазона. Если вы опустите аргумент Destination, данные вставляются, начиная с выбранной в данный момент ячейки. Использование аргумента Destination аналогично использованию команды Правка | Вставить (Edit | Paste). Если необязательный аргумент Link равен значению True, то должна быть задана ссылка на источник данных. Использование аргумента Link аналогично использованию команды Правка | Специальная вставка (Edit | Paste Special) с установленным флажком Связать (Link). Одновременное использование аргументов Destination и Link в одном операторе недопустимо. Работа с объектами Word До сих пор в данной главе обсуждалась работа только с объектами, доступными в Excel VBA. Word также создает многочисленные объекты, доступные VBA. В этой части главы вы узнаете, как управлять большинством наиболее важных и распространенных объектов Word. Во-первых, вы узнаете об объектах Document и Template, а затем о том, как управлять информацией, содержащейся в объекте Document. Работа с объектами Document В Word используется формат документа, в котором объекты и события полностью доступны VBA, что дает возможность управлять документом и его объектами при помощи VBA-кода. Такой формат документа Word позволяет выполнять наиболее распространенные задачи обработки текста быстрее и легче. В следующих нескольких разделах рассмотрены наиболее часто используемые объекты, методы и свойства Word. Доступ к объекту Document В Word каждый документ является объектом типа Document, а все открытые документы текущей сессии Word образуют коллекцию Documents. Для ссылок на конкретный документ следует использовать коллекцию Documents объекта Application. СИНТАКСИС Documents(index) Index может быть: Численным выражением, представляющим документ, который необходимо использовать. Число 1 означает первый документ, открытый в ходе текущей рабочей сессии, 2 — второй открытый документ и так далее. Управление host-приложениями УВД 423 Строковым выражением, представляющим имя открытого документа, который нужно использовать. Наиболее распространенным и в большинстве случаев наиболее удобным способом использования Index является текстовая строка. Листинг 16.19 демонстрирует пример использования коллекции Documents. Листинг 16.19. Использование коллекции Documents для возвращения документа 1 Sub SetDocumentActivate() 2 ' Делает (открытый) документ активным 3 4 Documents("с:\F.DOC").Activate 5 MsgBox "F.DOC становится активным!" 6 7 End Sub Выражение в строке 4, Documents("C:\F.DOC"), возвращает объектную ссылку на объект документ C:\F.DOC. Метод Activate делает указанный документ активным. Оператор MsgBox в строке 5 выводит об этом сообщение. (Документ C:\F.DOC в момент выполнения процедуры должен быть открыт, в противном случае вы получите сообщение о runtime-ошибке.) Для ссылок на активный документ нужно применять Application-свойство ActiveDocument. Свойство ThisDocument следует использовать для ссылок на документ, содержащий выполняемую в данный момент процедуру, особенно если вы намереваетесь преобразовать свою программу в Word-надстройку (add-in)1. Как открыть документ Если необходимый вам документ не открыт, для загрузки его в память используйте метод Open: СИНТАКСИС Documents.Open(Filename) Аргумент Filename является текстовой строкой, представляющей полный путь к документу: логический диск, папка и имя файла. Если вы не задали диск или имя папки, Word будет искать документ на текущем диске или в текущей папке. Листинг 16.20 демонстрирует действие метода Open. Листинг 16.20. Использование метода Open для открытия документа 1 2 3 4 5 6 7 8 9 1 Sub OpenTest() 2 ' Предлагает открыть документ и затем его открывает 3 4 Dim DocumentName As String 5 6 DocumentName = _ 7 InputBox("Введите полный путь к документу") 8 If DocumentName <> "" Then 9 Documents.Open FileName:=DocumentName 1 До появления локализованной версии Office 97 использовался термин «надстройка», в Office 97 появился термин «дополнение», тем не менее Microsoft Press пользуется привычным русским пользователям термином «надстройка». 424 Глава 16 10 End If 11 12 End Sub В данной процедуре переменная DocumentName объявляется как String (строка 4), а функция InputBox предлагает пользователю ввести имя документа (строки 6 и 7). Оператор If...Then (в строке 8) проверяет, не отменил ли пользователь диалог ввода. Если — нет (другими словами, если переменная Document-Name не пуста), метод Open использует ее для того, чтобы открыть заданный документ (строка 9). Чтобы избежать ошибок при открытии существующего на диске файла (пользователь вряд ли введет в диалоговом окне функции InputBox правильное имя файла), следует использовать встроенное в Word диалоговое окно Open. Вы можете использовать встроенное в Word диалоговое окно Open при помбщи коллекции Dialogs, как показано ниже (Dialogs содержит все диалоговые окна, встроенные в Word): Application.Dialogs(wdDialogFileOpen).Show Как создать новый документ Если вашей процедуре необходимо создать новый документ, используйте метод Add коллекции Documents, имеющий следующий синтаксис: СИНТАКСИС Documents.Add([Template], [NewTemplate]) Оба аргумента метода Documents.Add не являются обязательными. Template представляет строковое выражение, задающее имя шаблона документа, на ко-, тором должен основываться новый документ. Аргумент Template наряду с именем файла может включать имя диска и путь к папке. Включать полный путь необходимо, если шаблон документа расположен в папке, отличной от той, в которой по умолчанию хранятся шаблоны Word. Если вы опустите аргумент Template, Word создаст новый документ, основываясь на шаблоне Normal.dot. Аргумент NewTemplate может быть любым выражением типа Boolean. Если он равен значению True, Word создает новый документ в виде шаблона. По умолчанию значение этого аргумента равно значению False. Листинг 16.21 демонстрирует пример процедуры, создающей новый документ. Листинг 16.21. Использование метода Add для создания нового документа 1 Sub CreateNewLetter() 2 ' Содает документ на базе шаблона Professional Letter 3 4 Dim dPath As String 5 6 dPath = "E:\Program Files\Microsoft Office\Templates\1049\" 7 Documents.Add Template:=dPath & "Professional Letter" 8 With ActiveDocument 9 .BuiltlnDocumentProperties("Title") = _ 10 "Письмо из России" % 11 .BuiltlnDocumentProperties("Subject") = _ 12 Str(Date) 13 .BuiltlnDocumentProperties("Author") = 14 Application.UserName 15 End With 16 17 End Sub Управление host-приложениями УВД 425 Код листинга 16.21 создает новый документ на основании шаблона Professional Letter, поставляемого вместе с Word и Microsoft Office. Любой новый документ автоматически становится активным. В строках с 8 по 15 используется объект ActiveDocument для добавления некоторой общей информации, относящейся к новому документу. Свойства документа Title, Subject и Author хранятся в коллекции BuiltlnDocumentProperties объекта Document. В результате на экране появляется заготовка письма. Свойства активного документа, устанавливаемые в строках кода 8-15, можно увидеть в диалоговом окне Свойства (рис. 16.16). Рис. 16.16 Свойства активного документа, заданные в строках кода 8-15, можно увидеть в этом диалоговом окне Как сделать документ активным Если ваша VBA программа хранит несколько документов, открытых одновременно, вам может понадобиться переключаться с одного документа на другой. Для того чтобы сделать какой-либо из открытых документов активным, используйте метод Activate: СИНТАКСИС Object.Activate Object представляет собой ссылку на документ, который следует сделать активным. Листинг 16.22 представляет пример процедуры, использующей метод Activate. Листинг 16.22. Использование метода Activate для переключения к документу 1 Sub ActivateTest () 2 ' Активизирует два документа без изменения вывода на экран 3 4 Dim SaveDoc As String 5 6 SaveDoc = ActiveDocument.Name 7 8 Application.ScreenUpdating = False 'не обновлять экран 426 Глава 16 9 Documents("TestData.DOC").Activate 10 11 ' действие, выполненное над TestData.DOC 12 With Selection 13 .TypeText Text:="Документ данных установлен активным" 14 .Typeparagraph 15 End With 16 • 17 Documents(SaveDoc).Activate 18 Application.Screenupdating = True 'обновлять экран 19 20 End Sub Процедура листинга 16.22 демонстрирует два принципа хорошего стиля программирования: скрывать от пользователя промежуточные операции и всегда «возвращать пользователя» в то место, из которого он запустил программу. Назначение процедуры листинга 16.22 — переключиться из текущего документа в другой документ (TestData.doc), произвести в нем (программно) определенные изменения и затем вернуться к исходному документу. В первую очередь (в строке 6) имя текущего активного документа сохраняется в строковой переменной SaveDoc. Далее, чтобы избавить пользователя от наблюдения за подробностями выполнения процедуры, в строке 8 свойство ScreenUpdating задается равным значению False. В строке 9 активизируется документ TestData.doc. Строки с 12 по 15 представляют действия, выполняемые над документом TestData.doc. Данный фрагмент программы просто добавляет в документ некоторый текст. Чтобы «вернуть пользователя» обратно в исходный документ, в строке 17 документ вновь устанавливается активным. А в строке 18 свойство ScreenUpdating вновь получает значение True. Не следует без особой необходимости активизировать документ. Как правило, вы можете выполнить изменения или получить информацию о документе, просто ссылаясь на соответствующий объект Document. Например, чтобы выяснить, какой шаблон присоединен (если вообще какой-нибудь присоединен) к TestData.doc, вы можете использовать следующий оператор (не делая документ активным): DocTemplate = Document("TestData.doc").AttachedTemplate Как сохранить документ Если ваш VBA-код изменяет содержимое документа, вы должны быть уверены, что дадите пользователю возможность сохранить эти изменения, или обеспечить их сохранение с помощью вашей программы. Хотя вы можете включить встроенную в Word команду Save в меню и панели инструментов, вы, возможно, захотите сохранять документ под управлением процедуры, особенно если нужно не дать пользователю возможности отказаться от изменений, произведенных вашим VBA-кодом. Для сохранения документа используйте метод Save объекта Document: СИНТАКСИС Object.Save Object представляет ссылку на открытый объект типа Document, который необходимо сохранить. Можно воспользоваться и родственным методом SaveAs. Данный метод сохраняет документ под новым именем и изменяет имя документа. (Метод имеет шестнадцать необязательных аргументов, здесь для простоты указаны только два из них. В справочной системе вы можете найти полный синтаксис этого метода.) Управление host-приложениями УВД 427 СИНТАКСИС Object.SaveAs([FileName] , [FileFormat] ) Object — любая допустимая ссылка на открытый документ типа Document. Необязательный аргумент FileName — строковое выражение, указывающее новое имя, под которым должен быть сохранен документ. FileName может включать полный путь (включая диск и папку). Если опустить полный путь, документ сохраняется в текущей папке на текущем диске. Если вы полностью опустите аргумент FileName, документ сохранится под текущим именем, если документ с подобным именем уже существует, он будет переписан без предупреждения. Необязательный аргумент FileFormat определяет формат, в котором будет сохранен документ. Аргумент FileFormat может быть любой из встроенных констант (определенных в классе wdSaveFormat): wdFormatDocument, wdFormat-DOSText, wdFormatDOSTextLineBreaks, wdFormatEncodedText, wdFormat-FilteredHTML, wdFormatHTML, wdFormatRTF, wdFormatTemplate, wdFor-matText, wdFormatTextLineBreaks, wdFormatUnicodeText или wdFormatWeb-Archive. Листинг 16.23 демонстрирует пример процедуры, использующей как Save, так и SaveAs. Листинг 16.23. Применение методов Save и SaveAs 1 Sub CreateTemplate() 2 ' На базе активного документа создается новый шаблон документа 3 4 Dim NewName As String 5 6 With ActiveDocument 7 If Not .Saved Then .Save 8 NewName = Left(.Name, Len(.Name) - 3) & "dot" 9 ' .SaveAs FileName:=NewName, FileFormat:=wdFormatTemplate 10 End With 11 12 End Sub Процедура этого листинга сохраняет активный документ, а затем сохраняет копию активного документа как шаблон. Начинается код с объявления переменной, предназначенной для сохранения имени файла нового шаблона. Оператор With в строках с 6 по 10 содержит операторы, связанные с объектом ActiveDocument. Оператор If...Then (строка 7) проверяет свойство Saved документа. Если оно равно значению False, документ содержит изменения, которые еще не были сохранены, поэтому процедура вызывает метод Save. Имя файла шаблона создается в строке 8 конкатенацией полного имени документа, за исключением последних трех символов, со стандартным расширением для имени файла шаблона "dot". (Имя документа получается из его свойства .Name.) Результат используется в качестве аргумента для метода SaveAs (строка 9), который сохраняет копию документа в виде файла шаблона. Обратите внимание на использование аргумента FileFormat, имеющего значение wdFormatTemplate — данное значение аргумента сообщает Word о том, что необходимо сохранить документ как шаблон. Для проверки того, был ли документ когда-либо сохранен, следует использовать свойство Path объекта Document. Если Path возвращает пустую строку (""), то документ никогда прежде не сохранялся. к 428 Глава 16 Как закрыть документ Завершив работу с документом, вы должны закрыть его для освобождения памяти и других системных ресурсов. Закрыть документ можно, используя одну из следующих форм метода Close. СИНТАКСИС Documents.Close Object.Close([SaveChanges] [, OriginalFormat ] [, RouteDocument ]) Первая синтаксическая форма просто закрывает все открытые документы. Word предлагает перед закрытием документа (если это необходимо) сохранить сделанные в нем изменения. Вторая синтаксическая форма закрывает конкретный документ, на который указывает Object. Аргумент SaveChanges может быть равен одной из перечисленных ниже встроенных констант (определенных в классе wdSaveOptions): wdDoNotSaveChanges (документ закрывается без сохранения изменений), wdPromptToSaveChanges (Word запрашивает, нужно ли сохранять изменения), wdSaveChanges (изменения сохраняются). Аргумент OriginalFormat определяет формат сохранения для документа и может быть одной из следующих wdOriginalFormat-констант: wdOriginalDocumentFormat, wdPromptU-ser или wdWordDocument. Аргумент RouteDocument определяет необходимость передачи документа следующему получателю. В листинге 16.24 приведен код с использованием метода Close. ' Листинг 16.24. Применение метода Close 1 Sub CloseAll() 2 1 Закрывает все документы и предлагает сохранить изменения 3 4 Const qButtons = vbYesNo + vbQuestiion 5 6 Dim Doc As Document 7 Dim Ans As Integer 8 Dim MsgPrompt As String 9 10 For Each Doc In Documents 11 If Not (Doc.Name - ThisDocument.Name) Then 12 If Not Doc.Saved Then 13 MsgPrompt = "Сохранить изменения в " & Doc.Name & "?" 14 Ans = MsgBox(prompt:=MsgPrompt, Buttons:=qButtons) 15 If Ans = vbYes Then 16 Doc.Close SaveChanges:=wdSaveChanges 17 Else 18 Doc.Close SaveChanges:=wdDoNotSaveChanges 19 End If 20 Else 21 Doc.Close 22 End If 23 End If 24 Next Doc ' 25 26 End Sub Процедура листинга 16.24 закрывает все открытые документы (за исключением документа содержащего саму процедуру) и спрашивает у пользователя, нужно ли выполнять сохранение внесенных изменений для каждого из документов, Управление host-приложениями VBA 429 имеющих несохраненные изменения. Используйте подобную процедуру вместо метода Documents.Close, если необходимо заблокировать возможность отмены операции пользователем (встроенный в Word запрос Save имеет кнопку Cancel). После объявления константы и нескольких переменных, процедура запускает цикл For Each для обработки всех документов коллекции Documents. Поскольку закрытие документа, содержащего выполняемую в данный момент процедуру, приведет к завершению ее выполнения, в строке 11 находится оператор If...Then, проверяющий, не совпадает ли имя обрабатываемого в данный момент документа с именем документа, содержащего процедуру CloseAll. Если они совпадают, часть программы, закрывающая документ пропускается; строки с 12 по 22 выполняются только в том случае, если документ не содержит процедуры CloseAll (свойство ThisDocument возвращает ссылку на документ, содержащий выполняемую в данный момент программу). Если документ содержит изменения, которые не были сохранены (строка 12), функция MsgBox «спрашивает», нужно ли сохранять изменения. Если пользователь выбирает кнопку Yes (то есть в переменную Ans возвращается значение константы vbYes), процедура запускает метод Close с аргументом SaveChanges, равным значению константы wdSaveChanges (строки 15 и 16). В противном случае процедура закрывает документ с аргументом SaveChanges, равным значению константы wdDoNotSaveChanges (строка 16). Если документ не содержит несохранен-ных изменений, процедура выполняет метод Close без аргументов (строка 21). Работа с объектами Template В Word каждый шаблон документа является объектом типа Template, a Templates — коллекцией всех открытых шаблонов. Далее рассматривается, как выполнять основные операции с объектами Template. Как создать шаблон Коллекция Templates не имеет метода Add. Поэтому для добавления к ней нового шаблона нужно создать этот шаблон, сначала создав объект Document. Вы можете создать новый шаблон документа одним из следующих способов: Использовать метод Documents.Add с аргументом NewTemplate, равным True, для одновременного создания нового документа и преобразования его в объект Template. Использовать метод SaveAs объекта Document с аргументом FileFormat, заданным как wdFormatTemplate для сохранения документа в виде шаблона (в листинге 16.23 это уже использовалось). Как загружать и выгружать общие шаблоны Как вы уже можете знать, единственный способ сделать код в проекте VBA Word доступным всем открытым документам — это сохранить его в шаблоне документа, загруженном как общий. По этой причине вам, возможно, захочется поместить процедуру текущего документа в шаблон, загруженный как общий, делая таким образом процедуры и другие ресурсы данного шаблона доступными всем открытым документам. Коллекция Templates не имеет метода Open. Вместо этого следует загружать шаблон документа как общий посредством коллекции Addins объекта Applications Word. (Addins — коллекция всех доступных в Word надстроек, независимо от того, были они установлены или нет.) Поскольку они являются общими ресурсами для программ, панелей команд, стилей и других элементов, Word рассматривает общие шаблоны как разновидность надстройки. Если вы знаете, что ваша программа больше не нуждается в ресурсах конкретного шаблона, то можете выгрузить общий шаблон для освобождения системных ресурсов компьютера. 430 Глава 16 Чтобы загрузить шаблон как общий, используйте метод Add коллекции Addins в следующей синтаксической форме: СИНТАКСИС Object.Add(FileName [, Install]) Object представляет ссылку на объект Addins. Аргумент FileName является обязательным. Это — строковое выражение, содержащее имя файла шаблона, включая полный путь. Аргумент Install (необязательный) управляет установкой надстройки: при равенстве значению True (значение по умолчанию) надстройка устанавливается, при False — добавляется в список надстроек, но не устанавливается. Для того чтобы выгрузить общий шаблон, используйте метод Delete коллекции Addins в следующей синтаксической форме: СИНТАКСИС Addins(Name).Delete Name — строковое выражение, задающее имя шаблона, который нужно выгрузить, или численное выражение, указывающее номер индекса шаблона в коллекции. Как и для большинства других коллекций, следует пользоваться именами шаблонов, чтобы создавать удобочитаемые и надежные программы. Листинг 16.25 содержит две демонстрационные процедуры: одна загружает шаблон как общий, а другая выгружает общий шаблон. Листинг 16.25. Загрузка и выгрузка общего шаблона 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Sub LoadGlobalTemplate() ' Загружает и определяет общий шаблон Dim strName As String strName = InputBox(prompt:“"Введите имя шаблона:" & vbCr & "(включая полный путь)", _ Title:“"Загружается общий шаблон") If Trim(strName) = "" Then Exit Sub Addins.Add FileName:“StrName End Sub •- Sub UnloadGlobalTeplate() 1 Выгружает шаблон, заданный как общий Dim strName As String strName = InputBox(prompt:“"Введите имя шаблона:", _ Title:“"Выгрузка общего шаблона") 4 * * * * If Trim(strName) = "" Then Exit Sub Addins(strName).Delete End Sub Управление host-приложениями VBA 431 Как присоединить шаблон У вас может возникнуть необходимость определять, какой шаблон (если таковой вообще имеется) присоединен к документу. Или же у вас может появиться желание присоединить определенный шаблон к документу. Чтобы задать присоединенный к документу шаблон, используйте свойство AttachedTemplate объекта Document в следующей синтаксической форме: СИНТАКСИС Object.AttachedTemplate = Template Здесь Object — любая допустимая ссылка на объект типа Document. Template может быть как объектной ссылкой на уже открытый Template-объект, так и строковым выражением, задающим имя файла шаблона, который необходимо присоединить. Свойство AttachedTemplate всегда возвращает объектную ссылку на объект типа Template. Если документ не содержит присоединенного шаблона, свойство AttachedTemplate возвращает ссылку на Normal.dot. Следующий фрагмент программы присоединяет шаблон к активному документу (предполагается, что переменная TestTemplate содержит строку, включающую полный путь к файлу шаблона): ActiveDocument.AttachedTemplate = TestMyTemplate Для отключения от активного документа всех шаблонов достаточно использовать следующий код: ActiveDocument.AttachedTemplate = "" Компоненты объекта Document Документ в Word представляет собой конструкцию довольно свободной формы: он состоит из символов, слов, предложений и абзацев. Документ может содержать колонтитулы, сноски и прочие элементы. Как следствие, число и тип объектов, используемых для управления содержимым документа, может сначала вызвать замешательство. Каждый документ состоит из нескольких областей (stories). Каждая область документа соответствует конкретному разделу документа, такому как колонтитул, сноска основной текст документа, примечания и так далее. Многие методы объекта Document позволяют выбрать конкретную область. Многие объекты так же обладают свойствами, из которых можно извлечь значение, указывающее, какая область объекта документа в нем содержится. VBA Word предоставляет несколько внутренних констант (определенных в классе wdStoryType), которые вы можете использовать для задания конкретной области документа: wdMainTextStory, wdPrimaryFooterStory, wdPrimaryHeaderStory и другие. Текст внутри области документа может рассматриваться как коллекция символов, слов, предложений или абзацев. Word предоставляет коллекцию объектов для каждого из этих представлений: Characters, Words, Sentences и Paragraphs. Ниже дана краткая характеристика этих коллекций: Characters. Коллекция символов. В зависимости от того, из какого объекта вы получили доступ к коллекции, она может содержать некоторые или все символы области документа. Объект для одного символа отсутствует. Каждый элемент коллекции Characters является объектом типа Range, включающим только один символ. (Объекты Range Word будут рассмотрены далее в этом разделе.) Words. Коллекция слов. В зависимости от того, из какого объекта вы получили доступ к коллекции Words, она может содержать некоторые или все слова 432 Глава 16 области документа. В Word отсутствует объект слово. Каждый элемент коллекции Words является объектом типа Range, включающим только одно слово. (Слово — это группа символов, отделенная пробелами или знаками пунктуации.) Sentences. Коллекция предложений. В зависимости от того, из какого объекта вы получили доступ к коллекции Sentences, она может .содержать некоторые или все предложения области документа. Подобно коллекциям Characters ' и Words объект одно предложение отсутствует. Каждый элемент коллекции Sentences является объектом типа Range (который будет описан далее в этой главе), включающим единственное предложение. Paragraphs. Коллекция абзацев. В зависимости от того, Paragraphs-коллекция какого именно объекта используется, может содержать некоторые или все абзацы области документа. Каждый элемент коллекции Paragraphs является объектом типа Paragraph. Вы можете использовать свойства и методы объекта Paragraph для изменения стиля, увеличения или уменьшения интерлиньяжа и других, связанных с абзацем задач. Каждый объект типа Paragraph, в свою очередь, содержит объект типа Range, который содержит текст параграфа. Представленный обзор коллекций показывает, что доступ к тексту для каждой из этих коллекций, в конечном счете, осуществляется с помощью объекта Range. Объект Range является одним из основных объектов Word и появляется в виде свойства во многих других объектах Word. Каждый объект Range представляет непрерывную часть области документа, определяемую положениями начального и конечного символов. Объект Range может не содержать ни одного, содержать один или много символов и может представлять весь документ или любую его часть. Используя методы и свойства объекта Range, можно добавлять текст, форматировать его, добавлять поля или выполнять любые другие действия. Объект Range также предоставляет методы, позволяющие задавать или изменять диапазон символов, на который ссылается конкретный объект Range, и определять, в каком текстовом блоке документа находится диапазон. Другим основным объектом Word является объект Selection. Объект Selection представляет курсор вставки в окне, отображающем определенную часть документа. В каждом окне документа может находиться только один объект Selection, и только один объект Selection может быть активным в любой конкретный момент времени. Объект Selection используется для того, чтобы добавлять текст в место, на которое указывает курсор вставки, применять форматирование, выделять текст для копирования или вырезания, или любой другой задачи, которую можно выполнить интерактивно с помощью курсора вставки, вводя текст, щелкая, или перетаскивая его. Объект Selection может быть как непрерывной областью документа, так и сжатым до курсора вставки. В следующем разделе обсуждается, как с помощью свойств и методов объекта Selection выполнять основные операции с документом. В дополнение к только что описанным основным компонентам документа каждый объект Document также содержит несколько других коллекций, таких как Fields (коллекция полей, включая поля для простановки почтовых реквизитов в документе), TablesOfContents и другие. Различные коллекции объекта Word упоминаются при их использовании в этой и других главах книги. Как задать диапазон Прежде чем вы сможете работать с объектом Range, следует задать в документе диапазон текста, с которым необходимо работать. Объект Range может являться курсором вставки, не содержащим ни одного символа, или быть непрерывной областью документа. Вы можете создать в документе более одного объекта Range. Управление host-приложениями VBA 433 Как получить ссылку на объект Существует несколько различных способов сослаться на конкретный диапазон документа. Можно задать диапазон непосредственно или получить его при помощи одной из коллекций документа: Paragraphs, Sentences или Words. Для того чтобы задать диапазон в области основного текста документа непосредственно, воспользуйтесь *методом Range, применив следующую синтаксическую конструкцию: СИНТАКСИС Object.Range(Start, End) Здесь Object — любая допустимая ссылка на объект Document. Start и End — целые значения типа Long, задающие положение начального и конечного символов диапазона, соответственно. Метод Range возвращает объект Range. В следующем фрагменте программы метод Range используется для получения диапазона, начинающегося перед первым символом и заканчивающегося после двадцатого символа активного документа (AnyRange — объектная переменная): Set AnyRange = ActiveDocument.Range(Start:=0, End:=20) Ссылку на диапазон можно получить и с помощью свойства Range любой из коллекций диапазона, упоминавшихся ранее: Paragraphs, Sentences или Words. Представленные ниже примеры выражений демонстрируют, как это сделать: ActiveDocument.Sentences(3) ActiveDocument.Paragraphs(2) ActiveDocument.Words (10) Первое выражение возвращает объект Range, ссылающийся на третье предложение активного документа. Второе — возвращает объект Range, ссылающийся на второй абзац активного документа, а третье выражение возвращает объект Range, ссылающийся на десятое слово активного документа. Следующие два примера выражений немного сложнее. Первое из помещенных ниже выражений возвращает объект Range, ссылающийся на первое слово второго абзаца активного документа. Коллекция Paragraphs используется для возвращения ссылки на второй абзац документа, а коллекция Word, связанная с диапазоном объекта Paragraph, — для возвращения ссылки на первое слово абзаца. Второе выражение возвращает объект типа Range, ссылающийся на первое слово первого предложения активного документа. Коллекция Sentences используется для возвращения ссылки на первое предложение документа, а коллекция Words данного предложения — для возвращения объекта Range, ссылающегося на первое слово в предложении. ActiveDocument.Paragraphs(2).Range.Words(1) ActiveDocument. Sentences (1) .Words(1) Код листинга 16.26 демонстрирует пример процедуры, использующей различные диапазоны. Листинг 16.26. Использование объектов Range 1 2 3 4 5 6 7 8 1 Sub TestRangeO 2 1 В активном документе первое слово каждого 3 ' абзаца, имеющего стиль "Основной текст" и длину не менее 4 ' трех слов, выделяется курсивом 5 6 Dim mParagraph As Paragraph 7 8 For Each mParagraph In ActiveDocument.Paragraphs 434 Глава 16 9 With mParagraph 10 If .Style = "Основной текст" Then 11 If .Range.Words.Count >= 3 Then 12 .Range.Words(1).Italic = True 13 End If 14 End If 15 End With 16 Next mParagraph 17 18 End Sub Процедура TestRange выделяет курсивом первое слово каждого абзаца в главной области документа, если он содержит три или более слов и если стиль данного абзаца — Основной текст. В строке 8 начинается цикл For Each, который перебирает все абзацы коллекции Paragraphs документа. Строка 9 начинается с оператора With, включающего несколько операторов, ссылающихся на свойства и методы текущего объекта Paragraph. В строке 10 используется оператор If для определения того, действительно ли абзац имеет стиль Основной текст. Текущий стиль абзаца определяется при помощи свойства Style. В строке 11 используется оператор If для определения того, содержит ли абзац более двух слов. Поскольку символ конца абзаца считается словом, для любого абзаца, содержащего как минимум два слова, не считая символа конца абзаца, выражение в строке 11 будет равно значению True. В строке 12 первое слово абзаца выделяется курсивом. Сначала при помощи свойства Range объекта Paragraph, возвращается диапазон, на который ссылается данный абзац. В свою очередь, коллекция Words используется для того, чтобы возвратить объект типа Range, ссылающийся на первое слово в диапазоне абзаца. Чтобы выделить слово курсивом, свойство Italic объекта Range устанавливается равным True. Как выполнить ссылку на диапазон Размер области, на которую ссылается конкретный объект Range, можно изменять. Например, вы можете сначала получить диапазон, который ссылается на один абзац, а затем изменить область данного диапазона, включив в него два следующих абзаца. Область документа, на которую ссылается объект Range, можно расширить или уменьшить, и даже сжать диапазон до курсора вставки. Чтобы изменить область, на которую ссылается диапазон, используйте следующую синтаксическую конструкцию для метода SetRange: СИНТАКСИС Object.SetRange(Start, End) Здесь Object — любая допустимая ссылка на объект Range или Selection. Оба аргумента Start и End являются обязательными, каждый из них является целым числом типа Long, представляющим новые позиции начального и конечного символов диапазона, соответственно. Следующий фрагмент программы демонстрирует, как объектная переменная MyRange сначала устанавливается для ссылки на первое слово активного документа, а затем переопределяется и включает уже первые два слова: Set MyRange = ActiveDocument.Words(1) AnyRange.SetRange Start:=AnyRangeStart, _ End:= ActiveDocument.Words(2).End Вместо переопределения диапазона напрямую вы можете расширить или уменьшить диапазон до заданного размера или «свернуть» его полностью. Управление host-приложениями VBA 435 Метод MoveStart изменяет положение начального символа диапазона, в то время как метод MoveEnd изменяет положение конечного символа диапазона. Для увеличения или уменьшения области, на которую ссылается диапазон, вы можете перемещать конечную точку диапазона, используя методы MoveEnd или Move-Start при помощи следующих синтаксических форм: СИНТАКСИС Object.MoveEnd([Unit], [Count]) Object.MoveStart([Unit] , [Count]) В данном синтаксическом выражении Object — любая допустимая ссылка на объект Range. Как для метода MoveEnd, так и для метода MoveStart аргументы Unit и Count являются необязательными. Аргумент Unit задает элемент, для которого будет изменяться начало или конец диапазона. Unit может быть одной из констант wdUnits, перечисленных в таблице 16.1. Если вы опустите аргумент Unit, методы MoveStart и MoveEnd по умолчанию будут использовать wdCharacter. Аргумент Count — число элементов (units), на которое должна быть сдвинута конечная точка. Если вы используете для аргумента Count положительное число, конечная точка перемещается в документе вперед, если вы используете для аргумента Count отрицательное число, конечная точка перемещается назад. Ниже приведены операторы, демонстрирующие применение методов Move-Start и MoveEnd (AnyRange является объектной переменной, содержащей ссылку на объект Range): AnyRange.MoveStart Unit:=wdParagraph, Count:= -1 AnyRange.MoveEnd Unit:=wdWord, Count:=-2 AnyRange.MoveEnd Count:=6 AnyRange.MoveStart Count:=8 Таблица 16.1. Встроенные константы wdUnits Константа Описание wdCell Ячейка таблицы. wdCharacter Символ, включая скрытые и непечатаемые символы. wdColumn Столбец таблицы. wdLine Строка текста. Вы можете использовать данную константу только для аргумента Unit, если используемый метод применяется к объекту Selection. wdParagraph Абзац. Абзац ограничивается символом конец абзаца (Ц). Символ конца абзаца не отображается на экране пока вы не щелкните кнопку Показать все символы (Show АП) панели инструментов Word. wdRow Строка таблицы. wdSection Раздел документа. wdSentence Предложение. Предложение ограничивается знаками пунктуации, такими как точка (.), знак вопроса (?), и восклицательный знак (!). wdStory Область документа. 436 Глава 16 Константа Описание wdTable Таблица. wdWord Слово. Слово ограничено пробелами и символами пунктуации. Иногда вам может понадобиться расширить диапазон о*г его текущего значения, до размеров, включающих следующий, больший по величине компонент документа, например, расширить диапазон курсора вставки, чтобы он включал слово, в котором находится курсор вставки. Чтобы расширить диапазон, применяйте метод Expand в следующей синтаксической форме: СИНТАКСИС Object.Expand([Unit] ) Здесь Object — представляет любую допустимую ссылку на объект Range или Selection. Необязательный аргумент Unit определяет элемент, до которого расширяется диапазон, и может быть равен одной из констант WdUnits, перечисленных в таблице 16.1. Если вы опустите аргумент Unit, метод Expand использует по умолчанию значение константы wdWord. Ниже представлен фрагмент кода, выделяющий десятое предложение документа и затем расширяющий диапазон для включения в него всего абзаца, в котором находится десятое предложение (MyRange — объектная переменная): Set MyRange = ActiveDocument.Sentences(10) MyRange.Expand Unit:=wdParagraph Работа с объектом Selection Для большинства действий, связанных с управлением текстом документа, вы, вероятно, остановитесь на объекте Selection. Используя объект Selection можно создать VBA-программу, выполняющую с курсором вставки любые операции, которые можно выполнить в Word интерактивно: добавить текст, переместить курсор вставки, выделить текст и другие. Выполнить ссылку на объект Selection очень просто: необходимо только использовать свойство Selection объектов Application, Рапе или Window. В большинстве случаев используется свойство Application.Selection, чтобы получить ссылку на выделенный в данный момент фрагмент в активном документе. Как уже упоминалось в этой главе ранее, в любой момент может быть активным только один объект Selection и в любом окне, отображающем документ, может находиться только один объект Selection. Это вполне очевидно, поскольку объект Selection, по существу, является курсором вставки, который отображается на экране при интерактивной работе в Word. Вы можете связать объект Selection с любым диапазоном, используя метод Select объекта Range: MyRange.Select Данный оператор выделяет область документа, на которую ссылается объектная переменная MyRange. Объект Selection теперь также совпадает с диапазоном, на который ссылается MyRange. Управление host-приложениями VBA 437 Как переместить или «свернуть» объекты Selection и Range Вы уже знаете, как определить или переопределить диапазоны и как связать текущий выделенный фрагмент с конкретным диапазоном. Объекты Range и Selection имеют несколько методов, позволяющих перемещать диапазон или выделенный фрагмент. Чаще всего эти методы используются для перемещения объекта Selection перед добавлением й выделением текста. В действительности, существует пара методов, которые доступны исключительно в объекте Selection, они не имеют аналогов в объекте Range. Чтобы поместить объект Selection в начале или в конце текущей строки текста, столбца таблицы, строки таблицы или области документа и при желании выделить данную строку текста, столбец или строку таблицы, или же область, можно использовать методы НотеКеу или EndKey в следующей синтаксической форме: СИНТАКСИС Object.НотеКеу([Unit] , [Extend]) Object.EndKey([Unit], [Extend]) В обоих случаях Object представляет собой допустимую ссылку на объект Selection. В зависимости от конкретного значения используемого аргумента метод НотеКеу оказывает на выделенный фрагмент такое же действие, как и нажатие клавиш Home, Shift+Home, Ctrl+Home или Ctrl+Shift+Home. Аналогично метод EndKey оказывает на выделенный фрагмент такое же действие, что и нажатие в различных комбинациях клавиши End. Необязательный аргумент Unit задает элемент, в конце которого должен помещаться выделенный фрагмент (в конце строки, столбца и т.д.). Unit может быть значением одной из следующих констант wdUnits: wdStory, wdLine, wdColumn или wdRow. Если аргумент Unit опустить, то как НотеКеу, так и EndKey используют по умолчанию значение константы wdLine (в конце строки). Необязательный аргумент Extend определяет, должен ли выделенный фрагмент быть расширен или должен ли курсор вставки быть перемещен. В качестве Extend можно использовать значение одной из встроенных констант wdMo-vementType: wdMove или wdExtend. Использование wdMove приведет к «сворачиванию» выделенного фрагмента до курсора вставки, после чего курсор вставки переместится на начало или конец заданного элемента документа, определяемого аргументом Unit. Использование wdExtend оказывает такое же действие, как нажатие на клавиши Ноте или End при удерживаемой нажатой клавише Shift. Использование wdExtend приведет к тому, что выделенный фрагмент будет расширен до конца заданного элемента. Если вы опустите аргумент Extend, в качестве значения по умолчанию будет использована константа wdMove. В представленном ниже примере каждый из двух операторов использует один из только что описанных методов. Выполнение первого оператора «сворачивает» выделенный фрагмент до курсора вставки и затем перемещает курсор вставки в начало текущей строки. Выполнение второго оператора расширяет выделенный фрагмент до конца текущей строки. Selection.НотеКеу Selection.EndKey Extend:=wbExtend Хотя объекты Range и Selection имеют много различных методов для выполнения перемещений, возможно, наиболее мощным из них является метод GoTo. Метод GoTo позволяет помещать объекты Range и Selection в любое место в пределах текущей области и перемещать Selection или Range по документу вперед или назад на заданное количество символов, слов или абзацев. 438 Глава 16 Для перемещения объектов Selection или Range используйте метод GoTo в следующей синтаксической форме: СИНТАКСИС Object.GoTo([What], [Which], [Count], [Name]) Здесь Object — любая допустимая ссылка на объекты Selection, Range или Document. Если Object ссылается на Selection, то метод GoTo возвращает объект Range, представляющий новое положение выделенного фрагмента после его «сворачивания» до курсора вставки и перемещения в позицию символа, расположенного непосредственно перед заданным положением. Если Object ссылается на Range или Document, метод GoTo просто возвращает объект Range, представляющий начальное положение для заданной области. Все аргументы метода GoTo являются необязательными. Аргумент What задает тип элемента, в который должен быть перемещен выделенный фрагмент, и может быть любой из встроенных констант wdGoToItem. В таблице 16.2 перечислены некоторые из констант wdGoToItem. Для того чтобы просмотреть полный список констант, доступных в классе wdGoToItem, используйте Object Browser. Аргумент Which указывает, в какой элемент должен быть перемещен выделенный фрагмент. Which может быть равен любой из встроенных констант класса WdGoToDirection: wdGoToAbsolute, wdGoToFirst, wdGoToLast, wdGoToNext, wdGoToPrevious, wdGoToRelative. Аргумент Count задает число элементов документа, на которое должен быть перемещен выделенный фрагмент. По умолчанию значение аргумента Count равно 1. Использование аргумента Count подразумевает использование аргумента What, указывающего, куда необходимо выполнить перемещение, и аргумента Which, задающего, какой тип перемещения необходимо выполнить. Последний аргумент Name определяет имя области, в которую должен быть перемещен выделенный фрагмент. Вы можете использовать аргумент Name только в том случае, если аргумент What также используется и равен при этом значению одной из следующих констант: wdGoToBookmark, wdGoToCom-ment, wdGoToField или wdGoToObject. ' В результате выполнения приведенного ниже оператора выделенный фрагмент перемещается на следующую страницу: Selection.GoTo What:=wgGoToPage Результатом выполнения следующего оператора будет перемещение выделенного фрагмента на последнюю страницу документа: Selection.GoTo What:=wgGoToPage, Which:=wdGoToLast В результате выполнения приведенного ниже оператора выделенный фрагмент перемещается на две строки вниз относительно текущего местоположения: Selection.GoTo What:=wgGoToLine, Which:=wdGoToNext, Count:=2 Таблица 16.2. Встроенные константы WdGoToItem Константа Описание wdGoToBookmark Закладка. wdGoToField Поле, например поле даты или номера страницы. wdGoToHeading Заголовок, то есть текст отформатированный с помощью одного из стилей заголовка: Заголовок!, Заголовок2 и так далее. Управление host-приложениями VBA 439 Константа Описание wdGoToLine Строка документа. wdGoToPage Страница документа. wdGoToPercent Местоположение в документе, выраженное в процентах от длины документа. В дополнение к изменению положения выделенного фрагмента вы можете «свернуть» выделенный фрагмент (или диапазон) до курсора вставки. Для этого используйте метод Collapse в следующей синтаксической форме: СИНТАКСИС Object.Collapse([Direction]) Здесь Object — любая допустимая ссылка на объекты Selection или Range. Необязательный аргумент Direction задает направление, в котором диапазон или выделенный фрагмент должны быть «свернуты». Он может быть равен одной из констант класса WdCollapseDirection: wdCollapseEnd или wdCollapseS-tart. По умолчанию используется значение константы wdCollapseStart. Следующие операторы демонстрируют применение метода Collapse: ActiveDocument.Paragraphs(3).Range.Select Selection.Collapse Direction:=wdCollapseEnd Первый оператор выделяет третий абзац активного документа. Второй оператор «сворачивает» выделенный фрагмент до курсора вставки, помещенного в конец предыдущего выделенного фрагмента. Добавление текста ( Основным назначением программ подготовки текста является хранение и обработка текста. Одной из основных задач, выполняемых вами при интерактивной работе с Word, является ввод текста в документ. Точно также, одна из наиболее распространенных задач, которую вам придется выполнять под управлением I VBA-кода, будет заключаться в том, чтобы добавлять текст. Объекты Selection и Range имеют несколько методов, предоставляющих возможность добавлять текст. В первую очередь рассмотрим методы добавления текста объекта Selection, поскольку вам чаще всего придется иметь дело именно с этим объектом. Простейший способ добавить текст в документ состоит в использовании метода TypeText объекта Selection, сделать это можно при помощи следующей синтаксической конструкции: СИНТАКСИС Object.TypeText([Text]) Object — любая ссылка на объект Selection. Аргумент Text является обязательным, он может быть любым строковым выражением, и это — именно тот текст, который добавляется в документ. Метод TypeText помещает текст в то место, где расположен курсор вставки, как если бы вы ввели его с клавиатуры. Если Selection содержит диапазон и свойство ReplaceSelection равно значению True, то добавляемый текст заменяет выделенный фрагмент. В противном случае текст помещается перед курсором вставки объекта Selection. При установке Word свойство ReplaceSelection по умолчанию задается равным значению True. 440 Глава 16 Свойство ReplaceSelection соответствует флажку заменять выделенный фрагмент (Typing Replace Selection) на вкладке Правка диалогового Word-окна Параметры), которое можно открыть при помощи команды Сервис | Параметры. Можно также задать это свойство при помощи объекта Options. Если метод TypeText добавляет текст так, как будто вы ввели его с клавиатуры, то, очевидно, что объекту Selection необходим метод, эквивалентный нажатию клавиши Enter, для того, чтобы можно было добавлять новый абзац. Этот метод так и называется TypeParagraph. Синтаксическая конструкция этого метода выглядит следующим образом: СИНТАКСИС Object.TypeParagraph Object — ссылка на объект Selection. Метод TypeParagraph помещает в документ новый абзац аналогично тому, как это происходит при нажатии на клавишу Enter. Если объект Selection — диапазон, содержание диапазона заменяется новым абзацем. Если Selection — курсор вставки, добавляется новый абзац, а курсор вставки перемещается в документе вперед. Чтобы случайно не заменить выделенный фрагмент, используйте метод Collapse для «сворачивания» выделенного фрагмента в курсор вставки. Возможно, вам понадобится добавлять текст в диапазон, который не является выделенным. В этом случае следует использовать методы InsertAfter, InsertBefo-re, InsertParagraphAfter и InsertParagraphBefore. Все эти методы применимы как к объектам Selection, так и к объектам Range. Для добавления текста в начало или конец диапазона используйте методы InsertBefore или InsertAfter со следующим синтаксисом: СИНТАКСИС Object. InsertBefore(Text) Object. InsertAfter(Text) Здесь Object — ссылка или на объект Selection, или на объект Range. Text — строковое выражение для текста, который необходимо добавить. Аргумент Text обязателен для каждого из методов. Заданный текст помещается в диапазон, и диапазон расширяется, включая в себя добавленный текст. Оправдывая свое имя, метод InsertBefore помещает текст в начало диапазона или выделенного фрагмента, a InsertAfter помещает текст соответственно в конец диапазона или выделенного фрагмента. Применение метода InsertAfter имеет некоторые особенности, требующие дополнительных пояснений. Если выделенный фрагмент или диапазон включает целый абзац, метод InsertAfter вставляет текст как новый абзац. Так происходит потому, что выделенный фрагмент, включающий целый абзац, также включает и символ конца абзаца. Чтобы вставить текст в конец абзаца, необходимо или «свернуть» диапазон до курсора вставки в позиции перед символом конца абзаца, или таким образом изменить конечную точку диапазона, чтобы он содержал на один символ меньше. Для всех методов, добавляющих текст - TypeText, InsertAfter и InsertBefore, -можно использовать функцию Chr и встроенные константы VBA (vbCr, vbLf, vbCrLf, vbTab) как часть строки аргумента Text для добавления символов, которые нельзя набрать на клавиатуре, или символов, которые имеют в VBA специальное значение (например, кавычки). Управление host-приложениями VBA 441 Так же, как метод TypeText имеет сопутствующий ему метод TypeParagraph, который можно использовать для добавления нового абзаца, методы InsertBefore и InsertAfter имеют сопутствующие методы для добавления нового абзаца перед областью или после области, на которую ссылается определенный диапазон. СИНТАКСИС Object.InsertParagraphBefore Object.InsertParagraphAfter В каждой синтаксической конструкции Object — ссылка на объект Selection или на объект Range. Метод InsertParagraphBefore добавляет символ конца абзаца перед диапазоном или выделенным фрагментом, в то время как метод InsertParagraphAfter добавляет символ конца абзаца в конец диапазона или выделенного фрагмента. Ни тот, ни другой метод не имеют аргументов. Как и в случае с другими методами Insert..., диапазон или выделенный фрагмент расширяется для включения добавленного символа конца абзаца. Листинг 16.27 демонстрирует использование методов InsertBefore, Insert-After и InsertParagraphAfter. Листинг 16.27. Применение методов InsertAfter, InsertBefore, InsertParagraphAfter 1 Sub InsertDocumentlnformation() 2 ' Помещает в начало документа два абзаца 3 ' Первый абзац содержит имя файла, в котором хранится документ 4 ' Второй абзац содержит имя файла-шаблона документа 5 6 Dim aRange As Range 7 8 Set aRange = ActiveDocument.Range(Start:=0, End:=0) 9 10 With aRange 11 .InsertBefore ТехГ:="Имя файла документа: " & _ 12 ActiveDocument.FullName 13 ' .InsertParagraphAfter 14 , .InsertAfter Text:="Присоединенный к документу шаблон: " & 15 ActiveDocument.AttachedTemplate.FullName 16 .InsertParagraphAfter 17 End With 18 19 End Sub Как вырезать, скопировать, вставить и удалить текст Вам обязательно понадобится не только вводить, но и вырезать, копировать, вставлять или удалять текст в документе. Для выполнения этих задач, как объекты Selection, так и объекты Range имеют соответствующие методы. Чтобы вырезать, скопировать или вставить выделенный фрагмент в или из буфера обмена Windows, можно использовать один из следующих методов: СИНТАКСИС Object.Cut Object.Copy Object.Paste Для каждого из этих методов Object — любая ссылка на объект Selection или Range. При использовании метода Cut содержимое диапазона или выделенно 442 Глава 16 го фрагмента вырезается из документа и помещается в буфер обмена Windows. Объекты Selection или Range остаются в документе, «сворачиваясь» до курсора вставки. Метод Сору копирует содержимое диапазона или выделенного фрагмента в буфер обмена Windows. Объекты Selection или Range при этом не изменяются. Метод Paste вставляет содержимое буфера обмена Windows в заданный диапазон или выделенный фрагмент. Если диапазон или выделенный фрагмент не является курсором вставки, то текст, вставляемый из буфера обмена, заменяет содержимое заданного диапазона или выделенного фрагмента. Когда вы используете метод Paste с объектом Range, диапазон расширяется, включая в себя содержимое вставленного из буфера обмена текста. При использовании же метода Paste с объектом Selection выделенный фрагмент располагается после вставленного из буфера обмена текста; выделенный фрагмент не расширяется. Листинг 16.28 содержит процедуру, которая при помощи методов Cut и Paste объекта Selection меняет местами два абзаца документа. Код листинга 16.29 при помощи методов Cut и Paste объекта Range меняет местами два слова в документе. Листинг 16.28. Использование методов Cut и Paste совместно с объектом Selection 1 Sub TransposeParagrahs() 2 ' Меняет местами текущий абзац и абзац, следующий за ним. 3 ' Используется объект Selection. 4 5 With Selection б .Expand Unit:=wdParagraph 7 .Cut 8 .Move Unit:=wdParagraph 9 .Paste . 10 End With 11 12 End Sub Листинг 16.29. Использование Cut и Paste совместно с объектом Range 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Sub Transposewords() ' Меняет местами слово, на которое помещен курсор вставки, ' и слово, следующее за ним Dim MyRange As Range If Selection.Type <> wdSelectionIP Then Exit Sub Set MyRange = Selection.Range With MyRange .Expand Unit:=wdWord . Cut .Move Unit:=wdWord .Paste End With ' End Sub Для удаления из документа текста используйте метод Delete. Синтаксическая конструкция для его использования следующая: Управление host-приложениями VBA 443 СИНТАКСИС Object.Delete([Unit] , [Count]) Object — любая ссылка на объекты Selection или Range. Оба аргумента Unit и Count являются необязательными. Аргумент Unit может быть равен значению wdCharacter или wdWord. По умолчанию значение Unit равно wdCharac-ter. Аргумент Count задает количество символов или слов (в зависимости от значения аргумента Unit), которые должны быть удалены. Если объекты Range или Selection ссылаются на диапазон текста, метод Delete удаляет содержимое данного диапазона. Для удаления заданного числа символов или слов до или после диапазона или выделенного фрагмента сначала его необходимо «свернуть» до курсора вставки. Для того чтобы удалить элементы текста после курсора вставки, следует использовать в качестве аргумента Count положительное число, а чтобы удалить элементы текста до курсора вставки, — отрицательное. Если вы используете метод Delete как функцию, она возвращает значение, указывающее число удаленных элементов текста, или — 0, если операция удаления не удалась. Глава 17 Работа с другими приложениями: Automation В этой и следующих главах показано, как Visual Basic for Applications может управлять и работать с другим приложением, не являющимся текущим host-приложением VBA. Например, вы можете управлять операциями Excel из VBA Word или операциями Word из VBA Excel. Точно так же вы можете использовать VBA Excel или Word для управления такими приложениями, как Microsoft Access, и любыми другими приложениями, которые поддерживают OLE или Automation. Что такое OLE? / Прежде чем вы узнаете, как Visual Basic for Applications работает с объектами Automation и OLE, вам нужно понимать, что такое Automation и что такое OLE. Краткая история OLE OLE версии 2.1 (аббревиатура Objects Linking and Embedding — связывание и внедрение объектов) — это одна из попыток компании Microsoft дать пользователям возможность создавать действительно составные документы (compound documents). Составной документ — это любой файл, который содержит данные более чем одного приложения. Например, вы можете создать рабочий лист в Excel, который в дополнение к своим собственным числам и формулам будет содержать документ Word или рисунок из графической программы; такой рабочий лист является составным документом. Другим примером составного документа может служить документ Word, который содержит диаграммы Excel. Как вы увидите, OLE 2.1 существенно упрощает взаимодействие приложений. В ранних версиях Microsoft Windows вы могли передавать данные из приложения в приложение только через буфер обмена. Вы копировали данные из одной программы в буфер обмена, а затем вставляли их из буфера обмена в другое приложение. Если вам нужно было внести изменения в данные, вы должны были открыть оригинальное приложение, открыть соответствующий файл, ввести изменения, а затем повторить весь процесс копирования и вставки. Хотя способ передачи информации через буфер обмена лучше, чем отсутствие всякого способа, это не самое эффективное решение задачи. Чтобы уменьшить количество шагов, требуемых для обновления и передачи информации между двумя различными приложениями, Microsoft предложила такое решение, как динамический обмен данными (Dynamic Data Exchange — DDE). При использовании DDE вы по-прежнему должны создать данные в одном приложении (сервере), а затем скопировать их в буфер обмена. Однако приложение, которое поддерживает DDE (клиент), позволяет использовать команду Paste Link (вставить связь) вместо обычной команды Paste (вставить) для вставки данных из буфера обмена. Команда Paste Link устанавливает коммуникационную связь между двумя приложениями. Такая коммуникационная связь имеет два преимущества: Работа с другими приложениями: Automation 445 1. Если оба приложения выполняются в одно и то же время и данные, созданные приложением-сервером, изменяются, то документ приложения-клиента обновляется автоматически. 2. Если вы редактируете связанные данные в приложении-сервере, а приложение-клиент в это время закрыто, связанные данные автоматически обновляются и в приложении-клиенте. Это происходит, когда вы открываете в приложении-клиенте файл, содержащий связанные данные, или когда вы явно используете команду Update (Обновить) в приложении-клиенте. Не путайте термины.....и......... Клиент — это всегда приложение, которое по- лучает данные; сервер — это всегда приложение, которое поставляет данные. Динамический обмен данными — это значительное улучшение первоначальной методики копирования-вставки, но эта технология все еще имеет некоторые недостатки. Во-первых, данные, вставляемые из буфера обмена, независимо от того, вставляются ли они обычным образом или как DDE-связь, просто вставляются в приложение-клиент, практически, без какого-либо форматирования. Во-вторых, редактирование данных может быть трудной процедурой. Чтобы внести изменения в данные, связанные по технологии DDE, вы должны перейти в приложение-сервер для связанных данных (или запустить приложение-сервер). Ситуация остается, по меньшей мере, немного неудобной. Но особые трудности возникают в тех случаях, когда вы не уверены в том, какое приложение является сервером для данных, связанных через DDE, или вы просто не можете вспомнить, какой документ сервера содержит исходные данные. Чтобы обойти эти проблемы, Microsoft приняла новый подход к совместному использованию данных: связывание и внедрение объектов (Object Linking and Embedding — OLE). В технологии OLE данные, вставляемые из приложения-сервера, появляются в документе-клиенте как объекты. Каждый объект может вставляться одним из двух способов: как связанный, (linked) или как внедренный (embedded). Оба типа OLE-объектов сохраняют имя сервера OLE, а также любую информацию, в которой нуждается сервер. Эти два типа OLE-объектов имеют следующие возможности: 1. Связанные объекты: Объект содержит образ данных сервера и поддерживает связь между клиентом и сервером во многом аналогично технологии DDE. Оригинальные данные остаются в отдельном файле, находящемся под управлением приложения-сервера. Если данные изменяются, то эта связь гарантирует, что объект-клиент будет автоматически модифицироваться. Как правило, следует связывать объекты в тех случаях, когда другим приложениям может потребоваться доступ к тому же самому файлу данных. 2. Внедренные объекты: Объект содержит автономную версию данных сервера. По существу, это — копия данных сервера. Между сервером и клиентом не устанавливается никакой связи, поскольку в этом нет необходимости. Объект-клиент содержит не только данные, но также и всю основную информацию, связанную с приложением-сервером: имя приложения, структуру файла, коды форматирования и т.д. Как правило, вы должны внедрять объекты в тех случаях, когда планируете работать с данными только под управлением приложения-клиента. Другое преимущество OLE состоит в том, что часто вам не нужен документ сервера. Вы можете создать данные, запустив приложение-сервер из приложения-клиента, а затем вставить эти данные в документ-клиент как внедренный объект. Это означает, например, что вы могли бы вставить пустой документ Word в рабочий лист Excel как внедренный OLE-объект, а затем напечатать письмо, записку, замечание т.д. 446 Глава 17 Связываете вы или внедряете данные, OLE-объект сохраняет первоначальное форматирование данных. Это означает, что OLE-объекты появляются в документе-клиенте точно такими же, как в приложении-сервере. OLE-объект сохраняет имя своего приложения-сервера, и, если OLE-объект связан, в нем также сохраняется имя файла сервера, из которого исходил этот объект. Таким образом, вам никогда не требуется знать, какое приложение и какой файл являются источником внедренных данных. Вы просто выполняете двойной щелчок на объекте, а механизм OLE загружает приложение-сервер и в случае необходимости открывает нужный исходный файл данных. OLE 2.1 имеет следующие преимущества: 1. Обмен данными по технологии «перенести-положить» (drag-and-drop). Вы можете легко передавать информацию между двумя открытыми приложениями, поддерживающими OLE 2.1, буксируя мышью выбранные данные из одного приложения в другое. Если вы хотите скопировать данные, то при буксировке удерживайте нажатой клавишу Ctrl. 2. Вставка «по месту» (in-place inserting). Если вы вставляете объект OLE 2.1, находясь в приложении-клиенте, то клиент активизирует вставку «по месту». В этом состоянии некоторые возможности окна клиента, например панели инструментов и команды меню, временно заменяются возможностями OLE-сервера; приложение-сервер не отображается в отдельном окне. Другими словами, документ остается тем же самым, а изменяется окружающее приложение. 3. Редактирование «по месту» (in-place editing). Когда вы выполняете двойной щелчок на объекте OLE 2.1, чтобы его отредактировать, этот объект остается в документе, а окно клиента изменяется точно так же, как и в случае со вставкой «по месту». 4. Automation. Для VBA-программиста наиболее захватывающей возможностью OLE 2.1 является Automation. (Automation была известна в OLE 2.0 как OLE-Automation; по существу, OLE-Automation и Automation — одно и то же.) По технологии Automation объекты приложений (такие как Workbook, Worksheet, Document, Paragraph и т.д.) становятся видимыми для других приложений, поддерживающих Automation. В частности, видимые объекты приложения доступны для VBA, и вы можете написать VBA-процедуры в одном приложении, которые управляют объектами другого приложения. Например, процедура VBA в Excel может использовать Automation для управления объектами другого приложения OLE 2.1, такого как Microsoft Word, Microsoft Access. Любое приложение, которое поддерживает Automation, делает видимыми часть или все свои объекты, независимо от того, поддерживает оно VBA или нет. Это означает, что вы можете использовать свою VBA-программу для управления объектами приложений, которые не имеют VBA, но могут функционировать как сервер Automation или OLE. Работа Visual Basic for Applications с технологией OLE Компания Microsoft разрабатывала Visual Basic for Applications, ориентируясь на OLE: многие из объектов, с которыми вы работаете в VBA, являются также объектами Automation [их называют компонентами (components) Automation]. В частности, host-приложение обычно предоставляет в ваше распоряжение специальные объекты и коллекции объектов, посредством которых вы можете обращаться к OLE-возможностям других приложений. Эти объекты и их соответствующие коллекции имеют много свойств и методов, которые позволяют создавать свя-‘тнны! или внедренные данные и работать с ними. Кроме того, VBA может йспользовать объекты других приложений, которые поддерживают Automation. Это означает, например, что процедура VBA в Excel мо Работа с другими приложениями: Automation 447 жет обращаться к объектам и манипулировать объектами, которые созданы другим приложением, поддерживающим Automation. Причем происходит это таким образом, как если бы процедура VBA работала непосредственно в данном приложении. Поиск типа класса объекта В главе 7 вы узнали, что объекты host-приложения VBA разделены на различные классы. Объекты, которые приложение делает доступными для OLE и Automation-компонентов, также делятся на различные классы. Прежде чем вы сможете вызывать или использовать OLE-объект или Automation-компонент в своем VBA-коде, необходимо определить его класс. Указывая класс объекта, вы даете VBA информацию, которая нужна для поиска определения объекта и для выполнения методов объекта. Для того чтобы указать тип класса объекта — также называемого программным идентификатором (programmatic ID) — вы должны сначала узнать этот тип. Класс OLE-объекта или Automation-компонента однозначно указывает на характер объекта, которым может быть рабочий лист Excel, документ Word, база данных Access и т.д. Каждый класс имеет уникальное имя и код идентификатора, которые назначаются конкретному OLE-объекту или объекту Automation данного класса. Windows использует тип класса, чтобы определить, какое приложение является сервером для конкретного связанного или внедренного OLE-объекта. Windows поддерживает базу данных реестра (Registry data base), которая содержит, среди прочего, информацию о приложениях, установленных на вашей системе, включая специфическую информацию о «видимых» Automation-компонентах и OLE-объектах приложений. Один из секретов функционирования технологии OLE и Automation состоит в том, что реестр Windows содержит имена всех классов объектов, «видимые» различными приложениями или библиотеками, и «следит» за тем, какие исполняемые файлы обеспечивают ресурсы для этих объектных классов. Когда вашему VBA-приложению нужны «услуги» компонента Automation, VBA «просит» операционную систему Windows выполнить соответствующий код для этого объекта; Windows делает это, основываясь на типе класса объекта. Чтобы узнать значение программного идентификатора любого Automation-компонента или OLE-объекта, доступного на вашей компьютерной системе, вы можете найти тип класса этого объекта в базе данных реестра Windows. Альтернативный способ получить ту же информацию — запустить программу Microsoft System Information. Далее рассматриваются вопросы использования той и другой методики для поиска типа класса объекта. Использование реестра Windows База данных реестра Windows (или просто реестр) содержит полную информацию об аппаратных средствах вашей системы и конфигурации программного обеспечения. Для просмотра содержания реестра следует запустить редактор реестра (Registry Editor). (Редактор реестра обычно устанавливается в каталог Windows, но в меню Start (Пуск) Windows нет ярлыка этой программы.) Чтобы запустить редактор реестра, выполните следующие шаги: 1. В меню Start (Пуск) Windows выберите команду Run (Выполнить). 2. В окне редактирования Open (Открыть) напечатайте Regedit.exe и выберите ОК (рис. 17.1). Windows запустит редактор реестра, который выведет окно, показанное на рис. 17.2. Конечно, вид древовидной диаграммы зависит от конфигурации системы и может отличаться от того, который показан на этом рисунке. « 448 Глава 17 Рис. 17.1 В окне редактирования Open (Открыть) напечатайте Regedit.exe и выберите ОК (рис 17 1) Windows запустит редактор реестра О Type the name of a program, folder, document, or Internet resource, and Windows will open it for you » ,л| OK J | Cancel | j Browse Левая панель окна редактора реестра отображает древовидную диаграмму, отражающую содержание реестра, а правая панель — конкретные данные, содержащиеся в выбранном элементе. Многие ветви дерева реестра содержат в столбце Data (данные) в правой панели окна редактора реестра текст value not set (значение не присвоено), что и показано на рис. 17.2 для ветви HKEY_CLASSES_ROOT. Это не означает, что в данную ветвь не введено никаких данных: просто выбранная ветвь дерева ведет к дополнительным ответвлениям или элементам реестра. Рис. 17.2 Окно редактора реестра содержит древовидную диаграмму, которая сводит вместе данные о программном обеспечении и аппаратных средствах вашего компьютера Поиск объектного класса в реестре Реестр хранит информацию об OLE-объектах в ветви HKEY_CLASSES_ROOT, которая выбрана на рис. 17.2. Чтобы просмотреть зарегистрированные на вашей системе классы OLE-объектов и объектов Automation, выполните следующие шаги: 1. Щелкните в древовидной диаграмме небольшой квадрат, расположенный слева от ветви HKEY_CLASSES_ROOT, чтобы развернуть эту ветвь. Редактор реестра теперь отображает список всех зарегистрированных типов файлов и OLE-объектов. (Этот список обычно очень длинный.) 2. Прокручивайте древовидную диаграмму в левой панели окна редактора реестра до тех пор, пока не найдете имена зарегистрированных классов OLE-объектов. (Поскольку этот список содержит много различных расширений файлов, которые расположены в алфавитном порядке перед большинством имен классов OLE-объектов, вам нужно прокручивать список достаточно долго, прежде чем вы дойдете до имен классов OLE-объектов.) • * Работа с другими приложениями: Automation 449 Вы можете распознать типы классов OLE-объектов в реестре по тому признаку, что они обычно начинаются с имени приложения-сервера. На рис. 17.3 показана развернутая ветвь реестра HKEY_CLASSES_ROOT, прокрученная до точки, где в списке появляются OLE-объекты и Automation-компоненты Excel. На рис. 17.3 выбран объектный класс Excel.application. 10, который представляет непосредственно приложение Excel. Обратите внимание, что данные, показанные в правой панели окна редактора реестра на рис. 17.3, указывают имя выбранного объектного класса — Приложение Microsoft Excel. Обратите также внимание на то, что в левой панели окна редактора реестра можно видеть и другие OLE-объекты и Automation-компоненты Excel: Excel.Addin, Excel.Chart, Excel.Sheet и т.д. Каждый из этих элементов является именем OLE- или Automation-объекта, и именно это имя вы должны использовать, указывая тип класса объекта. & Registry Editor £dt View Favorites йф * z I Eventsystem Eventsystem Л Name $ ,_I EventSystem Eventsystem 1 ^(Default) Zj Excel Addn t Zj Excel Appteaoon Type Data REG_SZ Приложение Microsoft Excel |E. M Appt л ZJ Excel Backup * Z3 Excel Chart i | Excel Chart 5 ' * * Excel Charts » л I Excel CSV s t < Excel Dialog г Excel DIF 1 * Zj Excel Macrosheet J * t Excel Sheet । ♦ ZJ Excel Sheet 5 t ZJ Excel Sheet 8 * Zj Excel SLK v € > < My ComputerM-KEY CLASSES ROOT^xcel Appbcadoo 10 Рис. 17.3. Ветвь реестра HKEY_CLASSES_ROOT содержит зарегистрированные на вашей системе классы OLE-объектов После того как вы найдете в реестре нужный объектный класс, запишите его имя для будущих ссылок. В таблице 17.1 приведен список типов классов для нескольких, часто используемых объектов. Таблица 17.1. Типы классов для часто используемых объектов Объект Тип класса 1-2-3 Worksheet 123Worksheet Приложение Microsoft Access Access. Application. 10 Приложение Microsoft Excel Excel. Application.10 Диаграмма Microsoft Excel Excel.Chart Лист Microsoft Excel Excel.Sheet Приложение Microsoft Graph MSGraph. Application Приложение MS PowerPoint PowerPoint. Application 15 Программирование на VBA 2002 450 Глава 17 Объект Тип класса Приложение Microsoft Word W ord. Application. 10 Документ Microsoft Word W ord.Document Использование программы System Information Другой способ получить информацию об OLE-объектах и Automation-компонентах, установленных на вашей компьютерной системе, состоит в том, чтобы использовать апплет (applet) System Information (Сведения о системе), который поставляется вместе с Microsoft Office. Вы можете получить доступ к апплету System Information двумя способами: 1. Посредством команды Справка | О программе (Help | About), доступной в любом приложении пакета Microsoft Office. 2. Запустив программу Msinfo32.exe, хранящуюся в папке C:\Program Files\Com-mon Files\Microsoft Shared\MSInfo на ващем жестком диске. Чтобы запустить апплет System Information командой Справка | О программе (Help | About), выполните следующие шаги: 1. В любом из приложений Microsoft Office (например, Word иди Excel) выберите в меню команду Справка | О программе (Help | About). Приложение выведет диалог О программе <имя приложения* (About), который показывает имя приложения, версию и информацию об авторских правах на данную программу ' (рис. 17.4). Конкретный вид диалога О программе <имя приложения* немного отличается от приложения к приложению, но в каждом из них есть кнопки ОК, О системе (System Info) и Поддержка... (Tech Support). Рис. 17.4 Из этого окна можно запустить апплет System Information О программе Microsoft Word Microsoft® word 2002 (10 2627 2625) © Корпорация Майкрософт (Microsoft Corporation), 1983 2001 Все права защищены ОРФО ® Промрка «рфогррфии © Информатик А О 1990 2000 В« прав* 1*цищани ОРФО ® Ркст*ю»к» переносе» © Информатик А О , 1992 2000 Вс» права хшицвни ОРФО ® Тенурус © Информатик А О 1992 2000 Все пр*»* хащищаны ОРФО ® Гр«мм*тич«к*я и стилистическая проеерк* ©Информатик А О 1990 1997 Все пр*»* хашишены Portions of International CorrectSpel’* spelling correction system © 1993 by Lemout & Hauspi* Speech Products NV All nghts r»s*tv«d English th»s»utus content developed For Microsoft by Bloomsbury Publishing Pk The American Heritage® Dictionary of the English Language Third Edition Copyright © 1992 Houghton Mifflin Company Electronic version licensed from Lemout В Hauspie Speech Products N V All rights reserved РУТА"" Переефк» уч>а1нсмЫ орфосрафп ©Пролит Лтд 1997 2000 Уо прав* 1»ги«ено РУГА** Переноси » уфаьгемоп словах ©Пролит Лтд., 1997 2000 Va права авхищено РУТА*' Ttiaypyc yrpaiHcanti мо»и ©Прол1нгЛтд 1999 2000 Ус1 прав» хашиаеио Неиоторем иаблоны рахработанм для корпорации Майкрософт компанией Impress* Systems Санта Роха, Калифорния Сравнение версий ©Advanced Software Inc ,1993 2000 Все права зациценч Правом использования этой копии продукта обладает Владимир Кузьменко i Home computer s Номер продукта 54521 750 6140064-17694 Внимание! Данная программа защищена законами об авторских правах и международными соглашениями Незаконное воспроизведение или распространение данной программы или любой ее части влечет гражданскую и уголовную ответственность О системе Поддержка О1кп объекты j 2. В диалоге О программе <имя приложения* щелкните кнопку О системе. Приложение запустит апплет System Information, который выведет окно, аналогичное показанному на рис. 17.5. Если вы хотите использовать апплет System Information вне Microsoft Office, можете запустить его непосредственно из Windows, выполнив следующие шаги: Работа с другими приложениями: Automation 451 1. В меню Start (Пуск) Windows выберите команду Run (Выполнить). 2. Напечатайте в окне редактирования Open (Открыть) текст "C:\Program Files\ Common Files\Microsoft Shared\MSInfor\Msinfo32.exe" (предполагается, что компоненты Microsoft Office и Windows были установлены в папки, выбираемые по умолчанию) и щелкните кнопку OK. Windows запустит апплет System Information, который выведет окно, аналогичное показанному на рис. 17.5. Рис. 17.5 Апплет System Information позволяет просматривать список установленных OLE-объектов О System Information File Edit View loots tjelp ♦ Hardware Resources ♦ Components - Software Environment System Drivers Signed Drivers Environment Vanablt Print Jobs Network Connections Running Tasks Loaded Modules Services Program Groups Startup Programs Windows Error Repo * Internet Settings Object Windows Media Player 7 Windows Media Services DRM Stor WordPad Document Диаграмма Microsoft Excel BnarpaMMaMicrosoft Excel Диаграмма Miao soft Excel Диаграмма Microsoft Graph Документ Microsoft Word Документ Microsoft Word 6 0-70 Лист Microsoft Excel Лист Microsoft Excel Макрос Microsoft Excel 4 0 Презентация Microsoft PowerPoint Рисунок Microsoft Word Рисунок Microsoft Word 6 0-70 Слайд Microsoft PowerPoint Local Server ** Not Available Not Available *%programfilesH\window$ nt\accessories' Not Available 8\progra~1Vnicros'’,2\oftice1C\excel exe Not Available еДргод'аГ 1\micros~2\oflice10\graph exe e\progra~1\micros~2\oftice1C\winword ex> Not Available Not Available e\progra~’Vnicros*“2\oftice1C\exce1 exe Not Available e \progra~1 \micros'“2\offtce10\powerpnt e e\progra~1\micros~2\ofticelC\winword exi Not Available e\progra~1\miaos~2\office10\powerpnte v И Find what s П Search selected category only О Search category names only Апплет System Information отображает в левой панели окна древовидную диаграмму с определенной частью информации о конфигурации вашей системы. Правая панель окна System Information отображает специфическую информацию для категории, выбранной в левой панели. Щелчком на небольшом квадрате, расположенном с левой стороны от ветви, вы можете развернуть или свернуть ветвь «дерева». На рис. 17.5 правая панель окна отображает список всех OLE-объектов, которые установлены в базу данных реестра вашей системы. Информация в окне System Information не настолько полна, как та, которую вы можете получить из базы данных реестра, но апплет System Information намного проще в использовании и работать с ним безопаснее с точки зрения возможных повреждений системы, чем при работе с редактором реестра. Для многих целей быстрее и проще найти тип класса объекта с помощью апплета System Information, чем использовать базу данных реестра. Добавление связанных и внедренных объектов Технология OLE существенно расширяет ваши возможности при разработке VBA-приложения. Цена, которую платят «конечные» пользователи за эту технологию — дополнительная сложность приложения. Это особенно верно по отношению к неопытным пользователям, которые чувствуют себя не очень уверенно, имея в своем распоряжении большой набор различных возможностей, предоставляемых типовой операцией OLE. Например, если вы скопировали данные из приложения-сервера OLE, команда Paste Special (Специальная вставка) в приложении-клиенте дает вам целый ряд возможностей: вы можете вставить информацию как объект, как изображение или текст (в зависимости от данных); вы можете вставить данные как связанные или несвязанные; вы можете вставить данные в виде значка или в режиме полного просмотра. Чтобы упростить «жизнь» пользователям вашей программы, вы можете написать процедуры VBA для управления объектами OLE, поскольку VBA позволяет 15’ 452 Глава 17 контролировать каждую из приведенных выше возможностей на процедурном уровне. Например, вы можете предоставить вашим пользователям одиночную команду или кнопку в панели инструментов, которая создает определенный объект OLE, но скрывает все детали и варианты выбора, возникающие при его создании. В следующих разделах показано, как создавать объекты OLE в VBA. Объекты Shape и OLEFormat В главе 10 описывалась модель объектов слоя векторной графики в Microsoft Word, Microsoft Excel и Microsoft PowerPoint. В этой главе рассматриваются свойства и методы, предназначенные для управления OLE-объектами, находящимися в коллекции Shapes. Каждый объект Shape имеет свойство OLEFormat, которое возвращает объект OLEFormat. Объект OLEFormat содержит информацию о характеристиках OLE-объекта Shape. Определенные свойства и методы объекта OLEFormat изменяются в зависимости от того, работаете ли вы в Word, Excel или PowerPoint. Как и объект Shape, объекты OLEFormat в Word, Excel и PowerPoint имеют одинаковые свойства. Например, объекты OLEFormat имеют свойство Progid, которое сохраняет программный идентификатор конкретного OLE-объекта. Следующие несколько разделов этой главы объясняют, как добавлять OLE-объекты из различных источников в коллекцию Shapes. Использование метода AddOLEObject коллекции Shapes Чтобы добавить связанный или внедренный OLE-объект в коллекцию Shapes Word, Excel или PowerPoint, следует использовать метод AddOLEObject. Метод AddOLEObject использует немного различные наборы аргументов в зависимости от того, работаете ли вы в Word, Excel или PowerPoint, й имеет следующий синтаксис: СИНТАКСИС в Excel 2002: expression.AddOLEObject([ClassType][,FileName] [,Link] [,DisplayAsIcon] [,IconFileName] [,Iconindex] [,IconLabel] [,Left] [,Top] [, Width] [, Height]) в Word 2002: express!on.AddOLEObject([ClassType] [, FileName] [, LinkToFile] [,DisplayAsIcon] [,IconFileName] [,Iconindex] [,IconLabel] [,Left] [,Top] [, Width] [,Height], Anchor} в PowerPoint 2002: v expression.AddOLEObject([,Left] [,Top] [, Width] [, Height] [,ClassName] [, FileName] [,DisplayAsIcon] [,IconFileName] [,Iconindex] [,IconLabel] [,Link] ) Во всех трех случаях expression — это любое выражение, которое является допустимой ссылкой на коллекцию Shapes. Коллекция Shapes находится в объектах Worksheet, Document и Slide. FileName — (необязательный аргумент) строковое выражение, определяющее имя файла объекта, который необходимо вставить в качестве OLE-объекта; имя файла должно иметь расширение, соответствующее зарегистрированному приложению-серверу OLE. Используйте аргумент FileName для вставки существующего файла как OLE-объекта. Например, если вы хотите вставить существующий файл документа Word в рабочий лист Excel или слайд презентации, то в качестве аргумента FileName вы могли бы исполь Работа с другими приложениями: Automation 453 зовать строку следующего вида: "C:\My documents\MyWords.doc” (предполагается, что файл, который вы хотите вставить, имеет имя MyWords.doc и находится в папке с именем Му documents). Если указывается аргумент ClassType, то аргумент FileName игнорируется. Link (для Excel, PowerPoint) и LinkToFile (для Word) — (необязательный аргумент) указывает, связывается или внедряется объект, указанный в File-Name. Если значение аргумента равно True, объект OLE, определенный строкой FileName, связывается. Если — False (значение по умолчанию), объект OLE, определенный строкой FileName, внедряется. (Внедрение объекта создает независимую копию объекта.) Если вы определяете ClassType, аргумент Link/LinkToFile должен иметь значение False или должен быть опущен. DisplayAsIcon — (необязательный аргумент) определяет способ отображения объекта. Если значение аргумента равно True, то объект отображается на экране как значок. Если — False или значение опущено, то объект отображается в его нормальном виде. IconFileNате — (необязательный аргумент) используется только в тех случаях, когда аргумент DisplayAsIcon имеет значение True. IconFileName — это строка, определяющая имя файла, содержащего значок, который необходимо отобразить для вставленного OLE-объекта. Если IconFileNате не используется или заданный файл не содержит никакого значка, то для этого класса OLE используется значок, заданный по умолчанию. Iconindex — (необязательный аргумент) индекс значка в IconFileName. Некоторые файлы содержат несколько значков; аргумент Iconindex выбирает в файле значок, который необходимо отобразить. Нумерация значков начинается с 0; первый значок имеет индекс 0, второй — 1 и т.д. Используйте Iconindex только в том случае, когда аргумент DisplayAsIcon имеет значение True и вы указали аргумент IconFileName. Если вы задаете несуществующий индекс значка, номер значка получает значение 1 (т.е. используется второй значок в файле). По умолчанию аргумент Iconindex имеет значение 0. IconLabel — (необязательный) аргумент, применяемый для настройки надписи значка OLE-объекта (если только DisplayAsIcon имеет значение True). Значением IconLabel может быть любое строковое выражение. Left и Тор — (необязательные) аргументы, задающие положение (в пунктах) левого верхнего угла объекта, которое отсчитывается от левого и верхнего краев документа, рабочего листа (не экрана) или слайда. Позиция объекта коллекции Shapes отсчитывается в точках от левого и верхнего краев рабочего листа, документа или слайда, так что объект будет выведен на экран и напечатан с одним и тем же относительным местоположением. Аргументы Left и Тор имеют по умолчанию значение 0, т.е. положение левого верхнего угла объекта совпадает с левым верхним углом рабочего листа, документа или слайда. Width и Height — (необязательные) аргументы, задающие начальную ширину и высоту OLE-объекта (в пунктах). Anchor — (необязательный аргумент) доступен только в Word-версии метода AddOLEObject и определяет в документе диапазон, к которому должен быть привязан объект. Если вы включаете аргумент Anchor, OLE-объект привязывается к первому абзацу диапазона привязки. Если вы опускаете этот аргумент, новый объект будет выровнен по левому и верхнему краям страницы документа. ClassType (для Excel, Word) ClassName (для PowerPoint) — (необязательный аргумент) строковое выражение, определяющее имя класса объекта, который необходимо вставить в качестве OLE-объекта. Используйте этот аргумент, ко 454 Глава 17 гда необходимо вставить новый (чистый или пустой) OLE-объект. Когда вы обращаетесь к методу AddOLEObject, следует включать или аргумент Class-Type (ClassName), или аргумент FileName. В следующих таблицах приводятся возможные значения аргумента ClassType (ClassName) для различных OLE-объектов. Таблица 17.2а. Значения ClassType (ClassName) для ActiveX Controls Значения аргумента ClassType (ClassName) Создаваемый элемент управления Forms .CheckBox. 1 CheckBox Forms. ComboBox. 1 ComboBox Forms. CommandButton. 1 CommandButton Forms.Frame.l Frame Forms.Image.l Image Forms. Label. 1 Label Forms.ListBox.l ListBox Forms.MultiPage. 1 MultiPage Forms. OptionBu tton. 1 OptionButton Forms.ScrollBar. 1 ScrollBar Forms.SpinButton. 1 SpinButton Forms.TabStrip. 1 TabStrip Forms.TextBox. 1 TextBox Forms. ToggleButton. 1 ToggleButton Таблица 17.2b. Значения ClassType (ClassName) для объектов Microsoft Access Значение аргумента ClassType (ClassName) Создаваемый объект Access. Application Application Access.CodeData, Access.CurrentData CurrentData Access.CodeProject, Access.CurrentProject CurrentProject Access.Def aultWebOptions DefaultW ebOptions Таблица 17.2c. Значения ClassType (ClassName) для объектов Microsoft Excel Значение аргумента ClassType (ClassName) Создаваемый объект Excel. Application Application Excel. Addin Workbook Excel.Chart Workbook „ Excel.Sheet Workbook Работа с другими приложениями: Automation 455 Таблица 17.2d. Значение ClassType (ClassName) для объекта Microsoft Outlook Значение аргумента ClassType (ClassName) Создаваемый объект Outlook .Application Application Таблица 17.2е. Значение ClassType (ClassName) для объекта Microsoft PowerPoint Значение аргумента ClassType (ClassName) Создаваемый объект PowerPoint. Application Application Таблица 17.2f. Значения ClassType (ClassName) для объектов Microsoft Word Значение аргумента ClassType (ClassName) Создаваемый объект Word. Application Application Word.Document, Word.Template Document Word.Global Global Примеры использования метода AddOLEObject коллекции Shapes В следующих разделах рассматриваются несколько примеров использования метода AddOLEObject коллекции Shapes. Вставка нового внедряемого объекта Чтобы вставить новый внедряемый объект в рабочий лист или документ, необходимо выполнить метод AddOLEObject коллекции Shapes с аргументом Class-Type. В коде листинга 17.1 к коллекции ActivePresentation.Slides(l).Shapes добавляется новый документ (строки 4-6) с использованием в качестве аргумента ClassName строки "Word.Document" (см. табл. 17.2f) и новая рабочая книга (строки 9-11) с использованием в качестве аргумента ClassName строки "Excel.Sheet” (см. табл. 17.2с). На рис. 17.6 отображено окно приложения PowerPoint с помещенными на слайд значками Word и Excel (перед «захватом» экрана значки были вручную увеличены). Листинг 17.1. Использование метода AddOLEObject с аргументом ClassName 1 Sub AddOLEObjectExample2() 2 Set myDocument = ActivePresentation.Slides(1) 3 4 myDocument.Shapes.AddOLEObject Left:=100, Top:=100, 5 Width:=200, Height:=300, _ 6 ClassName:="Word.Document", DisplayAslcon:=True 7 8 9 myDocument.Shapes.AddOLEObject Left:=200, Top:=100, 456 Глава 17 10 Width:=200, Height:=3OO, _ 11 ClassName:="Excel.Sheet", DisplayAsIcon:=True 12 13 End Sub Рис. 17.6 Окно приложения PowerPoint с помещенными на слайд значками Word и Excel (перед «захватом» экрана значки были вручную увеличены) j Вставка существующего файла как внедренного объекта В коде листинга 17.2 к коллекции ActivePresentation.Slides(l).Shapes добавляется уже существующий документ (строки 4-6) с использованием в качестве аргумента FileName строки "c:\d.doc". Результат работы кода листинга 17.2 представлен на рис. 17.7. Рис. 17.7 Окно приложения PowerPoint с внедренным Word-документом Работа с другими приложениями: Automation 457 Листинг 17.2. Использование метода AddOLEObject с аргументом FileName (внедрение) 1 Sub AddOLEOb]ectExamplel() 2 Set myDocument = ActivePresentation.Slides(1) 3 4 myDocument.Shapes.AddOLEObject Left:=100, Top:=100, _ 5 Width:=200, fteight:=300, _ 6 FileName:="c:\d.doc" 7 8 End Sub Если вам необходимо отредактировать внедренный документ, щелкните на нем дважды. После этого вам предоставится возможность редактировать этот документ в (почти) обычной Word-среде (рис. 17.8). О документе-источнике можно забыть так же, как «забыло» о нем приложение PowerPoint. На рис. 17.8 в документ добавлена одна строка текста и нарисована небольшая таблица. Рис. 17.8 Внедренный Word-документ редактируется в PowerPoint и не имеет никакой связи с исходным документом ^Microsoft PowerPoint • [Презентация 19] Ч 39% Файл Правка Вид Вставка Формат Сервис Таблица Справка g ' 2 ' 3 ' 4 ' 5 < б > 7 > 8 । 9 । 10- _1 > 12- > 13 И Исправления в измененном документе Показать • Объекты S/мреи 0L£FofWil В главе 10 опнсывъл.-кь модель объектов слоя векторном графики в Microsoft Woid Microsoft Evtel н Mxiosoft ft) w₽i Point В этой главе рксматрнваются (вомствэ и методы преднтнэченкые для управления OLE объектами находящимися в коллекции shape* ттот документ не кмзет нголкои связи с исходным Слайд 1 из 1 юрмление по умолчан русский (Россия) Вставка существующего файла как связанного объекта Если вам необходимо вставить существующий файл как связанный, а не как внедренный, то следует задать аргумент Link метода AddOLEObject равным True, как показано в листинге 17.3. После выполнения кода этого листинга вы можете увидеть на экране такую же картинку, что и на рис. 17.7. Если же вам будет необходимо изменить содержимое документа, то редактировать нужно будет документ-источник. Листинг 17.3. Использование метода AddOLEObject с аргументом FileName (связывание) 1 Sub AddOLEObjectExample2() 2 ' Вставка связанного документа 3 4 Set myDocument = ActivePresentation.Slides(1) 5 6 myDocument.Shapes.AddOLEObject Left:=100, Top:=100, 458 Глава 17 7 Width:=700, Height:=400, _ 8 FileName:="c:\d.doc", Link:=msoTrue 9 10 End Sub Редактировать документ-источник (связанный документ) можно по-разному. Например, двойной щелчок на объекте в приложении-клиенте откроет приложение-сервер со связанным документом. После внесения исправлений сохраните и закройте документ. Ваши исправления сразу же появятся в приложении-клиенте (рис. 17.9). Рис. 17.9 Ваши исправления сразу же появятся в приложении-клиенте, если приложение-сервер запускалось из приложения-клиента । О Microsoft PowerPoint - [Презентация! 9] файл Ставка вид Вставка Формат Сервис Показ слайдов Окно Оправка D 7 ($ Коцструктор "* Создать слайд С Объекты Shift и OLErormat В главе 111 «нськша моднь ойиктов моя влторноп графики в Minowft Word Miaondt Exit) п Мнючнй PowerPoint В >mi главе ршипрнваются (Байства u истоды предаяиченные да упрлиюия OLE ж.агами, плодящимися в во и&щи Shapes ЬкД М№Ц J Ji Ы ШИ Действия*^] Автофигуры- \ \ Е i < гй!М О Ь» ' Слайд 1 из 1 юрмление по умолчат русский (Россия) С? Г Если же вы запустите приложение-сервер и отредактируете связанный документ, ваши исправления документа в приложении-клиенте появятся только при очередном запуске приложения-клиента (со связанным документом) и только с вашего разрешения — перед загрузкой приложения-клиента на экране появится диалоговое окно, представленное на рис. 17.10. Microsoft PowerPoint Презентация F \VB_books\VBA\Bce о 7ВА\Часть III Управление другими приложениями^"лава 19 Работа с другими приложениями Автоматизация\Презентация19 ppt содержит связанные объекты которые нельзя обновить |[ О&чоеить связи J Отмена j Справка Рис. 17.10. Исправления связанного документа, выполненные в приложении сервере, в приложении-клиенте появятся только при очередном запуске приложения клиента и только с вашего разрешения Коллекция Excel OLEObjects В дополнение к коллекции Shapes Excel поддерживает коллекцию OLEObjects — все связанные или внедренные OLE-объекты рабочего листа; каждый объект в коллекции OLEObjects — это OLEObject. В отличие от коллекции Shapes, которая может содержать линии, прямоугольники и другие элементы гра Работа с другими приложениями: Automation 459 фического слоя, коллекция OLEObjects содержит только связанные или внедренные OLE-объекты. Для добавления OLEObject в коллекцию OLEObjects, используйте метод Add со следующим синтаксисом: СИНТАКСИС Object.OLEObjects.Add( [ClassType] , [FileName] , [Link], [DisplayAsIcon] , [IconFileName] , [Iconindex], [IconLabel], [Left], [Top], [Width], [Height]) Object в этом методе — любая допустимая объектная ссылка на объект Worksheet. Метод OLEObjects.Add имеет такие же аргументы, как и метод Shapes.AddOLEObject. Описание аргументов метода OLEObjects.Add смотрите в описании синтаксиса метода Shapes.AddOLEObject, приведенном ранее в этой главе. В листинге 17.4 показана процедура, использующая коллекцию OLEObjects (вместо коллекции Shapes). Листинг 17.4. Использование метода Add Excel-коллекции OLEObjects 1 Sub EmbedWordDoc() 2 ' Внедрение существующего файла c:\d.doc 3 4 With Worksheets(1) 5 .OLEObjects.Add Filenamec:\d.doc" , _ 6 DisplayAsIcon:=True, _ 7 IconFileName:="E:\WIN_XP\setupl.exe", _ 8 Iconindex:=0, _ 9 IconLabel:="c:\d.doc - Double-click to open" 10 End With 11 12 End Sub Результат работы кода листинга 17.4 представлен на рис. 17.11. Обратите внимание на значок внедренного объекта (в строке 7 указан значок файла E:\WIN_XP\setupl.exe) и на надпись под значком (в строке 9 используется выражение c:\d.doc — Double-click to open). Рис. 17.11 Исправления связанного документа, выполненные в приложении-сервере, в приложении-клиенте появятся только при очередном запуске приложения-клиента и только с вашего разрешения 460 Глава 17 Коллекция InLineShapes в Word В дополнение к коллекции Shapes, Word также поддерживает коллекцию InLineShapes. В то время как коллекция Shapes содержит объекты Shape в графическом слое документа, коллекция InLineShapes содержит объекты InLineSha-ре, которые являются частью текстового слоя документа. Объект InLineShape обрабатывается в документе как символ текста и позиционируется подобно символам текста. Несмотря на то, что объект Shape связывается с определенным диапазоном текста, его можно свободно перемещать и позиционировать в каком-либо месте страницы; объект InLineShape всегда располагается на странице согласно его положению в строке текста. Чтобы включить в коллекцию InLineShapes новый OLE-объект, используйте метод AddOLEObject со следующим синтаксисом: СИНТАКСИС Object OLEObjects Add( [ClassType], [FileName] , [LinkToFile], [DisplayAsIcon], [IconFileName] , [Iconindex], [IconLabel] , [.Range] ) Здесь Object является любой допустимой ссылкой на коллекцию InLineShapes. Аргументы ClassType, FileName, LinkToFile, DisplayAsIcon, IconFileNa me, Iconindex и IconLabel идентичны аргументам с теми же именами, которые уже обсуждались для метода Shapes.AddOLEObject в Word. Аргумент Range является выражением, указывающим диапазон, в который будет помещен в текст объект InLineShape. Если диапазон не является местом вставки, то добавляемый объект InLineShape заменяет диапазон. Если вы опускаете аргумент Range, расположение объекта определяет приложение Word. Листинг 17.5 показывает пример вставки OLE-объекта как InLineShape-объекта Процедура EmbedPaintPicturelnLine вставляет файл E:\WIN_XP\ Gone Fishing.bmp как InLineShape-объект в текущее место вставки. На рис. 17.12 показан результат выполнения процедуры EmbedPaintPicturelnLine. Рис. 17.12 OLE объект, вставленный как объект InLineShape процедурой листинга 17 5 "Л Работа с другими приложениями Автоматизация - Microsoft WerJ файл Озавка Вид Вставка Формат Сдэеис Таблица дкно ^правка J Г& У ’ <1 120% v ? limes New Roman Ж Исправления в измененном документе Показать - *> & - & - tC , § * 2 3 5 б 8 10 Листинг 19 ' показывает пример вставки OLE-объекта как ] EmbedP lintPktui elnLine вставляет файл Е WIN XP Gone Fisluiig 1 текущее место вставь.! EinbedPaintPktui eliiLine Нт рис 19 12 показан л Стр Tintтинг 19 < Вставка OLE объекта как объекта InLiueShape 1 Sub Ejnbcdp'tmtFichuelnLuKO 2 Встроить существа тощий фзГп MSPnint как ооьект loLmeSInpe Кол 1 18 Разд 1 18/36 На О 7см русским (Ро С Работа с другими приложениями: Automation 461 Листинг 17.5. Вставка OLE-объекта как объекта InLineShape 1 Sub EmbedPaintPicturelnLine() 2 ' Встроить существующий файл MSPaint как объект InLineShape 3 4 With ActiveDocument.InlineShapes 5 .AddOLEObject Range:“Selection.Range, _ 6 FileName:="E:\WIN_XP\Gone Fishing.bmp" 7 End With 8 9 End Sub Объекты InLineShape можно вставлять как связанные, так и внедренные. Работа с объектом InLineShape подобна работе с объектом Shape. Вы можете преобразовывать объекты Shape в объекты InLineShape (и наоборот), используя метод Shape-объекта ConvertToInlineShape или метод InLineShape-объекта ConvertToShape. Работа со связанными и внедренными объектами После того как вы связали или внедрили OLE-объект в рабочий лист, документ или презентацию, вы можете, среди прочего, изменять размеры объекта и его форматирование, обновлять данные OLE-объекта, редактировать и удалять объект из рабочего листа, документа или презентации. Вы можете управлять связанными или внедренными OLE-объектами, используя свойства и методы объекта Shape и объекта OLEFormat, содержащегося в объекте Shape. В Excel также имеется возможность управления связанными или внедренными OLE-объектами посредством OLEObject-свойств и методов. В Word можно к тому же управлять объектами InLineShape при помощи свойств и методов объекта InLineShape и объекта OLEFormat, который в нем содержится. Доступ к OLE-объектам Прежде чем вы исследуете методы управления OLE-объектами, вы должны знать, как обращаться к OLE-объектам, включенным в рабочий лист, документ или презентацию. Один из способов состоит в использовании коллекции Shapes: СИНТАКСИС Object.Shapes(Index) Object является любой допустимой ссылкой на объект Worksheet, Document или Presentation.Slide, содержащий OLE-объект, с которым нужно работать. Аргумент Index может быть: номером, представляющим объект, к которому необходимо обратиться; число 1 означает первый объект Shape, вставленный в рабочий лист или документ, число 2 — второй вставленный объект Shape и т.д. текстовым именем объекта Shape, к которому необходимо обратиться; каждому OLE-объекту, добавленному в коллекцию Shapes, присваивается имя в форме Object п, где п — номер, соответствующий порядку, в котором объект был вставлен в рабочий лист, документ или слайд; первый OLE-объект имеет имя Object 1, второй — Object 2 и т.д. Если вы работаете в VBA Excel, вы также имеете возможность доступа к отдельным OLE-объектам через коллекцию OLEObjects с использованием того же самого синтаксиса доступа (показанного в следующем примере), что и для коллекции Shapes (оба выражения ссылаются на один и тот же OLE-объект в рабочей книге): 462 Глава 17 ActiveWorkbook.Worksheets("Sheet1").OLEObjects(1) ActiveWorkbook.Worksheets("Sheetl").OLEObjects("Object 1") В Excel вы можете выяснить имя любого OLE-объекта, щелкнув на нем и посмотрев на поле Name (Имя) в строке формул. В VBA Word к OLE-объектам, созданным как объекты InLineShape, можно обращаться через коллекцию InLineShapes. Объекты InLineShape не имеют имен; вы можете обратиться к элементу коллекции InLineShapes, используя только числовой индекс, как показано в следующем выражении (которое возвращает ссылку на второй объект InLineShape в документе): ActiveDocument.InLineShapes(2) Коллекция Shapes и в Word, и в Excel, и в PowerPoint может содержать не только OLE-объекты. Если объект OLEFormat объекта Shape ссылается на Nothing, то объект Shape не является OLE-объектом. Коллекция InLineShapes в Word может также содержать объекты, не являющиеся OLE-объектами. Если объект OLEFormat объекта InLineShape ссылается на Nothing, то объект InLineShape не является OLE-объектом. При помощи свойства Туре объектов Shape или InLineShape можно определить, является ли OLE-объект связанным или внедренным. Для определения типа объекта Shape используйте класс встроенных констант MsoShapeType (определенный в библиотеке Office). Свойство Туре связанных OLE-объектов имеет значение msoLinkedOLEObject, а внедренных OLE-объектов — msoEmbeddedOLEObject. Для объектов InLineShape используйте константы wdlnLineShapeEmbeddedOLE-Object и wdlnlineShapeLinkedOLEObject класса встроенных констант wdlnLine-ShapeType, определенного в библиотеке Word. Использование свойств OLE-объектов Подобно любому объекту в VBA объект Shape коллекции Shapes имеет ряд свойств, которые вы можете использовать в VBA-коде для изменения вида объекта Shape или его поведения. Одним из свойств объекта Shape является свойство OLEFormat, которое возвращает объект OLEFormat. Этот объект содержится в объектах Shape и сохраняет дополнительную информацию, необходимую для полного представления внедренного OLE-объекта. Другое свойство объекта Shape — LinkFormat — возвращает объект LinkFormat. Объект LinkFormat также содержится в объекте Shape и сохраняет часть дополнительной информации, необходимой для представления связанного OLE-объекта. В таблице 17.3 приведены наиболее часто используемые свойства, которые относятся к OLE-объектам. В дополнение к краткому описанию каждого свойства таблица показывает, для какого объекта доступно данное свойство и доступно ли это свойство одновременно для Word, Excel и PowerPoint. Таблица 17.3. Некоторые свойства OLE-объектов Свойство Приложение Объект-носитель Назначение Anchor Word Shape Объект Range указывает диапазон документа, с которым связывается объект Shape. Работа с другими приложениями: Automation 463 Свойство Приложение Объект-носитель Назначение AutoUpdate Excel, Word, PowerPoint * LinkFormat Имеет значение True, если связанный OLE-объект автоматически обновляется, когда изменяются данные приложения-сервера. Bottom-RightCell Excel Shape Возвращает объект Range, определяющий ячейку рабочего листа под правым нижним углом объекта Shape. Height Excel, Word, PowerPoint Shape Устанавливает или возвращает высоту объекта Shape, измеряемую в точках. Left Excel, Word, PowerPoint Shape Устанавливает или возвращает позицию левого края объекта относительно левого края рабочего листа или документа (в точках). Line Excel, Word, PowerPoint Shape Возвращает объект LineFormat, свойства которого управляют видом рамки OLE-объекта. LinkFormat Excel, Word, PowerPoint Shape Возвращает объект LinkFormat, свойства которого сохраняют информацию о связанном OLE-объекте. Name Excel, Word, PowerPoint Shape Имя объекта. Используйте это свойство, чтобы вернуть имя OLE-объекта или переименовать OLE-объект. Object Excel, Word, PowerPoint OLEFormat Возвращает Automation-объект, связанный с объектом. OLEFormat Excel, Word, PowerPoint Shape Возвращает объект OLEFormat, свойства которого содержат информацию как о связанных, так и о внедренных объектах. OnAction Excel Shape Вы можете использовать это свойство в Excel, чтобы установить или вернуть имя процедуры события для данного объекта Shape. Progid Excel, Word, PowerPoint OLEFormat Возвращает строку, содержащую тип класса OLE-объекта. Shadow Excel, Word, PowerPoint Shape Возвращает ссылку на объект ShadowFormat, который сохраняет информацию о состоянии тени, отбрасываемой объектом: видима она или — нет, ее цвет, величину сдвига относительно объекта и т.д. Top Excel, Word, PowerPoint Shape Устанавливает или возвращает позицию верхнего края объекта относительно верхнего края рабочего листа или документа (в точках). 464 Глава 17 Свойство Приложение Объект-носитель Назначение TopLeftCell Excel Shape Возвращает объект Range, определяющий ячейку рабочего листа, расположенную под верхним левым углом объекта Shape. Используйте TopLeftCell и BottomRightCell для поиска ячеек, перекрытых объектом Shape. Type Excel, Word, PowerPoint Shape Возвращает численное значение, указывающее тип объекта Shape. Используйте встроенные константы MsoShapeType для определения типа Shape. Visible Excel, Word, PowerPoint Shape Установите это свойство в состояние False, чтобы скрыть объект, или в состояние True, чтобы сделать его видимым. Width Excel, Word, PowerPoint Shape Устанавливает или возвращает ширину объекта Shape (в точках). В листинге 17.6 показана процедура Excel, которая демонстрирует использование некоторых из этих свойств, а на рис. 17.13 — результат работы этой процедуры: рисунок слева — это результат выполнения кода строк 7-13 (внедрение объекта), рисунок справа — это результат выполнения кода строк 15-21 (редактирование объекта). S Microsoft Excel - Книга!? ЕЗ Microsoft Excel - Книга! 9 8^ Файл Правка Вид вставка Формат Сдэеис Данные Окно Справка - s х й” - " < " Объект 11 ▼ д =ВНЕДРИТЬ( “Bitmap ____ __ . _ |п1адв„ .„) 2 Дважды щелкните для редактирования ► и\Лист1/Лист2 / Лист: [ < | j ► ГОТОЕ л If] Файл Правка Вид Вставка Формат Сдзеис Данные Окно Справка _ s х У? " Новое имяобъекта -г д =ВНЕДРИГЬ( "Bitmap . . д ... . „ image’',”") 2 Дважды щелкните для редактирования"' 3 • 6 7 ВИВИ 8 "ЗЭИВЭи и « ► м \Лист 1/Лист2 / Лист | < ! 1 ГОТОЕ , Рис. 17.13. Результат работы процедуры листинга 17.5 Листинг 17.6. Процедура Excel, использующая некоторые свойства OLE-объекта 1 2 3 4 5 6 7 1 Sub OLEObjectProperties() 2 ' Внедряет новый объект, а затем 3 ' устанавливает некоторые из его свойств 4 5 Dim BMPObject As Shape 6 7 With Worksheets("Лист!") Работа с другими приложениями: Automation 465 8 .Activate 9 .Cells(2, 2).Value = "Дважды щелкните для редактирования" 10 .Cells (4, 2).Select 11 Set BMPObject = .Shapes.AddOLEObject( _ 12 Filename:="E:\WIN_XP\Zapotec.bmp") 13 End With 14 15 With BMPObject * 16 .Line.Weight = xlThin 17 .Name = "Новое имя объекта” 18 .Shadow.Visible = True 19 .Shadow.OffsetX = 8 20 .Shadow.OffsetY = 8 21 End With 22 23 End Sub Процедура OLEObjectProperties вставляет внедряемое изображение в рабочий лист Excel, а затем устанавливает некоторые из свойств нового OLE-объекта. Процедура начинается с объявления переменной типа Shape (с именем BMPObject). Оператор в строках 11 и 12 использует метод AddOLEObject в качестве функции, создавая новый объект и одновременно возвращая ссылку на этот объект; при этом в рабочий лист вставляется файл Zapotec.bmp как внедренный OLE-объект. Строки 15-21 содержат оператор With, который использует переменную BMPObject для ссылок на только что вставленный OLE-объект. Строка 16 устанавливает толщину рамки объекта Shape (тонкая линия), присваивая значение константы xlThin свойству Weight объекта LineFormat, возвращаемого свойством Line объекта Shape. Строка 17 изменяет имя вставленного объекта, присваивая строку "Новое имя объекта" свойству Name — обратите внимание на окно Имя Excel-листа на правой половине рис. 17.12 (в левой половине этого рисунка в окне Имя указано имя объекта по умолчанию). Строки 18-20 устанавливают характеристики тени для объекта Shape, присваивая значения свойствам объекта ShadowFormat, возвращаемого свойством Shadow объекта Shape. Строка 18 устанавливает тень в видимое состояние, а строки 19 и 20 задают видимую область тени, устанавливая ее сдвиг относительно объекта Shape. , , Методы OLE-объектов Объекты Shape включают в себя несколько методов, которые можно использовать для управления этими объектами после их вставки. Многие из этих методов, например Copy, Cut, Delete, Activate и Select, не требуют разъяснений. Однако существуют два метода — Update и Verb (Doverb), которые доступны через свойство Shape.OLEFormat и имеют особое значение для OLE-объектов. В следующих двух разделах эти методы рассмотрены подробно. Метод Update Если вы вставляете объект Shape, который содержит связанный OLE-объект, связь между объектом и файлом сервера обычно является автоматической. Это означает, что каждый раз, когда файл сервера изменяется, объект-клиент модифицируется автоматически. В следующих двух случаях модификация не выполняется автоматически: Если вы переключили автоматическую связь на связь по запросу. (Вы можете сделать это, выбрав команду Правка | Связи, выбрав исходный файл в диалоговом окне Изменение связей (рис. 17.14 и 17.15), а затем — опцию по запросу. 466 Глава 17 Если вы закрыли, а затем вновь открыли документ-клиент и выбрали Нет, ко гда Word или Excel выдали запрос, не хотите ли вы восстановить связи. Рис. 17 15 Диалоговое окно Связи в PowerPoint Рис. 17.14 Диалоговое окно Изменение связей в Excel Связи Связи Тип Обновление Закрыть мС ,ь Обновить Открыть ИСТОЧНИК Изменить источник Разорвать связь Источник С DOC Tun Документ М crosoft Word Обновленке автоматическое вручную В этих ситуациях вы можете использовать метод Update для обновления объекта: СИНТАКСИС Object LinkFormat Update Здесь Object — это ссылка на объект Shape, содержащий связанный OLE-объект, который следует обновить. Если вы работаете в Word, Object может также быть ссылкой на объект InLineShape, который содержит связанный OLE-объ ект. Если вы работаете с объектами OLEObject Excel, то используйте следующий синтаксис для метода Update вместо приведенного выше (где Object — это ссылка на OLEObject в Excel): Object Update В листинге 17.7 приведен пример использования метода Update с объектами Shape. Листинг 17.7. Применение метода Update для обновления OLE объектов в рабочей книге Excel 1 2 3 1 Sub ExcelUpdateAllObjects() 2 1 Обновляет OLE-объекты в Excel 3 Работа с другими приложениями: Automation 467 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 End Dim aSheet As Worksheet Dim Obj As Object For Each aSheet In ActiveWorkbook.Worksheets Application.StatusBar = "Обновление в" _ & aSheet.Name For Each Obj In aSheet.Shapes If Obj.Type = msoLinkedOLEObject Then Obj.LinkFormat.Update End If Next Obj Next aSheet Application.StatusBar = False MsgBox prompt:="Обновление связанных объектов Title, Buttons:=vbInformation Sub завершено", Эта процедура VBA Excel обновляет все связанные OLE-объекты в каждом рабочем листе активной рабочей книги. Первый цикл For Each (строка 7) использует переменную aSheet для обработки каждого рабочего листа активной рабочей книги. Свойство StatusBar выводит имя каждого рабочего листа в строку состояния, чтобы пользователь мог наблюдать последовательность обработки связанных объектов для каждого листа (строки 8 и 9). Вложенный цикл For Each, начинающийся в строке 10, использует переменную Obj для обработки каждого объекта Shape текущего (для цикла) рабочего листа. В строке 11 проверяется, является ли объект Shape связанным OLE-объектом, т.е. равно ли свойство Туре значению константы msoLinkedOLEObject. Если объект Shape содержит связанный OLE-объект, то этот объект обновляется посредством вызова метода Update объекта LinkFormat (строка 12). Когда оба цикла For Each завершены, процедура «сбрасывает» строку состояния Excel (строка 17) и выводит сообщение о завершении работы (строки 19 и 20). В листинге 17.8 приведена процедура, предназначенная для обновления OLE-объектов в Word. Листинг 17.8. Применение метода Update для обновления QLE-объектов в документе Word 1 Sub WordUpdateAllObjects() 2 ' Обновляет все связанные объекты в Word 3 4 Dim Obj As Object 5 6 With ActiveDocument 7 ' обновить связанные объекты в коллекции Shapes 8 For Each Obj In .Shapes 9 If Obj.Type = msoLinkedOLEObject Then 10 Application.StatusBar = _ 11 "Обновление Shape-объекта: " & Obj.Name 12 Obj.LinkFormat.Update 13 End If 14 Next Obj 15 16 1 11 обновить связанные объекты в коллекции InLineShapes 17 For Each Obj In .InlineShapes 18 If Obj.Type = msoLinkedOLEObject Then 19 Application.StatusBar = _ 20 "Обновление InLineShape-объекта: " & Obj.Index 21 Obj.LinkFormat.Update 22 End If 468 Глава 17 23 Next Obj 24 End With 25 26 Application.StatusBar = "Обновление связанных объектов завершено" 27 28 MsgBox prompt:="Обновление связанных объектов завершено", _ 29 Title:="", buttons:=vblnformation 30 End Sub Процедура WordUpdateAllObjects в листинге 17.8 обновляет все связанные OLE-объекты в активном документе как в коллекции Shapes, так и в коллекции InLineShapes. В остальном код процедуры WordUpdateAllObjects почти не отличается от кода процедуры ExcelUpdateAllObjects . Методы Verb и DoVerb Каждый OLE-объект имеет один или большее количество команд (verbs), определяющих действия, которые могут быть выполнены над этим объектом. В отличие от методов, которые определяют, какие действия вы можете выполнить над объектом с точки зрения VBA, verb-команды определяют, какие действия вы можете выполнить над объектом с «точки зрения» сервера. Другими словами, verb-команды — это действия, выполняемые над OLE-объектом приложением, в котором вы создали этот объект. Типичным примером verb-команды является команда Edit; посылка verb-команды Edit OLE-объекту открывает приложение-сервер для редактирования объекта. Чтобы послать verb-команду OLE-объекту, следует использовать методы Verb или DoVerb. Метод Verb можно применять при работе с объектом OLEFormat Excel, а метод DoVerb — при работе с объектом OLEFormat Word. Перед тем как рассмотреть специфический синтаксис для методов Verb и DoVerb, приведем некоторые факты, которые надо иметь в виду при работе с verb-командами OLE-объекта: Все OLE-объекты имеют первичную verb-команду, совпадающую с действием, которое выполняется в ответ на двойной щелчок на объекте. Для большинства объектов, первичная verb-команда позволяет редактировать объект. Если вы хотите редактировать объект, но не точно знаете, что делает первичная verb-команда, используйте verb-команду Open. Если объект поддерживает вторичную verb-команду, вы можете определить эту verb-команду, используя число 2 в качестве значения для аргументов Verb или Verbindex (объясняется в обсуждении синтаксиса методов Verb и DoVerb). Для внедренных объектов, которые поддерживают OLE 2.0 или выше, первичная verb-команда позволяет редактировать объект «по месту», а вторичная — открыть объект в отдельном окне сервера. Метод OLEFormat.Verb имеет в Excel следующий синтаксис: СИНТАКСИС Object.Verb([Verb]) Object в этом синтаксисе является ссылкой на любой объект OLEFormat Excel. Необязательный аргумент Verb — это числовое выражение, определяющее действие verb-команды, которое должен выполнить OLE-сервер. Excel определяет класс встроенных констант xlOLEVerb для упрощения определения значений для аргумента Verb. Используйте константы хЮреп, чтобы послать verb-команду Open, и xlPrimary, чтобы послать первичную verb-команду. Если вы опускаете аргумент Verb, то OLE-серверу посылается verb-команда, заданная по умолчанию. Работа с другими приложениями: Automation 469 В листинге 17.9 показан пример применения метода Verb в процедуре VBA Excel. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Листинг 17.9. Применение метода OL.EFormat.Verb Excel для редактирования OLE-объекта Sub InsEditWordDoc() ' Добавляет в Excel-лист OLE-объект и предлагает его редактировать. ' Если пользователь отказывается редактировать "по месту", то ' для редактирования документа открывается отдельное Word-окно. ' Если пользователь отменяет редактирование, то внедренный 1 документ удаляется. Dim MyWordDoc As Object Dim Ans As Integer Dim aSheet As Worksheet ' создать внедренный документ: Set aSheet = ActiveWorkbook.Worksheets("Лист1") With aSheet .Activate .Cells(3, 1).Select Set MyWordDoc = _ .Shapes.AddOLEObject(ClassType:="Word.Document") End With ' предложить пользователю три варианта ' дальнейшей работы: Ans = MsgBox(prompt:="Редактировать документ 'по месту'?”, _ Buttons:=vbYesNoCancel + vbQuestion, _ Title ^"Редактирование документа") If Ans = vbYes Then ' выбрана кнопка Yes - редактировать OLE-объект ' в Excel-окне ("по месту"): MyWordDoc.OLEFormat.Verb xlPrimary Else If Ans = vbNo Then ' выбрана кнопка No - редактировать OLE-объект ' в отдельном Word-окне: MyWordDoc.OLEFormat.Verb xlOpen Else ' выбрана кнопка Cancel - удалить OLE-объект: MyWordDoc.Delete End I f End If \ End Sub Эта процедура внедряет новый документ Word в рабочий лист Excel. Затем процедура «спрашивает» пользователя, редактировать ли документ «по месту»; если пользователь отвечает «Нет» (выбирает кнопку No), то документ редактируется в отдельном окне. Если пользователь отменяет редактирование (выбирает кнопку Cancel), то внедренный объект-документ удаляется. На рис. 17.16 приведен пример редактирования документа при выборе режима редактирования «по месту». 470 Глава 17 Рис. 17.16 Редактирование документа «по месту» Метод OLEFormat.DoVerb Word имеет следующий синтаксис: СИНТАКСИС Object.DoVerb([Verbindex) ) Object — это ссылка на любой объект OLEFormat Word. Необязательный аргумент Verbindex является числовым выражением, определяющим действие verb-команды, которое должен выполнить OLE-сервер. Word определяет класс встроенных констант wdOLEVerb для упрощения определения значений аргумента Verbindex. Встроенными константами wdOLEVerb являются: wdOLE-VerbDiscardUndoState (снимает состояние отмены объекта, оставляя его активным), wdOLEVerbHide (скрывает интерфейс пользователя объекта), wdOLE-VerblnPlaceActivate (активизирует объект, но не отображает интерфейс пользователя объекта), wdOLEVerbOpen (открывает объект в отдельном окне), wdO-LEVerbPrimary (посылает эквивалент verb-команды объекту, на котором был выполнен двойной щелчок), wdoLEverbshow (показывает объект для редактирования или просмотра) и wdOLEVerbUIActivate (активизирует объект «по месту» и отображает его интерфейс). В листинге 17.10 показан пример применения метода DoVerb в процедуре VBA Excel. Листинг 17.10. Применение метода OLEFormat.DoVerb Word для редактирования OLE-объектов 1 Sub EditEmbWorksheets() 2 ' Создает внедренный Excel-объект. 3 ' Для всех объектов в коллекции Shapes ‘ 4 1 11 предлагает пользователю возможность редактирования 5 1 внедренного рабочего листа Excel либо "по месту", либо 6 1 в отдельном окне. 7 8 Const strTitle = "Внедренный рабочий лист" , 9 10 Dim MsgAns As Integer 11 Dim TmpObj As Shape, MyWordDoc 12 13 ' создать внедренный лист: 14 Set MyWordDoc = ActiveDocument.Shapes.AddOLEObject( 15 ClassType:="Excel.Sheet.8") 16 17 18 For Each TmpObj In ActiveDocument.Shapes Работа с другими приложениями: Automation 471 19 20 If TmpObj . Type = msoEmbeddedOLEObject Then 21 22 If TmpObj.OLEFormat.ProgID = "Excel.Sheet.8" Then 23 MsgAns = MsgBox(prompt:“"Редактировать " & _ 24 TmpObj.Name & " 'по месту'?", _ 25 ' buttons:=vbYesNo + vbQuestion, _ 26 * Title:=strTitle) 27 28 If MsgAns = vbYes Then 29 TmpObj.OLEFormat.DoVerb wdOLEVerbPrimary 30 Else 31 TmpObj.OLEFormat.DoVerb wdOLEVerbOpen 32 End If 33 34 Exit For 35 36 • 37 End If 38 39 End If 40 41 Next 42 43 End Sub Процедура Edit Emb Worksheets в листинге 17.10 создает внедренный рабочий лист (строки 14-15). В цикле For Each (начало в строке 18) проверяются все объекты коллекции Shape активного документа. Если встречается внедренный OLE-объект (определяется проверкой значения свойства Туре объекта Shape в строке 20), то проверяется значение свойства Progid этого объекта для определения того, является ли внедренный объект рабочим листом Excel (строка 22). Если внедренный объект — это рабочий лист Excel, оператор MsgBox в строках 23-26 предлагает редактирование листа в режиме «по месту». В случае положительного ответа (выбор кнопки Да) вызывается метод DoVerb с константой wdOLEVerbPrimary в качестве аргумента, иначе — метод DoVerb с константой wdOLEVerbOpen в качестве аргумента. При помощи оператора Exit For цикл заканчивается. Чтобы определить, какие verb-команды доступны для конкретного OLE-объекта, вы можете использовать редактор реестра Windows. Запустите редактор реестра, как описано ранее в этой главе, когда вы искали типы классов объектов, и используйте команду Find редактора реестра для поиска типов классов объектов. Нажимайте клавишу F3 (или Find Next)) до тех пор, пока не дойдете до ветви \HKEY_CLASSES_ROOT\<c/ass type> (где <class type> — тип класса, который вы ищете). Раскрывайте ветви реестра под этой ветвью, пока не увидите ветвь \HKEY_CLASSES_ROOT\<c/ass tj/pe>\protocol\StdFileEditing\Verb. Список ветви Verb содержит verb-команды, которые «понимает» класс данного типа. На рис. 17.17 показано окно редактора реестра после завершения поиска типа класса Excel.Sheet.8 и последующего раскрытия соответствующих ветвей реестра. Чтобы определить конкретную verb-команду, используйте его численное значение (0, 1 и т.д.) в ветви Verb базы данных реестра в качестве аргумента для методов Verb/DoVerb. 472 Глава 17 Рис. 17.17 Применение редактора реестра для поиска verb-команд, доступных OLE-объекту £ Registry Editor____________________________________________________LJB® 0е &it View Fgyorltes Нф Ll Insertable * Name Type Data Li Kfotlnsertable *b] (Default) REG_SZ ^Изменить - Li protocol - Li StdFiteEdrtng Ll server - L] verb * LJO ’ Li Excel Sheet 8 ‘ * Li Excel SLK I t Li Excel Template * Li Excel VBAModde v < > < > My ComputerVKEY CLASSES R.OOTi£xcel Sheet 5\protocol\StcFiieEdit]ng\verb\l Технология Automation Automation1 (OLE-Automation) — это технология управления объектами одного приложения из другого, технология на основе СОМ, позволяющая прикладной программе-серверу предоставлять свои сервисы в распоряжение других программ-клиентов. VBA может управлять объектами других приложений, поддерживающих Automation, точно так, как объектами своего host-приложения. Microsoft Access, Visio, Microsoft Graph, Microsoft Word, Microsoft Excel и PowerPoint — только некоторые из большого числа приложений, которые делают видимыми для VBA множество своих объектов. Например, Visio делает видимыми такие объекты, как документы, страницы, формы и окна, a Microsoft Access — формы, отчеты и модули. Каждый из этих объектов имеет собственную коллекцию методов и свойств, которые программа VBA может читать и изменять, как если бы это были свойства и методы Excel или Word. Вы можете использовать Automation для управления объектами Excel из VBA Word, а объектами Word из VBA Excel. Количество приложений Windows, которые в настоящее время поддерживают Automation, быстро растет, хотя их относительно мало. Разумеется, любое другое приложение, которое использует Visual Basic for Applications, будет также поддерживать и Automation. Действительно, компания Microsoft уже сделала Visual Basic for Applications частью своих основных Windows-приложений. Текущий список приложений Microsoft, являющихся host-приложениями VBA и поддерживающих Automation, включает Excel, Word, Access, Outlook, Project, PowerPoint, Visio и Visual Basic 6. t Доступ к объектам Automation Способ обращения к объекту Automation из VBA зависит от того, имеет ли объект соответствующий файл библиотеки объектов (.olb), файл библиотеки типов Часто этот термин переводят как Автоматизация. Словари, по крайней мере, это подтверждают. Но, если понять смысл, который вкладывается в слово Automation — технология на основе СОМ, позволяющая прикладной программе-серверу предоставлять свои сервисы в распоряжение других программ-клиентов, — то, похоже, что этот термин не имеет к автоматизации никакого отношения. Автоматический процесс — это процесс, происходящий без участия человека (или «умного» животного) с использованием некоторых приборов, собирающих информацию для управления, и механизмов, осуществляющих управление этим процессом. Технология Automation не подразумевает никакого автоматического процесса, она подразумевает манипуляции объектами одного приложения из кода некоторого другого приложения. Здесь ничего не происходит автоматически. Именно поэтому в данной книге используется только термин Automation как название технологии корпорации Microsoft. Работа с другими приложениями: Automation 473 (.tlb) или библиотеку динамической компоновки (.dll), которые содержат определения объектов, предоставляемых этой библиотекой другим приложениям. Microsoft Access, например, передает свои объекты через файл MSACC.OLB, Microsoft Word — через MSWORD.OLB, Microsoft Excel — через EXCEL.EXE1. Если приложение предоставляет библиотеку объектов, вы можете обращаться к этим объектам непосредственно в VBA-коде, как если бы вы обращались к объектам host-приложения VBA, в Котором работаете. Чтобы сделать объекты, определенные в файле библиотеки Automation, доступными для конкретного проекта VBA, выберите команду редактора VB Tools | References и убедитесь в том, что в диалоговом окне References установлен флажок для данной библиотеки объектов. Непосредственный доступ к объектам — это самый простой способ работы с Automation. Для доступа к объектам, определенным в другом приложении, используйте следующий синтаксис: СИНТАКСИС Application.ObjectName Здесь Application — это имя приложения, содержащее объект, к которому необходимо обратиться, a ObjectName — имя объекта. Каждый объект OLEFormat имеет свойство Object, которое может обеспечить доступ к имени приложения или к ссылке на приложение: Object.Object.Application Здесь Object является ссылкой на объект OLEFormat. (Объекты OLEFormat содержатся в объектах Shape.) Когда метод Application используется указанным способом, он возвращает строку, содержащую имя Automation-приложения. Вы можете также использовать метод Application для возвращения ссылки на исходное приложение объекта. Предположим, что вы внедрили документ Word в рабочий лист Excel и присвоили объектной переменной MyWordDoc такое значение, чтобы она сохраняла ссылку на объект Shape, который содержит внедренный документ Word. В этом случае для вывода имени свойства ActivePrinter приложения Word вы могли бы использовать следующий оператор: MsgBox "Активный принтер: " & _ MyWordDoc.OLEFormat.Object.Application.ActivePrinter В листинге 17.11 приведен пример доступа к Automation-объекту из VBA Excel. Здесь при помощи VBA-кода в рабочий Excel-лист внедряется новый документ Word, который затем редактируется также посредством кода — с использованием Automation, причем внедрение Word-документа в Excel-лист повлияло только на способ последующего доступа к Word-документу. Заметьте, что в диалоговом окне References не установлен флажок Microsoft Word 10.0 Object Library. Листинг 17.11. Ссылка на объекты Automation из VBA Excel 1 2 3 4 5 6 7 8 9 1 Sub AutoWordObject() 2 1 Эта процедура внедряет новый документ Word, а затем работает 3 1 с документом, используя собственные методы и приложение 4 5 Dim WdApp As Object 6 Dim WdDoc As Object 7 Dim aShape As Shape 8 9 Application.StatusBar = "Внедряем и редактируем документ" 1 Имя файла (и полный путь) можно увидеть в диалоговом окне References (в нижней секции) при установке флажка для конкретной библиотеки объектов. 474 Глава 17 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 '25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 End Application.Screenupdating = False 1 выбрать левую верхнюю ячейку With Worksheets("Лист1") .Activate ' ,Cells(2, 1).Select 1 создать новый внедренный документ: Set aShape = .Shapes.AddOLEObject(ClassType:="Word.Document") End With ' установить ссылки на приложение Word и внедренный документ: Set WdApp = aShape.OLEFormat.Object.Object.Application 1 проверить, на что ссылаемся: MsgBox "WdApp - Ссылка на: " & Chr(10) & Chr(13) & WdApp.Name Set WdDoc = aShape.OLEFormat.Object.Object 1 проверить, на что ссылаемся: MsgBox "WdApp - Ссылка на: " & Chr(10) & Chr(13) & WdDoc.Name ' Automation: WdDoc.Activate 1 активизировать внедренный документ 1 доступ к объекту приложения Word: With WdApp .Selection.TypeText Text:“"Вводимый в Word-документ текст" 1 расширить выделенный фрагмент до абзаца: . Selection.Expand Unit:=4 .Selection.Range.Bold = True End With ’ обновить представление объекта aShape.OLEFormat.Verb Verb:=xlVerbPrimary Cells (1, 1).Select Application.Screenupdating = True Application.StatusBar = False Sub Поскольку ссылка на Microsoft Word 10.0 Object Library не задана, переменные WdApp (ссылка на Automation-приложение) и WdDoc (документ), объявлены (в строках 5, 6) как Object (ни к чему не обязывающее описание ссылки на переменную типа Object). В строках 9-18 содержатся рассмотренные ранее (в этой главе) операторы для внедрения Word-документа в Excel-лист. В строке 21 переменной WdApp (до этих пор эта переменная имела значение Nothing) присваивается ссылка на Word-приложение. В этом можно убедиться при выполнении оператора в строке 23, который при помощи MsgBox выводит в диалоговом окне (рис. 17.18, а) текст «WdApp — Ссылка на:» и перенесенное на другую строку наименование приложения. В строке 25 переменной WdDoc (до этих пор эта переменная имела значение Nothing) присваивается ссылка на внедренный Word-документ. В этом можно убедиться при выполнении оператора в строке 27, который при помощи MsgBox выводит в диалоговом окне (рис. 17.18, Ь) текст «WdDoc — Ссылка на:» и перенесенное на другую строку наименование документа. То, ради чего был написан этот код (использование Automation), содержится в строках 30-38. Здесь документ становится активным, затем в него вставляется и редактируется некоторый текст (рис. 17.19). Работа с другими приложениями: Automation 475 Рис. 17.18 Результат выполнения строк 23 и 27 кода листинга 17.11 Рис. 17.19 Результат выполнения кода листинга 17.11 Создание нового Automation-объекта Если Automation-приложение предоставляет библиотеку объектов, вы можете использовать объекты этого приложения непосредственно в коде, создавая ссылку в проекте VBA на библиотеку объектов Automation (в диалоговом окне References). Если приложение не имеет библиотеки объектов или вы не хотите устанавливать ссылку на библиотеку объектов, можно для создания новых Automation-объектов использовать VBA-функцию CreateObject. Функция CreateObject Функция CreateObject является одной из функций VBA-класса Interaction и имеет следующий синтаксис: СИНТАКСИС CreateObject(Class) Аргумент Class является программным идентификатором (programmatic identifier) (т.е. типом класса), определяющим Automation-приложение и тип объекта, который необходимо создать. Например, для Word программным идентификатором является Word.Application, а для Excel — Excel.Application. Среди других примеров можно привести программный идентификатор для приложения Visio — Visio.Application и для приложения Access — Access.Application. Функция CreateObject возвращает объектную ссылку на созданный объект. В листинге 17.12 приведен пример использования функции CreateObject. Обратите внимание на то, что переменные MyWord (для ссылки на Word-приложение) и MyWdDoc (для ссылки на Word-документ) описаны как Object, то есть нет необходимости устанавливать ссылку на библиотеку Microsoft Word 10.0 Object Library. 476 Глава 17 Листинг 17.12. Применение CreateObject для создания объекта Automation 1 Sub CreateWordObject() 2 ' Запускает Word, создает новый документ, редактирует его, 3 1 устанавливает некоторые свойства документа, закрывает Word 4 5 Dim MyWord As Object 6 Dim MyWdDoc As Object • 7 Dim fName As String ' имя документа 8 Dim iconfName As String ' имя файла, содержащего значок 9 10 11 ' Создать экземпляр приложения Word 12 Set MyWord = CreateObject("Word.Application") . 13 14 ' установить имя файла, используя папку активной рабочей книги 15 fName = ActiveWorkbook.Path 16 fName = fName & "\Document Created by Excel VBA.doc" 17 18 ' создать новый документ и установить объектную ссылку на него 19 Set MyWdDoc = MyWord.Documents.Add 20 21 ' добавить в новый документ некоторый текст 22 With MyWord 23 .Selection.TypeText Text:="3TOT документ был создан " & _ 24 "VBA-кодом из Excel" 25 .Selection.TypeParagraph 26 End With , 27 2S With MyWdDoc 29 ' установить некоторые свойства документа 30 .BuiltinDocumentProperties("Title") = __ 31 "Тестовый документ" 32 .BuiltinDocumentProperties("Subject") = _ 33 "Automation-тестирование" 34 35 ' сохранить документ и закрыть его 36 .SaveAs fName 37 .Close 38 End With 39 40 MyWord.Quit ' Выйти из Word 41 42 End Sub Код этого листинга отличается от кода предыдущего способом создания нового документа (строки 12-19) — здесь для запуска Word-приложения используется функция CreateObject (строка 12), а для создания документа — метод Add (строка 19). В строках 22-26 документ редактируется (добавляется текст, изменяется стиль); в строках 30-33 для созданного документа устанавливаются свойства Title и Subject (рис. 17.20). Приведем еще один пример использования функции без использования ссылки на библиотеку объектов. Представьте, что при разработке вами некоторого приложения заказчик потребовал, чтобы у него имелась возможность.посылать вам сообщения с отзывами о работе этого приложения. Заказчик не совсем активно использует компьютер и не хочет для посылки сообщений изучать многочисленные почтовые приложения. Ему нужно диалоговое окно в вашем приложении (к этому он уже привык), в котором можно набрать текст, может быть, адрес, а затем только нажать на кнопку отправки. Согласитесь — это справедливо. Работа с другими приложениями: Automation 477 Рис. 17.20 Результат выполнения кода листинга 17 12 файл Правка Вид Вставка Формат И У 'Л Г 120% Свойства Document Ciet'ej jy Ever VBA Общие Документ j статистика j Состав Прочие Исправления в измененном документе Этот дою мент был с< Стр 1 Разд 1 1/1 Название Тема Автор Руководитель Учреждение Группа Ключевые слова Заметки База гиперссылки Шаблон .Этот документ был создан VBA кодом из I AutDmation-тестирование Владимир Кузьменко Home computer Normal Создать рисунок для предварительного просмотра На 1 Удй " Ct 1 К.6Л 7 1 Отмена £ус<?Кйй"1Г 2 3 Согласитесь также с тем, что эту задачу решить не трудно. Диалоговое окно в режиме разработки представлено на рис. 17.21, процедура обработки щелчка для кнопки Послать сообщение приведена в листинге 17.13. Код процедуры CmdSend_ Click создает при помощи функции CreateObject экземпляр Outlook-приложения (строка 10). Далее с использованием Automation-технологии создается новое сообщение (строка 13) и заполняются поля Subject, Body и То (строки 15-21). Код строки 24 посылает сообщение, а строки 26 -— закрывает Outlook-приложение. Рис. 17.21 Диалоговое окно для отправки E-mail-сообщения Текст сообщения Сообщение автору программы Адрес автора paleiiki@inail com Послать сообщение I Выход | Листинг 17.13. Применение CreateObject для создания объекта Automation 1 Private Sub CmdSend_Click() 2 ' Обработка события кнопки "Послать сообщение" 3 4 Dim OutlookApp As Object 5 Dim OutlookAddress As Object 6 Dim myltem As Object 7 Dim myRecipient As Object 8 9 ' создать Outlook-приложение. 10 Set OutlookApp = CreateObject("Outlook.Application") 11 478 Глава 17 12 ' создать новое сообщение: 13 Set myltem = OutlookApp.Createltem(olMailltem) 14 15 myltem.Sub]ect = UserForml.Caption 16 17 ' текст сообщения из текстового окна: 18 myltem.Body = Msglext.Text 19 20 ' записать адрес Outlook: 21 myltem.То = EmaliAdress.Text 22 23 ' послать сообщение: 24 myltem.Send 25 26 OutlookApp.Quit • 27 28 End Sub Использование ссылок на библиотеки объектов Если вы устанавливаете ссылку на библиотеку объектов для вашего VBA-проекта, то можете объявлять переменные, которые имеют специфические типы данных объектов библиотеки, а также создавать новые экземпляры объектов библиотеки, используя ключевое слово New. Для демонстрации использования ссылок на библиотеки объектов изменим предыдущий листинг (17.13), как показано в листинге 17.14. При этом в диалоговом окне References необходимо (до набора кода) установить флажок Microsoft Outlook 10.0 Object Library (рис. 17.22). Рис. 17.22 Для установки ссылки на библиотеку объектов Outlook в диалоговом окне References необходимо (до набора кода) установить флажок Microsoft Outlook 10 0 Object Library References - VBAPrcjeet Available References Cancel browse * * Visual Basic For Applications Microsoft Excel 10 0 Object Library * OLE Automation * * Microsoft Office 10 0 Object Library * ’ Microsoft Forms 2 0 Object Library ------------------------— VBAProject IAS Helper COM Component 1 0 Type Library IAS RADIUS Protocol 1 0 Type Library Active Directory Types Active Setup Control Library ActiveMovie control type library ASFChop 1 0 Type Library ASFChoo 1 0 Tvoe Librarv Microsoft Outlook 10 0 Object Library Location E \program Files\Microsoft Office\OfficelO\msoutl olb Language Standard Установка ссылки на библиотеку объектов дает нам дополнительные преимущества: как только (в строке 10) мы вводим ключевое слово New, VB-редактор предлагает в списке объектов необходимый объект Outlook (рис. 17.23), а после выбора этого объекта — его свойства (объекты). Листинг 17.14. Использование ссылки на библиотеку объектов 1 Private Sub CmdSend__Click () 2 ' обработка события кнопки "Послать сообщение" 3 Работа с другими приложениями: Automation 479 4 Dim OutlookApp As Outlook.Application 5 Dim OutlookAddress As Outlook.AddressLists 6 Dim myltem As Outlook.Mailltem 7 Dim myRecipient As Recipient 8 9 ' создать Outlook-приложение: 10 Set OutlookApp = New Outlook.Application 11 12 ' создать новое сообщение: 13 Set myltem = OutlookApp.Createltem(olMailltem) 14 15 myltem.Subject = UserForml.Caption 16 17 ' текст сообщения: 18 myltem.Body = MsgText.Text 19 20 ' запись адреса в Outlook: 21 myltem.To - EmaliAdress.Text 22 23 ' послать сообщение: 24 myltem.Send 25 26 OutlookApp.Quit , 27 28 End Sub Рис. 17.23 Как только мы вводим ключевое слово New, VB-редактор предлагает в списке объектов необходимый Outlook-объект Доступ к существующим объектам Automation Вместо создания нового экземпляра объекта вам может понадобиться работать с уже существующим экземпляром объекта. Если приложение-сервер уже выполняется, то, чтобы обратиться к существующему объекту Automation, вызовите VBA-функцию GetObject: СИНТАКСИС GetObject([pathname], [Class]) Здесь необязательный аргумент pathname является строкой, определяющей полный путь папки и имя файла, содержащего объект, который необходимо найти. Если вы опускаете аргумент pathname, то тогда следует указать аргумент Class. 480 Глава 17 Необязательный аргумент Class является строкой, определяющей программный идентификатор объекта, с которым вы хотите работать. (Для аргумента Class функции GetObject используйте тот же самый синтаксис, что и для аргумента Class функции CreateObject.) Если вы опускаете аргумент Class, то необходимо указать аргумент pathname. При этом класс объекта будет определяться файлом, который вы указали; тип файла определяется по его расширению. VBA обращается к реестру Windows, чтобы определить, какой Automation-сервер требуется для файла этого типа. В качестве примера использования функции GetObject рассмотрим ту же задачу посылки сообщения из Excel-кода, только добавим возможность указать имя прикрепленного файла. На рис. 17.24 приведено модифицированное для этого окно, а в листинге 17.15 — код обработчика события кнопки Послать сообщение. Рис. 17.22 Диалоговое окно (модифицированное) для отправки E-mail-сообщения Листинг 17.15. Использование функции GetObject для ссылки на открытое приложение 1 Private Sub CmdSend_Click() 2 ' обработка события кнопки "Послать сообщение" 3 4 Dim OutlookApp As Outlook.Application 5 Dim OutlookAddress As Outlook.AddressLists 6 Dim myltem As Outlook.Mailltem 7 Dim myRecipient As Recipient 8 9 10 On Error Resume Next 11 Set OutlookApp = Nothing 12 13 ' попытка получить ссылку на открытое приложение: 14 Set OutlookApp = GetObject(, "Outlook.Application") 15 16 If Err.Number 0 Then 17 Set OutlookApp = CreateObject("Outlook.Application") 18 End If 19 20 21 ' создать новое сообщение: 22 Set myltem = OutlookApp.Createltem(olMailltem) 23 24 myltem.Subject = UserForml.Caption 25 26 ' текст сообщения: 27 myltem.Body = MsgText.Text 28 Работа с другими приложениями: Automation 481 29 ' имя прикрепленного файла: 30 myltem.Attachments.Add TexTAttFile.Text 31 32 1 E-mail-адрес: 33 myltem.To = EmaliAdress.Text 34 35 ' послать сообщение: 36 myltem.Send 37 38 OutlookApp.Quit 39 40 End Sub В строке 14 делается попытка получить ссылку на открытое ранее приложение. Если приложение не будет найдено, то выполнится код в строке 17 (без генерации ошибки, благодаря коду строки 10). Все остальное — как всегда, только добавлена строка 30 для указания имени прикрепленного файла. Имейте в виду, что если сервер Automation зарегистрирован в реестре Windows как объект в единственном экземпляре (т.е. в любой данный момент на вашей системе может существовать только один экземпляр объекта), то независимо от того, сколько раз вы вызываете функцию CreateObject, будет создан только один экземпляр объекта. Точно так же функция GetObject всегда будет возвращать один и тот же экземпляр для объектов, существующих, по определению, только в одном экземпляре. 16 Программирование на VBA 2002 Глава 18 Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» В главе «Работа с другими приложениями: Automation» было показано, как применять технологию OLE и Автоматизацию в работе с другими приложениями Windows. В этой главе рассматривается еще один способ обмена информацией между приложениями — Dynamic data exchange (DDE). DDE — это механизм, поддерживаемый Microsoft-приложениями в Windows (и в Macintosh), для обеспечения «диалога» между двумя приложениями. Динамический обмен данными является таким способом «общения» приложений, когда два приложения непрерывно посылают друг другу данные и команды. Так же как и в технологии OLE, два приложения, включенные в этот процесс, называются клиентом и сервером. Приложение, которое инициирует и управляет DDE-обменом, называется клиентом (client); приложение, которое отвечает на запросы клиента, — сервером (server). Во время DDE-обмена приложение-клиент может запрашивать информацию и посылать команды приложению-серверу. Приложение-сервер может принимать/возвращать информацию и выполнять команды клиента (рис. 18.1). Рис. 18.1 Роли приложений, участвующих в DDE-обмене Приложение-клиент / \ ' DDE-канал , Приложение- сервер Инициирует "диалог" Посылает команды Запрашивает информацию Посылает информацию Заканчивает "диалог" Выполняет команды Обеспечивает информацией Принимает информацию Для инициирования DDE-обмена приложение-клиент должно определить имя приложения-сервера и предмет DDE-обмена (conversation topic). Имя приложения-сервера и предмет DDE-обмена однозначно определяют DDE-обмен. Если один из участников обмена изменяет имя приложения или предмет DDE-обмена, «диалог» между ними прекращается. Каждое приложение, поддерживающее технологию DDE, имеет уникальное DDE-имя. В Windows чаще всего (но не всегда) DDE-имя является именем исполняемого файла приложения (без расширения). В следующей таблице приведен ряд приложений Microsoft и их DDE-имена. Microsoft Access MSAccess Microsoft Excel for Windows Excel Microsoft FoxPro for Windows FoxPro Microsoft Project for Windows WinProj Microsoft Word for Windows WinWord Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш»483 С каждым DDE-«диалогом» связано приложение-сервер и предмет обмена, в роли которого чаще всего выступают открытые файлы приложения. В Microsoft Excel предметом обмена может быть рабочий лист, в Microsoft Word — документ, а в Microsoft Access — база данных, таблица базы данных. Особым предметом обмена, распознаваемым многими приложениями-серверами, является «System». В отличие от других предметов обмена, которые не всегда доступны (файл с листом, документом или базой может быть закрыт), «System» всегда доступен и может обеспечить списком других доступных в данный момент предметов обмена и другой информацией о приложении. В течение DDE-обмена приложение-клиент и приложение-сервер могут изменять информацию, относящуюся к одному или более элементам (items) в рамках предмета обмена. Например, для Microsoft Excel элементами, которые могут изменяться в течение DDE-диалога, являются ссылки на ячейки рабочего листа, для Microsoft Word — закладки (bookmarks), для Microsoft Access — команды SQL. Запуск приложения-сервера Основным требованием DDE-обмена является одновременное выполнение приложений-участников «диалога». Поскольку мы, вообще-то, выступаем от имени приложения, которое является клиентом, то есть выполняет в данный момент некоторый написанный нами код, то требование быть запущенным, по всей видимости, относится к приложению-серверу. Для того чтобы запустить другое приложение из процедуры VBA, следует вызвать VBA-функцию Shell: СИНТАКСИС Shell(РаthName [.Windowstyle}) Аргумент Pathname — это строковое выражение для (полного) имени исполняемого файла — запускаемого приложения. В строку аргумента Pathname можно включать любые ключи командной строки или аргументы запускаемого приложения. Аргумент WindowStyle — это число, которое указывает, какой тип окна появится после запуска приложения. VBA определяет несколько встроенных констант, которые упрощают использование аргумента WindowStyle; эти константы и их значения перечислены в Таблице 18.1. Если вы опускаете аргумент WindowStyle, приложение запускается в минимизированном состоянии и получает фокус. Если функция Shell была выполнена успешна, она возвращает числовое значение — идентификационный номер задачи (task identification number) для только что запущенного приложения (Windows присваивает каждому работающему в данный момент приложению уникальный идентификационный номер (ID) задачи; для каждого рабочего сеанса ID задачи меняется.) Если Shell была выполнена неудачно, то она генерирует ошибку. Shell выполняет приложение асинхронно, т.е. VBA запускает программу, а затем немедленно продолжает выполнение остальной части процедуры. Таблица 18.1. Встроенные константы VBA для аргумента WindowStyle функции Shell (WindowStyle Вид окна I vbHide Скрытое, с фокусом j vbNormalFocus Нормальный размер, с фокусом 16’ 484 Глава 18 WindowStyle Вид окна vbMinimizedFocus Минимизированное, с фокусом vbMaximizeFocus Максимизированное, с фокусом vbNormalNoFocus Нормальный размер, без фокуса vbMinizedNoFocus Минимизированное, без фокуса После того как вы запустили выполнение других программ, вашему приложению может потребоваться переключиться на какую-либо из этих программ. Например, вы планируете, что пользователь переключится из Excel в Control Panel, чтобы изменить различные настройки. Чтобы переключиться на любое запущенное из VBA-кода приложение, используйте оператор AppActivate: СИНТАКСИС AppActivate (Ti tie [, Wait] ) Аргумент Title может быть либо числовым выражением, результатом которого является допустимый номер идентификатора задачи (возвращаемый функцией Shell), либо строковым выражением, содержащим имя приложения, на которое вы хотите переключиться. В этом случае именем приложения является текст, который появляется в строке заголовка окна приложения. Для некоторых приложений строка заголовка окна включает как имя приложения, так и имя активного документа. Если Title не соответствует в точности ни одной строке заголовка работающих приложений, VBA пытается найти заголовок окна, который начинается со строки, переданной в аргумент Title. Если Title соответствует началу строки заголовка более чем одного выполняющегося приложения, то одно (произвольным образом) из этих приложений будет активизировано. Необязательный аргумент Wait — это значение типа Boolean, которое определяет, когда VBA переключается на заданное приложение. Если значение Wait равно True, то AppActivate ждет до тех пор, пока вызывающее приложение станет активным; для VBA это означает, что AppActivate ждет до тех пор, пока host-приложение VBA не станет активным (например, Word или Excel). Если значение Wait равно False или опущено, метод AppActivate переключается на другое приложение немедленно. Устанавливайте Wait в состояние True каждый раз, когда вам нужна гарантия того, что ваша VBA-программа активизирует другое приложение только в том случае, когда host-приложение VBA находится в активном состоянии, а не выполняется в фоновом режиме. Инициализация и завершение связи с DDE-сервером Обмен в технологии DDE состоит из трех этапов: 1. Инициализация связи между клиентом и сервером1. Эта связь, называемая каналом, является путем, по которому общаются два приложения. Поскольку инициализируют диалог VBA-процедуры, для DDE-связи клиентом является VBA. 2. Работа с сервером: Как только связь установлена, клиент может обмениваться данными с сервером и может управлять сервером, вызывая его внутренние макрокоманды или посылая на сервер «нажатия клавиш». 3. Завершение связи: Когда клиент завершил работу с сервером, VBA-процедура должна закрыть DDE-канал. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 485 Инициализация и завершение связи с DDE-сервером Для того чтобы инициализировать DDE-диалог, ваша VBA-процедура должна установить соединение с приложением-сервером. Для установления канала между host-приложением VBA и другим DDE-приложением необходимо использовать метод DDEInitiate, имеющий следующий синтаксис: СИНТАКСИС object.DDEInitiate(Арр, Topic) Здесь аргумент object является необязательным и представляет объект Application (DDEInitiate — метод, принадлежащий host-приложению VBA). Аргумент Арр является строкой, содержащей DDE-имя приложения-сервера, с которым вы хотите установить связь. DDE-имя зависит от приложения, с которым вы связываетесь, и, как правило, это имя исполняемого файла (без расширения), который запускает приложение. Например, DDE-имя для Excel — Excel, а DDE-имя Word — Winword. Аргумент Topic — это строка, определяющая часть сервера, с которой вы хотите работать. Можно считать, что это «предмет диалога» между клиентом и сервером. Для большинства приложений используется либо предмет System (когда происходит обращение к приложению-серверу в целом), либо имя конкретного файла сервера, с которым вы хотите работать. Если метод DDEInitiate завершается успешно, он возвращает значение типа Long, которое идентифицирует канал. На это значение следует ссылаться во всех последующих DDE-обменах между клиентом и сервером. Если приложение-сервер уже открыто, когда вы выполняете метод DDEInitiate, то открывается DDE-канал. Если DDE-сервер еще не запущен, выполнение метода DDEInitiate вызовет запуск приложения-сервера. Однако существуют несколько причин, по которым запуск приложения-сервера выполнением метода DDEInitiate может быть неудобным: Каждый раз, когда приложение-сервер запускается выполнением метода DDEInitiate, host-приложение VBA выводит сообщение о том, что удаленные данные недоступны и предлагает запустить приложение-сервер. Чтобы продолжить работу, пользователь должен щелкнуть кнопку Yes; если пользователь выбирает кнопку No, метод DDEInitiate генерирует runtime-ошибку VBA. Даже если вы попытаетесь обойти эту проблему, установив свойство Application.DisplayAlerts в состояние False, VBA все равно будет генерировать ошибку времени исполнения. Если в данный момент выполняется более одного экземпляра приложения-сервера DDE, пользователю может быть представлен диалог, спрашивающий, какой из экземпляров сервера нужно использовать. Если приложение-сервер DDE не находится в текущей папке или на диске, а также не находится на диске или в папке в пути поиска файлов DOS, метод DDEInitiate не сможет его найти. Чтобы решить эту проблему, перед вызовом метода DDEInitiate нужно вставить оператор VBA ChDir для перехода в папку DDE-сервера (или включить полный путь папки в определение аргумента Арр). В большинстве случаев перед вызовом метода DDEInitiate для открытия DDE-канала следует вызывать функцию Shell для запуска приложения-сервера. Когда приложение-клиент завершает DDE-«диалог», следует закрыть связь между клиентом и сервером. Для этого предназначен метод DDETerminate: 486 Глава 18 СИНТАКСИС DDETerminate Channel Здесь Channel — это число типа Long, указывающее DDE-канал, который должен быть закрыт; Channel должен ссылаться на допустимый номер DDE-кана-ла (тот номер, который был возвращен методом DDEInitiate). В листинге 18.1 показан пример процедуры, вызывающей методы DDEInitiate (для открытия DDE-канала) и DDETerminate (для закрытия DDE-канала). Листинг 18.1. Применение метода DDEInitiate для открытия DDE-канала 1 Option Explicit 2 Dim ddeChannel As Long 3 4 Sub OpenDDEchannel() 5 ' Открывает DDE-канал между Excel (клиент) c Word (сервер) 6 7 Const ITitle = "Открытие DDE-канала" 8 9 . On Error GoTo BadConnection 10 11 Shell PathName:="E:\Program Files\Microsoft Office\OfficelO" & 12 "\Winword.exe", WindowStyle:=vbMinimizedNoFocus 13 14 ddeChannel = DDEInitiate(App:="Winword", Topic:="System") 15 16 MsgBox prompt:="DDE-канал открыт!", Buttons:=vblnformation, _ Title:=lTitle 17 DDETerminate ddeChannel 18 Exit Sub 19 20 BadConnection: 21 MsgBox prompt:="Невозможно открыть DDE-канал", _ 22 Buttons:=vbExclamation, Title:=lTitle 23 End Sub Процедура OpenDDEchannel открывает DDE-канал между Excel (клиент) и Word (сервер). В строке 3 объявляется переменная уровня модуля ddeChannel; это дает возможность другим процедурам в этом модуле ссылаться на номер канала, возвращаемый методом DDEInitiate. Сама процедура OpenDDEchannel начинается со строки 5. Оператор в строке 10 включает обработчик ошибок. Включение обработчика ошибок в DDE-процедуру всегда оправдано, поскольку DDE-соединения известны своей ненадежностью. Вызов функции Shell (строки 12-13) запускает Word в минимизированном состоянии без фокуса; в данном случае возвращаемый функцией Shell результат игнорируется. Код строки 15 вызывает метод DDEInitiate; Word уже выполняется в результате вызова функции Shell, так что метод DDEInitiate только открывает DDE-канал. Если все идет нормально, номер канала сохраняется в переменной ddeChannel и (строка 17) оператор MsgBox сообщает пользователю, что соединение было установлено. Если происходит ошибка, выполнение кода переходит к метке BadConnection (строка 21) и выводится сообщение об ошибке (строки 22 и 23). Код в строке 18 закрывает DDE-канал — пока без дальнейшего «общения» с сервером. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 487 Управление приложением-сервером • Как только у вас есть открытый DDE-канал, вы можете использовать метод DDEExecute для управления приложением-сервером DDE. Вы можете посылать команды, которые «понимает» приложение-сервер, например команды на его макроязыке (если таковой имеется), или можете посылать приложению-серверу «нажатия клавиш». DDEExecute'имеет следующий синтаксис: СИНТАКСИС: DDEExecute(Channel, String) Channel — это номер канала, возвращаемый методом DDEInitiate, a String — строковое выражение, которое представляет команды или «нажатия клавиш», посылаемые серверу. Формат, используемый для команд, зависит от приложения-сервера DDE. Некоторые приложения «разрешают» использовать команды своего макроязыка, другие — используют специальные DDE-команды. (Информацию относительно DDE-команд, поддерживаемых конкретным приложением, можно получить из документации приложения-сервера или обратившись в отдел технической поддержки разработчика приложения.) Метод DDEExecute возвращает значение типа Boolean, указывающее, успешно ли выполнен метод. В листинге 18.2 приведен простой пример вызова метода DDEExecute. Листинг 18.2. Применение метода DDEExecute для управления приложением-сервером 1 Sub DDEExecuteExamplel() 2 ' Пример использования DDEExecute 3 4 Const ITitle = "Открытие DDE-канала" 5 Dim ddeChannel As Long 6 7 On Error GoTo The_End 8 9 Application.StatusBar = "Запуск WinWord..." 10 11 Shell PathName:="E:\Program Files\Microsoft Offrce\OfficelO" & _ 12 "\Winword.exe", Windowstyle:=vbMinimizedNoFocus 13 14 ' Инициализировать канал с "предметом диалога" - System 15 Application.StatusBar - "Opening test document..." 16 ddeChannel = DDEInitiate(App:="WinWord" , Topic:="System") 17 18 ' послать серверу команду на открытие документа: 19 DDEExecute Channel:=ddeChannel, _ 20 String:="[FileOpen ""F:\VB_books\DBMS\01.DOC""]" 21 22 ' закрыть канал: 23 DDETerminate ddeChannel 24 25 Exit Sub ' обойти метку The_End 26 27 The_End: 28 MsgBox prompt:="Что-то у нас не ладится", _ 29 Buttons:=vbExclamation, Title:=lTitle 30 Application.StatusBar = False 31 End Sub 488 Глава 18 Процедура DDEExecuteExamplel отличается от процедуры OpenDDEchannel (из листинга 18.1) только одним оператором (строки 19-20), который при помощи метода посылает серверу (приложению Word) команду открыть документ F:\VB_books\DBMS\01.DOC, который к этому моменту должен действительно находится в указанной папке. В результате работы процедуры вы можете увидеть указанный вами открытый документ. Если нужного документа на диске не окажется, вы поЛучите два сообщения (последовательно), приведенные на рис. 18.2. Кроме того, будет создан новый документ с именем по умолчанию. Рис. 18.2 Роли приложений, участвующих в DDE-обмене Run-time error '1076' Файл не найден Попробуйте выполнить следующие действия * Убедитесь, что имя документа введено правильно * Попробуйте другое имя файла (F AVB_books\PBMS\02.DOC) j End ‘ Г Qebug 1 Help В листинге 18.3 также приведен код с использованием метода DDEExecute. Здесь сначала повторяются операторы листинга 18.2 (строки 1-23), а затем в открытом документе выделяется фрагмент текста и копируется в Windows-буфер, из которого может быть помещен в любое приложение. Листинг 18.3. Применение метода DDEExecute для управления приложением-сервером 1 Sub DDEExecuteExample2() 2 ' Пример использования DDEExecute t 3 4 Const ITitle = "Открытие DDE-канала" 5 Dim ddeChannel As Long 6 7 On Error GoTo The_End 8 9 Application.StatusBar = " Запуск WinWord..." 10 11 Shell PathName:="E:\Program Files\Microsoft Office\OfficelO" & 12 "\Winword.exe", Windowstyle:=vbMinimizedNoFocus 13 14 ' Инициализировать канал с "предметом диалога"- System 15 Application.StatusBar = "Opening test document..." 16 ddeChannel = DDEInitiate(App:="WinWord" , Topic:="System") 17 18 ' послать серверу команду на открытие документа: 19 DDEExecute Channel:=ddeChannel, Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 489 20 String:="[FileOpen ""F:\VB_books\DBMS\01.DOC""]" 21 22 ' закрыть канал: 23 DDETerminate ddeChannel 24 25 ' Инициализировать канал с "предметом диалога"- документ 26 Application.StatusBar = "Copying text..." 27 ddeChannel = DDEInitiate(Арр:="WinWord", __ 28 Topic:="F:\VB_books\DBMS\01.DOC") 29 30 ' Перейти в начало документа: 31 DDEExecute Channel:=ddeChannel, String:="[StartOfDocument]" 32 ' Выделить первую строку документа: 33 DDEExecute Channel:=ddeChannel, String:="[EndOfLine 1]" 34 ' Копировать выделенный фрагмент в Windows-буфер: 35 DDEExecute Channel:“ddeChannel, String:="[EditCopy]" 36 37 DDETerminate ddeChannel ' закрыть DDE-канал 38 39 Exit Sub ' обойти метку The_End 40 41 The_End: 42 MsgBox prompt:="Что-то у нас не ладится!", 43 Buttons:=vbExclamation, Title:=lTitle 44 Application.StatusBar = False 45 End Sub Код в строках 27-28 открывает новый DDE-канал с «предметом диалога» — открытый предыдущими операторами процедуры документ. Команда, переданная по DDE-каналу серверу посредством 31 строки кода, переводит курсор (точку вставки) в начало документа. Посредством команды, переданной кодом строки 33, выделяется первая строка документа. Код строки 35 передает команду копирования выделенного фрагмента в Windows-буфер. После того как код листинга 18.3 выполнится, вы можете проверить, что оказалось в Windows-буфере, выполнив команду вставки либо в Excel, либо в Word. Обмен данными с приложением-сервером DDE Как вы только что видели, каждый DDE-диалог между клиентом и сервером имеет определенный «предмет диалога». Все, что два приложения «обсуждают» в текущем DDE-сеансе, ограничено темами, относящимися к заданному «предмету диалога». В предыдущем разделе вы видели, как включаются в DDE-обмен команды сервера. В этом разделе рассматривается другой предмет, который вы можете использовать в DDE-обменах: элементы данных. Каждое поддерживающее DDE приложение-сервер определяет один или большее количество элементов (items), которые оно может использовать совместно с клиентом. Например, типичным элементом рабочего листа является ячейка, а типичным элементом текстового процессора — закладка (закладка — это именованный блок текста). Эти элементы всегда составлены только из текста и чисел — в DDE-обмене вы не можете передать графику и другие объекты высокого уровня. В следующих двух подразделах показано, как использовать методы DDERe-quest и DDEPoke для обмена элементами данных между клиентом и сервером. Получение данных от DDE-сервера Если сервер имеет данные, которые следует передать приложению-клиенту, вы можете установить между двумя приложениями DDE-связь и вызвать метод DDERequest для получения данных: 490 Глава 18 СИНТАКСИС DDERequest(Channel, Item) Аргумент Channel — номер канала, возвращаемый методом DDEInitiate. Item — строка, определяющая элемент данных, который вы хотите получить от сервера. Как и с другими DDE-методами, DDERequest возвращает значение Boolean, указывающее на успешное или неуспешное выполнение операции. В листинге 18.4 приведен пример использования метода DDERequest. Листинг 18.4. Применение DDERequest для получения данных из приложения 1 Sub WordDataRequest() 2 ' Устанавливает закладку в документе Word; 3 ' восстанавливает текст закладки 4 Const ITitle = "Обмен по DDE-каналу" 5 Dim ddeChannel As Integer 6 Dim WordData As Variant 7 8 On Error GoTo Retreat 9 10 ' открыть документ (см. листинги 18.2, 18.3) 11 Shell PathName:="Е:\Program Files\Microsoft Office\OfficelO" & 12 "\Winword.exe", Windowstyle:=vbMinimizedNoFocus 13 ctdeChannel = DDEInitiate(App:“"WinWord" , Topic:“"System") 14 DDEExecute Channel:“ddeChannel, _ 15 String:="[FileOpen ""F:\VB_books\DBMS\01.DOC""]" 16 DDETerminate ddeChannel 17 18 ' открыть новый DDE-канал с предметом - документ 19 ddeChannel = DDEInitiate(Арр:“"Winword" , _ 20 Topic:="F:\VB_books\DBMS\01.DOC") 21 22 ' найти ключевое слово и вставить закладку 23 . DDEExecute Channel:“ddeChannel, String:="[StartOfDocument]" 24 DDEExecute Channel:“ddeChannel, _ 25 String:="[EditFind .Find = ""Database""]" 26 DDEExecute Channel;“ddeChannel, _ 27 String:="[SelectCurSentence]" 28 DDEExecute Channel:“ddeChannel, _ 29 String:="[EditBookmark .Name = ""Base""]" 30 31 WordData = DDERequest(Channel:“ddeChannel, Item:“"Base") 32 33 ' вставить WordData в первую ячейку рабочего листа ' 34 Worksheets("Sheetl").[Al].Value = WordData 35 36 DDETerminate ddeChannel 37 38 Exit Sub 39 40 Retreat: 41 DDETerminate ddeChannel 42 ’ ' 43 MsgBox prompt:="Что-то у нас не ладится", _ 44 Buttons:=vbExclamation, Title:“ITitle v 45 Application.StatusBar = False 46 End Sub Процедура WordDataRequest в листинге 18.4 находит определенный раздел текста в документе Word, считывает и передает его в Excel. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 491 Код строк 11-12 вызывает функцию Shell для запуска Word. Код строки 13 открывает DDE-канал для Word с «предметом обмена» System. В строках 14 и 15 находится оператор, который вызывает метод DDEExecute для передачи серверу команды открытия указанного файла с документом. После того как файл открыт, этот DDE-канал больше не нужен, поэтому он закрывается кодом строки 16 (методом DDETerminate). Код строк 19-20 открывает новый DDE-канал для Word, используя на этот раз открытый документ как «предмет обмена». В строках 23-29 содержатся четыре оператора, использующих метод DDEExecute: в строке 23 выполняется переход в начало документа, код строк 24-25 ищет в документе заданное слово, код строк 26-27 выделяет строку с искомым текстом, а код строк 28-29 вставляет закладку в выбранный текст. Код строки 31 вызывает метод DDERequest для передачи по DDE-каналу текста, отмеченного новой закладкой, и сохраняет этот текст в переменной Word-Data. Код строки 34 вставляет содержимое переменной WordData в первую ячейку указанного рабочего листа активной рабочей книги. В листинге 18.5 приведен пример использования метода DDERequest для запроса данных из приложения Access, до сих пор мало встречавшегося в этой книге. Как известно, Microsoft Access — это приложение для хранения и управления таблицами данных. Подобно тому, как в Excel основными объектами являются рабочие книги, листы и ячейки, в Access основные объекты — базы данных, таблицы, поля и строки таблиц. В четвертом разделе книги элементы баз данных будут рассматриваться более подробно, а в листинге 18.5 показан пример, как можно запросить данные из некоторой таблицы Access-базы данных. (Эта база данных может быть установлена в качестве примера при установке Microsoft Access.) Листинг 18.5. Применение DDERequest для получения данных из приложения Access 1 Sub AccessDataRequest() 2 ' Запрашивает данные из таблицы Access 3 4 Const ITitle = "Обмен по DDE-каналу" 5 Dim ddeChannell As Integer, ddeChannel? As Integer 6 7 8 On Error GoTo Retreat / 9 10 ' открыть канал ddeChannell: 11 ddeChannell = DDEInitiate(App:="MSAccess" , Topic:="System") 12 13 DDEExecute ddeChannell, _ 14 "[OpenDatabase ""E:\Program Files\Microsoft _ 15 OfficeXOfficel0\Samples\Борей.mdb""]" 16 ' открыть канал ddeChannel2: 17 ddeChannel? = DDEInitiate("MSAccess", "Борей;TABLE Товары ") 18 19 ' запросить данные из таблицы: 20 data = DDERequest(ddeChannel2, "All") 21 22 ' заполнить данными первые десять строк листа: 23 Worksheets("Лист1").[Al:К10].Value = data 24 25 DDETerminate ddeChannell 26 DDETerminate ddeChannel2 27 Exit Sub 28 29 30 Retreat: 492 Глава 18 31 32 DDETerminate ddeChannell 33 DDETerminate ddeChannel? 34 35 MsgBox prompt:="Что-то у нас не ладится", 36 Buttons:=vbExclamation, Title:=lTitle 37 38 End Sub Код строки 11 открывает первый канал для DDE-обмена с приложением Access (при этом, поскольку не использовалась функция Shell, Windows выдаст запрос на запуск Access). Код строк 13-14 посылает команду серверу для открытия файла Борей.шйЬ, который на разных компьютерах может располагаться в различных местах. Код в строке 17 открывает второй канал (до сих пор мы закрывали первый открытый канал и снова открывали его с другим «предметом обмена»), где в качестве «предмета обмена» уже используется таблица Товары открытого файла Bopeh.mdb. В строке 20 данные из таблицы Товары передаются в переменную data. В строке 23 полученные данные вставляются в рабочий лист в указанные столбцы. Видимая часть таблицы Товары базы данных Борей представлена на рис. 18.3. На рис. 18.4 представлен лист, в который были помещены запрошенные из Access данные. Товары : таблица | Код товара ! Марка________ |Genen Shouyu 2 Pavlova 3 Alice Mutton 4 Carnarvon Tigers 5 Teatime Chocolate Biscuits 6 Sir Rodney’s Marmalade 7 Sir Rodney's Scones 8 Gustafs Knackebrod 9 Tunnbrod 10 Guarana Fantastica 11 NuNuCa Nuss-Nougat-Creme АО Германия-Россия 12 Gumbar Gummibarchen АО Германия-Россия T ► I ИЭ 77 Д ‘ |_______Поставщик_______ Mayumi’s Pavlova Ltd Pavlova. Ltd Pavlova Ltd Specialty Biscuits Ltd Specialty Biscuits. Ltd Specialty Biscuits Ltd PB Knackebrod AB PB Knackebrod AB Refrescos Amencanas LTD Загиъ 1<Н |Г I__________Тип________ Приправы Кондитерские изделия Мясо/птица Рыбопродукты Кондитерские изделия Кондитерские изделия Кондитерские изделия Хлебобулочные изделия Хлебобулочные изделия Напитки Кондитерские изделия Кондитерские изделия Рис. 18.3. Видимая часть таблицы Товары базы данных Борей [ £3 Microsoft Excel - New Лист Microsoft Excel ИВИМИИИШВИИ.- i', -JH Фай'1 □эаека Вил Вставка Формат Сервис Данные Окно Справка - _ <5 х ’ Е - 100% ’ 7 Ала! • 10 ” ж к ч & & -% $ E13 -r a А В С D Е F GT 1 КодТовара Марка КодПоставщика КодТипа ЕдиницаИзмерения Цена НаСклс 2 1 Genen Shouyu 6 2 24 бутылки по 250 мп 697 5 3 ( 2 Pavlova 7 3 32 коробки по 500 г 785 25 4 3 Alice Mutton 7 6 20 банок по 1 кг 1755 5 4 Carnan/on Tigers 7 8 16 кг упаковка 2812 5 — 6 5 Teatime Chocolate Biscuits 8 3 10 коробок по 12 шт 414 7 6 Sir Rodney’s Marmalade 8 3 30 коробок 3645 8 7 Str Rodney’s Scones 8 3 24 упаковки по 4 шт 450 9 8 Gustafs Knackebrod 9 5 24 упаковки по 500 г 945 1 10 9 Tunnbrod 9 5 12 упаковок по 250 г 405 м < > н \лист1/ ЛИСТ2 Z ЛистЗ / bi I ► г Готово мим Рис. 18.4. Данные, полученные из таблицы Товары базы данных Борей Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 493 Передача данных DDE-серверу Как и все диалоги, обмен между DDE-клиентом и DDE-сервером может выполняться в обе стороны. Это означает, что приложение-клиент также может посылать данные серверу, используя метод DDEPoke: СИНТАКСИС: DDEPoke(Channel, Item, Data) Как обычно, Channel — номер канала, возвращаемый методом DDEInitiate; аргумент Item — строка, определяющая элемент сервера, куда вы хотите послать данные. Аргумент Data — данные, которые вы хотите послать; данные должны быть либо простым текстом, либо числами. Метод DDEPoke возвращает результат типа Boolean, который указывает, успешно ли выполнена операция. В листинге 18.6 приведен пример использования метода DDEPoke. Листинг 18.6. Применение DDEPoke для передачи данных приложению-серверу 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 Sub SendDataToServer() ' Передает данные приложению-серверу (Word) Dim ddeChannel As Integer Dim PokeData As Object On Error GoTo DDE_Error ' открыть документ (см. листинги 18.2, 18.3): Shell PathName:="E:\Program Files\Microsoft Office\OfficelO" ”\Winword.exe", Windowstyle:“vbMinimizedNoFocus ddeChannel = DDEInitiate(App:“"WinWord", Topic:“"System") DDEExecute Channel:“ddeChannel, _ String:="[FileOpen ""F:\VB_books\DBMS\01.DOC""]" DDETerminate ddeChannel ' открыть DDE-канал с "предметом" - документ: ddeChannel = DDEInitiate(App:“"Winword", _ Topic:“"F:\VB__books\DBMS\01.DOC") 1 перейти в конец документа: DDEExecute Channel:“ddeChannel, String:="[EndOfDocument]" ' вставить новый абзац: DDEExecute Channel:“ddeChannel, String:="[InsertPara]" 'создать закладку: DDEExecute Channel:“ddeChannel, _ String:="[EditBookmark .Name = ""NewBookmark""]" ' подготовить передаваемые данные: With Worksheets("Лист1") If .Cells (1, 1).Value = Then .Cells(1, 1).Value = "Просто - текст!" End If ' отправляемые серверу данные: Set DDEPokeData = .Cells(1, 1) End With 1 послать данные в место, отмеченное закладкой: Application.DDEPoke Channel:“ddeChannel, _ Item:“"NewBookmark", 494 Глава 18 41 Data:=DDEPokeData 42 DDETerminate ddeChannel 43 44 Exit Sub 45 46 DDE_Error: 47 DDETerminate ddeChannel 48 49 End Sub Процедура SendDataToServer передает данные (строки 39-41) из ячейки листа Excel (строки 30-36) в место Word-документа, которое отмечено закладкой, предварительно созданной самой же процедурой (строки 22-27). Передача «нажатий клавиш» другому приложению К сожалению, существуют много приложений Windows, которые не поддерживают Automation и не имеют макроязыка, с помощью которого можно управлять приложением через DDE-канал. Казалось бы, такими приложениями невозможно управлять из VBA-кода. Однако здесь — «не все так плохо». Этим приложениями можно управлять «нажатиями клавиш». В общем-то, многие приложения имеют команды (функции), имитирующие «нажатия клавиш», что очень полезно при отладке приложений или создания демонстрационных версий программ. При этом коды «нажатых клавиш» заранее записываются в некоторый буфер (хотя, конечно, это можно делать и в момент выполнения приложения), а затем извлекаются из него при помощи операторов, имитирующих «нажатия клавиш». В рассматриваемом нами случае управляемое приложение не само генерирует «нажатия клавиш», а получает их от приложения, которое является управляющим, при помощи VBA оператора SendKeys. Вы можете послать любую клавишу или комбинацию клавиш (в том числе такие комбинации, которые включают клавиши Alt, Ctrl и Shift) приложению-серверу DDE. Результат будет точно таким же, как если бы вы нажали эти клавиши непосредственно на клавиатуре. Оператор SendKeys имеет следующий синтаксис: СИНТАКСИС SendKeys (String [,Wait]) Аргумент String — это клавиша или комбинация клавиш, которую необходимо послать активному приложению. Для символов, чисел и знаков препинания следует заключить этот символ в кавычки, например "а". Для других клавиш используйте строки, перечисленные в таблице 18.2. Необязательный аргумент Wait — это значение типа Boolean, указывающее, будет или не будет VBA ждать, когда переданные приложению «нажатия клавиш» будут им обработаны. Если аргумент Wait имеет значение True, VBA «ждет», пока приложение закончит обработку переданных клавиш, прежде чем перейти к следующему оператору процедуры; в ином случае VBA продолжает выполнять процедуру (в которой появляется SendKeys), не ожидая завершения обработки. Для того чтобы использовать SendKeys, нет необходимости устанавливать DDE-связь. Все, что нужно сделать — активизировать программу, используя функцию Shell или AppActivate. После этого можно посылать любые «нажатия Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 495 клавиш», которые необходимы. Например, вы можете закрыть любое активное приложение Windows, послав комбинацию клавиш Alt+F4 следующим образом: SendKeys String:="%{F4}" Таблица 18.2. Строки, используемые в качестве аргумента String в методе SendKeys Клавиши Коды BACKSPACE {BACKSPACE}, {BS} или {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL или DELETE {DELETE} или {DEL} DOWN ARROW {DOWN} END {END} ENTER {ENTER} или - ESC {ESC} HELP {HELP} HOME {HOME} INS или INSERT {INSERT} или {INS} LEFT ARROW {LEFT} NUM LOCK {NUMLOCK} PAGE DOWN {PGDN} PAGE UP {PGUP} PRINT SCREEN {PRTSC} RIGHT ARROW {RIGHT} SCROLL LOCK {SCROLLLOCK} TAB {TAB} UP ARROW {UP} Fl {Fl} F2 {F2} F3 {F3} F4 {F4} F5 {F5} F6 {F6} F7 {F7} F8 {F8} F9 {F9} F10 {F10} Fll {Fll} 496 Глава 18 Клавиши Коды F12 {F12} F13 {F13} F14 {F14} F15 {F15} F16 {F16} Комбинируя клавиши из таблицы 18.2 с клавишами Alt, Ctrl и Shift, вы можете создать любую комбинацию клавиш. Для этого поставьте перед строкой из таблицы 18.2 одну или большее количество кодов, перечисленных в таблице 18.3. Таблица 18.3. Коды для клавиш Alt, Ctrl и Shift Клавиша Знак SHIFT + CTRL ALT % В листинге 18.7 приведен пример1 передачи «нажатия клавиш» программе Calculator при помощи функции SendKeys. Листинг 18.7. Использование функции SendKeys 1 Sub SendTestO 2 1 Запускает программу Calculator и передает ей "нажатия клавиш" 3 4 Dim MyAppID, I 5 MyAppID = Shell("CALC.EXE", 1) ’ запуск программы Calculator 6 AppActivate MyAppID ' активизация программы Calculator 7 8 For I = 1 To 50 9 ' послать в программу Calculator цифру и знак "+" 10 SendKeys I & "{+}", True 11 Next 12 13 SendKeys "=", True ' получить результат 14 15 16 End Sub Доступ к DLL из Visual Basic for Applications Библиотеки динамической компоновки (Dynamic link libraries, DLL) — это наборы функций и процедур, которые доступны всем приложениям Windows. Windows поставляется с набором DLL-файлов, которые предоставляют разработчикам сотни специализированных (и очень быстрых) функций. Обращение к этим процедурам — простой путь придать вашим VBA-программам исключительную функциональность Windows. Совокупность DLL-библиотек формирует то, что известно 1 Пример взят из справочной системы. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш»497 как Application Programming Interface (API) Windows (интерфейс прикладных программ Windows). API-функции условно делятся на четыре основные категории: для работы с приложениями (запуск и закрытие, обработка команд меню, перемещение и изменение размеров окон), для управления графическими изображениями, для использования системной информации (определение текущего диска, объема памяти, пользователя и т.д.), для работы с реестром Windows). Хотя большинство функций API сложны в техническом отношении, вы можете воспользоваться несколькими из них в своих VBA-процедурах. В следующих разделах показано, как обращаться к библиотекам DLL из VBA-кода. Объявление DLL-процедур Прежде чем вы сможете использовать функцию из библиотеки DLL, вы должны сообщить VBA, где найти DLL-файл и какие аргументы нужны этой функции. Для этого следует ввести оператор Declare на уровне модуля, то есть перед любыми объявлениями процедур в модуле. В зависимости от того, является ли процедура функцией (Function) или подпрограммой (Sub), используйте одну из следующих форм: СИНТАКСИС Declare [Pubic I Private] Function Name Lib "LibName" [Alias AliasName] (Arguments) [As Type] Declare [Pubic I Private] Sub Name Lib "LibName" [Alias AliasName] (Arguments) [As Type] Так же как с переменными и константами VBA, вы можете объявить DLL-процедуру либо как Public (чтобы сделать ее доступной всем модулям во всех проектах), либо как Private (чтобы сделать ее доступной только тому модулю, в котором она объявлена). Name — имя процедуры; LibName — имя DLL-файла, например "USER32". Если имя процедуры совпадает с ключевым словом VBA или с именем переменной, объявленной как Public, вы не сможете использовать оригинальное имя процедуры в своем коде. Вместо этого используйте AliasName (псевдоним) для определения другого имени процедуры. Arguments — это список аргументов, требующихся процедуре. Этот список имеет следующий синтаксис: СИНТАКСИС [Optional][ByVai|ByRef][ParamArray] VarName [As Type] Ключевое слово Optional указывает на то, что аргумент не является обязательным. Ключевое слово ByVai означает, что аргумент передается по значению (для большей части DLL-процедур). Ключевое слово ByRef означает, что аргумент передается по ссылке. ParamArray используется с массивами данных типа Variant. Аргумент, объявленный как ParamArray, должен быть последним в списке аргументов; нельзя использовать ParamArray в комбинации с Optional, ByVai или ByRef. VarName — имя аргумента, а Туре определяет тип данных аргумента. Следующий оператор, например, объявляет функцию с именем MessageBeep из DLL User32.exe* 1: 1 Когда имя DLL-файла заканчивается цифрами 32, это означает, что DLL содержит 32-разряд-иый код. Каждый раз, когда у вас есть выбор, вы должны использовать в своем VBA-коде 32-разрядные версии любой библиотеки DLL. 498 Глава 18 Declare Sub MessageBeep Lib "USER32" (ByVai BeepType As Integer) Сразу после объявления процедуры DLL, вы можете использовать ее в VBA-коде, как любую другую процедуру (Sub или Function). Примеры DLL В этом разделе приведены несколько примеров того, г£ак использовать DLL процедуры в VBA-коде. Чтобы узнать больше о DLL и API Windows, вы можете приобрести книгу Джеймса Маккорда (James McCord) Win32 API Desktop Reference. Эта книга полностью освещает данный предмет. VBA имеет простой оператор Веер, который вы можете использовать для привлечения внимания пользователя. К сожалению, Веер выдает только одиночный звук. В большинстве случаев это не является проблемой, но существует достаточное количество ситуаций, когда вы захотите преодолеть эти ограничения. Например, после завершения долгой операции вы можете привлечь внимание пользователя к экрану звуковым сигналом. Но как быть, если во время этой операции произошла ошибка? Было бы хорошо иметь другой звук, сопровождающий сообщения об ошибках. Если различные звуки — это то, что вам нужно, используйте DLL-процедуру MessageBeep, которая позволяет воспроизводить пять отдельных звуковых сигналов. Чтобы воспользоваться преимуществами MessageBeep, вы или пользователи вашей VBA-программы должны иметь звуковую плату, которая поддерживается Windows. DLL-библиотека User32, которая содержит процедуру MessageBeep, находится в файле с именем User32.dll в каталоге \Windows\System. Этот файл поставляется вместе с Windows. В дополнение к MessageBeep библиотека User32.dll содержит другие полезные функции и процедуры, которые являются частью стандартного 32-разрядного API Windows. Чтобы получить полную информацию относительно функций и процедур User32.dll, воспользуйтесь документацией Win32 Software Developer's Kit (Комплект разработчика программного обеспечения Win32). Оператор Declare, объявляющий функцию MessageBeep: Declare Sub MessageBeep Lib "USER32" (ByVai BeepType as Long) Аргумент BeepType принимает одно из пяти значений, приведенных в табл. 18.4. Таблица 18.4. Значения аргумента BeepType BeepType Звук 0 Default beep (Сигнал по умолчанию) 16 Critical stop (Аварийная остановка) 32 Question (Вопрос) 48 Exclamation (Восклицание) 64 Asterisk (Сноска) Все эти звуки определены в значке Sounds (Звуки) в Control Panel (Панели управления). В листинге 18.8 приведена процедура, которая последовательно воспроизводит все пять звуков, предварительно помещая в строку состояния (для Excel) наименования этих звуков. Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 499 Листинг 18.8. Применение DLL-процедуры MessageBeep 1 Option Explicit 2 3 Const DefaultBeep = 0 4 Const CriticalBeep = 16 5 Const QuestionBeep = 32 6 Const ExclamationBeep =48 7 Const AsteriskBeep = 64 8 9 Declare Sub MessageBeep Lib "USER32" (ByVai BeepType As Long) 10 11 Sub BeepTest() 12 ' Воспроизводит звуки посредством MessageBeep 13 14 Application.StatusBar = "Default Beep" 15 MessageBeep DefaultBeep 16 Application.Wait Now + TimeValue("00:00:03") 17 18 Application.StatusBar = "Critical Stop" 19 MessageBeep CriticalBeep 20 Application.Wait Now + TimeValue("00:00:03") 21 22 Application.StatusBar = "Question" 23 MessageBeep QuestionBeep 24 Application.Wait Now + TimeValue("00:00:03") 25 26 Application.StatusBar = "Exclamation" 27 MessageBeep ExclamationBeep 28 Application.Wait Now + TimeValue("00:00:03") 29 30 Application.StatusBar - "Asterisk" 31 MessageBeep AsteriskBeep 32 Application.Wait Now + TimeValue("00:00:03") 33 34 35 Application.StatusBar = False 36 37 End Sub Конкретные звуки, которые будет воспроизводить процедура BeepTest, зависят от конфигурации вашего компьютера. Если вы не установили все звуковые файлы, поставляемые с Windows, вы можете услышать только один или два различных звука для всех вариантов, которые должна воспроизводить процедура BeepTest. Вы можете заменить звуки, которые Windows воспроизводит для таких событий, как Asterisk, Question и других, запустив апплет Sounds (Звуки) в Control Panel (Панели управления). Функция CharToOemA конвертирует текстовую строку из Win- в DOS-кодировку. Оператор Declare, объявляющий функцию CharToOemA: Declare Function CharToOemA Lib "user32" (ByVai IpszSrc As String, _ ByVai IpszDst As String) As Long Аргумент IpszSrc — строка в Win-кодировке, IpszDst — строка в DOS-кодировке. В листинге 18.9 содержится код, преобразующий строку из Win- в DOS-кодировку с последующей записью результата в текстовый файл TESTFILE. Этот файл можно прочитать только в системе DOS. В Windows текст будет представлять примерно такую строку "Z iai - 0¥а !" — это можно проверить в окне Immediate, включив в код строку Debug.Print DOSString. 500 Глава 18 Листинг 18.9. Применение DLL-процедуры CharToOemA 1 Option Explicit 2 3 Declare Function CharToOemA Lib "user32" _ 4 (ByVai IpszSrc As String, _ 5 ByVai IpszDst As String) As Long 6 • 7 Sub CharToOemATest() 8 ' Тестирует функцию CharToOemA 9 10 Dim WinString As String 11 Dim DOSString As String 12 Dim code As Long ДЗ 14 WinString = "Опять - весна!" 'Строка в Win-кодировке 15 DOSString = Space(Len(WinString)) 16 code = CharToOemA(WinString, DOSString) 17 Open "TESTFILE" For Output As #1 18 Write #1, DOSString 19 Close #1 20 21 End Sub В листинге 18.10 содержится код, преобразующий строку из DOS- в Win-кодировку с использованием функции OemToCharA. Данные для тестирования этой функции считываются из текстового файла TESTFILE (строки 9-12), который был записан кодом листинга 18.9. Для проверки того, что текст действительно записан в DOS-кодировке, он печатается в окне Immediate (строка 18). Преобразованная функцией OemToCharA строка снова печатается (строка 18) в окне Immediate (рис. 18.5). Листинг 18.10. Применение DLL-процедуры OemToCharA 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Sub OemToCharATest() ' Тестирует функцию OemToCharATest Dim DOSString As String Dim WinString As String Dim code As Long ' открыть текстовый файл в DOS-кодировке: Open "TESTFILE" For Input As #1 ' считать строку из файла: t Input #1, DOSString ' закрыть файл: Close #1 ' убедиться в том, что данные нечитабельны: Debug.Print DOSString ' конвертировать в Win-кодировку: WinString = Space(Len(DOSString)) code = OemToCharA(DOSString, WinString) ' проверить результат: Debug.Print WinString End Sub Работа с другими приложениями: DDE, DLL и передача «нажатий клавиш» 501 Рис. 18.5 Считанная из файла и преобразованная строки печатаются в окне Immediate Функция Sleep приостанавливает выполнение программы на определенное аргументом время. Оператор Declare, объявляющий функцию Sleep: Declare Sub Sleep Lib "kernel32.dll" (ByVai dwMilliseconds As Long) Аргумент dwMilliseconds — количество миллисекунд для приостановки выполнения программы. В листинге 18.11 приведен пример использования функции Sleep, хотя наилучшим примером было бы применение этой функции при работе с различного рода строками состояния: помещаете в строку состояния некоторый текст, выполняете «засыпание» приложения, чтобы пользователь успел прочитать текст, а затем убираете запись из строки состояния. Листинг 18.11. Применение DLL-процедуры Sleep 1 Option Explicit 2 3 Declare Sub Sleep Lib "kernel32.dll" (ByVai dwMilliseconds As Long) 4 5 Sub SleepTestO 6 ' Тестирует функцию Sleep 7 8 If MsgBox("Поспим секунд пять?", _ 9 vbQuestion + vbYesNo, "Тест функции Sleep") = vbYes Then 10 Sleep 5000 11 MsgBox "Поспали!" 12 Else 13 MsgBox "Как хотите ..." 14 End If 15 16 End Sub В качестве следующего примера DLL-функции рассмотрим GetWindowsDi-rectory, которая определяет путь к папке Windows. Это удобно, если вам нужно выяснить, в какую папку установлена Windows или где расположен один из вспомогательных апплетов Windows. Функция GetWindowsDirectory объявляется следующим образом: 502 Глава 18 СИНТАКСИС Declare Function GetWindowsDirectory Lib "kernel32" _ Alias "GetWindowsDirectoryA" _ (ByVai Buffer As String, _ ByVai Size As Long) As Long Аргумент Buffer — строковая переменная, в которую GetWindowsDirectory помещает путь к папке Windows. Вы должны обеспечить такую длину передаваемой строки, чтобы в нее мог уместиться достаточно длинный путь, поскольку библиотеки DLL не могут увеличивать длину переданных им строк. Если строка не имеет достаточной длины, чтобы уместить путь папки, то строка, возвращаемая в аргумент Buffer, может испортить память, не зарезервированную для использования VBA. Последствия этого будут самыми неприятными: от ошибки General Protection Fault (Общая неисправность защиты) до аварийного отказа системы. Аргумент Size — максимальный размер буфера. Вы можете использовать функцию Len для определения длины переменной буфера и использовать результат как аргумент Size. Функция GetWindowsDirectory возвращает длину строки пути, скопированную в Buffer. В листинге 18.12 приведен пример использования функции GetWindowsDirectory для поиска и запуска апплета Sol. Листинг 18.12. Применение функции DLL GetWindowsDirectory 1 Option Explicit 2 3 Declare Function GetWindowsDirectory Lib "kernel32" _ 4 Alias "GetWindowsDirectoryA" _ 5 (ByVai Buffer As String, _ 6 ByVai Size As Long) As Long 7 8 Sub LaunchWordPad() 9 ' Запускает апплет sol 10 11 Dim WinDir As String * 255 12 Dim DirLength As Long 13 Dim FullName As String 14 15 DirLength = GetWindowsDirectory(Buffer:=WinDir, _ 16 Size:=Len(WinDir)) 17 18 If DirLength = 0 Then 19 MsgBox "Невозможно определить Windows-папку!" 20 Else 21 FullName = Left(WinDir, DirLength) & _ 22 "\system32\dllcache\sol.exe" 23 1 11 запустить апплет Sol: 24 Shell PathName:=FullName, WindowStyle:=vbMaximizedFocus 25 End If 26 27 End Sub Глава 19 Использование обработчиков событий Как вы видели из этой книги, Visual Basic for Applications имеет достаточно способов для запуска процедур. Вы можете запустить процедуру из диалога Макрос (Macro), нажатием «быстрой» клавиши, выбором собственной команды меню или кнопки в панели инструментов. Общая особенность этих методов состоит в том, что вы должны что то сделать, чтобы выполнить процедуру: выбрать команду меню, нажать комбинацию клавиш или щелкнуть кнопку в панели инструментов. VBA также имеет несколько методов, которые дают возможность создавать процедуры, выполняющиеся автоматически в ответ на некоторое событие, например открытие рабочей книги или документа. В этой главе рассматриваются эти автоматические подпрограммы. События и обработчики событий Ранее в этой книге вы познакомились с концепцией обработчика события и управляемого событиями программирования. В частности, в главе 14 вы узнали, как создавать обработчики событий для элементов управления, помещенных в форму пользователя. В этой главе вы узнаете, как создавать обработчики для событий, связанных с различными объектами host-приложения VBA. Однако сначала полезно будет сделать обзор некоторых фактов, относящихся к управляемым событиями программам и обработчикам событий. Управляемая событиями (event-driven) программа — это такая программа, которая вместо линейного выполнения кода от начала до конца циклически выполняет некоторый код, ожидая различные события и отвечая на них. Событие (event) — это то, что происходит в программе, например нажатие определенной клавиши, щелчок мыши, активизация рабочего листа, открытие или закрытие файла документа или рабочей книги. Поскольку во время выполнения программой заданного алгоритма происходят определенные события, считается, что программа управляется этими событиями, и отсюда следует термин управляемая событиями. Когда происходит событие, программа выполняет одну или несколько процедур, связанных с этим событием. Эти процедуры обычно упоминаются как обработчики событий (event handlers) или процедуры обработки событий (event procedures). Вы уже знаете, что объекты Excel и Word предоставляют доступ к их свойствам и методам, что позволяет управлять ими в VBA-коде. Небольшое количество объектов также делают видимыми некоторые события, например двойной щелчок мыши или открытие и закрытие файла. Вы можете создать свою собственную управляемую событием процедуру для любого события, предоставляемого объектом. Ваши обработчики событий могут (в зависимости от типа события) расширить, заменить или исключить встроенное поведение объекта для этого события. Например, вы можете лишить пользователя возможности изменять размеры окна документа, написав свой собственный обработчик события WindowResize. Хотя приложения Microsoft, поддерживающие VBA, содержат сотни объектов, только некоторые из этих объектов предоставляют события, которые вы можете перехватить своими собственными процедурами обработки событий. Напри- 504 Глава 19 мер, список объектов Excel, предоставляющих события, которые вы можете перехватить, ограничен объектами Application, Workbook, Worksheet и Chart; в Word имеется только два таких объекта — Application и Document; в PowerPoint — только Application. Чтобы узнать, какие события предоставляются объектом (и есть ли они вообще), используйте Object Browser. События объекта приложения перечисляются в списке Members of "class” и обозначены с левой стороны значком молнии (рис. 19.1). Рис. 19.1 События объекта приложения перечисляются в списке Members of "class" и обозначены с левой стороны значком молнии . Object Browser Classes ЙЗ DefaultWebOptions Й4 Diagram & DiagramNode <23 DiagramNodeChildren ЙЗ DiagramNodes <23 Dialog <23 Dialogs ЙЗ Dictionaries & Dictionary <23 Documents йЗ ПгппСяп_____ Class Document Member of W«h<I ЙШ Members of 'Document' * ManualHyphenation * Merge !₽ Name £ New I® NoLineBreakAfter й? NoLineBreakBefore 9 Open й? OpenEncoding eff OptimizeForWord97 e£* PageSetup E₽ Paragraphs ’S? Parent В дополнение к предоставленным объектами событиям вы можете также создать обработчики событий, которые отвечают на нажатие определенной комбинации клавиш или которые реагируют на наступление определенного времени дня. В Excel вы можете использовать метод ОпКеу, чтобы определить, какая процедура Excel должна выполняться в ответ на данное нажатие клавиш. Например, вы можете использовать метод ОпКеу Excel, чтобы определить, что некоторая процедура будет выполняться при каждом нажатии комбинации клавиш Ctrl+Alt+N. В Word можно использовать коллекцию KeyBindings, чтобы связать данную процедуру с некоторой комбинацией клавиш. Как Excel, так и Word предоставляют метод OnTime, который дает возможность создать события, связанные с конкретной датой и временем дня. Где хранится обработчик события Обработчики событий объекта хранятся не в стандартном модуле, а в модуле класса объекта. Каждый объект Excel, такой как Workbook, Worksheet и Chart, содержит модуль класса, где вы можете сохранять обработчики событий этого объекта. Объекты Document в Word также содержат модуль класса, в котором содержатся обработчики событий этого объекта. На рис. 19.2 показано открытое окно кода для модуля класса объекта рабочего листа в VBA Excel. Обратите внимание, что в списке объектов окна Code Window выбран объект Worksheet. В списке процедур в Code Window (на рис. 19.2 этот спи-, сок раскрыт) перечислены все события, для которых вы можете создать обработчики событий. Выбор события в списке процедур окна кода приводит к тому, что редактор VB вставляет «пустое» объявление (заголовок и оператор конца процедуры) обработчика этого события, если объявления еще не существует. На рис. 19.2 видно «пустое» объявление процедуры обработки события для события Selection-Change рабочего листа. Использование обработчиков событий 505 Рис. 19.2 Процедуру обработки события следует создавать в модуле класса объекта Visual Basic - Events,.ids - [Лист! (Code)] Fie Edit Ytew Insert Format Qebug Run Tools Add Ins &ndow Help З’Ц Й&М U Ln5,Coll - VBAProject (Events xls) - *'-» Microsoft Excel Objects О ЛиСЛ (Лист1) И) Лист2 (Лист2) И) ЛистЗ (ЛистЗ) <0 ЭтаКнка * %£ VBAProject (PERSONAL XLS) Option Explicit Private Sub Worksheet End Sub SelectionChange ' Activate BeforeDoubleChck BeforeRightChck Calculate Change ’ Deactivate FollowHyperhnk Исключением из правила, где и как сохраняются обработчики событий, является объект Application. Объект Application не имеет модуля класса, где можно хранить обработчики событий. Вместо этого обработчики событий объекта Application следует сохранять в модуле класса, который вы создаете. Чтобы отобразить на экране или создать процедуру обработки события для объектов (кроме объекта Application), выполните следующие шаги: 1. В редакторе VB откройте Project Explorer, если оно еще отображается. 2. В Project Explorer выберите объект, для которого хотите создать (или модифицировать) обработчик события. На рис. 19.2 выбран объект Лист1 рабочей книги Excel. 3. В Project Explorer щелкните кнопку View Code, чтобы вывести в окне кода модуль класса выбранного объекта (см. рис. 19.2). 4. В списке объектов окна Code Window выберите сам объект, т.е. если вы выбрали объект Worksheet (лист) в Project Explorer, вы должны выбрать пункт Worksheet в списке объектов, как показано на рис. 19.2. 5. В списке процедур выберите процедуру обработки события, которую хотите создать или изменить. Список процедур будет содержать только те процедуры, которые соответствуют событиям, предоставляемым объектом открытого вами модуля класса. Имена и объявление обработчиков событий VBA связывает определенную процедуру в модуле класса объекта с конкретным событием, опираясь на имя процедуры. По этой причине обработчики событий, которые вы создаете, должны соответствовать определенным именным соглашениям, а также нескольким другим правилам объявления таких процедур. В целом процедуры обработки событий должны иметь следующий синтаксис объявления: СИНТАКСИС Private Sub Object_EventName(Arguments) Процедуры обработки событий должны объявляться как закрытые (Private) для модуля класса объекта. В этом синтаксисе Object — имя объектного типа, которому принадлежит процедура обработки события, например Арр (для объекта Application), Workbook или Document. EventName — имя события, которое будет обработано, например, BeforeSave, BeforeDoubleClick и так да 506 Глава 19 лее. Arguments — список аргументов обработчика события. Списки аргументов для обработчиков событий обсуждаются в следующем разделе. В качестве примера можно привести строку, объявляющую процедуру для Worksheet, которая предназначена для обработки события Activate: Private Sub Worksheet_Activate() • Аргументы обработчика события Некоторые обработчики событий имеют аргументы. Обычно аргументы обработчика события выполняют одну из двух функций: передают обработчику события информацию, которая может понадобиться для обработки события, и предоставляют способ отмены встроенного в объект ответа на событие. Например, посмотрите на следующее объявление обработчика события: Private Sub VJcrkbook BeEoreClose (Cancel As Boolean) Процедура, созданная в соответствии с этим объявлением, будет вызываться каждый раз при закрытии объекта Workbook. Событие BeforeClose происходит непосредственно перед закрытием рабочей книги, независимо от того, закрывается рабочая книга в вашем VBA-коде или это происходит в результате действий пользователя в интерактивном режиме Excel. Обработчик события Workbook_Before-Close будет, следовательно, выполняться непосредственно перед закрытием рабочей книги. Процедура Workbook_BeforeClose могла бы содержать код, который проверяет правильность новых введенных данных или выясняет, были ли сохранены данные рабочей книги. Если в рабочей книге существуют недопустимые или несохраненные данные, вы можете предупредить ее закрытие. Аргумент Cancel позволяет вам сделать именно это. На тот момент, когда событие BeforeClose вызывает выполнение процедуры Workbook_BeforeClose, аргумент Cancel установлен в состояние False. Если вы устанавливаете аргумент Cancel в состояние True в некотором месте процедуры Workbook_BeforeClose, то закрытие рабочей книги будет предотвращено. Не каждая процедура обработчика события включает аргумент Cancel. В качестве еще одного примера рассмотрим следующее объявление процедуры обработки события: Private Sub Workbook—SheetActivate(ByVai Sh As Object) Это объявление процедуры обработки события предназначено для события SheetActivate объекта Workbook. Событие SheetActivate происходит каждый раз, когда активизируется любой лист рабочей книги. Аргумент Sh передает ссылку на активизируемый лист (рабочий лист или диаграмму). Поскольку это событие происходит внутри рабочей книги для любого активизируемого листа, ваш обработчик события должен уметь определять, какой лист был активизирован. Аргумент Sh обеспечивает решение этой задачи. Работа с событиями объекта Application В предыдущем разделе было показано, что обработчики событий для отдельных объектов приложения (Workbook, Worksheet, Document и т.д.У сохраняются в модуле класса, к которому относятся эти объекты. Однако объект Application не имеет модуля класса. Следовательно, создание обработчика события для объекта Application в Excel и Word — более сложная задача. В этом разделе приведен краткий обзор того, как создать процедуру обработки события для объекта Application. Использование обработчиков событий 507 Создание процедуры обработки события для объекта Application включает следующие основные шаги: 1. Создайте новый модуль класса в VBA-проекте. Вы можете дать этому модулю любое имя (в Properties Window) или оставить имя, данное модулю по умолчанию. 2. Добавьте следующее объявление в общую область модуля класса; объявление должно выглядеть точно так, как приведено ниже: Public WithEvents Арр As Application После того как вы введете это объявление, объект Арр появится в списке объектов модуля класса (в окне кода). 3. Напишите код обработчиков событий для объекта Арр в модуле класса, выбирая нужное событие из списка процедур в окне кода. 4. Свяжите процедуры обработки событий в модуле класса с объектом Application. Для этого сначала объявите переменную уровня модуля для вашего нового класса, а затем создайте процедуру, которая инициализирует эту переменную так, чтобы она ссылалась на объект Application. Вы можете создать это объявление и процедуру в любом модуле. Предположим, что ваш модуль класса называется AppEvents. Тогда, чтобы связать процедуру обработки события в модуле класса AppEvents с объектом Application, следует использовать следующее объявление и процедуру: Dim EventEnabledApp As New AppEvents Sub InitializeAppEvents() Set EventEnabledApp = Application End Sub На рис. 19.3 показано Code Window модуля класса Excel с именем AppEvents. Обратите внимание на то, что в общей области модуля класса видно объявление Public WithEvents Арр As Application (это объявление частично закрыто раскрывающимся списком процедур). Как только вы введете объявление переменной для объекта Арр в общую область модуля класса, в списке объектов окна кода появится объект Арр. На рис. 19.3 в списке объектов выбран объект Арр, а список процедур раскрыт и показывает, что модуль класса теперь автоматически перечисляет все события, доступные для объекта Application, точно так же, как это происходит для любого другого объекта. Рис. 19.3 Для создания процедуры обработки событий уровня приложения, следует создать специальный модуль класса, в котором они будут храниться 508 Глава 19 Если хотите, чтобы ваши процедуры обработки событий объекта Application всегда находились в работе, следует создавать модули класса для событий объекта Application в рабочей книге Personal.xls или в шаблоне документа Normal.dot. Работа с событиями объектов Excel Несмотря на то, что число объектов Excel, которые предоставляют события, довольно мало, вам доступно около 50 событий. В таблице 19.1 приведен список нескольких наиболее часто используемых событий объектов Excel, объектов, к которым они относятся, и описание этих событий. Разделы, следующие после таблицы 19.1, дают конкретную информацию относительно использования наиболее важных событий, приведенных в этой таблице. Таблица 19.1. Часто используемые события объектов Excel Событие Относится к Когда происходит Activate Chart, Workbook, Worksheet Когда объект активизируется VBA-кодом или действиями пользователя. Addininstall Workbook Когда рабочая книга устанавливается как надстройка (add-in). AddinU ninstall Workbook Когда выгружается рабочая книга-надстройка. BeforeClose Workbook Перед тем, как закрывается рабочая книга и перед тем, как пользователю выдается запрос о сохранении изменений. BeforeDoubleClick Chart, Worksheet При выполнении двойного щелчка внедренной диаграммы или рабочего листа, но перед заданным по умолчанию ответным действием на двойной щелчок. BeforePrint Workbook Перед печатью рабочей книги или ее части. BeforeRightClick Chart, Worksheet При выполнении правого щелчка внедренной диаграммы или рабочего листа, но перед заданным по умолчанию ответным действием на правый щелчок. | BeforeSave Workbook Перед сохранением рабочей книги. Calculate Chart, Worksheet После того как рабочий лист повторно вычислен или после рисования диаграммы по новым или обновленным данным. Change Worksheet Когда свойство Value ячейки изменяется либо кодом VBA, либо в результате действий пользователя. Deactivate Chart, Workbook, Worksheet Когда объект деактивизируется либо кодом VBA, либо в результате действий пользователя. NewSheet Workbook При создании в рабочей книге нового листа (диаграммы или рабочего листа). New W orkbook Application Когда создается новая рабочая книга. Использование обработчиков событий 509 Событие Относится к Когда происходит Open Workbook Когда открывается рабочая книга. SelectionChange Worksheet При изменении выделенного фрагмента в рабочем листе. SheetActivate Application, Workbook Когда активизируется любой лист. SheetBefore- DoubleClick Application, Workbook При выполнении двойного щелчка рабочего листа, но до ответного действия по умолчанию на двойной щелчок. SheetBefore-RightClick Application, Workbook При выполнении правого щелчка рабочего листа, но до ответного действия по умолчанию на правый щелчок. SheetCalculate Application, Workbook Когда рабочий лист перерасчитывается или изменяются данные на диаграмме. Sheetchange Application, Workbook Когда ячейка в рабочем листе изменяется пользователем или внешней связью. SheetDeactivate Application, Workbook Когда лист (рабочий лист или диаграмма) деактивизируется. SheetSelection- Change Application, Workbook При изменении выделенного фрагмента в рабочем листе. Window Activate Application, Workbook Когда активизируется любое окно рабочей книги. Window Deactivate Application, Workbook Когда деактивизируется любое окно рабочей книги. WindowResize Application, Workbook При изменении размеров любого окна рабочей книги. W orkbook Activate Application При активизации любой рабочей книга. WorkbookAddin-Install Application Когда любая рабочая книга устанавливается как надстройка (add-in). Workboo kAddin- Uninstall Application Когда выгружается любая рабочая книга-надстройка. WorkbookBefore- Close Application Непосредственно перед закрытием любой рабочей книги. WorkbookBefore-Print Application Непосредственно перед печатью любой рабочей книги (или ее части). WorkbookBefore- Save Application Непосредственно перед сохранением любой открытой рабочей книги. Workbook-Deactivate Application Когда любая открытая книга деактивизируется. WorkbookNewSheet Application При создании в любой открытой рабочей книге нового листа (рабочего листа или диаграммы). WorkbookOpen Application При открытии рабочей книги. 510 Глава 19 Событие Open Для правильного функционирования большинства VBA-программ приходится вносить некоторые изменения в среду host-приложения. Эти изменения могут включать добавление специальных команд меню, отображение специальной панели инструментов или установку опций host-приложения. В большинстве случаев эти изменения host-приложения должны быть сделаны сразу после запуска пользователем вашей VBA-программы, чтобы ее команды меню и панели инструментов были доступны с самого начала работы программы. Если вы хотите, чтобы ваша VBA-программа хорошо воспринималась, вы не должны перекладывать на пользователя работу по добавлению меню, линеек инструментов или по изменению состояния опций. Вы должны автоматически выполнить эти корректировки при запуске с помощью обработчика события Open рабочей книги. Событие Open генерируется каждый раз, когда открывается рабочая книга. Следовательно, код вашего обработчика события Open будет выполняться при каждом открытии рабочей книги, что дает идеальную возможность для установки любых специальных условий, необходимых для данной рабочей книги. Некоторые из элементов, которые вы можете включить в процедуру обработчика события Open, перечислены ниже: Код, который устанавливает или настраивает панель команд, чтобы создать меню и панели инструментов вашей VBA-программы. Такие установки программы, как режим вычислений, заданный по умолчанию путь файла, стандартный шрифт, объекты, которые будут выведены на экран (включая строку состояния и строку формул). Инициализация обработчиков событий ОпКеу и OnTime. Специальный диалог для установки опций вашей программы. Разумеется, вы можете включить любое другое действие, если вам нужно, чтобы оно выполнялось при каждом открытии рабочей книги. В листинге 19.1 показан пример процедуры обработки события Open. Для того чтобы процедура Workbook_Open из листинга 19.1 работала правильно, вы должны ввести ее в модуль класса объекта ThisWorkbook. В редакторе VB откройте Project Explorer и раскройте папку Microsoft Excel Objects, чтобы увидеть элемент ЭтаКнига (ThisWorkbook). Выполните двойной щелчок элемента ЭтаКни-га, чтобы вывести Code Window для модуля класса объекта ЭтаКнига. Затем выберите рабочую книгу в списке объектов окна кода и выберите в списке процедур пункт Open. Редактор VB автоматически введет объявление процедуры события Open; после этого вы можете ввести код из листинга 19.1. Листинг 19.1. Применение события Open рабочей книги 1 Private Sub Workbook_Open() 2 ' Запускается при каждом открытии рабочей книги 3 4 Application.StatusBar = "Загрузка VBA приложения..." 5 , 6 ' Инициализация среды 7 With Application 8 .AlertBeforeOverwriting = True 9 .Calculation = xlManual 10 .Caption = "Ореп-тест!" 11 .DisplayRecentFiles = False , 12 .MoveAfterReturn = False 13 .PromptForSummarylnfo = False 14 .SheetsInNewWorkbook = 8 15 .UserName = InputBox(prompt:^"Введите ваше имя:", __ 16 Title:="Событийная процедура открытия файла", Использование обработчиков событий 511 17 Default:=.UserName) 18 End With 19 20 ' Отобразить панель инструментов WordArt 21 With Application.CommandBars("WordArt") 22 .Visible = True 23 .Position = msoBarFloating 24 .Left = 400 . 25 .Top = 200 26 End With 27 Application.StatusBar = False 28 29 End Sub Процедура обработки события Open рабочей книги начинается с обращения к свойству StatusBar объекта Application для отображения в строке состояния сообщения, информирующего пользователя о том, что происходит (строка 4). Вы можете использовать свойство StatusBar в любой процедуре. Это — более простой способ информирования пользователя и не такой навязчивый, как функция MsgBox. Строки 7-18 содержат оператор With, который устанавливает несколько свойств объекта Application Excel. Большинство из этих свойств доступно в диалоге Параметры (Options); вы могли бы использовать команду Сервис | Параметры (Tools | Options), чтобы установить эти свойства вручную. Однако свойство Caption (строка 10) отличается от других свойств. Оно управляет текстом, который появляется в заголовке главного окна host-приложения. В Excel, например, обычно появляется текст Microsoft Excel, но вы можете заменить его любым другим текстом. В строках 15-17 устанавливается имя пользователя файла при помощи функции InputBox (рис. 19.4). Рис. 19.4 При открытии Excel-файла событийная процедура запрашивает имя пользователя Следующий оператор With (строки 21-26) отображает и позиционирует панель инструментов WordArt (рис. 19.5). Процедура заканчивается установкой свойства StatusBar в состояние False (строка 27), что очищает сообщение в строке состояния и возвращает управление строкой состояния Excel. Рис. 19.5 При открытии Excel-файла событийная процедура выводит на экран панель WordArt файл Правка Вид Вставка Фориат Сервис Данные Окно Оправка В1 Орел-тест! - Events Готово NUM 512 Глава 19 Для того чтобы Excel не выполнял процедуру обработки события Workbo-ok_Open, удерживайте нажатой клавишу Shift во время открытия рабочей книги. Событие BeforeClose Когда вы закрываете рабочую книгу, вам может понадобиться вернуть среду приложения Excel в исходное состояние, особенно в тех случаях, когда процедура Workbook_Open добавила команды меню или панели инструментов. Чтобы упростить эту работу, вы можете создать обработчик события Workbook_BeforeClose. Событие BeforeClose происходит непосредственно перед закрытием рабочей книги. В листинге 19.2 показан пример процедуры Workbook_BeforeClose. - Листинг 19.2. Применение события BeforeClose рабочей книги 1 Private Sub Workbook_BeforeClose(Cancel As Boolean) 2 ' Выполняется перед закрытием рабочей книги 3 4 Dim answ 5 6 answ = MsgBox("Вы действительно хотите закрыть книгу?", _ 7 vbCritical + vbYesNo, "Выход из Excel") 8 9 If answ = vbNo Then 10 Cancel = True 'отменить закрытие книги 11 End If 12 13 Application.StatusBar = "Отмена установок пользователя..." 14 15 ' Вернуть Excel-среду в исходное состояние 16 With Application 17 .Caption = Empty 18 .DisplayRecentFiles = True 19 .RecentFiles.Maximum = 5 20 .Calculation = xlAutomatic 21 .MoveAfterReturn = True 22 .PromptForSummarylnfo = True 23 .SheetsInNewWorkbook = 3 24 .CommandBars("WordArt").Visible = False 25 End With 26 27 ' сохранить новые установки рабочей книги 4 28 ThisWorkbook.Save 29 Application.StatusBar = False 30 31 End Sub Эта процедура «сбрасывает» многие параметры среды, которые изменились в предыдущей процедуре обработчика события Workbook_Open (строки 16-25). Обратите внимание, что в строке 17 свойству Caption присваивается значение Empty. Присвоение специального значения Empty свойству Caption восстанавливает заголовок главного окна оригинального приложения. Поскольку эта процедура изменяет параметры рабочей книги (набор опций, установленных этим кодом, сохраняется вместе с рабочей книгой), строка 28 сохраняет рабочую книгу перед ее закрытием; в ином случае Excel выведет сообщение, спрашивающее пользователя, нужно ли сохранять изменения в рабочей книге. Обратите внимание на то, что процедура Workbook_BeforeClose имеет аргумент Cancel. Вы можете отменить закрытие рабочей книги, установив Cancel в состояние True (строка 10). Использование обработчиков событий 513 Событие Activate Процедура Workbook_Open, приведенная ранее в этой главе, полезна для установки меню из VBA-программы, панелей инструментов и глобальных параметров, используемых каждой рабочей книгой и рабочим листом. Однако во многих программах, которые используют несколько рабочих книг и несколько листов в каждой рабочей книге, требуются различные установки для каждой рабочей книги и каждого листа. Например, у вас может возникнуть необходимость отображать специальный диалог ввода данных каждый раз, когда пользователь выбирает определенный рабочий лист. В другой ситуации вам может понадобиться настроить меню или вывести другую панель инструментов, когда пользователь переходит в определенную рабочую книгу. В этих случаях пользователь активизирует различные объекты: рабочие листы и рабочие книги. Активизация определенного объекта — это событие, и вы можете перехватывать такое событие, написав процедуру обработчика события Activate. Событие Activate доступно для объектов Chart, Workbook и Worksheet и происходит каждый раз, когда объект активизируется независимо от того, происходит это в VBA-коде или в результате взаимодействия пользователя с Excel. Объект активизируется тогда, когда он отображается в активном окне. В листинге 19.3 показан пример использования события Activate. Запись этой процедуры в модуль класса листа с именем Лист1 приведет к тому, что при активизации этого листа пользователю выдается предупреждение о том, что лист содержит важные данные. Листинг 19.3. Применение события Activate рабочего листа 1 Private Sub Worksheet_Activate() 2 ' Выполняется при каждой активизации листа Лист1 3 4 MsgBox prompt:="Важные данные! " & Chr(13) & Chr(10) & 5 "Перед изменением убедиться в наличии копии", _ 6 Title:="Внимание" 7 8 End Sub Событие Deactivate Как вы видели ранее в этой главе, обработчик события BeforeClose полезен для отмены любых изменений, сделанных в среде Excel обработчиком события Open. Точно так можно использовать событие Deactivate для создания обработчика события, который восстанавливает меню, проверяет правильность данных или выполняет другие задачи, когда деактивизируются объекты Worksheet, Chart или Workbook. Событие Deactivate происходит каждый раз, когда объект прекращает отображаться в активном окне. Листинг 19.4 показывает пример процедуры обработчика события Deactivate. Листинг 19.4. Применение события Deactivate рабочего листа 1 Option Explicit 2 3 Private Sub Worksheet_Activate() 4 ' Подготовить лист Счет к использованию 5 With Application.CommandBars("PivotTable") 6 .Visible = True 7 .Left = 100 8 .Top = 200 17 Программирование на VBA 2002 514 Глава 19 9 End With 10 End Sub 11 12 13 Private Sub Worksheet_Deactivate() 14 ' Удалить панель инструментов, выведенную для листа Счет 15 With Application.CommandBars("PivotTable") 16 .Visible = False , 17 End With 18 End Sub Листинг 19.4 содержит законченный модуль класса объекта Worksheet. Процедура Worksheet_Activate (строки 3-10) — это обработчик события Activate рабочего листа; он имитирует установку специальных условий для рабочего листа, отображая панель инструментов Pivot Table. Строки 13-18 содержат процедуру Worksheet_Deactivate, которая является обработчиком события Deactivate рабочего листа. Процедура Worksheet_De-activate предназначена для удаления любой специальной конфигурации, примененной процедурой обработчика события Activate. В данном случае процедура Worksheet_Deactivate просто скрывает панель инструментов Pivot Table. Не следует использовать объекты ActiveWorkbook или ActiveSheet внутри процедуры обработки события Deactivate. Excel переключится на новую рабочую книгу или лист до того, как выполнит процедуру обработки события. Следовательно, любой код, который ссылается на активную рабочую книгу или активный лист, может быть выполнен неправильно. Событие BeforeDoubleClick Двойной щелчок мыши в Excel приводит к различным результатам в зависимости от объекта, на котором выполняется щелчок. Например, двойной щелчок ячейки активизирует редактирование «по-месту» содержимого ячейки, а двойной щелчок диаграммы отображает диалог Формат области диаграммы (Format Chart). Любое из этих действий может быть «опасным», поскольку оно дает пользователю возможность редактировать ячейки или объекты, которые, быть может, не должны редактироваться. Чтобы перехватывать двойные щелчки в объектах Worksheet или Chart, вы можете использовать событие BeforeDoubleClick. Событие BeforeDoubleClick происходит непосредственно перед тем, как объект должен выполнить встроенный код в ответ на событие двойного щелчка. Событие BeforeDoubleClick содержит два аргумента: Target и Cancel. Используйте аргумент Target (ссылка на Excel-объект Range), чтобы определить, в какой ячейке рабочего листа был выполнен двойной щелчок. Аргумент Cancel используется для отмены встроенного кода объекта в ответ на событие двойного щелчка. В листинге 19.5 показан пример обработчика события BeforeDoubleclick для объекта рабочего листа, который использует оба доступных аргумента. Листинг 19.5. Применение события BeforeDoubleClick рабочего листа 1 Private Sub Worksheet_BeforeDoubleClick( _ 2 ByVai Target As Excel.Range, Cancel As Boolean) 3 ' Предотвращает редактирование ячеек в нечетных столбцах и строках 4 5 With Target 6 If ((.Column Mod 2) < 0) Or _ 7 ((.Row Mod 2) 0) Then 8 MsgBox prompt:“"Нельзя редактировать данные " & _ 9 "в нечетных колонках и строках!", 10 Title:“"Демонстрация обработки BeforeDoubleClick" Использование обработчиков событий 515 11 Cancel = True 12 End If 13 End With 14 End Sub Листинг 19.5 содержит только одну процедуру, которая является обработчиком события BeforeDoubleClick рабочей книги. Строки 1 и 2 содержат объявление процедуры Worksheet_BeforeDoubleClick (объявление было записано с символом продолжения оператора, чтобы оно уместилось в формат страницы этой книги). Обратите внимание на то, что процедура имеет два аргумента: Target и Cancel. Эти аргументы передаются автоматически объектом Worksheet, когда выполняется процедура обработки события. Аргумент Target —ссылка на ячейку, в которой был выполнен двойной щелчок мыши, а аргумент Cancel сохраняет значение типа Boolean, указывающее на то, необходимо ли, чтобы объект Worksheet игнорировал свой встроенный обработчик события двойного щелчка. В строке 5 начинается оператор With, который использует объектную переменную Target. В строках 6 и 7 содержится условное выражение оператора If, который проверяет, является ли номер строки или столбца ячейки нечетным числом. (Оператор Mod возвращает остаток операции целочисленного деления; если после деления на 2 имеется остаток, то данное число является нечетным.) Если номер столбца или строки ячейки — нечетное число, в строках 8-10 вызываются функция MsgBox, которая выводит сообщение, объясняющее, почему редактирование «по месту» содержимого ячейки не будет происходить. Обратите внимание на код в строке 11. Этот оператор устанавливает аргумент Cancel события BeforeDoubleClick в состояние True. Оператор в строке 11 отменяет вызов обработчика события двойного щелчка, встроенного в объект Workbook; в результате это запрещает редактирование «по месту» содержимого ячейки, для которой выполняется процедура обработки события BeforeDoubleClick. Событие двойного щелчка представлено также на уровне Application и Workbook как событие SheetBeforeDoubleClick; это событие генерируется в тех случаях, когда был выполнен двойной щелчок любого листа рабочей книги (для объектов Workbook) или когда был выполнен двойной щелчок любого листа в любой рабочей книге (для объекта Application). События Change и Selectionchange Чтобы гарантировать точность ваших данных в рабочем листе, можно проверять содержимое каждой ячейки. Например, вы могли бы проверить, что содержимое поля даты, действительно, является датой или что введенное число удовлетворяет определенным условиям, например, является положительным числом. Вы можете сделать это, написав процедуру обработки события Change. Событие Change содержит один аргумент — Target, который является ссылкой на Excel-объект Range. Листинг 19.6 показывает пример того, как использовать событие Change для проверки данных. Листинг 19.6. Применение события Change рабочего листа 1 Private Sub Worksheet_Change(ByVai Target As Excel.Range) 2 ' Использует событие Change для проверки данных рабочего листа 3 4 Static InError As Boolean 5 6 If InError Then 7 InError = False 8 Else 1’’ \ 516 Глава 19 9 If Not VerifiedData(Target) Then 10 InError = True 11 Target.Select 12 Target.ClearContents 13 End If 14 End If 15 16 End Sub 17 18 Private Function VerifiedData(ByVai SourceRef As Excel.Range) 19 ' Проверяет допустимость данных в определенной ячейке": 20 ' в столбце 1 должны быть даты, в столбце 2 должны быть 21 ' положительные числа 22 23 '24 25 26' 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 Const strTitle = "Проверка данных ячейки" VerifiedData = False ' предположим несоответствие данных With SourceRef Select Case .Column Case 1 ' поле даты If Not IsDate(.Value) Then MsgBox prompt:“"Недопустимые данные " & _ "в поле Date", Title:“StrTitle Exit Function Else .NumberFormat = "mmmm d, yyyy" End If Case 2 ' поле суммы If IsNumeric(.Value) Then If .Value < 0 Then MsgBox prompt:“"Отрицательное значение!", Title:“StrTitle Exit Function Else .NumberFormat = "$#,##0.00_); ($#,##0.00)" End If Else MsgBox prompt:“"Вводите числовые значения", _ Title:“StrTitle Exit Function End If End Select । End With ' если "мы" в этой точке, то значения допустимы VerifiedData = True 56 End Function Листинг 19.6 содержит код модуля класса рабочего листа. В строках 1-16 записан код обработчика события Change рабочего листа (Worksheet_Change); в строках 18-56 — функция проверки допустимости данных (VerifiedData). Сначала мы обсудим процедуру Worksheet_Change. Процедура обработки события Worksheet_Change выполняется каждый раз, когда изменяется свойство Value любой ячейки рабочего листа, независимо тот того, проведено изменение VBA-кодом или пользователь ввел изменения с клавиатуры. Обратите внимание на аргумент Target в строке 1; этот аргумент автоматически передается объектом Worksheet каждый раз, когда выполняется процедура Worksheet_Change. Аргумент Target содержит ссылку на ячейку, свойство Value которой было изменено. В строке 4 объявляется статическая переменная InError типа Boolean, которая отслеживает, обрабатывается ли в данный момент ошибка в ячейке. Использование обработчиков событий 517 В строке 6 проверяется значение переменной InError; если оно равно значению False, код в строке 9 вызывает функцию VerifiedData, которая возвращает значение True, если данные в ячейке, на которую ссылается Target, допустимы. В ином случае возвращается значение False. Если функция VerifiedData возвращает значение False, код в строке 10 присваивает переменной InError значение True для указания того, что в данный момент обрабатывается ошибка. Затем в строке 11 выбирается ячейка рабочего листа, на которую ссылается Target; это действие возвращает курсор вставки в ячейку, так чтобы пользователь мог легко исправить ошибочно введенные данные. Код строки 12 удаляет ошибочное значение из ячейки. При выполнении строки 12 процедура обработчика события Worksheet_Chan-ge вызывается снова, поскольку свойство Value ячейки рабочего листа изменилось; следовательно, процедура Worksheet_Change выполняется рекурсивно. Если здесь не будет предусмотрен какой-либо способ остановить рекурсию, обработчик события Worksheet_Change будет выполняться бесконечно. Статическая переменная In-Error используется для определения того, находится ли Worksheet_Change в рекурсивном вызове. Когда ошибка обнаружена в первый раз, InError присваивается значение True. Когда Worksheet_Change выполняется рекурсивно, значение In-Error равно значению True, и выполняется строка 7, сбрасывая переменную InError в состояние False. Рекурсивный вызов завершается, и также завершается первоначальный вызов Worksheet_Change. Таким образом, обработчик события Worksheet_Change проводит проверку допустимости значения ячейки. Если ячейка содержит недопустимые данные, курсор вставки возвращается в эту ячейку, выводится соответствующее сообщение об ошибке, ошибочное значение удаляется из ячейки. Функция VerifiedData получает единственный аргумент SourceRef, который является ссылкой на проверяемую ячейку. Когда процедура Worksheet_Change вызывает функцию VerifiedData, она передает диапазон Target в функцию VerifiedData посредством аргумента SourceRef. Функция VerifiedData использует оператор Case (строки 28-51), чтобы проверить правильность данных ячейки, основываясь на номере столбца данной ячейки. Ячейки первого столбца рабочего листа должны содержать значения типа Date, а ячейки второго столбца — положительные числовые значения. Если значение не соответствует заданному формату, VerifiedData выводит сообщение, описывающее, что неверно в данном значении, и возвращает значение False; в ином случае VerifiedData возвращает значение True. Рассмотрим следующую задачу. Необходимо при помощи сканера, читающего штрих-коды, например, сканера модели PS-700E, считывать номер изделия, помещать этот номер в рабочий лист Excel (для, быть может, дальнейшего перенесения данных в некоторую базу данных) и печатать этот номер и текущую дату в некоторый заранее подготовленный бланк, т.е. в определенную ячейку другого листа для дальнейшей печати. Листинг 19.7 содержит код обработчика события SelectionChange листа Лист1 для выполнения поставленной задачи, а на рис. 19.6 представлено «рабочее место», состоящее из принтера компьютера, сканера PS-700E, которым уже считано несколько штрих-кодов, записанных при помощи обработчика Worksheet_Se-lectionChange в Excel-лист. Листинг 19.7. Применение события Selectionchange рабочего листа 1 Private Sub Worksheet_SelectionChange(ByVai Target As Range) 2 3 On Error GoTo yyy 4 5 If Target.Column > 1 Then 6 Exit Sub 518 Глава 19 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ' 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 End If 1 введенный сканером код в ячейку: current = ActiveWorkbook.Worksheets("Лист1"). _ Cells (Target.Row - 1, Target.Column) .Value If Len(current) > 0 Then • 1 записать дату внесения кода: ActiveWorkbook.Worksheets("Лист1"). _ Cells(Target.Row - 1, Target.Column + 1).Value = _ Format(Now(), "dd/mm/yy") 1 записать код в ячейку для печати: ActiveWorkbook.Worksheets("Лист2").Cells(4, 8) = current & " / " & Format(Now(), "dd/mm/yy") If Trim(ActiveWorkbook.Worksheets("Лист1"). _ Cells (1, 6) .Value) = "Print" Then ' печать: ActiveWorkbook.Worksheets("Лист2") Printout Else ' предварительный просмотр области печати: ActiveWorkbook.Worksheets("Лист2").PrintPreview End If End If yyy: End Sub Рис. 19.6 Пользователь уже успел считать сканером PS-700E несколько штрих кодов изделий, которые записаны при помощи обработчика Worksheet_SelectionChange в Excel-л ист Событие Calculate Изменение одной переменной в рабочем листе с большой и сложной структурой может влиять на множество формул. Если вы не можете следить за всеми формулами (например, каждый раз проверять выполнение некоторого условия), то можно использовать событие Calculate, чтобы выполнить процедуру, которая проведет нужную проверку. Событие Calculate не имеет никаких аргументов. Листинг 19.8 показывает пример использования события Calculate. Использование обработчиков событий 519 Листинг 19.8. Применение события Calculate рабочего листа 1 Option Explicit 2 3 Private Sub Worksheet—Calculate() 4 ' Выполняется каждый раз, когда перерасчитывается рабочий лист 5 If Range("Прибыль") < 0.2 Then б MsgBox prompt*: ="Прибыль менее 20%", _ 7 Title:="Демонстрация события Calculate" 8 End If 9 End Sub Процедура обработки события Worksheet_Calculate в листинге 19.8 демонстрирует простейший вариант использования события Calculate. Эта процедура выполняется каждый раз, когда производятся вычисления рабочего листа, независимо от того, сделано ли это вручную или автоматически. Процедура обработки события Worksheet_Calculate в листинге 19.7 принимает, что в рабочем листе имеется некоторый диапазон, названный Прибыль, который отображает результат формулы, вычисляющей значение порога валовой прибыли. Когда рабочий лист вычислен, выполняется процедура Worksheet_Calculate, которая проверяет значение диапазона Прибыль; если это значение меньше 0.2 (то есть меньше 20 процентов), то выводится соответствующее сообщение. Другие события Как вы видели из таблицы 19.1, вам доступно намного больше событий, чем рассмотрено в предыдущих разделах. Событий Excel настолько много, что привести примеры для каждого из них в этой книге не представляется возможным. Однако вы должны знать о нескольких других событиях Excel-объектов, которые могут быть очень полезны. В следующем списке приведены эти события, сгруппированные по функциональному признаку. Печать Для объекта Workbook доступно событие BeforePrint, а для объекта Application — событие WorkbookBeforePrint. Используйте событие BeforePrint для выполнения любых задач, которые вы хотите выполнить непосредственно перед началом печати. Например, вы могли бы использовать обработчик события BeforePrint объекта Workbook, чтобы убедиться в том, что все рабочие листы были просчитаны, а отчет отформатирован, или чтобы выбрать специальные виды для печати. Обработчик события BeforePrint может помочь автоматизировать установку печати для сложных отчетов: пользователь просто выбирает команду Print, а затем ваш обработчик события BeforePrint может выбрать виды или листы для печати. Сохранение рабочих книг Для объекта Workbook доступно событие BeforeSave, а для объекта Application — событие WorkbookBeforeSave. Эти события происходят непосредственно перед сохранением рабочей книги (или, для объекта Application, перед сохранением любой рабочей книги). Используйте событие BeforeSave, чтобы выполнить проверку правильности данных, удалить временные рабочие листы или выполнить другие задачи до сохранения рабочей книги. Процедура обработки события BeforeSave имеет следующий заголовок: Private Sub Workbook_BeforeSave(ByVai SaveAsUi As Boolean, Cancel As Boolean) SaveAsUi — это значение типа Boolean; если оно равно True, то Excel отображает диалог Save As. Аргумент Cancel — это также значение типа Boolean; если вы уста 520 Глава 19 навливаете этот аргумент в состояние True, то операция сохранения отменяется после завершения работы вашей процедуры обработки события. Создание новых объектов Для объекта Workbook доступно событие NewSheet с заголовком процедуры обработки события: Private Sub Workbook_NewSheet(ByVai Sh As Object) Это событие происходит каждый раз, когда в рабочую книгу добавляется новая диаграмма или рабочий лист. Аргумент Sh — новый лист, который может быть объектом Worksheet или Chart. Объекту Application доступны события WorkbookNewSheet и NewWorkbook. Событие WorkbookNewSheet происходит каждый раз, когда в любую открытую рабочую книгу добавляется новый лист и имеет следующий заголовок процедуры обработки события: Private Sub Ojbject_WorkbookNewSheet(ByVai Wb As Workbook, ByVai Sh As Object) Аргумент Wb — рабочая книга, Sh — новый лист. Событие NewWorkbook происходит каждый раз, когда создается новая рабочая книга и имеет только аргумент Wb (рабочая книга). Используйте события NewSheet и NewWorkbook для добавления предопределенных элементов в созданную рабочую книгу или лист: заголовки столбцов, имена листов, именованные диапазоны и т.д. Изменение выделенного фрагмента Объекту Worksheet доступно событие Selectionchange, которое происходит каждый раз, когда изменяется выделенный фрагмент в рабочем листе, и имеет следующий заголовок процедуры обработки события: Private Sub Worksheet_SelectionChange(ByVai Target As Excel.Range) Здесь Target — новый выделенный диапазон. Объектам Application и Workbook доступно событие SheetSelectionChange с заголовком процедуры обработки события: Private Sub ojbject_SheetSelectionChange(ByVai Sh As Object, ByVai Target As Excel.Range) Используйте событие SelectionChange, чтобы предоставить пользователю варианты выделения ряда предопределенных элементов на рабочем листе или проверить правильность содержимого ячейки, когда выделенный фрагмент переместится из этой ячейки в другое место. Работа со свойствами и методами Excel, связанными с событиями В дополнение к доступным для объектов событиям, обсужденным в предыдущих разделах этой главы, Excel также имеет несколько свойств и методов, связанных с событиями. Вы можете использовать эти свойства и методы для создания процедур обработки таких событий, которые не предоставляются объектами Excel непосредственно. Например, вы можете использовать метод ОпКеу, чтобы создать свои собственные специальные командные клавиши; ваши процедуры командных клавиш будут вызываться каждый раз, когда на клавиатуре нажата соответствующая клавиша. Следовательно, метод ОпКеу предоставляет вам способ косвенного создания процедур, которые отвечают на определенные события клавиатуры. Использование обработчиков событий 521 Свойство OnWindow Excel Свойство OnWindow играет роль, аналогичную событию WindowActivate; OnWindow определяет процедуру обработки события, которая выполняется каждый раз, когда пользователь активизирует определенное окно. Используйте свойство OnWindow, если хотите выполнять определенную процедуру каждый раз, когда любое окно данного рабочего листа становится активным окном. Другое применение свойства OnWindow — если вам нужно оценить содержимое текущего окна и в зависимости от этого включить или отключить определенные команды меню или панели инструментов вашего приложения. (Не забудьте, что для одного рабочего листа вы можете иметь несколько открытых окон.) Свойство OnWindow доступно для объектов Application и Window. Синтаксис для установки свойства OnWindow имеет следующий вид: СИНТАКСИС Object.OnWindow = "ProcedureName" Здесь Object является объектной ссылкой или на объект Window, или на объект Application. Если Object ссылается на объект Window, то процедура обработки события выполняется каждый раз, когда пользователь переключается на определенное окно. Если Object ссылается на объект Application, процедура обработчика события выполняется каждый раз, когда пользователь переключается на любое окно. Чтобы процедура обработки события, связанная с окном посредством свойства OnWindow, не выполнялась, присвойте свойству OnWindow строку нулевой длины: Object.OnWindow = "" В листинге 19.9 показан пример применения свойства OnWindow. Листинг 19.9. Применение свойства OnWindow 1 Option Explicit 2 3 Sub SetWindowHandler() 4 ' Устанавливает обработчик события для OnWindow 5 ' 6 Windows("Events.XLS:2").OnWindow = "WindowHandler" 7 End Sub 8 9 10 Sub WindowHandler() 11 ' Обработчик события - открытие Окна Events.XLS:2 12 13 With Windows("Events.XLS:2" ) 14 .Splitvertical = 100 15 .DisplayFormulas = True , 16 .DisplayGridlines = False 17 .Displayzeros = False 18 .FreezePanes = True 19 .Windowstate = xlMaximized 20 End With 21 End Sub 22 23 24 Sub ClearWindowHandler() 25 ' Отменяет обработчик события для OnWindow 26 27 Windows("Events.XLS:2").OnWindow = "" 28 End Sub 522 Глава 19 Листинг 19.9 содержит весь стандартный модуль. В этом примере процедура с именем SetWindowHandler (строки 3-7) устанавливает свойство OnWindow для окна с именем Events.xls:2 (строка 6). Процедура обработки события Window-Handler устанавливает несколько свойств окна в блоке оператора With (строки 13-21). Окно делится вертикально (строка 14), отображаются формулы (строка 15), отменяется сетка (строка 16), скрываются нули (строка 17), закрепляются подокна (строка 18) и окно максимизируется (строка 19). (Процедура Window-Handler работает только в том случае, если лист, выведенный в данный момент в окно, является рабочим листом; в иных случаях процедура будет генерировать ошибку времени исполнения программы.) Для того чтобы процедура WindowHandler работала правильно, вы должны сначала выполнить процедуру SetWindowHandler после открытия второго окна рабочей книги Events.xls. Чтобы удалить обработчик события WindowHandler, выполните процедуру ClearWindowHandler. Имейте в виду, что процедуры обработки событий, которые вы создаете, присваивая их свойству OnWindow, могут сохраняться в любом модуле. Если хотите, чтобы некоторый ряд шагов выполнялся каждый раз, когда активизируется или деактивизируется любое окно, отображающее рабочий лист или рабочую книгу, используйте объектные события WindowActivate и Window-Deactivate вместо свойства OnWindow. Метод OnKey Excel Для запуска VBA-процедур в Excel вы можете устанавливать специальные комбинации клавиш в VBA-коде, используя метод ОпКеу. Как правило, комбинации клавиш имеют вид Ctrl + клавиша, где клавиша — символ алфавита. Excel «рассматривает» символы верхнего регистра и символы нижнего регистра раздельно. Хотя ваш выбор символов ограничен (тем более что Excel использует некоторые символы для встроенных комбинаций клавиш, например Ctrl+C для команды Правка | Копировать (Edit | Сору)), эта методика хорошо работает в большинстве приложений. Метод ОпКеу также полезен в тех случаях, когда вы хотите отключить определенные нажатия клавиш. Предположим, например, что вы хотите, чтобы пользователь не мог ничего удалить. Для решения этой задачи можно было бы использовать VBA-код, чтобы удалить кнопку Вырезать (Cut) из панели инструментов и команды Вырезать (Cut) и Удалить (Clear) из меню. А как быть с клавишей Delete? Вы можете использовать метод ОпКеу для создания собственного обработчик события для клавиши Delete или любых других нажатий клавиш: СИНТАКСИС Application.ОпКеу(Key, [Procedure] ) Обязательный аргумент Key — строка, определяющая клавишу или комбинацию клавиш, которую вы хотите перехватывать. Для букв, чисел или знаков препинания просто заключите символ в кавычки, например "а". Для других клавиш используйте текстовые строки, приведенные в таблице 19.2. Вы можете также создать комбинации клавиш, объединив клавишу символа или одну из клавиш таблицы 19.2 с одним или несколькими предшествующими кодами клавиш Alt, Ctrl и Shift, приведенными в таблице 19.3. (Значения клавиш, показанные в таблицах 19.2 и 19.3, аналогичны значениям клавиш, которые используются для метода SendKeys, рассмотренного в предыдущей главе.) Необязательный аргумент Procedure — строка, определяющая имя процедуры, которая должна выполняться каждый раз, когда пользователь нажимает определенную клавишу. Если вы используете в качестве значения аргумента Использование обработчиков событий 523 Procedure строку с нулевой длиной то данная клавиша будет заблокирована. Если вы опускаете аргумент Procedure, Excel переустанавливает клавишу в нормальное состояние. Таблица 19.2. Текстовые строки, использующиеся для аргумента Key метода ОпКеу Клавиша Строка BACKSPACE {BACKSPACE}, {BS} или {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL или DELETE {DELETE} или {DEL} DOWN ARROW {DOWN} END {END} ENTER {ENTER} или - ESC {ESC} HELP {HELP} HOME {HOME} INS или INSERT {INSERT} или {INS} LEFT ARROW {LEFT} NUM LOCK {NUMLOCK} PAGE DOWN {PGDN} PAGE UP {PGUP} PRINT SCREEN {PRTSC} RIGHT ARROW {RIGHT} SCROLL LOCK {SCROLLLOCK} TAB {TAB} UP ARROW {UP} F1-F16 {F1}-{F16} Таблица 19.3. Коды для клавиш Alt, Ctrl и Shift Клавиша Строка Alt % (процент) Ctrl Shift + (плюс) В листинге 19.10 приведен пример использования метода ОпКеу. 524 Глава 19 Листинг 19.10. Использование метода ОпКеу 1 Option Explicit 2 3 Sub SetShortcutKeys () 4 ' Установка процедур для Ctrl+Shift+O и Ctrl+Shift+G 5 6 With Application 7 .ОпКеу Кеу:="л+0", Procedure:“"DisplayGenOptions" 8 .ОпКеу Кеу:="л+С", Procedure:“"ToggleGridlines" 9 End With 10 11 End Sub 12 13 14 Sub DisplayGenOptions() 15 ' Выводит вкладку Общие (General) диалоговой z 16 ' панели Параметры (Options) 17 18 Application.Dialogs(xlDialogOptionsGeneral).Show 19 20 End Sub 21 22 Sub ToggleGridlines() 23 ' Переключает Сетку в состояние вкл. и откл. 24 25 With ActiveWindow 26 DisplayGridlines = Not .DisplayGridlines 27 End With 28 29 End Sub 30 31 Sub ResetShortcutKeys() 32 ' Отключение действий для Ctrl+Shift+O и Ctrl+Shift+G 33 34 With Application 35 .ОпКеу Кеу:="л+О" 36 .ОпКеу Key:="A+G" 37 End With 38 39 End Sub Листинг 19.10 содержит модуль с четырьмя различными процедурами. Первая процедура — SetShortcutKeys — два раза вызывает метод ОпКеу для установки двух комбинаций клавиш. Первый оператор ОпКеу (строка 7) определяет, что процедура DisplayGenOptions будет выполняться каждый раз, когда нажимается комбинация клавиш Ctrl+Shift+O. Второй оператор ОпКеу (строка 8) определяет комбинацию клавиш для процедуры ToggleGridlines — Ctrl+Shift+G. Процедура DisplayGenOptions (строки 14-20) вызывает метод Show (строка 18), для отображения вкладки Общие (General) диалоговой панели Параметры (Options) (определяется константой xlDialogOptionsGeneral). Процедура ToggleGridlines (строки 22-29) просто переключает свойство DisplayGridlines для ActiveWindow (строка 26). Процедура ResetShortcutKeys (строки 31-39) восстанавливает оригинальные действия двух комбинаций клавиш (для Ctrl+Shift+G оригинальное действие отсутствует), используя метод ОпКеу без аргумента Procedure (строки 35 и 36). Использование обработчиков событий 525 Метод OnTime Excel Метод OnTime Excel дает возможность выполнить процедуру VBA в указанное время и даже в определенный день. Этот метод полезен для создания процедур обработки событий, имеющих отношение ко времени и дате и решающих задачи следующего типа: Резервное копирование данных рабочей книги в определенные моменты времени. Если вы отходите на время от своего рабочего стола, вы могли бы запланировать выполнение нескольких длительных операций, например пересчет большого рабочего листа или печать отчета. Вы могли бы выводить в Excel напоминания относительно встреч, приглашений, перерывов и т.д. Вы могли бы выполнить другие действия в определенное время, чтобы проверить электронную почту или запустить какую-либо другую задачу. Общий синтаксис метода OnTime выглядит следующим образом: СИНТАКСИС Application.OnTime(EarliestTime, Procedure, [LatestTime], [Schedule]) Обязательный аргумент EarliestTime — число, представляющее время, когда должно начаться выполнение обозначенной процедуры. Для аргумента EarliestTime следует использовать последовательные значения даты. Обязательный аргумент Procedure — это строка, содержащая имя процедуры, которую необходимо выполнить при наступлении момента времени, заданного аргументом EarliestTime. Если Excel не «готов» выполнить определенную процедуру в момент времени EarliestTime, т.е. если Excel не находится в режимах Готов (Ready), Вырезать (Cut), Копировать (Сору) или Поиск (Find), он будет «пробовать» выполнить процедуру до наступления момента времени, определенного необязательным аргументом LatestTime. Аргумент LatestTime — это также значение даты. Если вы опускаете LatestTime, Excel выполняет заданную процедуру как можно быстрее после наступления момента времени EarliestTime. Необязательный аргумент Schedule — значение типа Boolean, которое указывает Excel, выполнить ли определенную процедуру в заданное время. Если аргумент Schedule имеет значение True или опущен, Excel выполнит обработчик события в планируемое время. Если аргумент Schedule имеет значение False, то Excel отменяет установку OnTime. Excel выполняет процедуру обработчика событие OnTime только один раз. Если вы выполните процедуру сегодня в полдень, та же самая процедура не будет выполнена завтра, даже если вы оставите компьютер включенным с загруженным Excel. Листинг 19.11 показывает пример работы метода OnTime. Листинг 19.11. Применение метода OnTime Excel 1 Sub SetOnTimeReminder() 2 ' Устанавливает событие OnTime 3 4 Application.OnTime EarliestTime:=TimeValue("7:57 AM"), 5 Procedure:="Events.XLS!RemindMe" 6 End Sub 7 8 526 Глава 19 9 Sub RemindMeO 10 ' "Напоминает" о встрече 11 12 Веер 13 MsgBox prompt:="Сейчас "4 14 Format(Time, "h:mm AM/PM") & & _ 15 vbCr & "He забудьте о встрече с клиентом!" 16 End Sub Листинг 19.11 содержит две процедуры. Первая процедура, SetOnTimeRemin-der (строки 1-6), вызывает метод OnTime, чтобы определить процедуру Remind-Ме, которая будет выполнена в 7:57 утра (строки 3 и 4). Процедура RemindMe (строки 9-16) подает звуковой сигнал через динамик компьютера (строка 12) и выводит сообщение, напоминающее о встрече (строки 13-15). Работа с событиями объектов Word Число объектов в Word, которые предоставляют доступ к событиям, намного меньше, чем в Excel. Word имеет только два таких объекта — Application и Document. В таблицах 19.4 и 19.5 приведен список событий объектов Word. Далее рассматриваются некоторые из событий, приведенных в этих таблицах. Таблица 19.4. События Word-объекта Application Событие Когда происходит DocumentBeforeClose Перед тем, как закрывается любой документ. DocumentBeforePrint Перед тем, как печатается любой открытый документ. DocumentBeforeSave Перед тем, как сохраняется любой открытый документ. Documentchange Когда изменяется открытый документ. DocumentOpen Когда открывается документ. EPostageinsert, EPostagePropertyDialog, MailMergeAfterMerge, MailMergeAfterRecordMerge, MailMergeBeforeMerge, MailMergeBeforeRecordMerge, MailMergeDataSourceLoad, MailMergeDataSourceValidate, MailMergeDataSource Validate, MailMergeWizardSendToCustom, MailMerge WizardStateChange При возникновении событий, связанных с использованием аппарата рассылки писем. % / NewDocument При создании нового документа. Quit Когда пользователь завешает работу с Word. Window Activate Когда любое окно документа становится активным. Использование обработчиков событий 527 Событие Когда происходит W indowBeforeDoubleClick Когда в редактируемой области окна документа выполняется двойной щелчок, перед выполнением действия по умолчанию. WindowBeforeRightClick Когда в редактируемой области окна документа выполняется правый щелчок, перед выполнением действия по умолчанию. WindowDeactivate Когда любое окно документа перестает быть активным. WindowSelectionChange Когда в окне активного документа изменяется выделенный фрагмент. WindowSize Когда окно приложения изменяется в размерах или перемещается. Таблица 19.5. События Word-объекта Document Событие Когда происходит Close Когда закрывается документ. New Когда новый документ создается на основе шаблона. Open При открытии документа. Событие Open Как и событие Open в Excel, событие Open объекта Document в Word используется для настройки среды вашего приложения: меню, панели инструментов, а также для установки параметров Word. Типичные действия, выполняемые внутри процедуры обработки события Open документа, перечислены ниже: Установка или настройка панели команд, чтобы создать меню и панели инструментов для программы VBA Word Настройка общих параметров программы, таких как загрузка глобальных шаблонов, установка стандартного шрифта и других. Добавление новых связанных клавиш или присвоение процедуры обработчика события OnTime. Вывод специального диалога для настройки параметров для программы. Вы можете включить в обработчик события Open любое действие, которое хотите выполнить или которое необходимо выполнить при каждом открытии документа. Событие Open для шаблона Normal.dot происходит тогда, когда вы открываете первый документ, основанный на шаблоне Normal, а не во время загрузки в память шаблона Normal. В листинге 19.12 приведен пример процедуры обработчика события Open для документа Word. Для того чтобы процедура Document_Open листинга 19.12 работала правильно, ее следует ввести в модуль класса объекта ThisDocument. В редакторе VB откройте Project Explorer и раскройте (в случае необходимости) ветвь Microsoft Word Objects, чтобы увидеть элемент списка ThisDocument. Выполните двойной щелчок элемента ThisDocument, чтобы открыть окно кода для модуля класса объекта ThisDocument. Затем выберите Document в списке объектов окна кода и выберите в списке процедур пункт Open. Редактор VB автоматически введет объявление процедуры события Open; после этого вы можете ввести код из листинга 19.12. 528 Глава 19 Кроме того, необходимо создать модуль для этого документа и поместить в него объявление функции GetUserNameA из DLL-файла: Declare Function GetUserNameA Lib "advapi32.dll" _ (ByVai IpBuffer As String, nSize As Long) As Long Листинг 19.12. Применение события Open документа 1 Private Sub Document_Open() 2 Dim username As String ' имя пользователя 3 Dim slength As Long ' длина строки 4 Dim retval As Long ' возвращаемое значение 5 6 ' отводим место для получения строки в буфере: 7 username = Space(255) * 8 slength = 255 9 10 ’ получаем имя пользователя: 11 retval = GetUserNameA(username, slength) 12 13 ' извлекаем информацию из буфера,отбрасывая Null: 14 username = Left(username, slength - 1) 15 16 ' сообщение пользователю с указанием его имени: 17 MsgBox username & "! Вы начинаете работу с файлом " & _ 18 Application.ActiveDocument.Name 19 20 ' установить необходимые для работы панели: 21 CommandBars("Standard").Visible = True 22 CommandBars("Drawing").Visible = True 23 24 End Sub Процедура обработки события Document_Open демонстрирует возможность обработки события Open для документа. Она определяет имя работающего с компьютером пользователя и имя открываемого файла. Сообщает пользователю эту информацию и устанавливает необходимые для работы панели инструментов. Для того чтобы Word не выполнял процедуру обработки события Docu-ment_Open, во время открытия документа удерживайте нажатой клавишу Shift. Word откроет документ, не выполняя обработчик события Open. Событие Close Когда вы закрываете документ, вам может потребоваться восстановить среду приложения Word, особенно в том случае, если процедура Document_Open настроила интерфейс пользователя. Вы можете создать процедуру обработчика события Document_Close; событие Close происходит непосредственно перед закрытием документа. Событие Close в Word доступно только для Document. Word всегда выполняет процедуру обработки события Document_Close, закрываете ли вы документ в VBA-коде или используете команды меню Word. В листинге 19.13 показан пример процедуры Document_Close. Листинг 19.13. Применение события Close документа | 1 Private Sub Document_Close() 2 ' Отменить панели инструментов: 3 4 CommandBars("Standard").Visible = False Использование обработчиков событий 529 5 CommandBars("Drawing").Visible = False 6 7 End Sub Событие New Событие New предоставляется объектом Document, но действительно полезно только в тех случаях, когда используется в документах, сохраненных как шаблоны. Хотя стандартный объект Document может содержать процедуру обработки события New, он никогда не генерирует событие New. Событие New генерируется только в том случае, когда новый документ создается из конкретного шаблона. Поэтому следует использовать событие New в документе, который предполагается преобразовать в шаблон. Типичные примеры применения обработчика события New — создание конвертов, установка адреса получателя и приветствия, а также другие действия, связанные с созданием нового документа. Событие Documentchange Объект Word Application предоставляет доступ к событию Documentchange. Это событие происходит каждый раз, когда изменяется активный документ; Word переключается на новый документ, а затем генерирует событие Documentchange. Вы можете использовать событие Documentchange для проверки того, был ли активизирован определенный документ, после чего можно предпринять какие-либо действия. Используйте событие Documentchange для запуска задачи, касающейся конкретного документа, чтобы предупредить действия пользователя, собравшегося переключиться на определенный документ до того, как было завершено выполнение задачи, а также, чтобы помочь пользователю пройти через определенный ряд документов. В листинге 19.14 приведен пример процедуры обработки события Documentchange. Листинг 19.14. Применение события Documentchange объекта Application Word 1 Option Explicit 2 3 Public WithEvents App As Application 4 5 • 6 Private Sub App_DocumentChange() 7 1 Если новый активный документ - это 8 ' "Глава 19.doc", 9 ' то перейти на закладку с именем "LastBookmark" 10 ' Если закладка не существует, то перейти 11 ' в конец документа 12 13 On Error Resume Next , 14 15 With ActiveDocument 16 If UCase(.Name) = _ 17 UCase("Глава 19.doc") Then 18 Selection.GoTo what:=wdGoToBookmark, _ 19 Name:="LastBookmark" 20 If Err.Number 0 Then 21 Selection.WholeStory 22 Selection.Collapse direction:=wdCollapseEnd 23 End If 24 End If 530 Глава 19 25 End With 26 27 End Sub Листинг 19.14 содержит модуль класса, поскольку процедуры обработки событий уровня Application должны находиться в модуле класса вашего VBA-проек-та. Чтобы процедура обработки события App_DocumentChange листинга 19.14 работала правильно, вы должны ввести код листинга 19.14 в модуль класса (модули класса были описаны в главе 10). Вы должны также создать объявление переменной уровня модуля, которая создает новый экземпляр вашего модуля класса, и процедуру, которая присваивает этой переменной ссылку на объект Application. Если вы ввели код листинга 19.14 в модуль класса с именем ApplicationEvents, вы должны добавить следующий код в любой другой модуль: Dim WordApp As New ApplicationEvents Sub InitializeAppEvents)) Set WordApp.App = Application End Sub Теперь выполните процедуру InitializeAppEvents, чтобы создать связь между обработчиком события в модуле класса ApplicationEvents и объектом Application. После того как вы завершили все эти шаги, ваши обработчики событий уровня приложения будут выполняться при возникновении связанных с ними событий. Строки 1-3 листинга 19.14 представляют собой общую область модуля класса. Объявление открытой переменной в строке 3 создает дескриптор, который VBA может использовать для связывания обработчика события в этом модуле класса с объектом Application. Переменная в этом объявлении должна иметь имя Арр, иначе VBA не сможет использовать дескриптор для подключения вашего обработчика событий к объекту Application. Строки 6-27 содержат процедуру App_DocumentChange, которая будет выполняться каждый раз при возникновении события Documentchange. Строки 15-25 содержат оператор With, упрощающий работу с ActiveDocument. Word генерирует событие Documentchange после переключения на новый документ, так что ActiveDocument ссылается на документ, который только что стал активным. Строки 16-17 содержат оператор If...Then, который проверяет, произошло ли переключение на документ Глава 19.doc. (Функция UCase используется для преобразования сравниваемых строк в верхний регистр.) Если документ, на который только что произошло переключение, имеет имя Глава 19.doc, то код строк 18-19 вызывает метод GoTo объекта Selection для перехода к закладке документа с именем LastBookmark. Если закладки не существует, то обработчик ошибок предотвращает ошибку во время выполнения программы и выполнение кода продолжается со следующего оператора (строка 20), независимо от того, произошла ошибка или нет. Код строки 20 проверяет значение свойства Number объекта Err. Если во время выполнения программы произошла ошибка (т.е. значение Err.Number не равно нулю), то закладки не существует. В этом случае код строк 21 и 22 переводит курсор вставки в конец документа. Событие Quit Событие Quit происходит каждый раз, когда заканчивается текущий сеанс работы Word, независимо от того, выбрал ли пользователь команду Файл | Выход (File | Exit) или вы вызвали метод Quit в VBA-коде. Вы можете использовать событие Quit для автоматического сохранения всех открытых документов, записи переменных в коллекцию Variables документа или для выполнения любой вспомогательной задачи, которую хотите выполнять при каждом выходе из Word. Использование обработчиков событий 531 Событие Quit происходит при выходе из Word и не имеет аргумента Cancel, так что вы не можете его использовать, чтобы помешать пользователю закончить сеанс работы Word. В листинге 19.15 показан пример обработчика события Quit. Листинг 19.15. Применение события Quit объекта Application Word 1 Option Explicit 2 3 Public WithEvents App As Application 1 4 5 6 Private Sub App_Quit() 7 ' поместить закладку с именем "LastBookmark" 8 1 в каждый открытый документ 9 Dim aDoc As Document 10 Dim Ans As Integer ’ 11 12 ' для всех документов 13 For Each aDoc In Application.Documents 14 With aDoc 15 Ans=MsgBox(prompt:="Вставить закладку 'LastBookmark'?" 16 , Title:=.Name, _ 17 buttons:=vbYesNo + vbQuestion) 18 If Ans = vbYes Then 19 .Activate 20 Selection.Collapse direction:=wdCollapseEnd 21 .Bookmarks.Add Name:^"LastBookmark" 22 , .Save 23 End If , ' 24 End With 25 Next aDoc 26 27 End Sub Листинг 19.15, как и листинг 19.14, содержит полностью весь модуль класса — тип модуля, обязательный для сохранения процедуры обработки события уровня Application. Строки 1-3 листинга 19.15 должны быть введены в общую область объявлений модуля класса. Обратите внимание, что этот модуль класса, как и в листинге 19.14, содержит объявление открытой переменной в строке 3, чтобы создать дескриптор, который VBA может использовать для связывания процедур обработки событий в этом модуле класса с объектом Application. Процедура обработки событий App_Quit «перебирает» все открытые документы и предлагает пользователю вставить закладку на текущем выделенном фрагменте. Вставка закладки на текущий выделенный фрагмент перед закрытием документа может помочь вам быстро найти место последнего редактирования. Если пользователь выбирает вставку закладки, то документ также и сохраняется. В строке 13 начинается цикл For Each, который «перебирает» все открытые документы и выдает запрос (строки 15-17) на вставку закладки для каждого документа. Имя документа отображается в заголовке диалогового окна функции InputBox (строка 16). Объект Selection (строка 20) всегда ссылается на выделенный фрагмент в активном документе. В строке 21 вызывается метод Add коллекции Bookmarks документа для вставки закладки. В заключение код строки 22 сохраняет документ без обращения к пользователю. Сохранение документа здесь необходимо потому, что Word уже задавал пользователю вопрос о сохранении документов, содержащих несохраненные изменения. Если вы изменяете документ в процедуре события Quit, вы также должны его сохранить. 532 Глава 19 Работа с коллекциями и методами, связанными с событиями Word Как и Excel, Word предоставляет несколько различных способов, которыми вы можете установить процедуры обработки событий для тех событий, к которым Word не предоставляет прямой доступ, в частности, к событиям клавиатуры и времени. Для сохранения процедур обработки событий специальных нажатий клавиш следует использовать коллекцию Key Bindings Word. Для создания процедур, которые должны выполняться в конкретный момент времени дня или при наступлении конкретной даты, используйте метод OnTime Word. Следующие несколько разделов этой главы описывают коллекцию KeyBindings и метод OnTime Word более подробно. Коллекция KeyBindings Вы можете присвоить комбинацию клавиш вашей процедуре VBA в Word в интерактивном режиме, выбрав команду Сервис | Настройка (Tools | Customize) для отображения диалога Настройка (Customize) и щелкнув кнопку Клавиатура (Keyboard) для вывода диалога настройки клавиатуры. Вы можете также установить специальные комбинации клавиш в вашем VBA-коде Word, используя коллекцию KeyBindings и объекты KeyBinding, которые она содержит. Свойство KeyBindings объекта Application возвращает коллекцию всех команд клавиатуры Word как объект KeyBindings. Как вы можете предполагать, коллекция KeyBindings содержит объекты KeyBinding. Каждый объект KeyBinding хранит информацию, которая связывает конкретную клавишу или комбинацию клавиш с соответствующей процедурой. На основе объектов KeyBinding и коллекции KeyBindings вы можете создавать процедуры, обрабатывающие определенные нажатия клавиш. Вы можете также использовать коллекцию KeyBindings для отключения определенных нажатий клавиши, вызывая метод Clear или Disable отдельного объекта KeyBinding. Для создания нового обработчика события нажатия клавиши, используйте метод Add коллекции KeyBindings со следующим синтаксисом: СИНТАКСИС Objесt.Add(КеуСаtegory, Command, KeyCode, [KeyCode2], [Commandparameter]) Здесь Object является ссылкой на объект KeyBindings; обычно для ссылки на коллекцию KeyBindings (в Word) следует использовать свойство Application.Key Bin dings. Обязательный аргумент KeyCategory —число типа Long, которое указывает категорию нового обработчика события нажатия клавиши: макрос, выделение шрифта, выделение стиля, элемент AutoText и т.д. Используйте константу wdKeyCategoryMacro для аргумента KeyCategory, если хотите присвоить одной из ваших VBA-процедур данное нажатие клавиши. KeyCategory может быть любой из констант класса WdKeyCategory: wdKeyCategoryAutoText, wdKeyCategoryCommand, wdKeyCategoryDisable, wdKeyCategoryFont, wdKeyCategoryMacro, wdKeyCategoryNil, wdKeyCategoryPrefix, wdKeyCate-goryStyle или wdKeyCategorySymbol. Обязательный аргумент Command — строковое выражение, определяющее имя процедуры VBA, которая будет выполняться в ответ на данное нажатие клавиши. В качестве альтернативы строка аргумента Command может опреде Использование обработчиков событий 533 лять встроенную команду Word, которая будет выполняться в ответ на данное нажатие клавиши. Аргумент KeyCode также обязательно должен присутствовать; это — число типа Long, соответствующее конкретной комбинации клавиш, которую будет представлять данный объект KeyBinding. Самый лучший способ задания аргумента KeyCode состоит в вызове метода Application.BuildKeyCode, описанного ниже в этом разделе. Аргументы KeyCode2 и CommandParameter необязательны. KeyCode2 — вторая комбинация клавиш, a CommandParameter — дополнительные данные, используемые некоторыми встроенными командами Word, которые вы можете присвоить KeyBinding. В описании синтаксиса метода KeyBindings.Add было упомянуто, что самый лучший способ конструирования аргумента KeyCode состоит в том, чтобы применить метод BuildKeyCode. Аргумент KeyCode может представлять не только одиночную клавишу, но и клавишу, объединенную с клавишами Ctrl, Shift и/или Alt. Метод BuildKeycode предоставляет простой способ определить числа, соответствующие нужным нажатиям клавиш: СИНТАКСИС: Object.BuildKeycode(Argl, [Arg2] , [АгдЗ], [Arg4]) Object в этом синтаксисе — необязательная ссылка на объект Application. Аргумент Argl — обязателен и является числом типа Long, представляющим конкретную одиночную клавишу. Чтобы определить значения аргументаArgl, используйте класс встроенных констант WdKey. Необязательные аргументы от Arg2 до Arg4 — также числа, представляющие конкретные одиночные клавиши; значение этих аргументов также определяются через константы WdKey. Метод BuildKeycode возвращает число типа Long, которое является числовым кодом для комбинации клавиш, которую вы определили в Argl-Arg4. В листинге 19.16 содержится пример работы метода BuildKeycode. Существует более сотни констант WdKey — слишком много, чтобы привести их здесь. Полный список доступных констант WdKey можно увидеть в окне Object Browser. Выберите Word в раскрывающемся списке Project/Library окна Object Browser, а затем выберите WdKey в списке Classes. Теперь список Members of WdKey отображает доступные встроенные константы клавиш. Листинг 19.16. Применение коллекции KeyBindings Word 1 Option Explicit 2 3 Sub SetShortcutKeys() 4 1 11 Устанавливает комбинации клавиш Ctrl+Shift+S и Ctrl+Shift+F 5 6 With Application.KeyBindings 7 .Add KeyCategory:=wdKeyCategoryMacro, _ 8 Command:="DisplayInfo", _ 9 KeyCode:=BuildKeyCode(wdKeyControl,wdKeyShift,wdKeyS) 10 .Add KeyCategory:=wdKeyCategoryMacro, _ 11 Command:="ViewFooter", _ 12 KeyCode:=BuildKeyCode(wdKeyControl,wdKeyShift,wdKeyF) 13 End With 14 15 End Sub 16 534 Глава 19 17 18 Sub Displayinfo () '(( 19 ' Выводит диалог "Сведения" 20 21 Application.Dialogs(wdDialogFileSummarylnfo).Show 22 23 End Sub . 24 ' •' 25 Sub ViewFooter() 26 ' Переключает вид на нижний колонтитул документа 27 28 If ActiveWindow.ActivePane.View.Type wdPageView Then 29 ActiveWindow.ActivePane.View.Type = wdPageView 30 End If 31 32 ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter 33 34 End Sub 35 36 Sub ResetShortcutKeys() 37 ' Сбросить комбинации клавиш Ctrl+Shift+S и Ctrl+Shift+F 38 Dim aKey As KeyBinding 39 40 For Each aKey In Application.KeyBindings 41 If UCase(aKey.Command) = UCase("DisplaySummarylnfo") Or _ 42 UCase(aKey.Command) = UCase("ViewFooter") Then 43 aKey.Clear 44 End If 45 Next aKey 46 47 End Sub Листинг 19.16 содержит модуль с четырьмя процедурами. Первая процедура, SetShortcutKeys (строки 3-15), устанавливает два обработчика событий нажатия клавиш. Вторая процедура — Displayinfo (строки 18-23) — это обработчик первой комбинации клавиш; она отображает диалог Сведения документа. Третья процедура — ViewFooter (строки 21-29) — это обработчик второй комбинации клавиш; она переключает текущий вид окна, отображая нижний колонтитул документа. Последняя процедура, ResetShortcutKeys (строки 32-42), сбрасывает обработчики событий нажатия клавиш в исходное состояние. Метод OnTime Word Метод OnTime Word дает возможность выполнить процедуру VBA в определенное время и в определенный день. Этот метод полезен для установки обработчиков событий, имеющих отношение ко времени и датам и решающих следующий круг задач: автоматическое резервное копирование; выполнение плановых действий, отнимающих много времени, в те моменты, когда вы не работаете на рабочем месте (например, печать длинных документов); вывод напоминаний о приглашениях, встречах и т.д. Метод OnTime Word немного отличается от метода OnTime Excel. Если вы вызываете метод OnTime в VBA Excel и VBA Word, то убедитесь в том, что вы уделили внимание различиям синтаксиса этих двух методов. Общий синтаксис для метода OnTime Word имеет следующий вид: СИНТАКСИС Application.OnTime(When, Name, [Tolerance]) Обязательный аргумент When — это число, определяющее дату и время запуска обозначенной процедуры. Аргумент When может быть строкой, например Использование обработчиков событий 535 "15/4 12:00", или последовательным значением даты. Обязательный аргумент Name — это строка, содержащая имя процедуры, которую вы хотите выполнить при наступлении момента времени, определенного аргументом When. Необязательный аргумент Tolerance определяет промежуток времени, в секундах, в течение которого Word будет «пытаться» выполнить процедуру Name, если он не может это сделать в момент времени, определенный аргументом When. Это происходит в тех случаях, когда в момент времени When на экране находится диалог или выполняется некоторая операция (например, сортировка). В листинге 19.17 показан пример вызова метода OnTime Word. Листинг 19.17. Применение метода OnTime Word 1 Sub SetOnTime () 2 ' Установить событие OnTime 3 Application.OnTime When:=Now + TimeValue("00:15:00”), _ 4 Name:="RemindMe" 5 6 End Sub 7 8 9 Sub RemindAboutFone () 10 1 Эта процедура выводит напоминание 11 MsgBox prompt:="Сейчас " & _ 12 Format(Time, "h:mm AM/PM") & _ 13 vbCr & _ 14 "Вы должны позвонить клиенту!" 15 End Sub Листинг 19.17 содержит две процедуры. Первая процедура, SetOnTime (строки 1-6), вызывает метод OnTime, чтобы установить процедуру RemindAboutFone, которая будет выполнена через 15 минут после текущего момента времени. Процедура RemindAboutFone (строки 9-15) выводит текст напоминания (строки 11-14). часть iv Доступ к базам данных из приложений Microsoft Office Глава 20 Введение в базы данных Так уж повелось, что практически в каждой книге по Visual-системе программирования имеется глава (иногда и более), в которой уделяется немного внимания достаточно важному явлению современной жизни — работе с базами данных. Это связано и с попытками привлечь внимание читателя к данному изданию, и с возрастающей ролью баз данных в развитии современного общества, и с увеличением возможностей Visual-систем по обработке информации, организованной в виде баз данных. Учитывая это, мы также уделим некоторое внимание вопросам разработки VBA-приложений, использующим базы данных. Тем более что принципы применения баз данных в VBA являются общими для Microsoft-приложений. Что такое «базы данных»? Начнем с краткого введения в терминологию, в дальнейшем используемую в этой и следующих главах. Что такое «базы данных», какие бывают типы баз данных? Базы данных — это системы, цель которых — та же, что и у файловых систем (различных операционных систем), а именно, сохранение данных конечного пользователя и управление этими данными. В отличие от файловых систем системы управления базами данных (СУБД) сохраняют не только сами данные (структуры данных), но и связи между этими данными, а также способы доступа к этим данным. Базы данных — это системы, содержащие множество различных объектов (в некоторых системах вместе с процедурами обработки объектов), объединенных таким образом, чтобы клиенты этих баз (пользователи и приложения) имели возможность быстрого и эффективного доступа к этим объектам. Иногда базами данных называют не только сами данные, но и СУБД. В общем случае под базой данных понимают систему, состоящую из пяти основных частей: аппаратных средств, программного обеспечения, бизнес-правил, данных и специалистов. Конечно, в книге, имеющей отношение к программному обеспечению, можно было бы не останавливаться на аппаратных средствах, но об этом следует обязательно помнить, если вам нужно объяснить, например, руководителю фирмы, что необходимо для создания базы данных, предназначенной для повышения эффективности управления фирмой. К аппаратным средствам относятся все физические устройства, которые обеспечивают ввод, обработку, хранение и представление данных. Конечно, наиболее идентифицируемым устройством базы данных является компьютер (микрокомпьютер, миникомпьютер или универсальная ЭВМ). Большое значение имеют (и часто определяются спецификой базы данных) различные устройства ввода информации и представления обрабатываемых данных. Например, если база данных предназначена для поддержки бизнес-процессов магазина или склада, то в качестве устройств ввода информации часто используются разного рода сканеры, считывающие, например, заводские номера изделий и позволяющие таким образом «следить» за движением товаров. Если к данным базы необходим доступ с удаленных компьютеров, то важным компонентом базы является компьютерная сеть (например, в системе заказа железнодорожных или авиабилетов). Под термином «программное обеспечение базы данных» обычно понимают СУБД. Правильнее было бы считать, что это — и программное обеспечение операционной системы, и СУБД, и прикладные программы и утилиты. Программное обеспечение операционной системы управляет всеми аппаратными компонентами Введение в базы данных 539 и делает возможным выполнение всех других программ вычислительной системы. Известными операционными системами являются DOS, OS/2, Windows 2000/NT/ ХР, UNIX; не очень известными — VMS, MVS. Программное обеспечение СУБД (под управлением операционной системы) обрабатывает данные базы данных. Примерами наиболее известных СУБД являются Microsoft Access, Microsoft Fox Pro, Microsoft SQL Server, Oracle, Sybase SQL Anywhere и DB2. Прикладные программы и утилиты необходимы для доступа и манипулирования данными в базе в некоторой компьютерной среде и обычно используются для непосредственного вода данных и генерации отчетов, упрощающих процесс принятия решений. Язык Visual Basic (как и многие другие языки Visual-систем программирования) не является языком баз данных в том смысле, что он не содержит команд и функций обработки записей файлов данных. Однако Visual Basic для управления базами данных использует процессор баз данных (database engine), т.е. систему «отвечающую» за хранение и выборку данных1. Процессор баз данных для Visual Basic, называется Microsoft Jet и представляет собой систему, используемую несколькими программными продуктами фирмы Microsoft. Бизнес-цравила — это инструкции и правила, которые оказывают влияние на проектирование и использование базы данных. Бизнес-правила играют важную роль для компании, так как они налагают стандарты, в соответствии с которыми ведется бизнес, и определяют способы контроля как данных, вводимых в базу данных, так и информации, которая генерируется на основе этих данных. Под данными понимают коллекцию фактов, сохраняемых в базе данных. Это — важнейшая составляющая базы данных. Поэтому особенно важно при создании базы данных определить, какие данные как будут храниться и обрабатываться базой. Большое значение имеет состав специалистов, участвующий в работе с базой данных. Обычно выделяют пять типов таких специалистов: системные администраторы, администраторы баз данных, разработчики баз данных, системные аналитики/программисты и «конечные» пользователи. Системные администраторы следят за общими операциями баз данных. Администраторы баз данных обеспечивают надлежащее функционирование баз данных. Разработчики баз данных разрабатывают структуру базы данных и являются, фактически, архитекторами баз данных. Системные аналитики и программисты разрабатывают и реализуют прикладные программы, проектируют и создают экранные формы ввода данных и отчеты в соответствии с бизнес-правилами компании. Именно этими экранными формами и отчетами пользуются «конечные» пользователи для выполнения ежедневных операций компании и принятия стратегических решений. Типы баз данных Базы данных можно классифицировать в соответствии с числом пользователей, местоположением базы, ожидаемым типом и степенью использования. В зависимости от числа пользователей базы данных классифицируются как однопользовательские или многопользовательские. Однопользовательская база данных одновременно поддерживает только одного пользователя; другие пользователи не могут получить доступ к данным, если в данный момент времени какой-либо пользователь работает с базой данных. Если однопользовательская база данных установлена на персональном компьютере, она называется также настольной (desktop). Многопользовательская база данных одновременно обеспечивает доступ к данным нескольким пользователям. Такая база данных может называться коллективной, если она используется относительно небольшим количеством пользовате 1 Программисты на языке С, в незапамятные времена «увлекавшиеся» базами данных, могут помнить первые версии подобных систем для работы с базами данных Paradox. 540 Глава 20 лей (не менее 50) или предназначена для работы некоторого отдела внутри компании. Если же база данных используется целым предприятием с большим количеством пользователей (более 50) нескольких отделов, то ее называют базой данных предприятия. База данных может быть централизованной (centralized), т.е. находящейся в одном рабочем месте (на одной компьютерной системе), и распределенной (distributed), если находится на нескольких рабочих местах. В настоящее время наиболее часто применяется классификация баз данных, которая отражает тип и степень использования базы. Например, информационная система может поддерживать сбыт продуктов или услуг, платежи и т.д. Такие транзакции являются критическими по времени и должны регистрироваться точно и немедленно. База данных, предназначенная для поддержки таких транзакций (непосредственного отклика), называется транзакционной (transactional). В такой базе данных очень важно поддерживать целостность и непротиворечивость данных. База данных, которая используется для получения информации, необходимой для тактических и стратегических решений на среднем или высшем уровне управления компанией, называется системой поддержки принятия решений (decision support system). Для такой системы временной фактор обычно не является критически важным. Здесь обычно используются «исторические» данные или данные, полученные в результате предварительной обработки данных из различных источников (в том числе и агрегированные данные). Эти обстоятельства позволяют предположить, что структура системы поддержки принятия решений должна существенно отличаться от структуры данных транзакционной базы. Функции систем управления базами данных Системы управления базами данных выполняют много важных функций, большая часть из которых невидима «конечному» пользователю. Эти функции, включают управление хранением данных, их преобразование и презентацию, обеспечение безопасности, управление мультидоступом, резервное копирование и восстановление, интерфейсы прикладного программирования и взаимодействия с базой данных. Средства СУБД позволяют создавать сложные структуры данных, освобождая разработчика базы данных от программирования физической организации данных, и обеспечивают хранение не только самих данных, но также форм для ввода данных, описаний отчетов, правил проверки корректности данных, кода с биз-нес-правилами и т.п. СУБД предоставляет процедуры резервного копирования и восстановления данных. СУБД преобразует вводимые пользователями данные для их соответствия структурам данных, которые необходимы для хранения данных, т.е. освобождает пользователя от необходимости делать различие между логическим и физическим форматом данных. СУБД транслирует логические запросы в команды, которые локализуют и выбирают запрашиваемые данные, находящиеся на физических носителях. Функцией СУБД является управление системой безопасности, которая обеспечивает конфиденциальность данных пользователя. Правила безопасности определяют, какие пользователи могут иметь доступ к базе данных, к каким именно данным и какие операции по обработке данных (чтение, добавление, удаление или модификацию) доступны тому или иному пользователю. Это особенно важно в многопользовательских базах данных, где одновременно к базе могут иметь доступ сразу несколько пользователей. Для обеспечения многопользовательского доступа СУБД / создает сложные структуры данных и использует сложные алгоритмы. Введение в базы данных 541 Модель данных В представлении информации в базах данных можно выделить два уровня абстракции: информационную модель, которая обычно бывает понятна пользователю этой базы, и физическую модель данных, которая связана с подробностями физического хранения данных в дисковых файлах. Информационная модель отображает программное обеспечение в терминах фактов, явлений, событий и предметов (а также связей между ними). Описание абстрактной информационной модели для представления в компьютере выполняется средствами модели данных, которую поддерживает СУБД. Средствами модели данных строится логическая схема информационной модели для внутреннего представления. При этом модель данных, которую поддерживает СУБД, определяется: допустимой структурой данных (разнообразием и количеством типов описываемых с помощью модели объектов), множеством допустимых операций над данными и ограничениями, необходимыми для обеспечения контроля за целостностью данных. Модели данных, поддерживаемые СУБД, делят на сетевые, иерархические и реляционные. В этой связи различают сетевые, иерархические и реляционные СУБД. В настоящее время ведутся активные работы над созданием объектно-ориентированных СУБД, но эти работы существенно тормозятся отсутствием теории соответствующей модели данных. Реляционная модель данных На персональных компьютерах наибольшее применение нашли СУБД, поддерживающие реляционную модель данных, концепция которой была предложена Коддом Е.Ф., сотрудником компании IBM, при решении им задачи обеспечения независимости представления и описания данных от прикладных задач. В основе этой концепции — понятие отношения (relation), которое удобно описывается обычной таблицей. Кодд показал, что совокупность отношений может быть использована для хранения данных об объектах реального мира. Например, некоторая фирма в качестве информационной системы имеет базу данных, состоящую из справочников товаров, торговых точек (складов, магазинов), таблиц наличия товаров. Для описания объекта «товар» можно построить следующее отношение (Товары): Код Наименование Цена оптовая Цена розничная 49019114414 Сабвуфер BSD 01 115 140 79019144420 Комплект акуст.МА-8008 100 130 49019142121 Усилитель АВ-209 250 270 46901923232 Громк.фронтальн. BS 809 190 230 39019105900 Громк.окруж.звука BSC 09 105 130 Колонки (столбцы) отношения называются атрибутами. Атрибуты имеют имена — заголовки. Каждая реализация объекта «товар» — строка в таблице — называется кортежем. Реляционная база данных — это совокупность взаимосвязанных отношений. Отношения реализуются посредством дисковых файлов. Между файлами, таблицами, отношениями и отображаемыми посредством отношений объектами имеются следующие соответствия: файл —► таблица —► отношение —► объект запись поле строка колонка кортеж атрибут экземпляр свойство 542 Глава 20 Операции над отношениями Кодд предложил применять к отношениям систему операций, позволяющую получать одни отношения из других, что позволяет делить информацию базы на хранимую и вычисляемую. Основными операциями над отношениями реляционной базы данных являются обычные операции над множествами: объединение (UNION), пересечение (INTERSECT), вычитание (DIFFERENCE), декартово произведение (PRODUCT), деление (DIVIDE); реляционные операции: проекция (PROJECT), соединение (JOIN) и выбор (SELECT). Эффективность конкретной СУБД определяется наличием и удобством использования тех средств, которые реализуют операции над отношениями. При рассмотрении операций над отношениями мы будем использовать следующие понятия: степень отношения — число входящих в отношение атрибутов; мощность отношения — число кортежей отношения; совместимые отношения — отношения, имеющие одинаковые степени и типы соответствующих атрибутов (можно также говорить, что они имеют совместимые схемы). Объединение Операция объединения (UNION) выполняется над совместимыми отношениями и имеет результатом отношение, которое включает все кортежи первого отношения и недостающие кортежи второго. Пример: Отношение 1: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 115 140 Комплект акуст.МА-8008 100 130 Отношение 2: Наименование Цена оптовая Цена розничная Усилитель АВ-209 250 270 Громк.фронтальн. BS 809 190 230 Громк.окруж.звука BSC 09 105 130 Результат операции объединения: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 115 140 Комплект акуст.МА-8008 100 130 Усилитель АВ-209 250 270 Громк.фронтальн. BS 809 190 230 Громк.окруж.звука BSC 09 105 130 Введение в базы данных 543 Пересечение Операция пересечения (INTERSECT) выполняется над совместимыми отношениями и имеет результатом отношение, содержащее только те кортежи первого отношения, которые имеются во втором. Пример: Отношение 1: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 115 140 Усилитель АВ-209 250 270 Комплект акуст.МА-8008 100 130 Отношение 2: Наименование Цена оптовая Цена розничная Громк.фронтальн. BS 809 190 230 Сабвуфер BSD 01 115 140 Комплект акуст.МА-8008 100 130 Громк.окруж.звука BSC 09 105 130 Результат операции пересечения: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 115 140 Комплект акуст.МА-800в 100 130 Вычитание Операция вычитания (DIFFERENCE) выполняется над совместимыми отношениями и имеет результатом отношение, содержащее только те кортежи первого отношения, которых нет во втором. Пример: Отношение 1: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 115 140 Усилитель АВ-209 250 270 Комплект акуст.МА-8008 100 130 Отношение 2: Наименование Цена оптовая Цена розничная Громк.фронтальн. BS 809 190 230 Сабвуфер BSD 01 115 140 Комплект акуст.МА-8008 100 130 Громк.окруж.звука BSC 09 105 130 544 Глава 20 Результат операции вычитания отношения 2 из отношения 1: Наименование Цена оптовая Цена розничная Усилитель АВ-209 250 270 Декартово произведение Операция декартова произведения (PRODUCT) выполняется над отношениями, которые могут иметь разные схемы, и имеет результатом отношение, степень которого равна сумме степеней отношений-операндов, а мощность — произведению их мощностей. Пример: Отношение 1: Наименование Сабвуфер BSD 01 Усилитель АВ-209 Комплект акуст.МА-8008 Отношение 2: Цена оптовая Цена розничная 190 230 115 140 Результат операции декартова произведения: Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 250 270 Сабвуфер BSD 01 115 140 Усилитель АВ-209 250 270 Усилитель АВ-209 115 140 Комплект акуст.МА-8008 250 270 Комплект акуст.МА-8008 115 140 Деление Операция деления (DIVIDE) выполняется над отношениями, одно из которых — делитель — должно содержать подмножество атрибутов отношения-делимого. Результирующее отношение содержит только те атрибуты делимого, которых нет в делителе, и включает только те кортежи, декартовы произведения с делителем которых содержатся в делимом. Пример: Отношение 1 (делимое): Наименование Цена оптовая Цена розничная Сабвуфер BSD 01 250 270 Сабвуфер BSD 01 115 140 Усилитель АВ-209 250 270 Введение в базы данных 545 Наименование Цена оптовая Цена розничная Усилитель АВ-209 115 140 Комплект акуст.МА-8008 250 270 Комплект акуст.МА-8008 115 140 Отношение 2 (делитель): Наименование Сабвуфер BSD 01 Комплект акуст.МА-8008 Результат операции деления: Цена оптовая Цена розничная 190 230 115 140 Проекция Операция проекции (PROJECT) выполняется над одним отношением. Результирующее отношение не имеет дублируемых кортежей и включает часть атрибутов исходного отношения, на которые выполняется проекция. Пример — проекция на атрибуты Наименование и Дата поступления (с целью, например, узнать даты поступления на фирму определенных товаров): Подразделение Наименование Цена Количество Дата поступления Склад №1 Сабвуфер BSD 01 6500 2000 01.08.2002 Склад №1 Усилитель АВ-209 5000 1000 01.12.2002 Склад №2 Сабвуфер BSD 01 6500 3000 01.10.2002 Склад №2 Комплект акуст.МА-8008 7000 2000 01.08.2002 Склад №2 Усилитель АВ-209 5000 1500 01.12.2002 Магазин №2 Усилитель АВ-209 5000 1230 01.12.2002 Результат выполнения проекции на атрибуты Наименование и Дата поступления: Наименование Дата поступления Сабвуфер BSD 01 01.08.2002 Усилитель АВ-209 01.12.2002 Сабвуфер BSD 01 01.10.2002 Комплект акуст.МА-8008 01.08.2002 18 Программирование на VBA 2002 546 Глава 20 Соединение Операция соединения (JOIN) выполняется над двумя или более отношениями, в каждом из которых должен присутствовать атрибут для соединения. Результирующее отношение включает все атрибуты первого и второго отношений. Пример: Отношение 1: Наименование Код Сабвуфер BSD 01 49019114414 Комплект акуст.МА-8008 79019144420 Усилитель АВ-209 49019142121 Громк.фронтальн. BS 809 46901923232 Громк.окруж.звука BSC 09 39019105900 Отношение 2: Подразделение Код Цена Количество Дата поступления Склад №1 49019114414 6500 2000 01.08.2002 Склад №1 46901923232 5000 1000 01.12.2002 Склад №2 49019114414 6500 3000 01.10.2002 Склад №2 79019144420 7000 2000 01.08.2002 Склад №2 49019142121 5000 1500 01.12.2002 Магазин №2 49019142121 5000 1230 01.12.2002 Результат операции соединения: Подразделение Наименование Код Цена Количество Дата поступления Склад №1 Сабвуфер BSD 01 49019114414 6500 2000 01.08.2002 Склад №1 Громк. фронтал ьн. BS 809 46901923232 5000 1000 01.12.2002 Склад №2 Сабвуфер BSD 01 49019114414 6500 3000 01.10.2002 Склад №2 Комплект акуст.МА-8008 79019144420 7000 2000 01.08.2002 Склад №2 Усилитель АВ-209 49019142121 5000 1500 01.12.2002 Магазин №2 Усилитель АВ-209 49019142121 5000 1230 01.12.2002 Выбор Операция выбора (SELECT) выполняется для всех кортежей, найденных в отношении. Результирующее отношение содержит подмножество выбранных кортежей. Пример: Введение в базы данных 547 Исходное отношение: Подразделение Наименование Цена Количество Дата поступления Склад №1 Сабвуфер BSD 01 6500 2000 01.08.2002 Склад №1 Громк.фроцтальн. BS 809 5000 1000 01.12.2002 Склад №2 Сабвуфер BSD 01 6500 3000 01.10.2002 Склад №2 Комплект акуст.МА-8008 7000 2000 01.08.2002 Склад №2 Усилитель АВ-209 5000 1500 01.12.2002 Магазин №2 Усилитель АВ-209 5000 1230 01.12.2002 Результат выбора всех строк: Подразделение Наименование Цена Количество Дата поступления Склад №1 Сабвуфер BSD 01 6500 2000 01.08.2002 Склад №1 Громк.фронтальн. BS 809 5000 1000 01.12.2002 Склад №2 Сабвуфер BSD 01 6500 3000 01.10.2002 Склад №2 Комплект акуст.МА-8008 7000 2000 01.08.2002 Склад №2 Усилитель АВ-209 5000 1500 01.12.2002 Магазин №2 Усилитель АВ-209 5000 1230 01.12.2002 Результат выбора всех строк, для которых в поле Подразделение содержится значение «Склад №2»: Подразделение Наименование Цена Количество Дата поступления Склад №2 Сабвуфер BSD 01 6500 3000 01.10.2002 Склад №2 Комплект акуст.МА-8008 7000 2000 01.08.2002 Склад №2 Усилитель АВ-209 5000 1500 01.12.2002 Следует отметить, что большинство СУБД поддерживают только такие ключевые операции, как SELECT, PROJECT и JOIN. Существует очень мало СУБД, которые поддерживают все восемь рассмотренных операций. Языки для выполнения операций над отношениями в реляционной СУБД делят на два основных класса: языки реляционной алгебры и реляционного исчисления. Первые из них основываются на реляционной алгебре и являются процедурными, так как, записывая последовательности операций над отношениями в соответствующем порядке, можно получать желаемый результат. Языки реляционного исчисления, не являясь процедурными, основываются на классическом исчислении предикатов и предоставляют набор правил для записи запросов к базе данных. Запрос содержит информацию о желаемом результате. Первый язык реляционного исчисления Alfa был разработан самим Коддом. В настоящее время широко используется язык структурированных запросов SQL (Structured Query Language), разработанный фирмой IBM. 18* 548 Глава 20 Связи между отношениями Отношения реляционной базы данных в зависимости от содержания подразделяют на объектные1 и связные. Объектные отношения предназначены для хранения информации об экземплярах, в то время как связные отношения имеют целью связывать между собой экземпляры, хранящиеся в объектных отношениях. В объектном отношении один из атрибутов всегда однозначно идентифицирует отдельный экземпляр сущности (объекта реального мира). В соответствующем этому атрибуту поле (дискового) файла хранится неповторяющаяся информация. Такой атрибут чаще всего используется в качестве ключевого и называется ключом отношения. Например, в отношении Товары в качестве ключевого, конечно же, следует выбрать атрибут Код_товара. Ключ отношения может включать несколько атрибутов и даже являться результатом выражения (в которое могут входить различные атрибуты). Далее будут приведены примеры с использованием подобных ключей. В качестве еще одного примера объектного отношения приведем таблицу-справочник складов и магазинов фирмы, где могут находиться товары. Назовем ее Подразделения: Подразделения Код_подразделения Наименование_подразделения Телефон 1518 СКЛАД №01 222-35-33 1346 СКЛАД №02 320-90-90 0220 МАГАЗИН №01 241-09-09 0240 РОЗН.МАГ.№10 333-44-44 Ключом этого отношения, конечно же, должен быть атрибут Код_подразделения. Связное отношение содержит ключи двух или более отношений для связи отношений. Например, используя отношения Товары и Подразделения можно определить связное отношение для хранения данных о количестве товаров в различных подразделениях фирмы (Запасы). Товары Наименование Код_товара Сабвуфер BSD 01 49019114414 Комплект акуст.МА-8008 79019144420 Усилитель АВ-209 49019142121 Громк.фронтальн. BS 809 46901923232 Громк.окруж.звука BSC 09 39019105900 Запасы Код_подразделения Код_товара Количество Дата_поступления 0220 49019114414 2000 01.01.2000 0220 79019144420 2332 01.12.1999 0220 49019142121 11222 01.10.2000 Здесь этот термин не имеет отношения к концепции объектно-ориентированного программирования. Введение в базы данных 549 Код_подразделения Код_товара Количество Дата_поступления 0240 49019114414 12343 01.11.2000 0240 79019144420 23 08.11.2000 1346 49019114414 22343 07.12.2000 1346 79019144420 1133 07.09.2000 1346 49019142121 77666 10.08.2000 1346 39019105900 12321 11.10.2000 1518 49019114414 778891 11.11.2000 1518 79019144420 34 21.11.2000 Как видно из последнего примера, код одного и того же склада, как и код товара, могут встречаться в отношении Запасы несколько раз. Каждая строка этого отношения отображает наличие определенного товара на некотором складе. Например, первая строка отображает тот факт, что в магазине с кодом 0220 [МАГАЗИН №01 — см. отношение Подразделения] находится товар с кодом 049019114414 [Сабвуфер BSD 01 — см. отношение Товары] в количестве 2000 единиц, поступивший в магазин 01.01.2000 (дата). Вторая строка сообщает о том, что в этом же магазине имеется товар с кодом 079019144420 [Комплект акуст.МА-8008] в количестве 2332 единиц. И так далее. Как вы уже могли заметить, связное отношение, кроме связываемых ключей, может иметь и другие атрибуты (в примере Запасы — это Количество, Дата_по-ступлеиия). Ключи в связных отношениях называются внешними, поскольку являются первичными ключами других отношений. Самой простой связью между отношениями (таблицами) является связь «одии-к-одиому», при которой одному кортежу первого отношения соответствует только один кортеж во втором. Такая связь обычно используется при разделении отношений, имеющих большое количество атрибутов. Наиболее часто в программировании приложений баз данных используется связь «один-ко-многим», которая позволяет поставить в соответствие один кортеж первого отношения нескольким кортежам второго отношения при помощи первичного ключа первого отношения и внешнего ключа второго отношения. Последний пример с использованием отношений Товары, Подразделения и Запасы — это типичный пример связи «один-ко-многим». Здесь отношение Товары связано с отношением Запасы при помощи первичного ключа Код_товара, а отношение Подразделения связано с отношением Запасы при помощи первичного ключа Код_подраз-деления. При этом в отношении Запасы атрибуты Код_подразделения и Код_това-ра являются внешними ключами. Обычно связи, о которых идет речь, схематично обозначаются так, как показано на рис. 20.1 (получена в Microsoft Access) или на рис. 20.2 (получена в ERWin). Рис. 20.1. Схема связей таблиц базы данных в Access 550 Глава 20 Подразделения___________ Код_подразделения Наименование_подразделе Телефон Запасы_________ Код_товара (FK) Код_подразделения (FK) Количество Дата_поступления Рис. 20.2. Схема связей таблиц базы данных в ERWin Товары_____________ КодТовара НаименованиеТовара В поле таблицы базы данных могут храниться различные типы данных. Обычно в момент создания таблицы для каждого поля указываются наименование, тип хранимых в нем данных, длина данных (число знаков после десятичной точки для действительных чисел). В некоторых системах (к ним относится и Access) указывается дополнительная информация, в том числе и форматирование данных при отображении. Кроме того, реляционные СУБД имеют механизмы (разные у разных СУБД) задания ключевых полей и связей между таблицами (при помощи ключевых полей). Если при этом СУБД позволяет представлять связи между таблицами графически, разработчик базы данных получает дополнительные преимущества. Ограничения реляционной модели На внешние ключи реляционной моделью накладывается ограничение, называемое ссылочной целостностью. Оно состоит в том, что каждому внешнему ключу должна соответствовать строка какого-либо объектного отношения. В противном случае внешний ключ не будет ссылаться ни на какой объект в базе данных. Другое, не менее важное, ограничение реляционной модели — отношения должны быть нормализованы. Это, в частности, означает, что каждый атрибут отношения должен быть простым. Например, недопустимо следующее отношение: Код товара Наименование товара Цена оптовая розничная 049019114414 Сабвуфер BSD 01 115,0 140,0 079019144420 Комплект акуст.МА-8008 100,0 130,0 049019142121 Усилитель АВ-209 250,0 270,0 469019145021 Громк.фронтальн. BS 809 190,0 230,0 039019105900 Громк.окруж.звука BSC 09 105,0 130,0 Это отношение содержит сложный атрибут Цена. Нормализация отношений Рассмотренные ранее отношения можно демонстрировать не только в качестве объектных и связных отношений, но и как пример нормализованных отношений реляционной базы данных. Эти отношения получились не сразу. Сначала для решения задачи о хранении товаров на складах и магазинах должна была появиться, например, следующая таблица (здесь не указан столбец с датами поступления товаров): Наименование подразделения Телефон Наименование товара Кол-во Цена оптовая Цена розничная МАГАЗИН №01 241-09-09 Сабвуфер BSD 01 2000 115,0 140,0 МАГАЗИН №01 241-09-09 Комплект акуст.МА-8008 2332 100,0 130,0 Введение в базы данных 551 Наименование подразделения Телефон Наименование товара Кол-во Цена оптовая Цена розничная МАГАЗИН №01 241-09-09 Усилитель АВ-209 11222 250,0 270,0 Р03Н.МАГ.№10 333-44-44 Сабвуфер BSD 01 12343 115,0 140,0 РОЗН.МАГ.№10 333-44-44 , Комплект акуст.МА-8003 23 100,0 130,0 СКЛАД №02 320-90-90 Сабвуфер BSD 01 22343 115,0 140,0 СКЛАД №02 320-90-90 Комплект акуст.МА-8003 1133 100,0 130,0 СКЛАД №03 320-90-90 Сабвуфер BSD 01 77666 115,0 140,0 СКЛАД №03 320-90-90 Громк.фронтальн. BS 809 12321 190,0 230,0 СКЛАД №01 222-35-33 Сабвуфер BSD 01 778891 115,0 140,0 СКЛАД №01 222-35-33 Комплект акуст.МА-8003 34 100,0 130,0 Представьте, что вы ведете учет не на компьютере, а на бумажном носителе информации. У вас, имеется 5-10 складов и магазинов и 50-100 наименований товаров. Не очень ленивый сотрудник напечатал таблицу, подобную вышеприведенной, а кто-то другой аккуратно меняет значения количеств товаров по мере их продажи и закупки. Кстати, это можно делать и при помощи, например, Excel. А потом некто (видимо, один из менеджеров) решил изменить все и сразу, наименования (даже хотя бы одно!) складов или магазинов, наименования товаров и цены. Простой вопрос: в каком случае даже на бумаге легче и без ошибок можно было бы исправить данные — при учете с одной (последней) таблицей или с тремя, ранее рассмотренными? Этот пример предваряет введение в понятие нормализации отношений в реляционной базе данных. Отношения в реляционной базе данных должны удовлетворять двум основным требованиям: между атрибутами не должно быть нежелательных функциональных зависимостей; группировка атрибутов должна обеспечивать минимальное дублирование данных. Для выполнения этих требований используется нормализация отношений — пошаговый обратимый процесс декомпозиции исходных отношений базы данных на более простые отношения. С процессом нормализации связаны нормальные формы, каждая из которых ограничивает типы допустимых функциональных зависимостей отношений. Если для некоторых атрибутов А и Б всегда каждому значению А соответствует не более одного значения Б, то говорят, что атрибут Б функционально зависит от А. Если неключевой атрибут зависит только от части ключа, то говорят о частичной зависимости. Если неключевой атрибут зависит от всего составного ключа и не находится в частичной зависимости от его частей, то говорят о его полной функциональной зависимости от составного ключа. 552 Глава 20 Если для некоторых атрибутов А, Б и В выполняются условия: Б функционально зависит от А и В функционально зависит от Б, а обратная зависимость отсутствует, то говорят, что В транзитивно зависит от А. Например, цена товара транзитивно зависит от кода товара. Если в отношении каждому значению атрибута А соответствует множество значений атрибута Б, не связанных с другими атрибутами (этого же отношения), то говорят, что атрибут Б многозначно зависит от А. Кодд выделил три нормальные формы1 и предложил правила последовательного приведения отношений к нормализованному виду. Отношение находится в первой нормальной форме, если все неключевые атрибуты функционально зависят от ключа. Для приведения к первой нормальной форме исходные данные (самая общая таблица с данными) разделяются на логически связанные таблицы, в большинстве из которых определяются первичные ключи. В такой совокупности таблиц не должно содержаться повторяющихся данных. Отношение находится во второй нормальной форме, если оно находится в первой нормальной форме и каждый неключевой атрибут функционально полно зависит от составного ключа. Таким образом, для приведения отношения к этой форме нужно поместить в отдельную таблицу данные, которые только частично зависят от первичного ключа. По Кодду следует построить проекцию1 2 без атрибутов, которые находятся в частичной функциональной зависимости от составного ключа, а затем построить проекцию на часть составного ключа и атрибуты, зависящие от этой части. Отношение находится в третьей нормальной форме, если оно находится во второй нормальной форме и в нем отсутствуют транзитивные зависимости неключевых атрибутов от ключа. Целью приведения отношения к третьей нормальной форме является устранение из него данных, не зависящих от первичного ключа. В рамках этой книги мы не будем далее углубляться в теоретические «лабиринты» реляционных баз данных, поскольку на полках книжных магазинов можно найти достаточно специализированной литературы по базам данных. К тому же на практике часто удается сразу сформировать базу из нескольких отношений, отвечающих третьей нормальной форме. С другой стороны, работая с таким языком, как SQL, иногда приходится думать о том, что отношения в базе данных излишне нормализованы, что влияет на производительность СУБД. Базы данных в Excel Простые (состоящие из одной таблицы) базы данных можно создавать в среде Excel. Например, заполните в качестве заголовков полей будущей таблицы базы данных три ячейки листа Excel, как показано на рис. 20.3. Выделите зти три ячейки и выберите Файл | Сохранить как. В окне Сохранение документа в текстовом окне Тип файла выберите, например, DBF 4 (Dbase IV). Закройте Excel-файл без сохранения выполненных изменений. Практически, вы только что получили, быть может, вашу первую базу данных, хотя и в очень «стареньком» для отрасли программирования формате. При помощи двойного щелка на значке записанного dbf-файла запустите Excel3. Обратите внимание (рис. 20.4) на заголовки полей таблицы: они содержат не более 10-ти символов. Это связано с тем, что в формате DBF заголовок поля не 1 В настоящее время определены семь нормальных форм. 2 Проекция — операция реляционной алгебры, создающая новую таблицу путем исключения «ненужных» столбцов из имеющейся таблицы. 3 Для этого нужно, конечно, чтобы Windows «понимал», что dbf-файлы вызывают запуск Excel, а не, например, FoxPro или какое либо другое приложение, обрабатывающее файлы в DBF формате. Введение в базы данных 553 Рис. 20.3 Заголовки будущей таблицы базы данных Е2 Microsoft Excel Книга! Файл Правка £ид Вставка Формат Сервис Данные £>кно ^правка - S X «> ’ Г ’ н Й Щ V К » f* Цена В ~“ 1 [Наименование Количество 2 3 4 ' 5 6 7 8 9 ‘ к < ► >i\Лист1/Лист2/ЛистЗ/| < * Готое NUM С1_____ А может включать более 10-ти символов. Кроме того, заметьте, что все символы заголовков — прописные, и, наконец, книга Excel содержит только один лист: одна таблица — один лист. Рис. 20.4 Заголовки полей таблицы содержат не более 10-ти символов Сразу после загрузки dbf-файла выберите Данные | Форма. На экране появится окно, приведенное на рис. 20.5, которое позволяет добавлять, редактировать и удалять (при помощи кнопок Добавить, Удалить) записи таблицы из трех полей, осуществлять «навигацию» по записям (при помощи кнопок Далее, Назад), использовать фильтрацию данных (при помощи кнопки Критерии). Рис. 20.5 Окно, которое позволяет добавлять и удалять записи таблицы из трех полей, осуществлять «навигацию» по записям, использовать фильтрацию данных 554 Глава 20 Введите в каждое текстовое поле какую-либо информацию и щелкните на кнопке Добавить. Сразу после этого во второй строке Excel-листа появятся введенные вами данные, как показано на рис. 20.6. Рис. 20.6 При введении первой записи во второй строке Excel-листа появятся введенные вами данные Mi*| £аил Оравка Вид Встарка Форцат Сервис Данин X Ч» ‘Ч • < А НАИМЕНОВАН В С ^КОЛИЧЕСТВО ЦЕНА 100 115 Кни1*1 А1 _1 [НАИМЕНОВАН 2 Сабвуфер BSD 01 3 НАИМЕНОВАН f КОЛИЧЕСТВО f ЦЕНА f Новая запись Добавить Назад Далее 9 10' Критерии 2акрь ть 12 13 и 1 » »|\Книга1/ Готово Если вы введете более одной строки (в терминологии баз данных — записи), ваши данные могут быть такими, как приведены на рис. 20.7. Обратите внимание на то, что в верхнем правом углу формы отображается номер текущей записи и общее количество записей ("1 из 14"). Рис. 20.7 В верхнем правом углу формы отображается номер текущей записи и общее количество записей ( 1 из 14") файл Правка Вид 56 НАИМЕНОВАН Сабвуфер BSD 01 Комплект акуст MA800S Усилитель АВ 209 Громк фронтальн BS809 5 Гг.....тг------- .... £ (Player 903KBS " Player АВ 908S CD RW SONY PS 7002 (RP) SONY PS MX чип 7002 SONY PS MX чип 9002 SONY PS NTSC (chip) SONY PS PAL SONY PS PAL MX чип 8 9 10 12 13 и « » >\«нига1/ Готово Вставка Формат С^еис * Ъ ’ W 5» 1000 в с КОЛИЧЕСТВО ЦЕНА 115 100 250 190 195 165 128 120 165 175 175 160 Данные | я KjiMiel НАИМЕНОВАН КОШТ-ЕСТВО (ZDOO 2000 2332 11222 12231 loooi 1000 1000 900 900 800 900 1900 ЦЕНА Удалить j Назад Далее | 2 3 D При помощи кнопок Назад и Далее вы можете перемещаться по записям таблицы. Причем, это очень похоже на перемещение по записям базы данных. Еще больше на работу с записями базы данных похоже использование фильтрации при помощи кнопки Критерии. Щелкните на ней и в текстовом окне КОЛИЧЕСТВО введите > 1000, что означает вывод в форме только тех записей, для которых значения поля КОЛИЧЕСТВО больше 1000. Импорт данных в Excel из баз данных Если мы имеем возможность создавать dbf-файлы в Excel, значит, мы можем также загружать из Excel базы данных (таблицы) формата DBF. Таким образом, Excel очень хорошо «понимает» формат данных такой СУБД, как dBASE, и может как считывать, так и записывать таблицы в формате DBF. С большинством других баз данных Excel имеет одностороннюю связь, т.е. может только импортировать таблицы. Введение в базы данных 555 Для импорта данных в Microsoft Excel следует использовать команду Импорт внешних данных меню Данные, при выборе которой на экран выдается диалоговое окно Выбор источника данных, приведенное на рис. 20.8. В этом окне уже могут находиться элементы подключения, которые вы (или ваши товарищи по совместному использованию персонального компьютера) определяли ранее (см. рис. 20.17). Рис. 20.8 Диалоговое окно для выбора источника данных Для подключения к базе данных Access необходимо в этом окне выделить элемент +Подключение к новому источнику данных и щелкнуть кнопку Открыть (можно, конечно, просто дважды щелкнуть этот элемент). Затем в окне Мастер подключения данных (рис. 20.9) следует выбрать в списке Выберите тип источника данных, к которому нужно подключиться элемент Дополнительно и щелкнуть кнопку Далее. Эти источники могут включать источники данных OLE DB и любые источники данных, поставляемые системным администратором. В мастере подключения данных нельзя фильтровать или объединять данные.) Рис. 20.9 В списке Выберите тип источника данных, к которому нужно подключиться следует выделить элемент Дополнительно и щелкнуть кнопку Далее Мастер „ОДИЛ10ЧСНИЯ данных Мастер подключения данных Мастер поможет подключить удаленный источник данных lW[ выберите тип источника даннык которому нужно подключиться Microsoft SQL Server Службы OLAP Microsoft SQL Server ODBC DSN Oracle Отмена Далее > Остается в появившемся окне Data Link Properties (рис. 20.10) выделить Microsoft Jet 4.0 OLE DB Provider и щелкнуть кнопку Next», чтобы, наконец, увидеть на экра- 556 Глава 20 не окно (в котором можно указать имя mdb-файла1), с одной из таблиц которого необходимо установить связь (рис. 20.11). Рис. 20.10 Для подключения к базе данных Access следует выделить Microsoft Jet 4.0 OLE DB Provider и щелкнуть кнопку Next» W*i Data Link Properlies... fx! Provider | Connection | Advanced AH | S elect the data you want to connect to: MediaCatalogDB OLE DB Provider MediaCatatogMergadDB OLE DB Provider MediaCatalogWebDB OLE DB Provider Microsoft ISAM 11 OLE DB Provider Microsoft Jet 3 51 OLE DB Provider ;м=ск>?*гЫ-н OLE de: Pi.%~ Microsoft OLE DB Provider For Date Mmg Services Microsoft OLE DB Provider for Indexing Service Microsoft OLE DB Provider for Internet Publishing Microsoft OLE DB Provider for ODBC Drivers Microsoft OLE DB Provider for OLAP Services 8 0 Microsoft DLE DB Provider for Oracle Microsoft OLE DB Provider for SQL Server Microsoft OLE DB Smple Provider MSDalaShape OLE DB Provider for Microsoft Directory Services | Hext» 1 OK i Отмена Справка Рис. 20.11 Окно, в котором можно указать имя mdb-файла Data Link Properties fx: Provider Connection Advanced Al! S elect the data you want to connect to OLE 0B Providers) MediaCatalogDB OLE DB Provider MediaCatalogMergedDB OLE DB Provider MeciaCatatogWebOB OLE DB Provider Microsoft ISAM 1 1 OLE DB Provider Microsoft Jet 3 51 DLE DB Provider [Mr 40 fO vB hcAnw Microsoft OLE DB Provider For Data Mining Services Microsoft OLE DB Provider for Indexing Service Microsoft OLE DB Provider for Internet Publishing Microsoft OLE DB Provider for ODBC Drivers Microsoft OLE DB Provider for OLAP Services В 0 Microsoft DLE DB Provider foi Oracle Microsoft OLE DB Piovidet for SQL Server Microsoft OLE DB Smple Provider MSDalaShape OLE DB Provider for Microsoft Directory Services OK , Отмена j Справка Чтобы убедиться в том, что подключение выполнено успешно, необходимо щелкнуть кнопку Test Connection. Если на экране появится окно, похожее на приведенное на рис. 20.12, то все — в порядке. Рис. 20.12 Так Microsoft сообщает пользователю об успешном подключении к источнику данных Microsoft Data Link ... Д Test connection succeeded 1 Файлы Microsoft Access имеют расширение mdb. Введение в базы данных 557 Проверив успешность подключения, следует щелкнуть кнопку ОК и в следующем окне (рис. 20.13) указать таблицу, которая будет загружаться в лист Excel при данном подключении. Рис. 20.13 Здесь следует указать таблицу, которая будет загружаться в лист* Excel при данном подключении i Мастер подмшвчения данных выбор данных Выбор базы данных и таблицы Выберите базу данных и таблицу или куб содержащие нужные данные Выберите базу данных, содержащую нужные сведения Р” Подключение к определенной таблице Имя Описание □T1NACL2C Q T1NC Временная таблица для записи инвентаризациннои ведомости и □ tlnc_temp О t2_dop ПТ2С Отз □ TGROUP Г > Отмена < Назад Готово । В окне Мастер подключения данных-выбор данных можно закрепить за выбранным набором данных некоторое описание. Щелчком на кнопке Готово выбор данных завершается. Рис. 20.14 В окне Мастер подключения данных - выбор данных можно закрепить за выбранным набором данных некоторое описание Mdcicp подключения данных Готово Сохраните файл подключения данных и завершите работу Введите имя и описание файла подключения данных, а затем нажмите кнопку Готово" для его сохранения Обзор Имя файла |(по умолчанию) tmpOl ode Г* Сохранить пароль в файле Описание Поиск ключевых слов Отмена < Назад ( Готово Окно Импорт данных, приведенное на рис. 20.15 позволяет указать место, куда следует поместить данные из выбранного источника. Рис. 20.15 Окно позволяет указать место, куда следует поместить данные из выбранного источника 558 Глава 20 Как можно видеть из рис. 20.16, в mdb-файле хранится обыкновенная таблица, которую мы легко можем расположить в ячейках листа Excel. Рис. 20.16 В следующий раз, когда будет необходимо подключиться к этой же таблице, уже не нужно проходить такой длинный путь Достаточно выбрать Данные | Импорт внешних данных и в окне Выбор источника данных найти результат предыдущих стараний О Microsoft Excel Книга! I* liHjfXj &*| £анл Правка Вид Вставка Формат Сервис Данные Окно Справка - S X D айн SB? & ’ «1 tt XI “ ж к ” А1 - А А в С ‘ 0 Е — 1 |Наиненование )л во Олтов цена Закуп цен а 2 (ЗОС) Cool Boarders BURRRN 100 60 0 3 (3DC) Evolution 200 50 0 4 (3DC) Cool Boarders BURRRN 345 50 0 5 (A) DROM SonyPS30 blocks 200 3 0 6 (A) OROM SonyPS Naki 200 165 0 7 (PC CD) Корабль похищенных душ 290 4 0 I 8 (PC CD) Корлевство снов 200 25 0 9 (PC CD) Красная Шапочка 300 25 0 } 10 (PC CD) Макс и секретная форму 200 25 0 111 (VCD) Белые волки 300 35 0 I 12 ffll Bal 002 (Tuf/Ch&/Ch&2/Ch3r 300 1 9 о К ► и \Лист1 X ЛистЗ X ЛистЗ / HI I ► г Г отово CAPS Следует отметить, что мы не открыли mdb файл, как это возможно с dbf файлом Речь идет о том, что из некоторой таблицы mdb-файла можно считать данные в Excel-лист Рис. 20.17 В следующий раз, когда будет необходимо подключиться к этой же таблице, достаточно выбрать Данные | Импорт внешних данных и указать источник в списке При создании нового источника данных Excel-приложением был создан ODC-файл, который можно открыть для просмотра в обозревателе Microsoft Internet Explorer, а для редактирования использовать Microsoft Excel, блокнот (приложение Notepad) и другие приложения Microsoft Office, если файл не указывает на источник данных OLAP. Папка, в которой находится ODC-файл (вместе с другими файлами'для подключения к источникам данных) указывается в поле Папка диалогового окна Выбор источника данных На рис. 20.18 приведено окно с текстом ODC-файла (частью текста), который только что был создан для импорта таблицы из MDB-файла. Введение в базы данных 559 Рис. 20.18 ODC-файл можно редактировать при помощи текстовых редакторов Microsoft Как видно из рис. 20.18, для редактирования такого файла нужно вообще-то знать его структуру (и язык XML), но чтобы убедиться в том, что это действительно возможно, можно вместо имени таблицы tmpOl, записать имя t2c. После такой замены можно увидеть, что при выборе источника с именем (по умолчанию) tmpOl из окна Выбор источника данных в Excel будет загружаться именно таблица t2c. Аналогичным образом можно выполнить подключение к таблице некоторой базы данных, хранящейся на SQL Server удаленного компьютера. При этом, конечно, у вас должны быть соответствующие полномочия. Следующий пример показывает последовательность подключения к базе данных ServiceCenter, находящейся на сервере с именем VOVA (это — не имя пользователя, но — имя сервера). В окне Выбор источника данных (рис. 20.17) следует выбрать +новое подключение к SQL-серверу. В появившемся на экране окне (рис. 20.19) остается указать имя сервера и пользователя, а также — пароль. Если вы еще не являетесь пользователем SQL Server, то можете установить эту систему даже на свой компьютер или обратиться к системному администратору, если, конечно, это каким-либо образом связано с вашей служебной деятельностью (вряд ли системный администратор сделает вас пользователем SQL Server для удовлетворения вашего любопытства). Рис. 20.19 Здесь необходимо указать имя сервера и пользователя, а также — пароль MdGinp подключения данных Подключение к серверу баз данных Введите сведения, требуемые для подключения серверу баз данных 1 Дмя сервера, Гуо'уд' 2 Учетные сведения Г" Использовать систему безопасности windows 2000 (• Использовать следующие имя пользователя и пароль Имя пользователя |6нм"' Пароль' [♦*** Отмена < Назад | Далее » После щелчка на кнопке Далее (в окне Мастер подключения данных) в следующем окне (рис. 20.20) можно увидеть все таблицы указанной базы данных. 560 Глава 20 Рис. 20.20 В этом окне можно увидеть все таблицы базы данных и выбрать ту, данные из которой будут помещаться Excel-лист Мастер подключения данных -выбор данных Выбор базы данных и таблицы Выберите базу данных и таблицу или куб, содержащие нужные данные. Выберите базу данных, содержащую нужные сведения: IserviceCenter ..................... ......... $7 Подключение к определенной таблице1 * Владелец Описание Изменен Создан dbo dbo dbo dbo dbo dbo dbo Имя Ш Детали О Доступ О Изделия ШП Инвентаризация! Ей Инвентаризация2 ЕЙ Неисправности 10/29/2002 5 16 58 РМ 9/11/2002 10.28 28 AM 10/30/2002 5.39:58 РМ 9/10/2002 7.29.52 РМ 9/10/2002 7 29:54 РМ 10/30/2002 12:29.01 РМ 10/19/2002 6'28.55 РМ Тип л TABLE TABLE TABLE TABLE TABLE TABLE TABLE v Отмена < Назад I ^алее > Готово 1 В следующем окне можно изменить имя ODC-файла, если имя по умолчанию недостаточно «красиво», и описать созданное подключение. Рис. 20.21 В этом окне можно изменить имя ODC-файла и описать созданное подключение Мастер подключения данных -1 отово Сохраните файл подключения данных и завершите работу Введите имя и описание файла подключения данных, а затем нажмите кнопку "Готово" для его сохранения. Обзор .. Имя файла: |¥О¥А ServiceCenter ОрганПродаж.одс Описание: >угш поОзВагВяям понять, к чему ьыгЩкййтЙ Сохранить пароль в файле Поиск ключевых слов: Отмена | < Назад ; Готово Окно Импорт данных уже не относится к созданию нового подключения и просто помогает указать место для размещения импортируемых данных. Рис. 20.22 Окно Импорт данных помогает указать место для размещения импортируемых данных На рис. 20.23 показан результат импорта данных из таблицы базы данных, находящейся на SQL Server локальной сети. Введение в базы данных 561 Е? Microsoft Excel - Книга! -НГх- Файл Прайса Вид Вставка Формат Сервис Данные Окно Справка ’ - Я X □ в а "4 v 'J «> - < ь - 4. ДО ” ю - | ж к чк - <*» - д v v А1 ▼ А А В CD Е —‘ 1 |КодИ|>гПрод|НдиОргП1>од АдрИндекс АдрКраиОоласгь АдрГород АдрУл 2 1 Нет сведении о продаже 3 759343 000 ТЕЛЕТЕХНИКА" Новосибирск ул Дик 4 759502 ИП Савенко Сергеи Васильевич Росто на Дону ул Фр 1 5 759585 ПБОЮЛ Каменский А Ю Ростов на Дону ул Фр 6 759780 ПБОЮЛ Валерьянова Л Г Ростов на Дону ул Нел 7 760067 Нет сведении о продаже 8 760169 ПБОЮЛ Першуков Игорь Викторович м Новомосковск ул Мос 9 760336 ООО "Навигатор В’ Москва ул Дор 10 760410 Аэлита Таганрог ул фр' 11 760568 м н Дюал Новосибирск Пр KL 12 760694 ЗАО РИККОН Москва 13 760773 ТЦ Электронный Раи ПБОЮЛ Удоденко Москва 14 760861 000 ВИКТОРИЯ (отдел компьютеров) Санкт Петербур ; 15 761006 Предприниматель Колесников А М Калуга ул Либ И 4 ► ► \Лист1/Пист2 ^ПистЗ / 1<| 1 иг Готово Рис. 20.23. Результат импорта данных из таблицы базы данных, находящейся на SQL Server локальной сети Как вы можете заметить, кроме создаваемых вами источников данных, в окне имеются дополнительные источники: Курсы валют MSN MoneyCentral Investor, Биржевые индексы MSN MoneyCentral Investor и Биржевые котировки MSN MoneyCentral Investor. Рис. 20.24 В Excel-лист можно загрузить данные, используя встроенный источник Курсы валют MSN MoneyCentral Investor О Microsoft Excel - КнигИ файл Правка Вид Вставка Формат Сервис Данные Окно Справка - в X DB Currency Rates Provided by MSN MoneyCentral Investor Cl ck here t j vibit MSN Mo ~ieyOr tial i westor 2 3 ElName In USS Per USS 5 r j ntire Г г 0 28249 3 54 6 z нЧ alnn Dollar 0 5642 1 772 7 A jc-triar ~'rhill nej 0 07387 13 538 BjiWaiibanfi 0 0252 39 60[ 9 Bahraini D nar 2 6525 0 377 10 Bolivian Boliviano 013558 7 376 11 Brazilian Real 0 28265 3 538 12 Bt t oh Pjund 1 5913 0 628 13 C anadtan Pollcti 0 63894 1 565 14 Chilean Peso 0 00141 ( 711 2 и < ► н\Лист 1/ли:т2/Листа/ Готово l«' А А С D Е В Создание базы данных в Access Обычная технология разработки приложений для баз данных с использованием систем программирования, не являющихся системами управления базами данных (СУБД), заключается в том, что собственно база данных (таблицы, связи между ними) создается при помощи интегрированной среды одной из СУБД, а интерфейс и код управления данными — при помощи Visual-системы программирования. Для Visual Basic более «родным» является mdb-формат, который поддержи вается СУБД Access. Поэтому в этом разделе мы рассмотрим вопросы создания баз данных в интегрированной среде Access. 562 Глава 20 bj Microsoft Ixc ol Файл Правка £ид Вставка Формат Сервис Данные Окно справка П О R*. X <? < И 3 ” 18 ’ [*'* А1 ▼ £ Stock Quotes Provided by MSN Money MStock Quotes Provided by MSN Mone 2 Click here tn \isit MSN Morey 3 DOW JONES INDUSTRIAL 4 AVERAGE INDEX 5 DOW JONES COMPOSITE IN^FX . 6 UoyNpnosW^rort Идк 7 Dow Jones Utility lrde< i 9 Frankfurt 9 SEISE. 10 Hong Kong Hang Seng AMEX INTERACTIVE WEEK 11 INTERNET lNDEX II « > и\Лист1 \Лист2/ПистЗ/ Chart Chart Chart ОШ Chart Chart Ch&l News Mews News News News News News News Last 8537 13 2378 79 2346 88 195,87 3079,1 4034 6 9770 6 81,34 Previous Close 8586 24 2400 65 2350 62 202 28 3155 66 4081 3 9844 3 82 49 High 8668 91 2420,64 2382 21 201 95 3174 39 4091 6 9796 4 83,74 Low 8498 92 2371 84 2331 31 195,84 3072 81 4026 2 9708 1 80,86 Volume 250 130 000 _0 0. Cl _0 _0 0 Готово Рис. 20.25. В Excel-лист можно загрузить данные, используя встроенный источник Биржевые индексы MSN MoneyCentral Investor СУБД Access позволяет разрабатывать законченные приложения с использованием баз данных. При этом и таблицы со всеми связями между ними, и код для обработки данных в этих таблицах находятся в одном mdb-файле. Кто-то считает, это удобным, а кто-то — наоборот. Мне больше нравится хранить данные отдельно от кода. Например, если база содержит данные, зависящие от текущего месяца и года (накладные продаж и прочее), то удобно хранить такие данные не только отдельно от кода, но и отдельно от других таблиц в отдельном файле. Представьте себе файл с базой данных, которая будет непрерывно расти с каждым месяцем. Ее трудно архивировать, переносить на съемных носителях, ну а если уж файл «разрушится», так со всеми данными за все месяцы и годы. Кроме недостатка, связанного с хранением данных и обрабатывающего кода в одном месте, не совсем удобен способ создания этого кода в Access. Эта система изобилует специальными приемами и конструкторами, которыене только создают не всегда понятный код, но и требуют постоянной тренировки. Это очень похоже на программирование с использованием машинных команд. В случае длительного перерыва в работе можно потерять навыки, приобретенные упорным трудом. Хотя следует отметить, что разрабатывать приложение в рамках Access можно и без использования встроенных конструкторов, а просто писать код на языке Visual Basic, как это делается для Excel и Word. В этом случае VB-код будет отличаться от VB-кода для Excel и Word (и других приложений Microsoft Office) только в методах доступа к базам данных, поскольку Access — это СУБД. Бизнес-задача: разработка базы данных для учета движения товаров на складе В этом разделе мы рассмотрим вопрос создания базы данных, как набора взаимосвязанных таблиц, но предварительно попытаемся как можно лучше понять предметную область. Итак, у нас имеется склад, с товарами которого выполняются следующие операции: 1) регистрация (как нового), 2) прием с другого склада, 3) прием из магазина (оптового или розничного), 4) возврат от (оптового) покупателя, 5) оптовая продажа, 6) отпуск на другой склад, 7) отпуск в магазин (оптовый или розничный). При отпуске (приеме) товара создаются накладные, с которыми производятся манипуляции, такие как аннулирование с восстановлением состояния склада, удале Введение в базы данных 563 ние (без восстановления состояния склада), выделение части накладных (за указанный период времени) из общей базы для передачи в центральный офис, выделение накладных отпуска на некоторые склады для передачи их на эти склады с целью автоматической регистрации. Система должна также создавать определенные отчеты, например, по денежным суммам в накладных, инвентаризационную1 ведомость и, быть может, товарный отчет о движении товаров согласно накладным. Структурное описание бизнес-процессов1 2, выполняемых на складе, приведено на рис. 20.26. Рис. 20.26. Структурное описание бизнес-процессов, выполняемых на складе Согласно этой схеме, полученной при помощи системы BPWin3 * * * * В, основными функциями бизнес-процессов на складе: являются отпуск и принятие товаров, а также учет товаров в виде инвентаризационной ведомости и накладных. Эти функции (в соответствии с правилами функциональных SADT-диаграмм) изображены в виде блоков. На диаграмме, кроме блоков с основными функциями, имеются дуги, которые определяют для бизнес-процессов: слева — входы, справа — выходы, снизу — средства (на данной диаграмме не указаны) и исполнителей, сверху — управление. Например, для формирования инвентаризационной ведомости необходимо иметь некоторую таблицу с наименованиями (и, может быть, ценами) товаров и знать о том, какие именно товары в данный момент имеются на складе. В процессе же отпуска товаров можно воспользоваться инвентаризационной ведомостью, чтобы, во-первых, зря не искать отсутствующий товар и, во-вторых, оформить выдачу товара в соответствии с его точным наименованием и ценой. При 1 Вместо этого термина в книге иногда используется термин «инвентарная» с целью сокращения длины названия таблиц. 2 К сожалению, автор не является специалистом в области структурного анализа и проектирования, поэтому представленная структура может содержать ошибки. 3 BPWin — система описания и моделирования бизнес процессов, являющаяся одним из инстру- ментальных средств Методологии структурного анализа и проектирования (SADT — Structu- red Analysis & Design Technique). Согласно исследованиям разработчиков SADT — Дэвида А. Марка и Клемента МакГоуэна, наибольший процент ошибок при разработке программных систем возникает в процессе анализа и проектирования и гораздо меньший — при реализации. В тоже время исправление ошибки на стадии проектирования стоит в 2 раза, на стадии тестирования — в 10 раз, а на стадии эксплуатации — в 100 раз дороже, чем на стадии анализа. 564 Глава 20 этом также необходимо однозначно указать место, куда товар отправляется, для чего желательно иметь некоторый справочник, обозначенный на диаграмме как Таблица контрагентов. Процесс отпуска товара может иметь следствием создание накладной, которая является одним из документов о том, что товар не просто «ушел» со склада и исчез из инвентаризационной ведомости, а был передан в известное место в указанном количестве и с соответствующей ценой. После каждой операции с товарами требуется корректировка инвентаризационной ведомости, на что указывают дуги, связывающие выходы блоков 2 и 3 с управлением блока 1. Далее мы будем рассматривать блоки диаграммы более подробно, а сейчас нас интересуют таблицы базы данных, которые необходимы для разработки информационной системы, поддерживающей бизнес-процессы, выполняемые на складе. Сейчас можно четко обозначить следующие из них: Таблица товаров, Инвентаризационная ведомость, Таблица контрагентов и Накладные (Заголовки накладных и Спецификации накладных). Перед созданием базы данных хорошо было бы представить графически ее таблицы и связи между ними. Современные средства разработки баз данных не только позволяют представлять таблицы, но и ограждают разработчика от некоторых ошибок. На рис. 20.27 (логический уровень) и 20.28 (физический уровень) представлена схема базы данных1, состоящая из 6-ти таблиц, причем некоторые из них связаны при помощи ключевых полей. Инвентаризационная ведомость Рис. 20.27. Схема базы данных (логический уровень) из 6-ти таблиц Таблица товаров (Товары) включает поле Код товара, которое будет содержать уникальное для каждого товара значение, однозначно определяющее товар (первичный ключ)1 2. Для этого поля нам достаточно 12-ти символов. Поле Наименование товара описывает товар; его длина зависит от действительных наименований товаров. Будем считать, что 30-ти символов нам достаточно. Таблица Инвентаризационная Ведомость (Инвентарная_ведомость) содержит два внешних ключа3 (Код товара, Код склада) для связи с таблицами Товары и Склады и поле для указания количества товара. Поле Код склада необходимо для обслуживания одной базой данных нескольких складов. Если склад — один, в этом поле нет необходимости. 1 Схема создана в системе ERWin. 2 Система ERWin отделяет ключевые поля от не ключевых одинарной разделительной линией. 3 Система ERWin помечает внешние ключи символами (FK) — Foreign Key, — а блоки, обозначающие таблицы, содержащие внешние ключи, отображаются с закругленными углами. Введение в базы данных 565 Инвентарная_ведомость КодТовара VARCHAR(12) КодСклада SMALLINT Товары_________________________ КодТовара VARCHAR(12)__________ НаименованиеТовара VARCHAR(30) ЦенаОптовая DOUBLE PRECISION ЦенаРозничная DOUBLE PRECISION НаклСпецификации________________ КодТовара VARCHAR(12)___________ Дата DateiTirne Номер INTEGER Количество Long Integer ЦенаОлерации DOUBLE PRECISION N.....—........-.......... ...... Количество INTEGER НаклЗаголовки КодКАгента SMALLINT КодСклада SMALLINT Дата DateTTime Номер INTEGER ТипНакладной INTEGER > ............. t ..Л Склады КодСклада SMALLINT____________ НаименованиеСкпада VARCHAR(4 Адрес Text(18) Контрагенты____________________ КодКАгента SMALLINT____________ НаименованиеКАгента SMALLINT Адрес Text(20) Рис. 20.28. Схема базы данных (физический уровень) из 6-ти таблиц Таблицы Склады и Контрагенты содержат подобные поля (включая первичные ключи) и при некоторых дополнительных строках кода в программном обеспечении разрабатываемой системы могли бы быть объединены в одну таблицу. Для учета накладных удобно1 иметь две таблицы (Заголовки накладных и Спецификации накладных), в одной из которых могут храниться списки товаров (количества, цены) — спецификации, а в другой — общая для каждой накладной информация (коды складов и контрагентов, тип накладной) — заголовки. На рис.20.28 для этой цели изображены блоки с таблицами НаклЗаголовки и НаклСпецификации. В этих таблицах, как и в таблице Инвентарная_Ведомость, поле КодСклада необходимо для обслуживания одной базой данных нескольких складов. Если склад — один, в этом поле нет необходимости. Создание таблицы в Access Запустите Access, укажите, что создается новая база данных, и введите имя файла, в котором она будет сохранена (например, dbs.mdb). Если вы все сделаете правильно, то получите на экране окно, изображенное на рис. 20.29. Выберите пункт Создание таблицы в режиме конструктора, и на экране появится окно, показанное на рис. 20.30. Теперь можно создать таблицу в открытой базе данных. В столбце Имя поля укажите имя поля, в столбце Тип данных — тип. Для начала создадим таблицу Товары (рис. 20.31). В нижней части диалогового окна имеются настройки для дополнительного описания свойств атрибутов. Обратите внимание на изображение ключа слева от имени поля КодТовара. Это означает, что поле КодТовара является первичным ключом. В Microsoft Access очень просто указать ключевое поле: достаточно сделать в режиме конструктора нужное поле текущим и щелкнуть кнопку Ключевое поле на панели инструментов, которая, как вы можете заметить, меняет набор своих кнопок при смене режима работы Access. Если вы не указываете ключевое поле, Access преложит создать специальное ключевое поле. Чаще всего следует отказываться от такого предложения. 1 Удобно для хранения наименьшего количества невычисляемой информации, но не очень удобно для обработки базы с использованием SQL запросов. 566 Глава 20 Рис. 20.29 Новая база данных в Access Ы Microsoft Access файл Правка Вид Вставка Сервис Окно Справка п к? «а '? - ил - ®. dbs ; Раза ;цшных (с|х>рм<11 Access 7000) £ЦОткрыть ^Конструктор □Создать -а > j';’ коздант табл»w в режиме конструктора! Q Таблицы | Создание таблицы с помощью мастера _ея _ ® j Создание таблицы путем ввода данных запросы “* з Формы я Отчеты 4j) Страницы 2 Макросы Модули ' Г руппы >1 Избранное Г отово Рис. 20.30 Создание таблицы в режиме конструктора На рис. 20.32 приведена таблица Инвентарная_ведомость в режиме конструктора Access. Подобно выглядят и остальные таблицы, которые здесь не приводятся. В Access имеется замечательная возможность связывания таблиц базы данных. После того как разработчик укажет необходимые связи (в том числе и их типы), СУБД будет не только более эффективно «работать» с записями в таблицах, но и будет защищать данные от неправильного их использования. Для установления связей между таблицами можно щелкнуть кнопку Схема данных на панели инструментов или выполнить команду Сервис | Схема данных (или воспользоваться контекстным меню). Если ранее для данного набора таблиц схема данных не создавалась, на экране появится пустое окно Схема данных, в которое сначала следует помесить необходимые таблицы. Хотя для установки связей Введениевбазь1даннь1х 567 Рис. 20.31 Только что созданная таблица в режиме конструктора Microsoft Access Имя поля Я---------- i__ НаименованиеТовара |__ЦенаОптовая :_ЦенаРозничная кодТова^ _____I Тип данных | Описание | л Текстовый । Текстовый Денежный Денежный v Свойства поля । Подстановка | 12 Общие Размер поля Формат поля Маска ввода Подпись Значение по умолчанию Условие на значение Сообщение об ошибке Обязательное поле Пустые строки Индексированное поле Сжатие Юникод Режим ХМЕ Режим предложений IME Нет Да Да (Совпадения не допуо Да Нет контроля Нет можно помещать в окно Схема данных только связываемые таблицы, следует в целях документирования разработки помещать все таблицы базы в это окно. Поместить таблицы в окно позволяет диалог Добавление таблицы, который можно вызвать из контекстного меню окна Схема данных (рис. 20.33). Рис. 20.32 Таблица без ключевых полей После добавления всех таблиц к окну Схема данных оно может быть похоже на то, которое приведено на рис. 20.34. Для установления связей между таблицами, следует расположить таблицы в окне Схема данных так, чтобы связные таблицы (отношения) располагались между связываемыми объектными, например, как это представлено на рис. 20.35. Чтобы установить связь с таблицами Товары и Инвентарная_ведомость, щелкните на атрибуте КодТовара таблицы Товары и при нажатой левой кнопке мыши протащите курсор до аналогичного атрибута таблицы Инвентарная_ведомость (форма курсора должна заметно измениться). После этого отпустите кнопку мыши. На экране появится диалоговое окно Изменение связей (рис. 20.36), в котором вам следует (как минимум) установить флажок Обеспечение целостности данных. На рис. 20.37 представлен результат установления связи между таблицами Товары и Инвентарная_ведомость, а на рис. 20.38 — результат установления всех необходимых связей (см. также рис. 20.27 и 20.28). 568 Глава 20 Рис. 20.33. Поместить таблицы в окно позволяет диалог Добавление таблицы, который можно вызвать из контекстного меню окна Схема данных Рис. 20.34. Так может выглядеть окно Схема данных после добавления к нему всех таблиц рассматриваемой базы данных Рис. 20.3S Для установления связей между таблицами, следует расположить таблицы в окне Схема данных так, чтобы связные таблицы (отношения) находились между связываемыми объектными Ej Microsoft Access [Схем* данных] Файл Правка £ид Связи Сервис фено Справка °П 8° §81 х С а ’ © D а#И « I •КодТовара [Количество - s х :КодСклада ^НаименованиеСклада :Адрес I КодТовара НаймемсваниеТовара ЦенаОптовая |ЦенаРозничная Дата Номер КодСклада КодТоеера Количество |Д<зта Номер КодСклада КодКАгента ТипНакладной [КодКАгента [НаимемованиеКАгента ! ;АДрес Готово Введение в базы данных 569 Рис. 20.36 В окне Изменение связей вам следует (как минимум) установить флажок Обеспечение целостности данных Рис. 20.37 Результат установления связи между таблицами Товары и Инвентар-ная_ведомость Рис. 20.38 Результат установления всех необходимых связей (см также рис 20 27 и 20 28) Готово Другие способы создания базы данных Для создания базы данных Jet можно воспользоваться программой Visual Data Manager, которая поставляется в изданиях Visual Basic Professional и Enterprise и позволяет создать базу данных, совместимую с Microsoft Access. При этом этот пакет позволяет также на основе структур баз данных создавать интерфейсные формы для использования с Visual Basic. 570 Глава 20 В последнее время появляется все больше средств автоматизации проектирования и разработки баз данных, которые позволяют сопровождать проект от этапа проектирования до создания кода для приложения баз данных. Несмотря на значительные преимущества этих систем по сравнению с традиционным кодированием, чтобы научиться работать с такими системами, следует сначала освоить обычную технику (по крайней мере, для понимания того, какого результата следует ожидать от автоматизированного средства). Самым эффективным способом создания базы данных, конечно, является создание базы при помощи кода, в том числе и VB-кода. Этого не нужно делать в процессе начального изучения баз данных, но, когда вы научитесь работать с ними достаточно уверенно, обязательно освойте технику создания баз данных из VB-кода. Занесение данных в таблицы баз данных В таблицы базы данных формата mdb вносить данные можно либо при помощи какой-либо СУБД, либо посредством кода. Проще всего занести данные в mdb-файл, если использовать Microsoft Access, в котором, как мы уже выяснили, легко и создаются таблицы базы данных. Даже когда вы научитесь заносить данные в таблицы при помощи специализированных приложений или из кода на языке Visual Basic (или каком-либо другом), все равно при разработке того или иного приложения вам часто придется заносить (или редактировать) данные при помощи Microsoft Access. Иногда нужно будет просто просмотреть данные, чтобы понять, почему приложение «не хочет» работать. Для внесения данных при помощи Microsoft Access дважды щелкните в главном окне (рис. 20.39) на имени нужной таблицы, например, Склады. При этом появляется окно Склады: таблица (рис. 20.40), в котором и производится добавление, удаление и редактирование данных (рис. 20.41). Работа с таблицей в этом окне проста и интуитивно понятна, поэтому мы не будем подробно ее рассматривать. Рис. 20.39 Для внесения данных дважды щелкните в главном окне на имени нужной таблицы dbs : бдел данных (({юрмат Access 2000) Объекты ^Создать -о §!! 23 Склады 3 Товары а] 1 Создание таблицы в режиме конструктора 1 Создание таблицы с помощью мастера ' 1 в Таблицы Запросы ! Создание таблицы путем ввода данных Инвентарная_ведомость КонтрКдгента 13 Формы и Отчеты . НаклЗаголовки Страницы : НаклСпецификации Г руппы < > Рис. 20.40 Здесь и производится добавление, удаление и редактирование данных Введение в базы данных 571 Рис. 20.41 Работа с таблицей в этом окне проста и интуитивно понятна В Сн'Пщы: таблица | КодСклада ^Наименование Адрес * 0001 ♦ 0002 Первый склад Второй склад ул Ленина, 95 ул Советская, 77 ► * 0003 Третий склад ул Гайдара 122 Запись И | 11 « ....».1 .и > | из 4 В следующей главе нам понадобятся заполненные таблицы Товары, Склады, Инвентарная_ведомость и другие. Там же и будет приведена информация, которую можно занести в них для демонстрации примеров. Гйвю 21 Основы языка SQL • Конечно, описать язык SQL в рамках одной главы невозможно. Ему посвящено много книг — и больших, и небольших. Эта глава предназначена для того, чтобы показать, насколько полезен язык SQL при работе с базами данных, разрабатываемыми в рамках Microsoft Office. Вам в дальнейшем нужно будет обязательно приобрести хорошее пособие по SQL для углубленного изучения этого языка, необходимого для разработчика баз данных. SQL — это язык структурированных запросов (Structured Query Language) к реляционным базам данных. История SQL тесно связана с историей развития реляционных баз данных. В 1974-1975 годах был создан первый прототип реляционной СУБД. Кроме разработки самой СУБД, в рамках проекта System/R в компании IBM проводилась работа над созданием языка запросов к базам данных. Первый язык запросов получил название SEQUEL — Structured English Query Language. Вторая реализация проекта System/R была установлена на компьютерах нескольких заказчиков IBM с целью опытной эксплуатации в 1978-1979 гг. В этой реализации язык запросов имел уже название SQL, но до сих пор еще можно услышать от пользователей старое название этого языка. В 1982 году компания IBM начала поставки на рынок коммерческого продукта SQL/Data System, а в 1983 году объявила о создании версии SQL/Data System для операционной системы VM/CMS. В 1983 году IBM выпустила новую реляционную СУБД — Database 2 (DB2). Благодаря влиянию компании IBM на рынок вычислительных систем SQL DB2 стал фактическим стандартом языка баз данных. Во второй половине восьмидесятых годов резко увеличилась производительность реляционных СУБД и с развитием реляционных технологий связывались большие надежды. Появились, в частности, новые версии СУБД Ingress и Oracle с производительностью, в два-три раза превышающей производительность предыдущих версий. Росту производительности СУБД способствовало и увеличение общего быстродействия компьютеров. Опубликование в 1986 году стандарта SQL (ANSI/ISO) официально утвердило SQL как стандартный язык реляционных СУБД. С появлением более мощных персональных компьютеров и объединением их в локальные сети возникла необходимость в новых СУБД. Поставщики таких СУБД снова стали ориентироваться на SQL-технологии. И, наконец, SQL стал ключевой частью архитектуры клиент/сервер. Первоначально SQL фирмы IBM имел простой синтаксис, но на протяжении нескольких лет производители программного обеспечения в области систем управления базами данных добавляли к своим реализациям новые возможности, многие из которых вошли в стандарты ANSI SQL. Версия языка ANSI SQL была принята организацией International Standards Organization (ISO), отделением ООН со штаб-квартирой в Женеве и комитетом International Electrotechnical Commission (IEC) как продукт ISO/IEC9075:1992 или язык баз данных SQL (SQL-92). Отдельный стандарт ANSI X.3.168-1989 определяет встроенный язык баз данных SQL(SQL-89). Современные СУБД поддерживают SQL-89 и многие дополнения из SQL-92. Кроме того, большинство СУБД имеют свои ключевые SQL-слова для создания патентованных диалектов SQL, таких как Transact-SQL (сервера SQL Server) или SQL Jet. В этой и следующей главе мы будем использовать SQL Jet и Transact-SQL, не уделяя внимания их отличиям от ANSI SQL-92. Отметим, что историческое название SQL не совсем точно отражает суть этого языка, поскольку он предназначен не только для построения запросов (если, ко Основыязыка SQL 573 нечно, под «запросом» понимать только извлечение информации из базы данных). Сейчас SQL позволяет реализовать все функции СУБД: организацию данных, извлечение информации, модификацию данных, управление доступом, совместное использование данных, обеспечение целостности данных. Типы команд SQL . В ANSI SQL имеется шесть основных типов команд: команды языка определения данных [data definition language — DDL) позволяют создавать новые таблицы в базе данных, добавлять индексы и т.д.; основными командами языка определения данных являются: CREATE TABLE Создать таблицу ALTER TABLE Модифицировать таблицу DROP TABLE Удалить таблицу CREATE INDEX Создать индекс ALTER INDEX Модифицировать индекс DROP INDEX Удалить индекс команды языка обработки данных [data manipulation language — DML) используются для добавления, корректировки и удаления строк в таблицах и включают: INSERT Вставить данные в таблицу UPDATE Обновить данные DELETE Удалить данные команда языка запросов данных {data query language — DQL) (единственная команда) используется для получения данных из таблиц и определения формы представления этих данных: SELECT Выполнить запрос из таблиц базы команды языка управления данными {data control language — DCL) определяют доступ отдельных пользователей и групп пользователей к объектам базы данных посредством полномочий, предоставляемых и отменяемых командами: GRANT Предоставить привилегии REVOKE Отменить привилегии команды языка обработки транзакций {transaction processing language — TPL) обеспечивают обновление всех строк, используемых в операторе DML, и включают следующие команды: BEGIN TRANSACTION Начать транзакцию COMIT TRANSACTION Завершить транзакцию SAVE TRANSACTION Создать точку сохранения внутри транзакции 574 Глава 21 команды языка управления курсорам (cursor control language — CCL) выполняют операции с отдельными строками одной или нескольких таблиц и включают: DECLARE CURSOR, FETCH INTO и UPDATE WHERE CURRENT. Создатели СУБД, в общем-то, не обязаны поддерживать все команды SQL-92, и можно с уверенностью утверждать, что, практически, нет ни одной коммерческой СУБД, которая реализовала все команды SQL-92. В частности, в SQL Jet не поддерживаются никакие зарезервированные слова команд DCL и CCL. SQL в Visual Basic В Visual Basic (и Microsoft Access) SQL применяется в основном для выполнения запросов. Используя SQL-запросы можно выбирать из таблиц базы данных только необходимые записи, можно манипулировать структурой базы данных. При этом мы можем получить доступ не просто к одной таблице, а к сложной выборке из связанных между собой таблиц или наборов данных. SQL-запросы можно также применять в приложениях, использующих объектные модели DAO, RDO1 или ADO. Кроме того, SQL как стандартный способ управления базами данных реализован во многих СУБД, включая Microsoft Access и SQL Server. Конечно, у нас нет возможности в этой книге для систематического изложения языка SQL, поэтому мы рассмотрим только некоторые аспекты использования SQL-запросов в VBA приложениях с целью пробудить у читателя интерес к изучению SQL. Инструкция SELECT Для работы с базами данных в Visual Basic используется язык запросов, включающий единственную инструкцию SELECT. Рассмотрим некоторые вопросы, связанные с ее использованием. Синтаксис (неполный) инструкции (команды) SELECT в SQL Jet следующий: SELECT [ALL | DISTINCT | DISTINCTROW | TOP] { * I table.* | , [table.]fieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]) FROM tablel [tablelAlias] [, table2 [table2Alias] [, ...] [WHERE criteria] [GROUP BY groupfieldlist] [HAVING groupcriteria] [ORDER BY fieldl [ASC I DESC ][, field2 [ASC | DESC ]][, ...]]] [WITH OWNERACCESS OPTION] Инструкция SELECT включает следующие основные элементы: SELECT означает, что из некоторых таблиц базы данных необходимо выбрать набор (таблицу данных). Необязательные слова ALL, DISTINCT, DISTINCTROW и TOP называются предикатами (predicates) и определяют выбор следующим образом: ALL указывает, что в набор передаются все строки (даже с дублируемыми значениями); DISTINCT указывает, что в набор передаются только недублированные строки; DISTINCTROW указывает, что в результирующий набор будет включена каждая строка, в которой есть отличие в значении любого из полей исходных таблиц (а не только полей, указанных для отображения в операторе SELECT); ТОР используется для отображения некоторого количества (точного или в процентном отношении) начальных или конечных записей из результирующего набора. 1 Модель RDO в данной книге не рассматривается. Основы языка SQL 575 Список { * | table.* | [table.Jfieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]} (фигурные скобки здесь обозначают список) состоит из имен полей таблиц(ы) запроса. Звездочка (*) означает выбор всех полей таблицы. Если в запросе указывается несколько таблиц, то для определения поля используется наименование таблицы, отделяемое от имени поля точкой (.). Поле может получать «алиасное» имя при помощи ключевого слова As. • После слова FROM указываются таблицы, из которых выбираются ранее указанные поля. Здесь tableexpression — это имя таблицы (или таблиц), содержащей данные, externaldatabase — имя базы данных, если не используется текущая база. Остальные элементы инструкции SELECT мы будем рассматривать по мере изучения более сложных запросов к таблицам. Для примеров использования SELECT будем работать с базой данных, которую мы рассматривали в конце предыдущей главы. Для изучения работы SELECT, как и других инструкций, легче всего использовать Access, тем более что именно в нем мы и создали нашу базу данных. Заметим, что при работе с Visual Basic мы будем использовать инструкции SQL немного по-другому. Чтобы начать работу с инструкциями языка SQL, необходимо заполнить таблицы некоторой информацией. Причем, пока мы не рассматривали возможности СУБД по вводу данных при помощи специально разработанных диалоговых окон, следует сделать это при помощи Access. (О том, как можно заполнить таблицы в Access вручную, кратко описано в предыдущей главе.) Для рассмотрения самых простых запросов при помощи инструкции SELECT нам достаточно будет трех таблиц, представленных на рис. 21.1-21.3. Рис. 21.1 Таблица Товары с данными to Товары : ыб.1иц<5 i- '[ч® | КодТовара НаименованиеТовара | ЦенаОптовая | ЦенаРозничная| ♦ 006019170049 (S) Tazmania ЗО.ООр Зб.ООр ♦ 036019164741 (S) Cool Spot 42,ООр 49,00р * 006019165803 (S) Road Rush II 42,ООр 49,ООр ► ♦ 028019095823 (VCD) Older Marouani 90,ООр 105,ООр ♦ 028019100222 (VCD) Голая мишень ЭО.ООр 105,00р ♦ 028019100018 (VCD) Whami The best of 105,00р 123,ООр „„ ♦ 010415090732 (VCD) Пастырь 111,00р 130,ООр ♦ 010415090937 (VCD) Шоссе в никуда 120,00р 140,00р * 010428144348 (VCD) Доберман 135,00р 158,00р ♦ 010414114438 (VCD) Патриот 138,00р 161,ООр ♦ 186100175232 (3DC) Super Runabout 750,00р 875,ООр I— * 174500175521 (3DC) Star Gladiator 2 750,ООр 875,00р * 174500175359 (3DC) Street Fighter 3 Wimpact 750,00р 875,ООр „| Запись: Н | < j| 4 ► | >1 |»Ж| из 13 Рис. 21.2 Таблица Склады с данными Ни (.клады : таблица Ий® | КодСклада | НаименованиеСклада | Адрес * 1958 СКЛАД (Брак) ул Ленина,95 * 1508 СКЛАД (МНЕВНИКИ) ул Советская, 77 + 0429 СКЛАД (Мультимедиа) ул Гайдара,122 9 + 1518 СКЛАД (НЕЙРОН) ул К Маркса, 1 Запись: Н1 4 ► I »11»*1 из 4 Напомним, что две из этих таблиц (Товары и Склады) являются объектными: они описывают такие объекты, как товары (наименования, цены) и склады (наименования, адреса). Таблица Инвентарная_ведомость указывает, где (на каком складе) и в каком количестве находятся товары. 576 Глава 21 Рис. 21.3 Таблица Инвентарная_ведомость с данными ! аблица % Bl М 1 1 II 1 1 1 1 [ 1 1 'll 1 Г 1 1 0429 006019165603 1506 006019165603 1516 006019165603 0429 006019170049 1506 006019170049 1518 ОЙ6019170049 1506 010414114438 1958 010414114438 1506 010428144348 1958 010428144348 0429 036019164741 1506 036019164741 1518 036019164741 1506 174500175359 1958 174500175359 0429 174500175521 1958 174500175521 0429 186100175232 1958 186100175232 3000 200 1200 1000 500 1000 400 3300 800 4200 2000 600 1400 600 2200 1500 2300 2000 1300 — За пись. К | < || 19 ► | ► 1 |»Ж| из 19 Для тестирования SQL-инструкций в среде Access выберите в левой части главного окна Access в меню Объекты опцию Запросы и дважды щелкните команду Создание запроса в режиме конструктора1. Появившееся окно Добавление таблицы нам в данном случае не нужно2, поэтому его следует закрыть. Рис. 21.4 Создание запросов в Access начинается с выбора объекта Запросы Не обращая внимания на средства Access, предназначенные для легкого создания запроса (в нижней части диалогового окна), выберите команду Режим SQL в меню Вид (рис. 21.6), чтобы, наконец, получить доступ к тому окну, в котором можно будет набирать SQL-инструкции (рис. 21.7). Инструкцию SELECT будем изучать по принципу «от простого — к сложному»: сначала выбросим из полного синтаксиса этой инструкции все необязательные элементы, а затем постепенно будем использовать их, получая более сложные Автор не утверждает, что это единственный способ создания SQL-запроса. Это окно помогает создать запрос пользователю, не умеющему работать с языком SQL. Основы языка SQL 577 запросы. Если отбросить все необязательные предложения и из списка { * | table.* | [table.Jfieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]} оставить только элемент *, то синтаксис самой простой SELECT-инструкции (SQL-запроса) будет иметь вид: SELECT * FROM table 19 Программирование на VBA 2002 578 Глава 21 Здесь знак * означает выбор значений всех полей, a table — имя таблицы, из которой выбираются значения. Поэтому самая простая SELECT-инструкция для одной из рассматриваемых нами таблиц может выглядеть так: SELECT * FROM Товары Введите эту инструкцию в окно Запрос 1: запрос на выборку, как показано на рис. 21.8, и щелкните кнопку Запуск на панели Конструктор запросов. Результат выполнения этой очень простой SQL-инструкции приведен на рис. 21.9. Рис. 21.9 Результат выполнения очень простой SQL инструкции в среде Microsoft Access Рис. 21.8 Введите эту инструкцию в окно Запрос 1: запрос на выборку, как показано на рис 21 8, и щелкните кнопку Запуск Ltl ' Т'-'". _________J.-...............1.' Файл Правка £ид Вставка Формат Записи Сервис Окно Справка - (5 х КодТовара | НаименоеаниеТовара Г ШДЫЕИ» (S) Road Rush II _ 006019170049 (S) Tasmania _ 010414114438 (VCD) Патриот [ ЦенаОптовая j ЦенаРозничная [ _ 010415090732 __ 010415090937 __010428144348 _ 028019095823 __ 028019100018 __ 028019100222 _ 036019164741 _ 174500175359 _ 174500175521 1ЯЙ1ПП17£Т5") Запись H | jp (VCD) Пастырь (VCD) Шоссе в никуда (VCD) Доберман (VCD) Dider Marouani (VCD) Wham1 The best of (VCD) Голая мишень (S) Cool Spot (3DC) Street Fighter 3 Wimpact (3DC) Star Gladiator 2 Г5ПГ"| Q, ног D nohr t 1 ► I H 1>*1 из 13 42 OOp 30 OOp 138 OOp 111 OOp 120 OOp 135 OOp 90 OOp 105 OOp 90 OOp 42 OOp 750 OOp 750 OOp 7АШ ППн 49 OOp 35 OOp 161 OOp 130 OOp 140 OOp 158 OOp 105 00р 123 00p ft 105 00p 49 00p * 875 OOp 875 OOp Я7К ЛПн И Режим таолиць Выбор в SQL-запросе определенных полей Чаще всего вам не нужно будет получать набор со всеми полями одной (или более) таблицы. Например, поскольку поле КодТовара в таблице Товары предназначено в основном для связи с другими таблицами, то не часто его следует включать в SQL-запрос. В SELECT-инструкции можно указать конкретные наименования используемых полей некоторой таблицы, используя следующий синтаксис: SELECT fieldl [,field2 [, ...]] FROM table Например1: SELECT НаименованиеГовара, ЦенаОптовая From Товары Результат этого запроса представлен на рис. 21.10. 1 Для возврата к окну ввода SQL инструкций выберите команду Режим SQL в меню Вид. Основы языка SQL 579 Рис. 21.10 В SELECT-инструкции можно указать конкретные наименования используемых полей и Запрос1 : запрос на выборку ИИКЗЭЁЗ I ЦенаОптовая | -*-J : ► tS) Road РизКЩ—ИИ 42,00p f 1 (S) Tazrnania 30,OOp j (VCD) Патриот 138,OOp j ; (VCD) Пастырь 111,OOp ; (VCD) Шоссе в никуда 120,OOp | (VCD) Доберман 135,OOp ‘ - (VCD) Dider Marouani 90,OOp I (VCD) Whami The best of 105,OOp j (VCD) Голая мишень 90,OOp j (S) Cool Spot 42,OOp j (3DC) Street Fighter 3 Wimpact 750,OOp | (3DC) Star Gladiator 2 750,OOp I (3DC) Super Runabout 750,OOp |< Запись: К | | j 1 ► | ►! |»Ж| из 13 Для выбираемых в запросе полей можно указать отличные от наименований полей заголовки: видимо, не совсем хорошо будет выглядеть на документе заголовок НаименованиеТовара, хотя бывают заголовки и «похуже». Чтобы указать наименования полей результирующего запроса, необходимо использовать такой синтаксис: SELECT fieldl [AS aliasl] [,field2 [AS alias2] [, ...]] FROM table В следующей инструкции мы исправляем ситуацию с «плохими» наименованиями в запросе (результат — на рис. 21.11): SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] From Товары Рис. 21.11 Для выбираемых в запросе полей можно указать отличные от наименований полей заголовки is1 Зинрсп 1 laupop i№fiojMy. НаименованиеТовара ЦенаОптовая |? ► 42,00p (S) Tazrnania 30,OOp j (VCD) Патриот 138,OOp ; (VCD) Пастырь 111,00p ; (VCD) Шоссе в никуда 120,OOp (VCD) Доберман 135,00р (VCD) Dider Marouani 90,00p (VCD) Whami The best of 105,OOp (VCD) Голая мишень 90,OOp (S) Cool Spot 42,00p (3DC) Street Fighter 3 Wimpact 750,00p ? (3DC) Star Gladiator 2 750,OOp | (3DC) Super Runabout 750,OOp |£ Запись: 14 j | j 1 ► | ►! ► Ж| из 13 Выбор в SQL-запросе определенных записей Ключевое слово WHERE в синтаксисе инструкции SELECT позволяет указывать определенные типы записей, которые должны попадать в набор. При этом инструкция SELECT имеет следующий синтаксис: SELECT { * I fieldl [AS aliasl] [,field2 [AS allas2] [, ...]]} FROM table [WHERE criteria] Например, вы можете запросить только те товары, цены которых не более 100 денежных единиц (результат — на рис. 21.12): SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] From Товары WHERE ЦенаОптовая < 100 19* 580 Глава 21 Рис. 21.12 Ключевое слово WHERE в синтаксисе инструкции SELECT позволяет указывать определенные типы записей, которые должны попадать в набор si" Запрос! : запрос на выборы r—--------:---- Наименование товара | Цена оптовая|: 42 ООр 30 ООр " 9°,QQp 90.°0р И 42,00р „0-°°Р„Й |(S) Road Rush ll| (S) Tazmania (VCD) Голая мишень (VCD) Dider Marouani (S) Cool Spot * Запись1 К | | ( Использование в SQL-запросе функций для вывода определенных записей В области слова WHERE можно располагать довольно сложное условное выражение с использованием знаков логических операций и функций. Например: SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаОптовая > 50 AND ЦенаОптовая 200 ИЛИ SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаОптовая > 50 AND Len(ЦенаОптовая) < 20 В первом случае запрашиваются товары, оптовая цена которых находится в диапазоне оптовых цен (55-200), а во втором — цены которых больше 50 денежных единиц и длина наименования не превышает 20 символов. Кроме операций < и >, в инструкции SELECT можно использовать операции = (равно), <= (меньше или равно) и >= (больше или равно), а также AND, OR и NOT. Но еще большие возможности по отбору необходимых записей предоставляют такие операторы, как IS NULL, BETWEEN, IN и LIKE. Оператор IS NULL позволяет найти в таблице записи, в полях которых не указаны данные, например: SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная IS NULL OR ЦенаОптовая < 50 Оператор BETWEEN позволяет указать диапазон, в котором находятся данные некоторого поля, например: SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная BETWEEN 42 AND 120 Оператор IN позволяет указать список, в котором находятся данные некоторого поля, например: SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная IN (42, 105,750) В SQL-инструкции можно также использовать оператор LIKE, например инструкция Основы языка SQL 581 SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE НаименованиеТовара LIKE "(VCD)*” позволяет получить только те записи (рис. 21.13), у которых в наименовании первые пять символов совпадают со строкой "(VCD)”. Рис. 21.13 Вывод только тех записей, у которых в наименовании первые пять символов совпадают со строкой "(VCD)" кЦ.. Запрос!.: запрос на выборку Наименование товара | Цена оптовая ► tVCD) ПатриотЦМ^^Н^Ц 138,00p (VCD) Пастырь 111,00р. (VCD) Шоссе в никуда 120,00р (VCD) Доберман 135,00р. (VCD) Голая мишень 90,00р. (VCD) Dider Marouani 90,00р. (VCD) Whami The best of 105,00р. * 0,00р. Запись: Н | < ] Г ..-•Лиамам - 1 » |Н I»! из 7 Оператор LIKE можно использовать для контекстного поиска, например, если пользователь введет текстовую строку, содержащую часть наименования товара, то эту строку легко использовать в виде шаблона. Следующая инструкция выполняет поиск записи, в которой наименование содержит в качестве подстроки строку "(мишень)" (результат — на рис. 21.14): SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE НаименованиеТовара LIKE "‘мишень*" Рис. 21.14 Результат использования инструкции, которая выполняет поиск записи, где наименование содержит в качестве подстроки строку "мишень” Оператор NOT, который инвертирует логическое выражение, может использоваться с операторами IS NULL, BETWEEN, IN, LIKE. При этом, практически, речь идет об операторах IS NOT NULL, NOT BETWEEN, NOT IN и NOT LIKE, например, как в следующих четырех инструкциях: SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная IS NULL OR ЦенаОптовая < 50 SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная BETWEEN 42 AND 120 SELECT НаименованиеТовара as [Наименование товара], ЦенаОптовая as [Цена оптовая] FROM Товары WHERE ЦенаРозничная IN (42, 105,750) 582 Глава 21 SELECT НаименованиеТовара as [Наименование товара] , ЦенаОптовая as [Цена оптовая] FROM Товары WHERE НаименованиеТовара LIKE "(VCD)*" Форматирование выводимых в запросе данных Результирующие данные запроса можно форматировать с использованием, например, функции Format. В следующем запросе данные форматируются при помощи строки "### ##0.00$" (результат — на рис. 21.15): SELECT НаименованиеТовара as [Наименование товара], Format(ЦенаОптовая,"### ##0.00$") as [Цена оптовая] From Товары WHERE ЦенаОптовая < 100 Рис. 21.15 Результирующие данные запроса можно форматировать с использованием функции Format ]S) Road Rush ll| (S) Tazmama (VCD) Голая мишень (VCD) Older Marouani (S) Cool Spot | Цена оптовая 42,00$ 30 00$ 90,00$ 90 00$ 42,00$ Для форматирования выводимых в запросе данных можно использовать функции преобразования строк. Например, в следующем запросе наименования товаров выводятся символами верхнего регистра, поскольку здесь используется функция StrConv (результат — на рис. 21.16): SELECT StrConv(НаименованиеТовара,1) AS [Наименование товара], ЦенаОптовая AS [Цена оптовая] FROM Товары Рис. 21.16 Наименования товаров выводятся символами верхнего регистра, поскольку здесь используется функция StrConv ig! 3anpoc1 : запрос на «ыворку Цена оптовая * ifil(S) ROAD RUSH цм^|Н|||Ы| 42,00p (S) TASMANIA 30,OOp I <VCD) ПАТРИОТ 138,00p I (VCD; ПАСТЫРЬ 111,00p I ! (VCD) ШОССЕ В НИКУДА 120,OOp I (VCD) ДОБЕРМАН 135,OOp _ (VCD) DIDER MAROUANI 90 OOp (VCD) WHAMl THE BEST OF 105 OOp (VCD) ГОЛАЯ МИШЕНЬ 90,OOp (S) COOL SPOT 42,00p | (3DC) STREET FIGHTER 3 WIMI 750,OOp (3DC) STAR GLADIATOR 2 750,OOp Q(3DC) SUPER RUNABOUT 750 OOp ,| * Запись M | 11 1 ► j ►! ; ►*] из 13 Основы языка SQL 583 Выбор данных из более чем одной таблицы Имея базу данных из нескольких таблиц, мы до сих пор получали при помощи инструкции SELECT наборы данных только из одной таблицы. Рассмотрим теперь задачу выбора из базы данных товаров некоторого склада. Перед тем как рассмотреть использование слова WHERE для связи таблиц, заметим, что в инструкции SELECT можно перед именем.поля указывать имя таблицы, которое отделяется от имени поля точкой: SELECT { * | [tablel.]fieldl [AS aliasl] [, [table2.]field2 [AS alias2] [, ...]]} FROM tablel [tablelAlias] [, table2 [table2Alias] [, ...] [WHERE criteria] Например: SELECT Товары.НаименованиеТовара AS [Наименование товара], Товары.ЦенаОптовая AS [Цена оптовая] FROM Товары или SELECT а.НаименованиеТовара AS [Наименование товара], а.ЦенаОптовая AS [Цена оптовая] FROM Товары а Во второй инструкции использовано альтернативное имя таблицы (локальный псевдоним), но обе инструкции выдают один и тот же результирующий набор. Следующая инструкция позволяет получить наименования (из таблицы Товары) и количества (из таблицы Инвентарная_ведомость) товаров (результат — на рис. 21.17): SELECT Товары.НаименованиеТовара AS [Наименование товара], Инвентарная__ведомость . Количество AS [Количество] FROM Товары, Инвентарная_ведомость WHERE Товары.КодТовара=Инвентарная_ведомость.КодТовара Рис. 21.17 Результат инструкции, которая позволяет получить наименования (из таблицы Товары) и количества (из таблицы Инвентарная_ведомость) 3ai>por1 : запрос на выборку Наименование товара I ► ЭЕШЗЕЖ _ (S) Road Rush II ___lS) Road Rush II ___(S) Tazrnania [__(S) Tazrnania ___(S) Tazrnania ___ 'CD) Патриот ___(VCD) Патриот ___(VCD) Доберман ___(VCD) Доберман 'S) Cool Spot __ ',) Cool Spot __lS) Cool Spot janecb H | || “ иьш I Количеств j 30C ‘ 2C-. 12C ’ 1ооояВ1 500 ЮС 4С= зэоо 1ЕЫ ВС 42С 20С j бооИИИ 14С Обратите внимание на выражение Товары.КодТовара=Инвентарная_ведо-мость.КодТовара. Именно оно и используется для связи таблиц Товары и Инвен-тарная_ведомость по ключевому полю КодТовара. Результат выполнения предыдущей инструкции напоминает инвентаризационную ведомость без указания места, где находится товар. Следующая инструкция позволяет получить наименования (из таблицы Товары) и количества (из таблицы Инвентарная_ведомость) только для тех кодов товаров, записи которых в таблице Инвентарная_ведомость в поле Код_склада содержат строку "0429": SELECT Товары.НаименованиеТовара AS [Наименование товара], Инвентарная__ведомость.Количество AS [Количество] FROM Товары, Инвентарная_ведомость 584 Глава 21 WHERE Инвентарная—ведомость.Код_склада='0429' AND Товары.КодТовара=ИнвентарнаЯ—ведомость.КодТовара При помощи локальных псевдонимов можно сократить предыдущую инструкцию (результат — на рис. 21.18): SELECT а.НаименованиеТовара AS [Наименование товара], Ь.Количество AS [Количество] FROM Товары а, Инвентарная—ведомость b WHERE b.КоД—склада='0429' AND а.КодТовара=Ь.КодТовара Рис. 21.18 Наименования товаров выводятся только для одного склада is! Запрос.1 : запрос на выборку Наименование товара ] Количество 3000 1 (S)Tazmama 1000 _ (S) Cool Spot 2000 _ (3DC) Star Gladiator 2 1500 (3DC) Super Runabout 2000 [S) Road Rush ll| Запись: К | | [ Следует заметить, что вообще-то коды, как товаров, так и складов, не предназначены для использования клиентами. Они необходимы для связи между таблицами. Часто менеджеры, использующие базы данных, даже не знают о наличии кодов в таблицах баз данных. По этой или подобной ей причине нам следует избавиться от «публичного» использования кода склада в SELECT-инструкции. Хотя, конечно, инструкция при этом немного усложнится: SELECT а.НаименованиеТовара AS [Наименование товара], Ь.Количество AS [Количество] FROM Товары а, Инвентарная—ведомость Ь, Склады с WHERE а.КодТовара=Ь.КодТовара AND b.КодСклада=с.КодСклада AND с.НаименованиеСклада="СКЛАД (Мультимедия)" В этой инструкции использована таблица Склады, а при помощи поля КодСк-лада эта таблица связана с таблицей Инвентарная_ведомость. Вывод выбранных данных в определенном порядке Вы могли уже давно заметить, что наименования товаров в наших таблицах и выводимых наборах не отсортированы. Это бывает особенно заметно, когда данных очень много (например, в окне списка), а нужно найти только некоторые из них. Для сортировки данных в инструкции SELECT имеются слова ORDER BY: SELECT { * I [table.]fieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]} FROM tablel [tablelAlias] [, table2 [table2Alias] [, ...] [WHERE criteria] [ORDER BY fieldl [ASC I DESC ][, field2 [ASC I DESC ]][, ...]]] Здесь к тем элементам SQL-запроса, которые уже рассмотрены, добавлено необязательное предложение ORDER BY. Как следует из синтаксиса инструкции SELECT, используя слова ASC и DESC, можно изменять «направление» сортировки («по возрастанию» и «по убыванию»). Сортировать можно по нескольким полям (сначала по одному, затем — по другому, и так далее) и даже по различным элементам одного и того же поля с использованием функций (как встроенных, так и пользовательских). Основы языка SQL 585 В следующей инструкции используется сортировка выводимого набора по наименованиям (результат — на рис. 21.19): SELECT а.НаименованиеТовара AS [Наименование товара], Ь.Количество AS [Количество] FROM Товары а, Инвентарная__ведомость Ь WHERE а.КодТовара=Ь.КодТовара AND b.Код_склада='0429' ORDER BY а.НаименованиеТовара Рис. 21.19 Сортировка данных в инструкции SELECT и’ Janpocl:запрос на выборку |f3DC) Star Gladiator 2| Наименование товара | Кол, PDC) Super Runabout (S) Cool Spot (S) Road Rush II (S) Tazmania Агрегирующие функции в инструкции SELECT В инструкциях языка ANSI SQL предусмотрены так называемые агрегирующие функции, которые определяют количество записей, вычисляют суммы всех значений полей в наборе, находят минимальные или максимальные, а также средние значения. К агрегирующим функциям относятся функции COUNT, SUM, MAX, MIN и AVG. Функция COUNT используется для определения количества записей в запросе. Например, в окне на рис. 21.20 введена инструкция для вычисления количества записей в таблице Товары, а на рис. 21.21 показан результат выполнения этой инструкции. Рис. 21.20 Окно с инструкцией SELECT для определения общего количества записей в таблице Рис. 21.21 Результат определения общего количества записей в таблице 1? Запрос? : запрос па пыбп | Запись: Н | 11 Г ' I И h I из Следующая инструкция вычисляет количество записей, в которых значение поля ЦенаОптовая меньше 100. На рис. 21.22 приведен результат выполнения этой инструкции. SELECT COUNT(НаименованиеТовара) AS [Всего наименований] FROM Товары WHERE ЦенаОптовая < 100 586 Глава 21 Рис. 21.22 Результат определения количества записей в таблице при определенном условии Функция SUM позволяет для группы строк вычислить итоговую сумму значений некоторого поля, например (результат — на рис. 21.23):. SELECT SUM(Количество) as [Общее количество товаров] FROM Инвентарная_ведомость Рис. 21.23 Результат вычисления итоговой суммы значений некоторого поля При использовании функции SUM можно ограничить количество записей запроса при помощи некоторого условия, например (результат — на рис. 21.24): SELECT SUM(Количество) AS [Количество на складе] FROM Инвентарная_ведомость WHERE КодСклада='0429' Рис. 21.24 При использовании функции SUM можно ограничить количество записей запроса Функция AVG в инструкции SELECT позволяет найти среднее значение для строк, входящих в запрос. Например, следующая инструкция определяет среднюю цену на товары, наименования которых начинаются со строки "(VCD)" (результат — на рис. 21.25): SELECT AVG(ЦенаОптовая) AS [Среднее значение] FROM Товары WHERE НаименованиеТовара LIKE '(VCD)*' Рис. 21.25 При помощи функции AVG можно вычислить среднее значение Функции МАХ и MIN использовать также просто, как и AVG, например: SELECT МАХ(ЦенаОптовая) AS [Максимальная цена] FROM Товары WHERE НаименованиеТовара LIKE '(VCD)*' или ' SELECT MIN(ЦенаОптовая) AS [Макси,л1пьная цена] . FROM Товары WHERE Наименование г'вара LIKE '(VCD)*' В первой из приведенных инструкций определяется максимальное значение цены на товары, наименования которых начинаются со строки "(VCD)' во второй — минимальное значение цены на подобные товары. Основы языка SQL 587 В конкретных реализациях SQL имеются другие агрегирующие функции, которые следует использовать только в том случае, если вы уверены, что никогда не захотите использовать фрагменты своего кода в различных СУБД. Группировка данных в инструкции SELECT Часто в наборах, получаемых при помощи SELECT-инструкций, встречаются повторяющиеся значения. Для рассматриваемой нами базы данных это могут быть, например, коды товаров или складов в таблице с инвентаризационной ведомостью, номера и даты накладных в таблице со спецификациями накладных. Такие повторяющиеся значения можно объединять в группы, используя для групп агрегирующие функции. В инструкции SELECT для объединения значений в группы используется предложение GROUP BY. Следующая инструкция имеет результатом список складов и суммарные количества товаров на каждом складе (результат — на рис. 21.26): SELECT с.НаименованиеСклада, SUM(Ь.Количество) AS Количество FROM Инвентарная__ведомость Ь, Склады с WHERE b.КодСклада=с.КодСклада GROUP BY с.НаименованиеСклада Рис. 21.26 Список складов и суммарные количества товаров на каждом складе [СКЛАД (Брак)| НаименованиеСклада | Количество I? Запрос.): аапрос на «ыб... _ СКЛАД (МНЕВНИКИ) СКЛАД (Мультимедиа) СКЛАД (НЕЙРОН) ' Запись: |< | * 11 Г 133001 31001 9500 J 36001 Если эта инструкция вам кажется сложной, выполните ее аналог, в котором вместо наименований складов используются их коды: SELECT b.КодСклада, SUM(Ь.Количество) AS Количество FROM Инвентарная_ведомость b GROUP BY Ь.КодСклада Заметьте, что эта инструкция использует данные только одной таблицы. Здесь суммируются значения поля Количество для одинаковых значений полей КодСклада. В этом — смысл предложения GROUP BY. В предыдущем запросе мы просто вместо кодов подставили (посредством WHERE Ь.КодСклада=с.КодСклада) наименования складов, использовав для этого справочник Склады; смысл самого запроса, практически, такой же. Предположим, что нам нужна информация о суммарном количестве товара только на тех складах, где это количество меньше определенного числа. Чтобы выполнить этот запрос, мы не можем использовать предложение WHERE, так как оно «работает» со значениями данных, расположенными в таблице, а нам нужно наложить некоторые ограничения на вычисляемые данные. Для решения подобной задачи следует использовать предложение HAVING, которое так же связано с предложением GROUP BY, как WHERE с SELECT. Другими словами, предложение HAVING налагает некоторые условия на выбранные посредством предложения GROUP BY данные. Следующая инструкция позволяет получить список складов и суммарное количество товаров на них. Причем в список включаются только те склады, на которых суммарное количество товаров меньше, чем 1000 (результат — на рис. 21.27): SELECT с.НаименованиеСклада, SUM(Ь.Количество) AS Количество FROM Инвентарная__ведомость Ь, Склады с WHERE b.КодСклада=с.КодСклада GROUP BY с.НаименованиеСклада HAVING SUM(b.Количество) < 10000 588 Глава 21 Рис. 21.27 В список включаются только те склады, на которых суммарное количество товаров меньше чем 1000 Запрос4 : запрос на выборку [». ||П п Х| 3100 9500 3600 НаименованиеСкладаГ Количество СКЛАД (МНЕВНИКИ) СКЛАД (Мультимедиа) СКЛАД(НЕЙРОН Запись: Н | Ч |Г Подзапросы в инструкции SELECT Подзапрос — это запрос, который размещается внутри другого запроса, а точнее, является частью предложения WHERE (или HAVING) основного запроса и заключается в круглые скобки. Иногда подзапросы называют вложенными запросами. Запрос, содержащий подзапрос, называют сложным запросом. При выполнении сложного запроса сначала выполняется подзапрос (он для этого и заключается в скобки!), а затем — основной запрос. Выходные данные подзапроса обычно используются при оценке выражения в предложении WHERE (или HAVING) основного (по отношению к данному подзапросу) запроса с использованием таких операторов, как =, >, <, <>, IN, NOT IN, AND, OR. (Эти операторы можно использовать и внутри подзапроса.) Очень важно понимать, какие данные возвращает подзапрос, поскольку от этого зависит синтаксис использования предложения WHERE. Необходимо при написании сложных запросов соблюдать следующие правила: Предложение SELECT подзапроса обычно содержит только один столбец и, следовательно, может иметь результатом массив однородных (только строковые значения, только целые значения и т.д.) значений или только одно значение. Очень редко встречаются случаи использования нескольких столбцов. Если подзапрос возвращает массив значений, соответствующее этому подзапросу предложение WHERE может содержать только многозначные операторы, например, IN. Предложение ORDER BY следует использовать только в основном запросе. В подзапросе для упорядочения данных необходимо применять предложение GROUP BY. Недопустимо использование в основном запросе предложения BETWEEN. Простой синтаксис подзапроса для оператора SELECT следующий: SELECT ( * | table.* I [table.]fieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]) FROM tablel [tablelAlias] [, table2 [table2Alias] [, ...] WHERE fieldl operator (SELECT { * | table.* I [table.]fieldl [AS aliasl] [, [table.]field2 [AS alias2] [, ...]]} FROM tablel [tablelAlias] [, table2 [table2Alias] [, ...] WHERE [criteria]) Проще всего продемонстрировать использование подзапроса, если он имеет результатом единственное значение. Например, пусть нам необходимо получить список товаров склада, на котором их больше всего. Для начала нам нужно определить этот склад. Создадим запрос, который возвратит код склада с наибольшим количеством товаров: SELECT ТОР 1 КодСклада FROM Инвентарная_ведомость GROUP BY КодСклада ORDER BY SUM(Количество) DESC Предложение TOP 1 указывает на то, что в результирующий набор попадает только одна запись, а поскольку набор сортируется (по убыванию) по суммарным количествам товаров, то в результате мы получаем код склада с наибольшим количеством товаров. Остается использовать ранее рассмотренный запрос, который воз Основы языка SQL 589 вращает список товаров для указанного кода склада, но если ранее мы указывали этот код, то теперь определяем его в подзапросе (результат — на рис. 21.28): SELECT а.НаименованиеТовара AS [Наименование товара], Ь.Количество AS Количество FROM Товары AS а, Инвентарная—ведомость AS Ь WHERE а.КодТовара=Ь.КодТовара AND Ь.КодСклада = (SELECT ТОР 1 КодСклада FROM Инвентарная—ведомость GROUP BY КодСклада ORDER BY SUM(Количество) DESC) Рис. 21.28 Результат выполнения сложного запроса Запрос4 : запрос на выборку KK Наименование товара Количество[ ► fyCD) Патриот 33C (УСО) Доберман 42C (3DC) Street Fighter 3 Wimpact 22C (3DC) Star Gladiator 2 23C (3DC) Super Runabout 13C Запись: 11 1 ► | ► ! j из 5 Целью следующего запроса является получение ведомости товаров склада, где имеется больше наименований (кодов) товаров (результат — на рис. 21.29). SELECT а.НаименованиеТовара AS [Наименование товара], Ь.Количество AS Количество FROM Товары AS а, Инвентарная_ведомость AS Ь WHERE а.КодТовара=Ь.КодТовара AND Ь.КодСклада = (SELECT ТОР 1 КодСклада FROM Инвентарная—ведомость GROUP BY КодСклада ORDER BY COUNT(КодТовара) DESC) Здесь в подзапросе вместо функции SUM используется COUNT — счетчик количества записей. Рис. 21.29 Результат выполнения сложного запроса i? Запросе : запрос на выборку Наименование товара Количес - | ► LSI Road Rush (S) Tazrnania (VCD) Патриот (VCD) Доберман (S) Cool Spot (3DC) Street Fighter 3 Wimpact I Запись Н J |j 1 ► | Н | из 6 Для следующих далее примеров нам необходимо заполнить данными таблицы НаклЗаголовки и НаклСпецификации (рис. 21.30 и рис. 21.31): Рис. 21.30 Заполненная данными таблица НаклЗаголовки И НаклЗаголовки : таблица ’ " ""' ' ’ Дата | Номер | КодСклада | КодКАгента |ТипНакладной * 11/1/2002 1 0429 1958 5 11/1/2002 5 1506 1518 2 11/2/2002 1 0429 1958 2 11/2/2002 2 0429 1506 5 11/2/2002 3 0429 1506 5 11/2/2002 4 0429 1958 5 11/3/2002 1 0429 1518 5 11/3/2002 2 0429 1958 2 11/3/2002 3 0429 1518 5 ► 11/3/2002 |l 0429 1958 5 rJ Запись 14 |<|| 10 ► | H|k^| из 10 < 3 ! d 590 Глава 21 Рис. 21.31 Заполненная данными таблица Накл Спецификации М НаклСлецификации : таблица Дата | Номер | КодСклада | КодТовара Количество |ЦенаОперации(А 11/1/2002 1 0429 010415090937 100 120 00 11/1/2002 1 0429 010414114438 200 135 00{ 11/1/2002 5 1506 028019100222 546 83 00 11/2/2002 1 0429 006019165803 100 42 00 ► 11/2/2002 1 0429 028019100222 140 88 00 11/2/2002 2 0429 186100175232 100 750 00 11/2/2002 2 0429 174500175521 * 200 750 00 11/2/2002 2 0429 028019100222 60 89 00 11/2/2002 2 0429 010415090732 120 109 00 11/2/2002 3 0429 174500175359 200 750 00 11/2/2002 3 0429 028019100222 545 85 00 11/2/2002 4 0429 174500175521 222 750 00 11/2/2002 4 0429 028019100222 334 88 00 11/2/2002 4 0429 186100175232 767 745 00 11/3/2002 1 0429 028019100222 232 88 00* 11/3/2002 1 0429 010415090732 222 110 00 11/3/2002 2 0429 010415090732 111 111 00 11/3/2002 2 0429 174500175359 234 750 00 11/3/2002 3 0429 174500175359 432 750 00 11/3/2002 4 0429 174500175521 67 750 00 11/3/2002 5 0429 186100175232 231 750 00 Запись Н j || 5 ► I и !►*!иэ 21 Наличие базы данных с накладными дает возможность, по крайней мере, просмотра этих накладных. Рассмотрим ряд вопросов, которые могут возникнуть при просмотре таблиц с накладными. Если бы нам нужно было создать форму для просмотра накладных, то она, вероятно, была бы похожа на ту, которая изображена на рис. 21.32. Изображенная на этом рисунке форма получена в редакторе VB только с одной целью — понять, какие SQL-запросы были бы необходимы для заполнения такого диалогового окна. Во-первых, для заполнения окна комбинированного списка в секции Подразделение необходим запрос, в результате которого получался бы список подразделений, накладные которых имеются в таблице НаклЗаголовки. Во-вторых, следует заполнить окно комбинированного списка в секции Дата датами (уникальными) из таблицы НаклЗаголовки. Далее, после выбора пользователем данных в секциях Подразделение и Дата в окне комбинированного списка Накладная следует поместить список накладных (с указанием номера накладной, типа накладной и наименованием контрагента) Для этого необходимо построить запрос с целью получения таблицы номеров, типов, контрагентов накладных для определенного подразделения и указанной даты. Рис. 21.32 Так могло бы выглядеть диалоговое окно для просмотра накладных I Просмотр нанладяык Подразделение Справка f I § Д^та Накладная | Наименование Количество Цена 1 3 Выход л Основы языка SQL 591 После заполнения данными списка Накладная и пользовательского выбора в этом окне останется только для известного подразделения, даты и номера накладной сформировать запрос по таблице НаклСпецификации, чтобы получить данные о конкретной накладной. Итак, рассмотрим первый запрос — формирование списка подразделений, накладные которых имеются в таблице НаклЗаголовки. Целесообразно получить таблицу наименований и кодов подразделений. Наименованиями следует заполнить окно комбинированного списка для отображения в диалоговом окне. Коды необходимо записать в список, не отображаемый в окне, но синхронизированный с видимым списком. После выбора пользователем необходимого подразделения можно узнать и код этого подразделения. Запрос, о котором идет речь, должен быть следующим: SELECT DISTINCT b.КодСклада, а.НаименованиеСклада FROM Склады а, НаклЗаголовки b WHERE а.КодСклада=Ь.КодСклада Если его выполнить для данных, отображенных на рис. 21.30и21.31 (и таблицы Склады), то получится набор, приведенный на рис. 21.33. Рис. 21.33 Склады, накладные которых имеются в таблице НаклЗаголовки vr Запрос4 : запрос на выборку КодСклада |НаймёниБаниеС|<лада | ? __0429 СКЛАД (Мультимедиа) •_ ±J1596I СКЛАД fМНЕВНИКИ) Запись: Н | 4 || 2 | >1 | | из 2 Таким образом, если пользователь выберет необходимый склад, то мы (или программа, поддерживающая диалоговое окно) будем знать код этого склада. Считая известным код склада, создадим очень простой запрос для формирования данных списка дат, например, для склада с кодом "0429”: SELECT DISTINCT Дата FROM НаклЗаголовки WHERE КодСклада="0429" Результатом этого запроса может быть таблица, приведенная на рис. 21.34. Рис. 21.34 Склады, накладные которых имеются в таблице НаклЗаголовки После выбора пользователем склада и даты необходимо сформировать запрос для списка Накладная с целью получения таблицы номеров, типов, контрагентов накладных для определенного подразделения и указанной даты (например, 11.02.2002). Правильным будет упорядочить результат запроса по номерам накладных: SELECT а.Номер, b.НаименованиеКАгента, а.ТипНакладной , FROM НаклЗаголовки AS а, КонтрКАгенты AS b WHERE а.КодКАгента = Ь.КодКАгента AND а.КодСклада="0429" AND а.Дата = CDate("11/02/2002") ORDER BY а.Номер Результатом этого запроса может быть таблица, приведенная на рис. 21.35. Осталось сформировать запрос для заполнения таблицы со спецификацией выбранной накладной (например, с номером 2): SELECT Ь.НаименованиеТовара, а.Количество, а.ЦенаОперации FROM НаклСпецификации а, Товары b WHERE а.КодТовара=Ь.КодТовара AND а.КодСклада="0429" AND а.Дата=СОаЬе("11/02/2002") AND Номер =2 ORDER BY b.НаименованиеТовара Результатом запроса может быть таблица, приведенная на рис. 21.36. 592 Глава 21 Рис. 21.35 Такая таблица может послужить источником данных для списка Накладная й* Запрос? : запрос на выборку Номер] НаименованиеКАгента ]ТипНакладной| ► 1 СКЛАД^Брак) 2 _ 2 СКЛАД (МНЕВНИКИ) 5 _ 3 СКЛАД (МНЕВНИКИ) 5 ~J 4 СКЛАД (Брак) 5............ Запись Н | < | [ Г* ► [ И *| из 4 Рис. 21.36 Таблица со спецификацией накладной Запрос# : запрос на выборку НаименованиеТ овара 3DC) Star Gladiator >j (3DC) Super Runabout (VCD) Голая мишень __](VCD) Пастырь | Количество[ценаОперации 200 750 00 100 750 00 60 89 00 ___ _J20 __ J09 00 d*3 4 4JJ ?i Этим примером заканчивается глава, посвященная введению в язык SQL, который имеет много не рассмотренных здесь возможностей. В следующих двух главах приведены некоторые примеры использования SQL-инструкций в VB-коде. Среди этих инструкций встречаются те, которые не обсуждались в этой главе. Глава 22 Доступ к базам данных из VBA-кода Как вы могли заметить, в двух предыдущих главах нет ни единой строки VBA-кода. В этой главе мы снова возвращаемся к программированию на языке Visual Basic и теперь в качестве объектов кода будем использовать новые объекты — элементы баз данных. Поскольку Visual Basic не является языком баз данных, для доступа к данным следует использовать предназначенные для этого объекты (их свойства и методы). В этой главе рассматриваются две модели объектов доступа к данным: Data Access Objects (DAO) и ActiveX Data Objects (ADO). Microsoft DAO Microsoft DAO (Data Access Objects — объекты доступа к данным) позволяет работать с базами данных из приложения, поддерживающего Visual Basic for Applications. Объекты DAO подразделяются на те, которые отражают структуру базы данных, и на те, которые являются данными и позволяют взаимодействовать со многими типами баз данных из любого приложения, поддерживающего Visual Basic for Applications. При помощи объектов DAO можно: создавать базы данных, изменять их структуру; извлекать, добавлять, удалять и обновлять данные, хранимые в таблицах баз данных; подключаться к базам данных на удаленных серверах и разрабатывать клиент-серверные приложения. DAO позволяет осуществлять доступ к базам данных различных форматов, которые можно разбить на три категории: Формат Microsoft Jet — все базы данных, построенные на основе ядра баз данных Microsoft Jet (включая созданные с использованием Microsoft Access, Microsoft Visual Basic, Microsoft Visual C++ и Microsoft Excel). Формат, поддерживаемый устанавливаемыми драйверами ISAM, которые обеспечивают доступ к внешним базам данных через DAO или Microsoft Jet. Драйверы ISAM имеются для таких форматов, как Microsoft FoxPro, dBASE, Microsoft Excel и других. Источники данных ODBC (например, Microsoft SQL Server). Для операций с источниками данных ODBC модель DAO можно использовать через Microsoft Jet или ODBCDirect. Технологию DAO для операций с источниками данных ODBC можно использовать двумя способами: посредством Microsoft Jet [если необходимы уникальные возможности этого ядра, например, создание и модификация объектов, или объединение данных из баз различных форматов] или ODBCDirect [если нужно выполнять запросы или процедуры, хранимые на сетевом сервере, или если клиентскому приложению требуются специфические возможности ODBC, например, пакетное обновление или асинхронные запросы]. Поскольку же посредством ODBCDirect доступны не все возможности DAO, в Microsoft DAO предусмотрена поддержка ODBC ядром Microsoft Jet. Таким образом, для работы с источниками данных ODBC можно использовать и Microsoft Jet, и ODBCDirect или и то, и другое. 594 Глава 22 Выбор доступа к источникам данных ODBC зависит от типа рабочего пространства (workspace), которое определяет активный сеанс, связанный с учетной записью конкретного пользователя. Рабочие пространства DAO Объекты DAO, как все объекты приложений Microsoft, организованы в иерархическую структуру. Объекты содержат коллекции, коллекции — другие объекты. Объект DBEngine находится на вершине иерархической объектной модели DAO. DAO поддерживает две различные среды баз данных (databases environments) или два типа рабочего пространства: Microsoft Jet workspace — обеспечивает доступ к данным в базах Microsoft Jet, ODBC-источниках через Microsoft Jet и в базах в формате устанавливаемых драйверов ISAM, таких как Microsoft FoxPro, dBASE, Paradox, Microsoft Excel, Microsoft Exchange и Outlook, Lotus 1-2-3 и др. DAO-модель для Microsoft Jet workspace представлена на рис. 22.11. ODBCDirect workspace — обеспечивает доступ к данным посредством ODBC, без загрузки ядра (engine) базы данных Microsoft Jet. DAO-модель для ODBCDirect workspace представлена на рис. 22.2. [DBEngine | -| Errors ]—| Error || -| Workspaces |—| Workspace || -| Databases |—I Database || -| Containers |—| Container || Documents |—| Document j -| QueryDefs [—{ QueryDef [| -| Fields |—’I Field || *-| Parameters ]—| Parameter || -| Recordsets |—[ Recordset [| ^~l Fields |—| Field -| Relations [—[Relation L| Fields |—pFiZid ^-| Fields" -| TableDets |—| TableDef || -[ Fields -| Indexes 1-| Field || ]—| Index || L| Fields |-| Field -| Groups [—| Group || Qju ters I—f User -| Users Groups ]—| Group ' || Рис. 22.1. DAO-модель для Microsoft Jet workspace 1 На рисунках 22.1 и 22.2 затененные прямоугольники представляют коллекции, а незатененные — объекты. Доступ к базам данных из УВА-кода 595 [DBEngine | -| Errors |—| Error -| Workspaces |—| Workspace [| -| Connections |—[ Connection || » -| QueryDels |—[ QueryDel [| L| Parameters Parameter [| -| Recordsets |—| Recordset [| Ч Fields ~ ]-| Field -| Databases |—| Database || Ч Recordsets |—[ Recordset || L| Fields |—| Field Рис. 22.2. DAO-модель для ODBCDirect workspace Рабочее пространство Microsoft Jet следует использовать при работе с базами Microsoft Jet (.mdb-файлами) и другими настольными (desktop) ISAM-базами или, если вам необходимы преимущества некоторых уникальных возможностей системы Microsoft Jet, таких как объединение данных из нескольких баз с различными форматами. Рабочее пространство ODBCDirect удобно, когда необходимо выполнить запрос или хранимую процедуру (stored procedure) на удаленном сервере, таком как Microsoft SQL Server. Вам могут понадобиться некоторые преимущества ODBC, например, пакетное обновление (batch update), выполнение асинхронного запроса (asynchronous query). DAO имеет 17 различных типов объектов. Каждый DAO-объект (кроме DBEngine) имеет соответствующую коллекцию, которая включает все существующие объекты этого типа. Например, коллекция Recordsets содержит все открытые Recordset-объекты. Каждая коллекция принадлежит объекту, который расположен на предыдущем уровне в иерархической DAO-структуре. Например, объект Recordset «владеет» коллекцией Fields. Большинство DAO-объектов имеют коллекции и свойства по умолчанию. Например, коллекцией по умолчанию объекта Recordset является Fields, а свойством по умолчанию объекта Field является Value. На вершине DAO-моделей находится единственный объект DBEngine. Чтобы успешно работать с объектом DBEngine, необходимо хорошо знать его свойства и методы. DBEngine имеет следующие свойства: DefaultType Тип — Long. Тип рабочего пространства (Microsoft Jet или ODBCDirect), который будет использоваться при создании Workspace-объекта. По умолчанию свойство устанавливается равным значению константы dbUseJet (стандартным является пространство Microsoft Jet). Создавая рабочее пространство явно, мож-но указать значение этого свойства при помощи аргумента метода CreateWorkspace, используя константу dbUseJet или dbUseODBC (для ODBCDirect). 596 Глава 22 DefaultUser Тип — String. Имя пользователя, используемое при создании рабочего пространства по умолчанию. Строка может быть длиной от 1 до 20 символов в рабочем пространстве Microsoft Jet и любой длины в рабочем пространстве ODBCDirect. Она может включать алфавитно-цифровые символы, пробелы и любые символы, кроме: " (двойные кавычки), / (прямой слэш), \ (обратный слэш), [] (квадратные скобки), : (двоеточие), | (символ конвейеризации), < (знак меньше чем), > (знак больше чем), + (знак плюс), = (знак равенства), ; (точка с запятой), , ( запятая), ? (знак вопроса), * (звездочка), «ведущих» пробелов и управляющих символов (ASCII 00 to ASCII 31). По умолчанию свойство DefaultUser устанавливается равным строке "admin”. Имя пользователя обычно «чувствительно» к регистру. Default-Password Тип — String. Пароль, используемый при создании рабочего пространства по умолчанию. DefaultPassword — строка длиной до 14 символов в рабочем пространстве Microsoft Jet и любой длины в рабочем пространстве ODBCDirect. Может включать любые символы, кроме ASCII 0. Значение по умолчанию — строка нулевой длины (""). Пароль «чувствителен» к регистру. IniPath Информация о ключе в Windows Registry, который содержит значения для Microsoft Jet database engine (только для рабочего пространства Microsoft Jet). Ядро Microsoft Jet можно конфигурировать с использованием Windows Registry. Реестр можно использовать для уста|ювки таких параметров, как настраиваемые ISAM DLL. Чтобы эта опция имела какой-либо эффект, необходимо установить свойство IniPath перед тем, как ваше приложение активизирует любой другой DAO-код. Для инициализации параметров некоторых настраиваемых ISAM-драйверов можно также использовать Windows Registry. LoginTimeout Количество секунд, через которое выдается ошибка при неудачной попытке подключения к ODBC-базе данных. SystemDB Путь для текущего местонахождения файла с информацией рабочей группы (только для рабочего пространства Microsoft Jet). Version Рабочее пространство Microsoft Jet: для DBEngine-объекта возвращается используемая версия DAO. Для объекта Database возвращается версия Jet, в которой был создан mdb-файл. Рабочее пространство ODBCDirect: для DBEngine-объекта возвращается используемая версия DA0. Для объекта Database возвращается версия используемого драйвера ODBC. Объект DBEngine создавать не нужно. Можно написать простую программу для считывания некоторых свойств этого объекта: Sub DBEngineTest() MsgBox DBEngine.DefaultType 1 возвращает 2 MsgBox DBEngine.LoginTimeout ' возвращает 20 MsgBox DBEngine.Version ' возвращает 3.6 End Sub Для указания используемого типа рабочего пространства (Microsoft Jet или ODBCDirect) можно либо непосредственно установить свойство DefaultType объекта DBEngine, либо использовать метод CreateWorkspace. Следующие операторы непосредственно задают свойство DefaultType объекта DBEngine: DBEngine.DefaultType = dbUseJet DBEngine.DefaultType = dbUseODBC Доступ к базам данных из УВА-кода 597 В этих операторах использованы DAO-константы dbUseJet и dbUseODBC, которые предназначены для указания типа рабочего пространства. Как видно из рис. 22.1 и 22.2, обе модели имеют коллекции Workspaces с объектами типа Workspace (рабочее пространство), содержащими открытые базы данных и предоставляющими механизмы работы с таблицами базы. Объект Workspace можно не включать в коллекцию Workspaces, если он используется только в той процедуре (подпрограмме), в которой и создан. В рабочем пространстве Microsoft Jet для доступа к данным базы Microsoft Jet, источникам, требующим драйверов ISAM, и ODBC-источникам можно использовать DAO совместно с ядром Microsoft Jet. В рабочем пространстве ODBCDirect для доступа к источникам данных ODBC допускается использование DAO без обработки запросов ядром Microsoft Jet. Использование DAO-модели для Microsoft Jet Рабочее пространство Microsoft Jet включает объекты (рис. 22.1), определяющие структуру базы данных: TableDef, Field, Index, QueryDef, Parameter и Relation. Здесь же находятся объекты, предназначенные для манипуляций с данными, например, Recordset. Для защиты данных предназначены такие объекты, как User, Group, Container и Document. Для создания рабочего пространства следует использовать метод Create Workspace объекта DBEngine со следующим синтаксисом: синтаксис Set workspace = CreateWorkspace(name, user, password [, type]) Аргумент name — строка с уникальным наименованием нового Workspace-объекта. Аргумент user — строка с именем владельца Workspace-объекта. Аргумент password — строка с паролем Workspace-объекта (до 14-ти символов). Необязательный аргумент type — значение одной из констант dbUseJet или dbUseODBC (по умолчанию — dbUseJet). В следующих операторах для указания используемого типа рабочего пространства применяется метод CreateWorkspace: Dim wrkJet As Workspace Set wrkJet = CreateWorkspace ("Jetworkspace", "admin", "") Объект Database Объект Database в модели DAO представляет открытую базу данных. Для открытия базы данных и получения ссылки на представляющий ее объект Database во всех приложениях (кроме Microsoft Access) следует использовать метод Open-Database объекта BDEngine или Workspace (на них можно не ссылаться для открытия базы в стандартном рабочем наборе). Синтаксис метода OpenDatabase следующий1: СИНТАКСИС Set database = [workspace.]OpenDatabase(dbname [, options] [, read-only] [, connect]) Здесь database — объектная переменная, ссылающаяся на Database-объект; workspace — объектная переменная, представляющая существующее рабочее пространство (по умолчанию — стандартное пространство). Единственный обязательный аргумент dbname — строка с именем существующего файла 1 Приведен полный синтаксис метода — не только для Microsoft Jet. 598 Глава 22 базы данных Microsoft Jet (mdb-файла) или DNS (data source name) ODBC-источника данных. Необязательный аргумент options устанавливает некоторые опции для базы данных: Для пространства Microsoft Jet можно использовать значения констант True (открывает базу для единоличного использования) и False (открывает базу для коллективного использования) — значение по умолчанию. Для пространства ODBCDirect можно использовать значения констант dbDri-verNoPrompt [ODBC Driver Manager1 использует строку соединения (connection string)2, предоставляемую аргументами dbname и connect. Если информации будет недостаточно, возникнет runtime-ошибка], dbDriverPrompt [ODBC Driver Manager отображает диалоговое окно ODBC Data Sources, которое содержит любую релевантную информацию, предоставляемую аргументами dbname или connect. Строка соединения состоит из DSN, которое пользователь выбирает посредством диалоговых окон. Если пользователь не указывает DSN, используется DSN по умолчанию.], dbDriverComplete (значение по умолчанию) [Если аргументы connect и dbname включают всю необходимую для соединения информацию, ODBC Driver Manager использует строку в connect. Иначе он действует, как в случае, когда указывается константа dbDriverPrompt] и dbDriverCompleteRequired [оказывает действие, подобное действию константы dbDriverComplete, за исключением того, что ODBC-драйвер запрещает запросы любых данных, которые не требуются для выполнения соединения]. Аргумент read-only — может принимать значение константы True для доступа «только на чтение» и — False (по умолчанию) для разрешения вносить изменения в базу. Аргумент connect — строковое выражение для определения информации о подключении, включая пароль. Объект BDEngine (или Workspace) позволяет не только открыть существующую базу данных Microsoft Jet, но и создать новую с использованием метода CreateDatabase со следующим синтаксисом: СИНТАКСИС Set database = [workspace.]CreateDatabase (dbname, locale [, options]) Здесь database — объектная переменная, ссылающаяся на Database-объект; ' workspace — объектная переменная, представляющая существующее рабочее пространство (по умолчанию — стандартное пространство). Аргумент dbname — строка с (полным) именем создаваемого файла базы данных Microsoft Jet (mdb-файла). Аргумент locale — строковое выражение, которое определяет порядок сортировки по умолчанию текстовых значений создаваемой базы данных; в качестве значений этого аргумента следует использовать константы dbLangGeneral, dbLangArabic, dbLangCyrillic и другие (см. справочную систему). Этот же аргумент можно использовать для задания пароля для создаваемой базы данных, конкатенируя значение необходимой константы со строкой вида ";pwd=NewPassword", например: , dbLangCyrillic & ";pwd=NewPassword" , 1 Приложение, которое управляет соединениями между источниками данных, доступными посредством ODBC, и драйверами, используемыми для доступа. 2 Строка, используемая для определения источника данных внешней базы и обычно назначаемая свойству Connect объектов QueryDef, TableDef, Connection или Database или аргументу метода OpenDatabase. Доступ к базам данных из VBA-кода 599 Необязательный аргумент options — константа (или комбинация констант), определяющая дополнительные свойства создаваемой базы данных. В качестве констант могут использоваться: dbEncrypt (база данных с шифрованными данными), dbVersionlO (используется формат файлов версии Microsoft Jet database engine 1.0), dbVersionll (используется формат файлов версии Microsoft Jet database engine 1.1), dbVersion20 (используется формат файлов версии Microsoft Jet database engine 2.0), dbVersion30 (значение по умолчанию, используется формат файлов версии Microsoft Jet database engine 1.0, совместимый с версией 3.5). Database-объект имеет свойства и методы, которые позволяют манипулировать данными открытой базы. Например, для любого типа базы данных можно использовать метод Execute для выполнения запроса-действия (action query)1 или задавать свойство Connect для установления связи с ODBC-источником данных. Для ограничения времени ожидания выполнения запроса для ODBC-источника данных можно использовать свойство QueryTimeout. Метод OpenRecordset позволяет выполнить запрос на выбор данных (select-запрос)2 и создает Recordset-объект. С базой данных Microsoft Jet (mdb-файл) можно также использовать такие методы и свойства (и коллекции) для манипулирования Database-объектами, как: методы CreateTableDef и CreateRelation для создания таблиц и связей; метод CreateProperty для определения новых Database-свойств; метод CreateQueryDef для создания постоянного (persistent) или временного определения запроса; методы MakeReplica, Synchronize и PopulatePartial для создания и синхронизации полных или частичных реплик3 базы данных; свойство CollatingOrder для установления алфавитного порядка сортировки полей, содержащих символьные данные. В рабочем пространстве ODBCDirect можно использовать: Свойство Connection для получения ссылки на объект Connection, который соответствует Database-объекту. Объект Recordset Объект Recordset представляет набор записей в базе данных и позволяет манипулировать данными базы на уровне записи. В DAO’ имеется пять типов Recordset-объектов: Table-type Recordset (табличный) — (только в рабочих пространствах Microsoft Jet) представление (в коде) базисной таблицы в базе данных. В рабочем пространстве Microsoft Jet объект Recordset этого типа можно использовать для добавления, удаления и обновления записей в таблице. Свойство Record-Count табличного объекта Recordset возвращает число записей в таблице. Dynaset-type Recordset (динамический набор) — результат запроса по одной или нескольким таблицам. Этот набор записей позволяет добавлять, модифицировать и удалять записи из входящей в него таблицы или таблиц. Объект 1 Запрос позволяет извлекать данные или изменять их в базе данных. 2 Запрос, который «отвечает на вопрос», какие данные хранятся в базе данных, и возвращает Recordset-объект без изменения данных. После нахождения Recordset-данных их можно проверять и изменять в основных таблицах. В отличие от этих запросов запросы-действия могут изменять данные, но не возвращают наборов данных. 3 Копия базы данных, включающая ее таблицы, запросы, формы, отчеты, макросы и модули. 600 Глава 22 Recordset этого типа можно создавать в рабочих пространствах Microsoft Jet и ODBCDirect. Snapshot-type Recordset (статический, набор) — результат запроса. Набор содержит значения всех полей, указанных в запросе. Данные в наборе нельзя модифицировать, но объект Recordset такого типа требует меньше ресурсов, чем динамический набор. Forward-only-type Recordset (статический набор с последовательным доступом) — результат запроса. Объект Recordset этого типа похож на Recordset статического набора, за исключением того, что по его записям можно «продвигаться» только в направлении от начала к концу набора. Dynamic-type Recordset (динамический) — (только в рабочих пространствах ODBCDirect) результат запроса из одной или более таблиц. Объект Recordset создается методом OpenRecordset объекта Database. Синтаксис метода следующий: СИНТАКСИС г; Set recordset = object. OpenRecordset (source [, type] [, options'] I, locked!ts]) Здесь recordset — объектная переменная, представляющая открываемый объект Recordset; object — объектная переменная, представляющая уже созданный объект, используемый для создания нового Recordset-объекта; source — строка, определяющая источник записей [имя таблицы или запроса, SQL-инструкция, возвращающая записи; для табличного объекта Recordset в базе данных Microsoft Jet допускается указание только имени таблицы в mdb-файле]. Необязательный аргумент type указывает тип объекта Recordset и может принимать значение одной из констант: dbOpenTable — для открытия Recordset-объекта типа «табличный»; dbOpenDynaset — для открытия Recordset-объекта типа «динамический набор»; dbOpenSnapshot— для открытия Recordset-объекта типа «статический набор»; dbOpenForwardOnly — для открытия Recordset-объекта типа «статический набор с последовательным доступом»; dbOpenDynamic — для открытия Recordset-объекта типа «динамический». Необязательный аргумент options определяет характеристики нового Recordset-объекта и может принимать значение одной из констант: dbAppendOnly — позволяет добавлять новые записи в набор, но не разрешает редактирование и удаление существующих записей (только для типа «динамический набор» Microsoft Jet); dbSQLPassThrough — передает SQL-инструкцию ODBC-источнику, доступному посредством Microsoft Jet (только для типа «статический набор» Microsoft Jet); dbSeeChanges— генерирует runtime-ошибку, если один пользователь изменяет данные, которые редактируются другим пользователем (только для типа «динамический набор» Microsoft Jet); dbDeny Write — не разрешает другим пользователям модифицировать и добавлять записи (только для Recordset-объекта Microsoft Jet); dbDenyRead — не разрешает другим пользователям считывать данные из таблицы (только для типа «табличный» Microsoft Jet); dbForwardOnly — создает статический набор с последовательным доступом (только для Recordset-объекта типа «статический набор» Microsoft Jet). Не Доступ к базам данных из УВА-кода 601 обходим только для обратной совместимости; при этом в качестве аргумента type нужно использовать значение константы dbOpenForwardOnly; dbReadOnly — не допускает внесение изменений в Recordset-объект (только для Microsoft Jet). Присвоение значения константы dbReadOnly аргументу lockedits заменяет эту константу, которая предназначена только для обратной совместимости; dbRunAsync — запускает асинхронный запрос (только для рабочего пространства ODBCDirect); dbExecDirect — выполняет запрос, пропуская SQLPrepare и вызывая непосредственно SQLExecDirect (только для ODBCDirect). Следует использовать эту опцию только для Recordset-объекта, не основанного на запросе с параметрами1; dblnconsistent — позволяет выполнять несогласованные обновления (только для Recordset-объекта типа «динамический набор» и «статический набор» Microsoft Jet); dbConsistent — позволяет выполнять только согласованные обновления (только для Recordset-объекта типа «динамический набор» и «статический набор» Microsoft Jet). Необязательный аргумент lockedits устанавливает тип блокировки данных и может принимать значение одной из констант: dbReadOnly — запрещает пользователям вносить изменения в Recordset-объект (только для рабочего пространства ODBCDirect). Можно использовать dbReadOnly либо в аргументе options, либо в lockedits, но не в обоих. В противном случае возникает runtime-ошибка; dbPessimistic — использует «пессимистическую» блокировку для определения порядка внесений изменений в Recordset в многопользовательской среде. Страница1 2, содержащая редактируемую запись, блокируется сразу при использовании метода Edit (по умолчанию для рабочих пространств Microsoft Jet); dbOptimistic — использует «оптимистическую» блокировку3 для определения порядка внесений изменений в многопользовательской среде. Страница, содержащая редактируемую запись, не блокируется, пока не используется метод Update; dbOptimisticValue — использует «оптимистический» параллелизм, основывающийся на значениях строк (только для рабочего пространства ODBCDirect); dbOptimisticBatch — позволяет выполнять «оптимистическое» обновление пакетов4 (только для рабочего пространства ODBCDirect). 1 Запрос, который требует предоставления одного или нескольких значений-критериев перед выполнением запроса. 2 Часть базы данных, в которой хранятся записи. В зависимости от размера записей страница может содержать более одной записи. В базах данных Microsoft Jet (mdb-файлы) страница имеет длину 2048 (2К) байтов. 3 Тип блокировки, при которой страница данных, содержащая одну или несколько записей, включая редактируемую запись, недоступна другим пользователям, только пока запись обновляется методом Update, но доступна между вызовами методов Edit и Update. «Оптимистическая» блокировка используется при доступе к ODBC-базам данных или, когда свойство LockEdit объекта Recordset равно значению константы False. 1 Модель курсора для клиентов, которые работают с курсорами, но не блокируют сервер или выдают обновление по одной строке. Вместо этого клиент обновляет несколько строк, которые буферизуются локально, а затем использует пакетное обновление. Эта модель курсора дает возможность пользователю отменять соединение с сервером и вновь устанавливать соединение с тем же или даже другим сервером. 602 Глава 22 Для работы с объектом Recordset необходимо знать его свойства и методы. Некоторые из них приведены в следующей таблице. Метод Описание AddNew Добавляет новую (пустую) запись. После внесения в поля записи данных следует вызвать метод Update. Close Закрывает Recordset-объект. Delete Удаляет текущую запись (которая была достигнута методами MoveFirst, MoveLast, MoveNext, MovePrevious, FindFirst, FindLast, FindNext, FindPrevious, Seek) в Recordset-объекте. Edit Устанавливает режим редактирования текущей записи Recordset-объекта. После редактирования записи следует вызвать метод Update. MoveFirst, MoveLast, MoveNext, MovePrevious Устанавливает в качестве текущей первую, последнюю, следующую или предыдущую запись Recordset-объекта, соответственно. FindFirst, FindLast, FindNext, FindPrevious Устанавливает в качестве текущей соответственно первую, последнюю, следующую или предыдущую запись, удовлетворяющую заданным условиям (в виде текстовой строки с условным выражением). Seek Устанавливает в качестве текущей запись, удовлетворяющую некоторым условиям, в индексированном Recordset-объекте типа «табличный». Update Сохраняет результаты методов AddNew и Edit. CancelUpdate Отменяет все изменения в Recordset-объекте, выполненные посредством методов AddNew и Edit. Свойство Описание BOF, (EOF) Возвращает значение константы True, если указатель текущей записи находится перед первой записью (после последней записи) набора. NoMatch Возвращает значение константы True, если необходимая запись найдена. RecordCount Возвращает количество записей в Recordset-объекте. Для получения подробной информации о методах и свойствах объекта Recordset следует обратиться к справочной системе или к многочисленным изданиям по программированию на VBA и VB. ' , Пример работы подключения VBA-кода к базе данных Рассмотрим пример использования объекта Recordset в Excel-приложении. В предыдущих двух главах была создана база данных и заполнены ее таблицы в среде Access. Воспользуемся таблицей Товары этой базы для вывода информации в диалоговом Excel-окне, которое в режиме разработки представлено на рис. 22.3. Доступ к базам данных из УВА-кода 603 Рис. 22.3 Форма в режиме разработки для тестирования методов объектов Database и Recordset Несмотря на то что форма довольно простая, приведем, как обычно, ее элементы управления в следующей таблице: Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание UserForm Name UserForml Имя главной формы, на которое можно ссылаться в коде. Frame Name Frame 1 Имя, на которое можно ссылаться в коде. Caption Список товаров Текст - заголовок. ListBox Name ListBox 1 Имя, на которое можно ссылаться в коде. CommandButton Name CmdLoad Caption Загрузить список Заголовок для кнопки. CommandButton Name CmdExit Caption Выход Заголовок для кнопки. Cancel True Клавиша Esc также вызовет процедуру CmdExit_Click. Код модуля этой формы, включающий две событийные процедуры, приведен в листинге 22.1. Листинг 22.1. Открытие существующей базы данных и считывание ее записей в элемент управления формы 1 Private Sub CmdLoad_Click() 2 3 Dim my_base As Database 4 Dim rstNwind As Recordset DAO-объект: база данных DAO-объект: набор данных 604 Глава 22 5 б ' открыть базу данных: 7 Set my_base = OpenDatabase("d:\dbs.mdb") 8 9 ' открыть набор: 10 Set rstNwind = my_base.OpenRecordset("Товары", dbOpentTable) 11 12 If rstNwind.RecordCount > 0 Then 13 14 rstNwind.MoveFirst ' перейти к началу набора 15 16 ' до конца набора добавлять записи в список 17 ‘ Do While Not rstNwind.EOF 18 ListBoxl.Additem rstNwind.Fields(1) 19 rstNwind.MoveNext '20 21 Loop 22 End If 23 24 End Sub 25 26 27 Private Sub CmdExit_Click() 28 Unload Me 29 End Sub В строках 1-24 описана событийная процедура для кнопки с заголовком «Загрузить список». В строках 3—4 описываются переменные my_base и rstNwind, одна из которых имеет тип Database, другая — Recordset. (Для успешной работы кода необходимо в окне References установить ссылку на Microsoft DAO 3.6 Object Library.) Код в строке 7 использует метод OpenDatabase объекта DBEngine, чтобы открыть существующую базу данных. Код в строке 10 открывает Recordset-объект rstNwind с записями таблицы Товары. В строке 12 проверяется условие наличия записей в наборе rstNwind. Пока не было обращения к записям набора, свойство RecordCount не содержит точного количества записей в наборе rstNwind, но, по крайней мере, его значение будет больше нуля, если в таблице Товары имеется хотя бы одна запись. Если записи в таблице Товары имеются, то выполняются строки кода 14-21: метод MoveFirst устанавливает текущей первую запись набора, далее в цикле считываются записи второго столбца таблицы с использованием коллекции Fields — полей набора, которым соответствуют кортежи отношения. В строке 17 находится заголовок цикла Do While, который в качестве условия окончания цикла использует значение свойства EOF набора rstNwind. В строке 19 применяется метод MoveNext объекта Recordset для перемещения к следующей записи набора. Результат работы процедуры CmdLoad_Click приведен на рис. 22.4. Рис. 22.4 Диалоговое окно в режиме исполнения для тестирования методов объектов Database и Recordset Доступ к базам данных из УВА-кода 605 В строках 27-29 описана событийная процедура кнопки с заголовком «Выход», которая просто завершает работу приложения. Рассмотрим подробнее строку 10 кода листинга 22.1, которая связывает с Re-cordset-объектом rstNwind набор записей таблицы Товары из mdb-базы данных: Set rstNwind = my_base.OpenRecordset("Товары", dbOpenTable) В этом операторе используется константа dbOpenTable для выбора Recordset-объекта rstNwind типа «табличный». В результате в набор попали все поля таблицы (все кортежи отношения) Товары, хотя нам, на самом деле, нужны были только наименования товаров. По этой причине в строке 18 при извлечении наименований из набора используется оператор, в котором указан номер второго поля набора: ListBoxl.AddItem rstNwind.Fields(1) Если данные всей таблицы Товары действительно не нужны, то набор rstNwind можно открыть другим оператором: Set rstNwind = my_base.OpenRecordset("SELECT НаименованиеТовара FROM Товары", dbOpenDynaset) И поскольку теперь коллекция Fields содержит только один элемент типа Field, оператор в строке 18 должен иметь вид: ListBoxl.Additem rstNwind.Fields(0) Что изменилось в вызове метода OpenRecordset? В качестве первого аргумента используется строка с SQL-запросом, поэтому переменная rstNwind ссылается на набор, состоящий из таблицы с одним столбцом. Но важно в данном случае то, что мы, вообще-то, можем использовать не только этот простой QSL-запрос, а любой — какой только нам будет нужен. Изменим немного рассматриваемую форму: добавим к форме текстовое окно для ввода строки и вместо элемента ListBox поместим на форму элемент MSFlexGrid, который позволяет выводить несколько столбцов таблицы (рис. 22.5). При этом таблица со свойствами элементов управления формы будет иметь следующий вид: Тип элемента Свойство, которое изменено(используется в коде) Значение Примечание UserForm Name UserForml Имя главной формы, на которое можно ссылаться в коде. Frame ' Name Frame 1 Имя, на которое можно ссылаться в коде. Caption Список товаров Текст - заголовок. MSFlexGrid Name MSFlexGrid 1 Имя, на которое можно ссылаться в коде. CommandButton Name CmdLoad Caption Загрузить список Заголовок для кнопки. CommandButton Name CmdExit Caption Выход Заголовок для кнопки. । 606 Глава 22 Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание Cancel True Клавиша Esc также вызовет процедуру CmdExit_Click. Label Name Label 1 Метка для TextBoxl. TextBox Name TextBoxl Текстовое окно для ввода строки с SQL-запросом. Рис. 22.5 Диалоговое окно в режиме разработки для тестирования методов объектов Database и Recordset С учетом свойств элемента MSFlexGrid событийная процедура кнопки с заголовком «Загрузить список» может выглядеть так, как приведено в листинге 22.2. Листинг 22.2. Открытие существующей базы данных и считывание ее записей в элемент управления формы MSFlexGrid 1 Private Sub CmdLoad_Click() 2 3 Dim my_base As Database ' DAO-объект: база данных 4 Dim rstNwind As Recordset ' DAO-объект: набор данных 5 Dim SQLstr As String 6 * 7 ' открыть базу данных: 8 Set my_base = OpenDatabase("d:\dbs.mdb") 9 10 ' ввести SQL-запрос: 11 SQLstr = TextBoxl.Text 12 13 1 11 открыть набор: 14 Set rstNwind = my base.OpenRecordset(SQLstr, dbOpenDynaset) 15 16 If rstNwind.Recordcount > 0 Then 17 18 rstNwind.MoveFirst ' перейти к началу набора 19 20 ' задать количество строк: 21 MSFlexGridl.Cols = rstNwind.Fields.Count + 1 22 Доступ к базам данных из УВА-кода 607 23 ' установить ширину первых колонок: 24 MSFlexGridl.ColWidth(0) = 1 25 ’ If MSFlexGridl.Cols > 1 Then MSFlexGridl.ColWidth(1) = 1500 26 If MSFlexGridl.Cols > 2 Then MSFlexGridl.ColWidth(2) = 2000 27 28 ' до конца набора добавлять записи в таблицу: 29 Do While Not rstNwind.EOF 30 31 ' сформировать элемент добавления к таблице: 32 newElement = "" 33 For i - 0 То rstNwind.Fields.Count - 1 34 newElement = newElement & Chr(9) & rstNwind.Fields(i) 35 Next 36 37 ' добавить элемент к таблице: 38 MSFlexGridl.Additem newElement 39 40 rstNwind.MoveNext 41 Loop 42 End If 43 44 End Sub В строке 11 приведенного кода считывается, возможно, строка с SQL-запросом, который затем используется в строке 14 в качестве аргумента метода OpenRecordset. В строке 21 задается свойство Cols (количество столбцов должно соответствовать количеству столбцов Recordset-объекта) объекта MSFlexGridl. В строках 24-26 задается ширина первых трех столбцов объекта MSFlexGridl. Эта часть кода существенно зависит от выводимых данных, поэтому ее трудно сделать универсальной. В строках 32-35 формируется строка для добавления в объект MSFlexGridl. Эта строка состоит из значений полей набора rstNwind (rstNwind.Fields.Count — количество полей в наборе), разделяемых символом табуляции. В строке 38 к объекту MSFlexGridl добавляется очередная строка с данными. Конечно, код процедуры CmdLoad_Click должен иметь обработчик прерываний для обработки ошибок, но для простоты кода этого не сделано, так как чаще всего такие естественные для разработчика элементы программного кода затеняют главную цель того или иного примера. На рис. 22.6 приведено диалоговое окно данного приложения, в котором в текстовое поле введена строка "Товары", т.е. здесь не используется SQL-инструкция, а просто указывается имя таблицы. В результате работы процедуры CmdLo-ad_Click в объекте MSFlexGridl отображаются все поля таблицы. Рис. 22.6 Диалоговое окно отображает все поля таблицы Товары UscrForml SQL-запрос ’ Товары Список товаров 006019165803 006019170049 010414114438 010415090732 010415090937 010428144348 028019095823 028019100018 (5) Road Rush II (5) Tasmania (VCD) Патриот (VCD) Пастырь (VCD) Шоссе в никуда (VCD) Доберман (VCD) Didrr Marouani (VCD) Wham1 The best of 028019100222 (VCD) Голая мишень 036019164741 (5) Cod Spot 174500175359 ) Street Fighter 3 Wimpact 42 30 138 111 120 135 90 105 90 42 750 130 15S 105 123 105 49 875 Загрузить список Выход 608 Глава 22 На рис. 22.7 приведен результат работы процедуры CmdLoad_Click, код которой использует (из текстового окна TextBoxl) следующий SQL_3anpoc: SELECT а.НаименованиеТовара, Ь.Количество FROM Товары а, Инвентарная_ведомость b WHERE а.КодТовара=Ь.КодТовара Рис. 22.7 Диалоговое окно отображает поля, полученные в наборе в результате SQL-запроса Userforml SQL-iarqjoc SELECT а НаименованиеТовара b Количество FROM Товары а, Инвентарная_ведомость b WHERE а КодТовара-! Список товаров (S) Road Rush II (5) Road Rush II \S) Tazmama (S) Tasmania (S) Tasmania (VCD) Патриот (VCD) Патриот (VCD) Доберман (VCD) Доберман (S) Cool Spot (S) Cool Spot 200 1200 1000 500 1000 400 3300 800 4200 2000 600 Загрузить список । Выход На рис. 22.8 приведен результат работы процедуры CmdLoad_Click, код которой использует (из текстового окна TextBoxl) следующий SQL_3anpoc: SELECT с.НаименованиеСклада, SUM(Ь.Количество) FROM Инвентарная_ведомость Ь, Склады с WHERE Ь.КодСклада=с.КодСклада GROUP BY с.НаименованиеСклада Рис. 22.8 Диалоговое окно отображает поля, полученные в наборе в результате SQL-запроса Пример создания базы данных из кода VBA Рассмотрим пример создания базы данных из кода VBA. Создавать базы данных из кода приходится в основном для каких-либо временных таблиц или для данных, которые существенно связаны с датами. Например, если создается база данных с накладными некоторой производственно-торговой фирмы, то есть смысл накладные для каждого отчетного периода (например, месяца) хранить в отдельных mdb-файлах. Относительно небольшой размер файла за период будет способствовать увеличению скорости обработки информации, а хранение данных в нескольких файлах поможет решить задачи надежности — при порче файла текущего периода информация, хранящаяся в файлах с данными предыдущих периодов (быть может, даже защищенных от записи), не пострадает. Впрочем, задачи эффективности и надежности не являются темами данной книги. Доступ к базам данных из VBA-кода 609 В листинге 22.3 приведен код простой процедуры, которая создает файл с именем test_mdb.mdb и таблицу Телефоны с тремя полями. Листинг 22.3. Создание базы данных из VBA-кода 1 Sub CreateDatabaseTest() 2 ' создает базу данных test_mdb.mdb с таблицей Телефоны 3 4 Dim myDatabase As Database 5 Dim myTable As TableDef 6 Dim myField As Field 7 8 ' создание базы данных: 9 On Error GoTo NotCreateBase 10 Set myDatabase = DBEngine.CreateDatabase("test_mdb", dbLangGeneral) 11 MsgBox "База данных test_mdb.mdb создана" 12 13 ' создание таблицы базы данных с тремя полями: 14 On Error GoTo NotCreateTable 15 16 Set myTable = New TableDef 17 18 With myTable 19 .Fields.Append .CreateField("Фамилия", dbText) 20 .Fields.Append .CreateField("Имя", dbText) 21 .Fields.Append .CreateField("Телефон", dbText) 22 End With 23 24 ' присвоить имя таблице: 25 myTable.Name = "Телефоны" 26 myDatabase.TableDefs.Append myTable 27 28 Set myDatabase = Nothing 29 .: 30 MsgBox "Таблица создана" 31 Exit Sub 32 33 NotCreateBase: 34 MsgBox "У нас проблема с созданием базы данных test_mdb.mdb" 35 Exit Sub 36 37 NotCreateTable: 38 MsgBox "У нас проблема с созданием таблицы" 39 40 End Sub В строках 4-6 описываются переменные типа Database (база данных), TableDef (определение таблицы) и Field (поле таблицы), место которых в модели DAO показано на рис. 22.1. Эти типы данных доступны в VBA-коде, если в окне References (меню Tools ] References) установлен флажок Microsoft DAO 3.6 Object Library. ' Для проверки того, поддерживается ли VBA-системой тот или иной тип данных, не следует торопиться набирать этот тип с клавиатуры. Лучше подождать после набора ключевого слова As, пока VB-редактор предложит выбрать поддерживаемый тип данных из всплывающего списка. Полезно также набирать наименования свойств и методов на одном регистре - если VB-редактор не изменяет отдельные символы в таких наименованиях, значит (из-за ошибки при вводе) они ему неизвестны. В строке 9 «включен» обработчик ошибок для сигнализации о том, что по каким-то причинам mdb-файл не создан. В строке 10 находится оператор, создающий 20 Программирование на VBA 2002 610 Глава 22 новую базу данных при помощи метода CreateDatabase объекта DBEngine. Если обработчик ошибки создания базы не запускается, значит, база создана, можно выполнять код дальше. При возникновении ошибки выполнение кода продолжается с оператора в строке 34: перед завершением процедуры выдается сообщение. В строке 14 устанавливается новый обработчик ошибок. В строке 16 создается новый объект типа TableDef. В строках 18-22 для нового объекта создаются три текстовых поля. В строке 25 новая таблица получает имя, а в строке 26 созданная таблица добавляется к базе данных. Доступ к источникам данных ODBC При доступе к данным ODBC рабочее пространство Microsoft Jet обеспечивает следующие (некоторые) возможности, отсутствующие в рабочем пространстве ODBCDirect: Обновляемые объединения: возможность модификации данных в Recodrset-объектах, представляющих объединения нескольких таблиц. Поддержка подключенных таблиц: возможность хранить в локальной базе данных Microsoft Jet постоянные связи с сервером баз данных с возможностями кэширования информации о структуре, полях и индексах подключенной таблицы в локальной базе данных. Поддержка методов поиска: доступность методов FindFirst, FindNext, Find-Previous и FindLast объекта Recodrset. * Нестандартные свойства: возможность добавлять новые свойства к существующим объектам. Перекрестные запросы: возможность использовать SQL-оператор TRANSFORM для создания перекрестных запросов. Доступ к неоднородным данным: возможность работать с удаленными данными, данными mdb-файлов и данными, доступными посредством устанавливаемых драйверов ISAM. Возможность объединять данные из разных источников. Язык определения данных (Data Definition Language, DDL): возможность модифицировать структуру базы данных. Технология ODBCDirect дает возможность осуществления доступа к удаленным данным посредством модели DA0 поверх интерфейса ODBC API, что позволяет устанавливать соединения, создавать курсоры и выполнять сложные процедуры при минимальном использовании ресурсов локального компьютера, минуя ядро Microcoft Jet. ODBCDirect имеет следующие преимущества: Прямой доступ: VBA-приложение может непосредственно обращаться к источникам данных ODBC, что позволяет повысит производительность, снизить сетевой трафик, переложить на сервер большую часть нагрузки по обработке данных. Улучшенный доступ к специфическим возможностям сервера: приложение получает доступ к функциям сервера баз данных, недоступным через Microsoft Jet. Например, можно задавать входные параметры для хранимых (на сервере) процедур и контролировать возвращаемые значения. Асинхронные запросы: после выдачи запроса, можно выполнять любой программный код, не дожидаясь результата запроса, время от времени проверяя, не завершен ли запрос. Пакетное обновление с нежесткой блокировкой (batch optimistic updating): приложение может локально кэшировать изменения объекта Recordset и передавать их на сервер единым пакетом. Выполнение хранимых процедур: приложение может обрабатывать возвращаемые значения и выходные параметры хранимых процедур. Доступ к базам данных из УВА-кода 611 Перед использованием ODBC необходимо зарегистрировать источник данных ODBC, информация о котором сохраняется в реестре и становится доступной всем приложениям. Зарегистрировать источник данных можно с помощью диспетчера источников данных ODBC или из VB-кода. В следующей главе показано, как зарегистрировать базу данных на удаленном сервере, а здесь в качестве примера зарегистрируем как источник ODBC базу данных d:\dbs.mdb, для работы с которой использовалась форма, представленная на рис. 22.5-22.8. Щелкните (один раз или дважды, в зависимости от настройки вашей системы) значок (рис. 22.9) диспетчера источников данных ODBC. Рис. 22.9 Значок диспетчера источников данных ODBC Data Sources (ODBC) i- .t Возможно, окно диспетчера источников данных ODBC будет похоже на представленное на рис. 22.10. Рис. 22.10 Возможно, окно диспетчера источников данных ODBC будет похоже на это окно ODBC Data Source Administrator User DSN ^System DSN File DSN ’ Drivers 1 Tracing | Connection Pooling About § User Data Sources Файлы dBASE 1 Файлы Excel Driver „„ _ , t_ Microsoft Access Driver (*mdb) Microsoft dBase Driver (* dbf) Microsoft Excel Driver (* xls) Bemove Configure A^d An ODBC User data source stores information about how to connect to the indicated data provider AUser data source is only visible to you andean only be used on the current machine j Help Щелкните кнопку Add (добавить) для добавления нового источника и в списке Select a driver for which you want to set up a data source (рис. 22.11) окна Create New Data Source выберите Microsoft Access Driver (*.mdb). Затем щелкните кнопку Finish. Рис. 22.11 В списке Select a driver for which you want to set up a data source выберите Microsoft Access Driver (*.mdb) 20* 612 Глава 22 В текстовом поле Data Source Name (Имя источника данных) окна ODBC Microsoft Access Setup (Установка драйвера ODBC для Microsoft Access) введите имя нового источника (то, на что из VB-кода мы будем ссылаться как на DSN), например, Test_dbs (рис. 22.12). Для выбора базы данных для ODBC-источника щелкните кнопку Select. Рис. 22.12 В текстовом поле Data Source Name окна ODBC Microsoft Access Setup введите имя нового источника В диалоговом окне Select Database очень просто указать базу данных (рис. 22.13). Рис. 22.13 В диалоговом окне Select Database очень просто указать базу данных Select Database Database N§me ^dbs mdb Directories d\ __— CD ads_win_zip О binom200099 ; cd girls I CD netsp ‘ Cd VBA_2002 CD VBprojects CD Vs6sp5vb I OK Cancel Help J [“ Read Only ( Exclusive List Files of Type Access Databases f mdl Drives 'Isa d Network В результате в окне ODBC Microsoft Access Setup можно будет увидеть то, что представлено на рис. 22.14, а в окне ODBC Data Source Administrator (рис. 22.15) появляется новый источник ODBC-данных — Test_dbs. Использование DAO-модели для ODBCDirect Модель объектов рабочего пространства ODBCDirect включает подмножество объектов рабочего пространства Microsoft Jet и объект Connection (см. рис. 22.2). Объект Workspace, содержащий коллекцию Connections, представляет рабочее пространство ODBCDirect и может быть включен в коллекцию рабочих пространств Workspaces. Доступ к базам данных из УВА-кода 613 Рис. 22.14 В диалоговом окне ODBC Microsoft Access Setup должна быть именно такая информация ODBC Microsoft Access Setup Data Source Цате Test_dbs Qescnption | Database Database D\dbsmdb , j Greats । Repair | Compact System Database • Nong Database Й8 OK Cancel Help Advanced 2ptions>> | Рис. 22.15 В окне ODBC Data Source Administrator появляется новый источник ODBC-данных — Test_dbs J-tODBC DataSource Administrator UserOSN | System DSN } File DSN Drivers Tracing j Connection Pooling About User DataSources ’Driver................. ___________ Microsoft Access Driver (*mdb) База данных MS Access Microsoft Access Driver (* mdb) Microsoft dBase Driver (* dbf) Microsoft Excel Driver (*xls) Name , Файлы dBASE Файлы Excel An ODBC User data source stores information about how to connect to the indicated data provider A User data source is only visible to you andean only be used on the current machine OK Cancel j Help Объект Connection является элементом коллекции Connections (все открытые объекты Connection), представляет соединение с источником ODBC в рабочем пространстве ODBCDirect и предоставляет следующие возможности для доступа к ODBC-данным: Асинхронное подключение. Программа может асинхронно подключаться к источнику данных ODBC, не ожидая установления, но впоследствии проверяя результат выполнения соединения. Асинхронные запросы. Программа может асинхронно выполнять запросы к ODBC-источнику, не ожидая выполнения длительных запросов, но впоследствии проверяя результат выполнения запроса. Объекты QueryDef. Для работы с данными ODBC-источника можно определять объекты QueryDef, представляющие запросы. Для создания объекта Connection следует использовать метод OpenConnection объекта Workspace с синтаксисом: .СИНТАКСИС’ Set connection = (workspace.]OpenConnection (dbname (, options] [, readonly] (, connect]) 614 Глава 22 Здесь connection — объектная переменная типа Connection, которая будет ссылаться на новое соединение. Необязательная переменная workspace — переменная типа Workspace, ссылающаяся на рабочее пространство, которое будет содержать новое соединение. Аргумент dbname — строковое выражение, определяющее имя зарегистрированного источника данных. Необязательный аргумент options определяет, следует ли и когда выдавать запрос на подключение, следует ли устанавливать асинхронное соединение. Для этого аргумента предусмотрены следующие константы: dbDriverNoPrompt — ODBC Driver Manager (диспетчер драйверов ODBC) использует строку подключения, исходя из содержимого аргументов dbname и connect. и dbDriverPrompt — ODBC Driver Manager выводит на экран диалоговое окно ODBC Data Sources, которое отображает любую релевантную информацию, содержащуюся в dbname или connect. Строка подключения (connection string) определяется DSN, выбранным пользователем в этом окне. dbDriverComplete — (значение по умолчанию) Если аргумент connect включает всю необходимую информацию для выполнения соединения, ODBC Driver Manager использует в качестве строки соединения значение аргумента connect. В противном случае поведение диспетчера аналогично поведению при использовании константы dbDriverPrompt. dbDriverCompleteRequired — Использование этой константы имеет такой же результат, как и при использовании dbDriverComplete, но ODBC-драйвер блокирует запросы любой информации, которая не требуется для завершения подключения. dbRunAsync — Выполнять метод асинхронно. Может использоваться с любой другой options-константой. Необязательный аргумент readonly (тип Boolean) определяет режим доступа: при значении True — доступ только на чтение; при False (значение по умолчанию) — на чтение и запись. Необязательный аргумент connect — строка подключения, содержащая параметры для диспетчера драйверов ODBC. Она может включать имя пользователя, пароль, имя базы данных по умолчанию и имя источника данных, переопределяющее значение аргумента dbname. Строка подключения начинается с "ODBC;" и содержит последовательность именованных параметров, необходимых драйверу для доступа к данным. Состав именованных параметров зависит от источника данных, но как минимум, требуются идентификатор пользователя (UID), пароль (PWD) и имя источника данных (DSN). Если аргумент не указывается, значения UID и/или PWD берутся из свойств UserName и Password объекта Workspace. Для полученного в предыдущем разделе ODBC-источника данных с именем Test_dbs событийная процедура CmdLoad_Click из листинга 22.2 может быть переписана, как показано в листинге 22.4. Листинг 22.4. Открытие существующей базы данных и считывание ее записей в элемент управления формы MSFlexGrid 1 Private Sub CmdLoad__Click () 2 3 Dim my_wrk As Workspace 4 Dim my cnn As Connection 5 Dim ConnectStr As String 6 Dim rstNwind As Recordset Доступ к базам данных из УВА-кода 615 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Dim SQLstr As String Dim newElement As String, i As Integer Connectstr = "ODBC;DSN=Test_dbs;UID=;PWD=" ' ввести SQL-запрос: SQLstr = TextBoxl.Text Set my_wrk = DBEngine.CreateWorkspace("NewODBCDirect" , __ "sa", dbUseODBC) Set my_cnn = my_wrk.OpenConnection("Test_dbs" , _ dbDriverNoPrompt, False, ConnectStr) ' открыть набор: Set rstNwind = my_cnn.OpenRecordset(SQLstr, dbOpenDynaset) rstNwind.MoveLast ' перейти в конец набора для иницализации Recordcount If rstNwind.Recordcount > 0 Then rstNwind.MoveFirst ' перейти к началу набора ' задать количество строк: MSFlexGridl.Cols = rstNwind.Fields.Count + 1 1 установить ширину первых колонок MSFlexGridl.ColWidth(0) = 1 If MSFlexGridl.Cols > 1 Then MSFlexGridl.ColWidth(1) = 1500 If MSFlexGridl.Cols > 2 Then MSFlexGridl.ColWidth(2) = 2000 ' до конца набора добавлять записи в список Do While Not rstNwind.EOF « 1 сформировать элемент добавления: newElement = "" For i = 0 To rstNwind.Fields.Count - 1 newElement = newElement & vbTab & rstNwind.Fields(i) Next 1 добавить элемент к таблице: MSFlexGridl.Additem newElement rstNwind.MoveNext Loop End If End Sub Этот пример приведен только для демонстрации использования ODBC-источника данных. Аналогичным образом можно в качестве источника данных ODBC использовать файл в dbf-формате. Microsoft ADO Основным методом доступа к разделяемым файлам и базам данных кли-ент/сервер становятся технология ActiveX Data Objects (ADO) и OLE DB, пришедшие на смену прикладному интерфейсу программирования Open Database Connectivity (ODBC). Технология ADO является еще одной моделью доступа к базам данных и представляет собой объектно-ориентированный интерфейс для технологии доступа к данным OLE DB. ADO поддерживает ключевые возможности для построения клиент/серверных и Web-приложений, а также обеспечивает функции Remote Data Service (RDS), посредством которого можно перемещать данные с сер 616 Глава 22 вера в клиентское приложение или на Web-страницу, манипулировать данными «на стороне клиента» и возвращать обновленные данные серверу. В данном разделе речь пойдет о самой малой части возможностей этой технологии для доступа к базам данных. Для более детального ознакомления с ActiveX Data Objects и OLE DB можно воспользоваться как справочной информацией, так и многочисленными изданиями по разработке баз данных для приложений Windows. На рис. 22.16 показано окно Object Browser с несколькими первыми членами класса Connection библиотеки ADODB. Обратите внимание на наличие событий в окне Members of'Connection' [Для того чтобы можно было увидеть объекты библиотеки ADODB в окне Object Browser, необходимо в окне References установить ссылку на Microsoft ActiveX Data Object 2.7 Library.] Рис. 22.16 Окно Object Browser с несколькими первыми членами класса Connection библиотеки ADODB апопв obj»c- AJ Member Class Search Results | Library? ~~~~~ Classes ° <globals> iP ADCPROP_ASYNCTHRE^ i/3 ADCPROP_AUTORECAL( ADCPROP-UPDATECRITI ADCPROPJJPDATERES'i AffectEnum iP BookmarkEnum ьЬ Command лЛ CommandTypeEnum iP ConnectModeEnum Members nf Connection ВЗЁ* Attributes BeymTrans f BeginTransComplete Cancel Close Э? CommandTimeout CommitTrans V CommitTransComplete £ ConnectComplete aS* Connectionstring Й? ConnectionTimeout CursorLocation Class Connection Member of Как видно из модели ADO (рис. 22.17), вместо иерархии объектов здесь имеется независимый набор объектов (и коллекций). Причем объект Error и коллекция Errors, объекты Recordset и Fields (и их коллекции) имеют аналоги и одно и то же назначение в моделях DAO и ADO. Объект ADO Connection соответствует объекту DAO Workspace, а объект ADO Command похож на DAO QueryDef. Однако свойст- Рис. 22.17 Объекты и коллекции модели ADO [connection] - [ Errors |—| Erroi ~| _| Properties |—| Property"] | Command*] - ) Parameters |—| Parameter] _| Propertied]—| Property-] | Recordset] - | Fields |—| Field ~| - | Properties [—| Property*] | Record | L| Fields |—| Field ~] Stt earn Доступ к базам данных из УВА-кода 617 ва и методы объектов ADO явно отличаются от свойств и методов соответствующих объектов модели DAO, хотя рассмотренные при изучении модели DAO понятия очень пригодятся при освоении модели ADO. Объект Connection Объект Connection — основной объект ADO верхнего уровня. Именно с него начинается подключение к источнику данных, после чего можно использовать связанные с соединением объекты Command или Recordset. Объект Connection имеет следующие свойства1: Attributes Определяет использование транзакций и может быть суммой XactAttributeEnum-значений: adXactAbortRetaining (новая транзакция запускается при вызове метода RollbackTrans), adXactCommitRetaining (новая транзакция запускается при вызове метода CommitTrans). Значение по умолчанию равно 0 — поддерживающие транзакции не используются. Command-Timeout Определяет время (в секундах), через которое прекращается неуспешное выполнение метода Execute соответствующего объекта Command (тип Long). Значение по умолчанию — 30. Connection-String Строка с информацией, необходимой для провайдера2, чтобы открыть соединение с источником данных. Пример: "Provider=MSDASQL;DSN=dsnName;UID=userName; PWD=userPassword;" Connection-Timeout Определяет время (в секундах), через которое прекращается неуспешная попытка установки соединения (тип Long). Cursor-Location Определяет используемый механизм курсора (элемент базы данных, определяющий «перемещение» по записям) и может быть одним из CursorLocationEnum-значений: adUseClient [курсор на стороне клиента], adUseNone [не использовать механизм курсора], adUseServer [курсор на стороне сервера, значение по умолчанию] (тип Long). Default-Database Определяет имя базы данных по умолчанию для объекта Connection, если оно не было указано в Connectionstring, (тип String). Isolation- Level Определяет поведение транзакций, которые взаимодействуют с другими одновременно выполняющимися транзакциями, и может быть одним из IsolationLevelEnum-значений: adXactUnspeci-fied [провайдер использует различные уровни транзакции, которые нельзя определить], adXactChaos [транзакция не будет переписывать изменения, выполненные транзакциями более высокого уровня изоляции], adXactBrowse [разрешается чтение незафиксированных изменений в других транзакциях], adXactReadUncom-mitted [то же назначение, что и у adXactBrowse], adXactCursor-Stability [разрешается чтение только зафиксированных изменений в других транзакциях], adXactReadCommitted [то же назначение, что и у adXactCursorStability], adXactRepeatableRead [разрешается чтение изменений в других транзакциях], adXact-Isolated [все транзакции не зависят от других (изолированных) транзакций], adXactSerializable [то же назначение, что и у adXactlsolated] (тип Long). 1 Как и для других объектов, приведены все свойства, несмотря на то, что некоторые из них в этой книге не обсуждаются и не используются. 2 Термин, к которому можно привыкать постепенно, сначала подразумевая под ним «драйвер». 618 Глава 22 Mode Определяет режим доступа на чтение и запись для объектов Connection, Record или Stream1 и может быть одним из ConnectModeEnum-значений: adModeRead [режим с разрешением только чтения], adModeReadWrite [режим с разрешением чтения и записи], adModeRecursive, adModeShareDenyNone [разрешает другим пользователям открывать соединение с любым режимом доступа], adModeShareDenyRead [запрещает чтение данных другими пользователями], adModeShareDenyWrite [Запрещает другим пользователям открывать соединение с правами на запись], adModeShareExclusive [режим монопольного использования], adModeUnknown [режим по умолчанию; указывает на то, что не установлены никакие разрешения на соединение], adModeWrite [режим с разрешением только записи] (тип Long). Provider Строка, указывающая имя провайдера (если он не задан в строке Connectionstring). По умолчанию используется значение MSDASQL (Microsoft OLE DB Provider for ODBC). State Указывает состояние соединения: открыто или закрыто. Возвращает значение (типа Long) и может быть одним из ObjectStateEnum-значений: adStateClosed [объект закрыт — значение по умолчанию], adStateOpen [объект открыт], adStateConnecting [объект соединяется], adStateExecuting [вызван метод Execute объекта Connection или Command], adStateFetching [в объект Recordset возвращаются строки]. Version Указывает номер версии объектной модели ADO (тип String). Объект Connection имеет следующие методы: BeginTrans Запускает транзакцию. 1 Cancel Отменяет вызов асинхронного метода. Close Закрывает открытый объект и любые зависимые объекты. | CommitTrans Завершает транзакцию, закрепляя изменения в источнике данных. Разрешает запуск новой транзакции. I Execute Выполняет определенный запрос: SQL-инструкцию, хранимую процедуру или текст, определяемый провайдером. | Open Открывает соединение с источником данных. Open Schema Возвращает информацию о схеме базы данных. 1 RollbackTrans Отменяет любые изменения, выполненные во время транзакции, и завершает транзакцию (отменяет транзакцию). Разрешает запуск новой транзакции. Поскольку технология ADO представляет собой объектно-ориентированный интерфейс, объект Connection имеет события, которые полезны для перехвата ошибок, при выполнении асинхронных операций с базами данных и в других случаях. В этой книге не рассматриваются вопросы использования событий при работе с базами данных, а читателю, конечно же, следует изучить эту тему самостоятельно, не дожидаясь следующего издания данной книги. Для подключения к источнику данных можно использовать метод Open объекта Connection библиотеки ADO. При этом необходимо посредством свойства 1 Представляет поток двоичных или текстовых данных. Доступ к базам данных из УВА-кода 619 ConnectionString предоставить информацию об источнике в виде строки подключения, подобной строке подключения ODBC. Провайдера данных можно указать также в свойстве Provider. Это должна быть строка с типом провайдера OLE DB для подключения. При использовании провайдера ODBC для OLE DB его можно вообще не указывать, так как он используется по умолчанию. Однако хорошим «тоном» считается указывать провайдера явно. Строка подключения (свойство ConnectionString) в ADO применяется для подключения к серверу базы данных. При использовании провайдера ODBC для OLE DB строка подключения должна быть точно такой же, как и строка подключения ODBC. Например, в коде листинга 22.5 используется провайдер ODBC для OLE DB. Строка подключения включает только имя источника данных, указанное в диалоговом окне ODBC Microsoft Access Setup в текстовом поле Data Source Name (рис. 22.14). Листинг 22.5. Открытие ADO-соединения с ODBC-источником 1 Dim cn As ADODB.Connection 2 3 Function ADODB_ConnectedODBC () As Boolean 4 ' устанавливает соединение для ODBC 5 Set cn = New ADODB.Connection 6 7 On Error GoTo err_not_connection 8 9 Set cn = New ADODB.Connection 10 cn.Provider = "MSDASQL" 11 cn . ConnectionString = " DSN==Test dbs; " 12 cn.Open 13 • 14 ADODB__ConnectedODBC = True 15 Exit Function 16 17 err_not_connection: 18 ADODB_ConnectedODBC = False 19 20 End Function 21 22 23 Sub Main_ADODB() 24 ' тестирует ADODB_ConnectedODBC 25 26 If ADODB__ConnectedODBC () Then 27 MsgBox "Похоже, соединение установлено..." 28 29 1 код, использующий установленное соединение: 30 ... 31 cn.Close ' закрыть соединение 32 Else 33 MsgBox "Что-то не сложилось с соединением!" 34 35 ' код, который не использует соединение: 36 ... 37 38 End If 39 40 End Sub Функция ADODB_Connected только открывает соединение и возвращает значение константы True, если не возникает ошибка при подключении к источнику данных. Поскольку ошибки при подключении к источникам данных — дело обыч- 620 Глава 22 ное, следует всегда не забывать вставлять в код операторы, реагирующие на возможные отказы для улучшения «отношений» между пользователем и разрабатываемым для него приложением. Процедура Main_ADODB вызывает функцию ADODB_Connected и выполняет тот или иной код, основываясь на возвращаемом функцией значении. В этой же процедуре открытое соединение закрывается методом Close (строка 31). Код листинга 22.6 отличается от кода листинга 22.5 только использованием другого провайдера — Microsoft .Jet. OLEDB. 4.0 (строка 11). Имя функции AD0-DB_ConnectedODBC, предназначенной для установления соединения, изменено на ADODB_Connected J et. Листинг 22.6. Открытие ADO-соединения с использованием Jet-провайдера 1 Dim cn As ADODB.Connection 2 3 Function ADODB_ConnectedJet() As Boolean 4 ' устанавливает соединение для Jet-провайдера 5 6 Set cn = New ADODB.Connection 7 8 On Error GoTo err_not_connection 9 10 Set cn = New ADODB.Connection 11 cn.Provider = "Microsoft.Jet.OLEDB.4.0" 12 cn.Connectionstring = "d:\dbs.mdb" 13 cn.Open 14 15 ADODB_ConnectedJet = True 16 Exit Function 17 18 err_not_connection: 19 ADODB_ConnectedJet = False 20 21 End Function 22 23 Sub Test_ADODB_Connected() 24 ' тестирует ADODB_Connected: устанавливает соединение и 25 ' использует данные из таблицы Товары 26 27 If ADODB_ConnectedJet() Then 28 MsgBox "Похоже, соединение установлено..." 29 ' код, использующий установленное соединение: 30 31 Set rs = New ADODB.Recordset 32 rs.CursorType = adOpenDynamic ‘ 33 rs.Source = "SELECT * FROM Товары" 34 Set rs.ActiveConnection = cn 35 rs.Open 36 37 MsgBox rs.Fields(1) & " " & rs.Fields(1).Name & " " & rs.Fields(1).Type 38 39 cn.Close ' закрыть соединение 40 Else , 41 MsgBox " Что-то не сложилось! " 42 End If 43 44 End Sub ADO-объект Command предназначен для выполнения параметризованных хранимых процедур в виде временных операторов или постоянных SQL-операто- Доступ к базам данных из УВА-кода 621 ров, предварительно скомпилированных. В данной книге этот объект не рассматривается, но читателю настоятельно рекомендуется ознакомиться с этим объектом и его коллекциями, используя справочную систему. В некоторой степени можно использовать также книги по разработке приложений, связанных с базами данных, в системе программирования Visual Basic. Одним из наиболее полезных методов (после Open, конечно) объекта Connection является метод Execute/имеющий следующий синтаксис: ^СИНТАКСИС -и... ... . и невозвращающий набор: connection.Execute CommandText [, RecordsAffected} возвращающий набор (объект Recordset): Set recordset = connection.Execute (CommandText [, RecordsAffectedi) Аргумент CommandText — строка, содержащая SQL-инструкцию, имя таблицы, хранимой процедуры, URL или текст, определяющий провайдера. Необязательный аргумент RecordsAffected — переменная типа Long, в которую провайдер возвращает число записей, принимающих «участие» в операции. Пример использования метода Execute приведен далее при рассмотрении объекта Recordset, поскольку именно при помощи этого объекта можно легко увидеть результат выполнения метода Execute. Объект Recordset Конечной целью большинства приложений, использующих базы данных, является создание просмотр и обновление наборов записей. ADO-объект Recordset предназначен, как и в модели DAO, для доступа к наборам записей в источнике данных (можно говорить «к информации, предоставляемой провайдером»). ADO-объект Recordset имеет довольно много свойств, методов и событий, которые вряд ли можно освоить одновременно и сразу. Скорее, на их изучение уйдет много времени и этому должна быть посвящена специальная книга. Те же свойства и методы, которые дают понятные и самые необходимые результаты, приведены ниже. Свойства ADODB.Recortset ActiveConnection Указатель на открытое соединение, которому соответствует объект Recordset. BOF При равенстве значению константы True означает то, что указатель записи установлен перед первой записью (строкой) набора и нет текущей записи. Bookmark Значение (типа Variant), возвращающее ссылку на определенную запись. CacheSize Определяет число записей в локальной памяти (КЭШе) для уменьшения числа обращений к серверу (тип Long). 622 Глава 22 CursorType Определяет тип курсора набора и может принимать значение одной из CursorTypeEnum-констант: adOpenDynamic [используется динамический курсор; отображаются добавления, изменения и удаления, выполняемые другими пользователями; все типы перемещения по записям набора доступны, за исключением перемещения на закладку, если его не поддерживает провайдер], adOpenForivardOnly [набор с однонаправленным перемещением курсора и записей только для чтения], adOpenKeyset [подобен динамическому курсору, но данные, добавляемые другими пользователями, скрываются, данные, удаляемые другими, недоступны, а изменяемые — остаются видимыми], adOpenStatic [используется статический курсор; статическая копия набора записей для нахождения данных и генерации отчетов; добавления, изменения или удаления данных другими пользователями невидимы]. По умолчанию используется значение константы adOpenForwardOnly (тип Long). EditMode Возвращает состояние редактирования набора и может принимать значение одной из EditModeEnum-констант: adEditNone [операции редактирования не выполняются] (значение по умолчанию), adEditlnProgress [текущая запись редактировалась, но не сохранена], adEditAdd [использовался метод AddNew, в буфере копирования находится новая 1 запись, которая не была сохранена в базе данных], adEditDelete [текущая запись была удалена] (тип Long). EOF При равенстве значению константы True означает то, что указатель записи установлен за последней записью набора и нет текущей записи. RecordCount Возвращает количество записей (тип Long) в объекте Recordset. Sort Строка, содержащая SQL-выражение предложения ORDER BY без самих зарезервированных слов и определяющая порядок сортировки записей набора. Source Строка, содержащая SQL-инструкцию, имя таблицы, хранимой процедуры или связанного объекта Command. Методы ADODB.Recortset AddNew Добавляет новую запись к изменяемому набору данных. Clone Создает копию объекта Recordset с независимым указателем записи. Close Закрывает объект Recordset. Delete Удаляет текущую запись из набора. Find Ищет записи, удовлетворяющие некоторому критерию. GetRows Возвращает двумерный массив (строки и столбцы) записей (тип Variant). GetString Возвращает разделяемую табуляцией строку для указанного количества записей. Move Перемещает указатель записи с текущей записи. MoveFirst Перемещает указатель записи к первой записи. Доступ к базам данных из УВА-кода 623 MoveLast Перемещает указатель записи к последней записи. MoveNext Перемещает указатель записи к следующей записи. MovePrevious Перемещает указатель записи к предыдущей записи Open Открывает набор данных активного объекта Connection (или Command). Save Создает файл, содержащий копию набора записей. Update Применяет результат модификации набора записей. UpdateBatch Применяет результат всех модификаций набора записей пакетного типа. : Коллекция Field как свойство объекта Recordset Прежде чем подробно рассмотреть некоторые свойства и методы объекта Recordset, следует отметить коллекцию Fields, которую можно рассматривать как свойство этого объекта. Именно посредством этого свойства можно из кода VBA получить доступ к данным, хранящимся в полях записей. Коллекция Fields имеет одно свойство Count (количество полей набора Recordset) и два метода: Item (указывает определенный элемент коллекции) и Refresh (обновляет объект в коллекции). Свойства объекта Fields (см. справочную систему) в основном предназначены для чтения, например свойство Name, возвращающее имя поля в наборе, или свойство Туре, возвращающее тип поля. Наиболее часто используется свойство Valua (возвращающее значение поля), которое имеет статус «только для чтения» в наборах данных с последовательным доступом и наборах, открытых с блокировкой «только для чтения». Далее рассматриваются некоторые свойства и методы объекта Recordset. В листинге 22.7 процедура Test_ADODB_Connected (из листинга 22.5) дополнена строками 10-16 для считывания информации из таблицы Товары. В строке 10 создается объект rs типа Recordset; в строке 11 свойству CursorType объекта rs присваивается значение константы adOpenDynamic. В строке 12 определяется SQL-выражение для указания считываемых полей из источника данных (в этом случае — все поля таблицы Товары). В строке 13 посредством свойства Active-Connection объекта rs назначается открытое соединение сп, а в строке 14 набор rs открывается методом Open. В строке 16 используется свойство Value объекта rs.Fields(l) — значение второго по порядку поля набора rs. Ключевое слово здесь не указано, так как это свойство применяется по умолчанию. Свойство rs.Fields(l).Name в строке используется для получения наименования второго поля набора, a rs.Fields(l).Type — для типа поля. В строке 18 методом Close соединение сп закрывается. Листинг 22.7. Открытие ADO-соединения и считывание информации из таблицы базы данных 1 2 3 4 5 6 7 8 9 10 11 1 Sub Test_ADODB_Connected() 2 1 тестирует ADODB_ConnectedODBC: устанавливает соединение и 3 ' использует данные из таблицы Товары 4 5 6 If ADODB_ConnectedODBC() Then 7 MsgBox "Похоже, соединение установлено..." 8 ' код, использующий установленное соединение: 9 10 Set rs = New ADODB.Recordset 11 rs.CursorType = adOpenDynamic 624 Глава 22 12 rs.Source = "SELECT * FROM Товары" 13 Set rs.ActiveConnection = cn 14 rs.Open 15 16 MsgBox rs.Fields(l) 4 " "4 rs.Fields(1).Name 4 " "4 rs.Fields(1) .Type 17 18 cn.Close ' закрыть соединение ► 19 Else 20 MsgBox "Что-то не сложилось!" 21 End If 22 23 End Sub Для формы, показанной на рис. 22.5, теперь можно написать код, представленный в листинге 22.8. Процедура CmdLoad._Click для установления соединения при помощи ADO и провайдера для ODBC1 11 использует функцию ADODB_Connected-ODBC. Листинг 22.8. Открытие ADO-соединения и считывание информации в элемент управления MSFIexGrid 1 Dim cn As ADODB.Connection 2 3 4 Function ADODB_ConnectedODBC() As Boolean 5 1 устанавливает соединение для ODBC 6 Set cn - New ADODB.Connection 7 8 On Error GoTo err_not_connection 9 10 Set cn = New ADODB.Connection 11 cn.Provider = "MSDASQL" 12 cn.Connectionstring = "DSN=Test_dbs;" 13 cn.Open 14 . ' 15 ADODB_ConnectedODBC = True 16 Exit Function 17 18 err_not_connection: 19 ADODB_ConnectedODBC = False 20 21 End Function 22 23 ’ 24 Private Sub CmdExit_Click() 25 Unload Me 26 End Sub 27 28 29 Private Sub CmdLoad_Click() 30 31 Dim rstNwind As ADODB.Recordset 32 Dim newElement As String, i As Integer 33 34 If Not ADODB_ConnectedODBC() Then 35 MsgBox "Что-то не сложилось!" 36 Exit Sub 37 End If 1 В следующей главе будет использоваться провайдер для SQL Server. Доступ к базам данных из УВА-кода 625 38 39 40 Set rstNwind = New ADODB.Recordset 41 42 ' открыть набор: 43 rstNwind.Open TextBoxl.Text, cn 44 45 rstNwind.MoveFibst ' перейти к началу набора 46 47 ' задать количество строк: 48 MSFlexGridl.Cols = rstNwind.Fields.Count + 1 49 50 ' установить ширину первых колонок 51 MSFlexGridl.ColWidth(0) = 1 52 If MSFlexGridl.Cols > 1 Then MSFlexGridl.ColWidth(1) = 1500 53 If MSFlexGridl.Cols > 2 Then MSFlexGridl.ColWidth(2) = 2000 54 55 ' до конца набора добавлять записи в список 56 Do While Not rstNwind.EOF 57 58 ' сформировать элемент добавления: 59 ’ newElement = "" 60 For i = 0 To rstNwind.Fields.Count - 1 61 newElement = newElement & vbTab & rstNwind.Fields(i) 62 Next 63 64 ' добавить элемент к таблице: 65 MSFlexGridl.Additem newElement 66 67 rstNwind.MoveNext 68 Loop 69 70 End Sub В отличие от предыдущего примера здесь имеется возможность в качестве свойства Source указать строку, вводимую во время работы приложения в текстовое окно. Как и ранее, в это текстовое окно можно ввести SQL-инструкцию для выбора данных из нескольких таблиц для определенных записей. В строке 43 записан оператор для открытия набора rstNwind: rstNwind.Open TextBoxl.Text, cn Ранее вместо этого использовались операторы, подобные следующим: rstNwind.Source = TextBoxl.Text Set rstNwind.ActiveConnection = cn rstNwind.Open Для примера использования метода Execute объекта Connection добавим к форме, которая приведена на рис. 22.5, текстовую строку и кнопку с наименованием «Выполнить инструкцию» (рис. 22.18). Событийная процедура кнопки «Выполнить инструкцию» содержит всего один оператор (кроме заголовка и оператора окончания процедуры): Private Sub CommandButtonl_Click() cn.Execute TextBox2.Text End Sub Таким образом, эта процедура использует содержимое текстового окна Text-Вох2 в качестве аргумента CommandText метода Execute и выполняет этот метод для соединения сп. Конечно, необходимо предусмотреть обработчик ошибок в этой процедуре, так как пользователь может ввести неверную инструкцию, но сейчас это не очень важно. 626 Г лава 22 Рис. 22.18 Форма для тестирования приложения с использованием метода Execute объекта Connection в режиме разработки Для тестирования приложения следует выполнить: запустить приложение; в окне SQL-запрос ввести строку "Товары"; щелкнуть кнопку Загрузить список; ввести в нижнем окне SQL-инструкцию INSERT INTO Товары (КодТовара, НаименованиеТовара) VALUES ('1','Совсем новый товар1) щелкнуть кнопку Выполнить инструкцию; щелкнуть кнопку Загрузить список; Если все сделать так, как указано, в окне списка Список товаров можно будет увидеть новый товар (рис. 22.19). Рис. 22.19 Форма для тестирования приложения с использованием метода Execute объекта Connection в режиме выполнения Далее можно вводить любые релевантные SQL-инструкции, например DELETE FROM Товары WHERE КодТовара»'1 ' Эта инструкция удалит запись, которая содержит в поле КодТовара значение "1". Добавлять записи в набор можно не только SQL-инструкцией для метода Connection.Execute. Это позволяет сделать метод AddNew объекта Recordset, который имеет следующий синтаксис: Доступ к базам данных из VBA-кода 627 СИНТАКСИС recordset.AddNew [FieldList] [, Values] Необязательный аргумент FieldList — одно имя, массив имен или порядковых номеров полей в новой записи. Необязательный аргумент Values — одно значение или массив для полей в новой записи. Если Fieldlist — массив, Values должен быть тоже массивом с тем же самым количеством элементов. Обычно аргументы этого метода не используются. Чаще всего метод применяется для добавления пустой записи, а затем запись редактируется, как в следующем примере. Изменим форму, приведенную на рис. 22.19: вместо текстового окна и кнопки в нижней части формы поместим на форму текстовые окна и кнопку для ввода данных, как показано на рис. 22.20. При этом таблица со свойствами элементов управления формы будет иметь следующий вид: Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание UserForm Name UserForm 1 Имя главной формы, на которое можно ссылаться в коде. Frame Name Framel Имя, на которое можно ссылаться в коде. Caption Список товаров Текст - заголовок. MSFlexGrid Name MSFlexGridl Имя, на которое можно ссылаться в коде. CommandButton Name CmdLoad Caption Загрузить список Заголовок для кнопки. CommandButton Name CmdExit Caption Выход Заголовок для кнопки. Cancel True Клавиша Esc также вызовет процедуру CmdExit_Click. Label Name Labell Метка для TextBoxl. TextBox Name TextBox1 Текстовое окно для ввода строки с SQL-запросом. Frame Name Frame2 Имя, на которое можно ссылаться в коде. Caption Добавление записи Текст - заголовок. Label Name Label2 Метка для TextBox2. Label Name Lab el 3 Метка для TextBox3. Label Name Label4 Метка для TextBox4. TextBox Name TextBox2 Текстовое окно для ввода кода товара. TextBox Name TextBox3 Текстовое окно для ввода наименования товара. 628 Глава 22 Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание TextBox Name TextBox4 Текстовое окно для ввода цены товара. CommandButton Name CmdAdd Кнопка для добавления записи. Caption Добавить Заголовок кнопки. Рис. 22.20 Форма для тестирования приложения с использованием метода AddNew объекта Recordset в режиме разработки В листинге 22.9 приведен код модуля формы, которая отображена на рис. 22.20. В строках 81-93 описана событийная процедура CmdAdd_Click, которая добавляет к набору новую (пустую) запись (строка 84), а затем, используя содержимое текстовых окон TextBox2, TextBox3 и TextBox4, изменяет содержимое полей этой записи (строки 87-89). Код строки 91 добавляет запись в базу данных. Листинг 22.9. Добавление данных в таблицу, отображаемую в объект Recordset 1 Dim cn As ADODB.Connection 2 Dim rstNwind As ADODB.Recordset 3 4 Function ADODB_ConnectedJet () As Boolean 'i 5 ' устанавливает соединение для Jet-провайдера 6 7 Set cn = New ADODB.Connection 8 / 9 On Error GoTo err_not_connection 10 11 Set cn = New ADODB.Connection 12 cn.Provider = "Microsoft.Jet.OLEDB.4.0" 13 cn.Connectionstring = "d:\dbs.mdb" 14 cn.Open 15 16 ADODB_ConnectedJet = True 17 Exit Function 18 19 err_not_connection: 20 ADODB_ConnectedJet = False Доступ к базам данных из VBA-кода 629 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 End Function Private Sub CmdExitClick() rstNwind.Close cn.Close » Unload Me End Sub < Private Sub CmdLoad_Click() ' загрузка списка записями набора Dim newElement As String, i As Integer If Not ADODB_ConnectedJet() Then MsgBox "Что-то не сложилось!" Exit Sub End If Set rstNwind = New ADODB.Recordset rstNwind.Source = TextBoxl.Text rstNwind.LockType = adLockOptimistic Set rstNwind.ActiveConnection = cn rstNwind.Open ' открыть набор: 1 rstNwind.Open TextBoxl.Text, cn rstNwind.MoveFirst ' перейти к началу набора ' задать количество строк: MSFlexGridl.Cols = rstNwind.Fields.Count + 1 ' установить ширину первых колонок MSFlexGridl.ColWidth(0) = 1 If MSFlexGridl.Cols > 1 Then MSFlexGridl.ColWidth(1) = 2500 If MSFlexGridl.Cols > 2 Then MSFlexGridl.ColWidth(2) = 2000 ' до конца набора добавлять записи в список Do While Not rstNwind.EOF ' сформировать элемент добавления: newElement = "" For i = 0 To rstNwind.Fields.Count - 1 newElement = newElement & vbTab & rstNwind.Fields(i) Next ' добавить элемент к таблице: MSFlexGridl.Additem newElement rstNwind.MoveNext Loop End Sub Private Sub CmdAdd_Click() ' добавление записи (без проверки уникальности кода) 630 Глава 22 84 rstNwind AddNew ' добавить пустую запись в набор 85 86 ' редактирование данных в добавленной записи 87 rstNwind Fields(0) - TextBox2.Text 88 rstNwind Fields(1) = TextBox3 Text 89 rstNwind Fields(2) = TextBox4 Text 90 91 rstNwind Update ' сохранить запись * 92 93 End Sub Одним из наиболее «интересных» методов объекта ADODB.Recordset являет ся метод Save, который записывает данные набора в файл и имеет следующий синтаксис: СИНТАКСИС recordset Save FileName, PersistFormat Здесь FileName — полное имя файла для записи, PersistFormat — значение константы, определяющей формат файла: adPersistADTG (является значени ем по умолчанию и указывает на формат, являющийся собственностью Advanced Data Tablegram) или adPersistXML (XML-формат). Далее рассматривается пример использования метода Save объекта ADODB.Re-cordset. Для этого предлагается создать диалоговое окно на базе формы, представленной на рис. 22.21. В следующей ниже таблице описаны некоторые свойства элементов управления формы. Рис. 22.21 Форма для тестирования приложения с использованием методов ASave и Open объекта Recordset в режиме разработки Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание UserForm Name UserForm2 Имя главной формы, на которое можно ссылаться в коде. Caption Тестирование Recorset.Save ListBox Name ListBoxl Окно для отображения списка. CommandButton Name CmdLoad Имя кнопки. Доступ к базам данных из УВА-кода 631 Тип элемента Свойство, которое изменено (используется в коде) Значение Примечание Caption Запись в файл Заголовок для кнопки. CommandButton Name CmdClear Имя кнопки. Caption Очистить список Заголовок для кнопки. CommandButton Name CmdRead Имя кнопки. Caption Чтение из файла Заголовок для кнопки. CommandButton Name CmdExit Имя кнопки. Caption Выход Заголовок для кнопки. Cancel True Клавиша Esc также вызовет процедуру CmdExit Click. Label 1 Name Label 1 Caption Структура базы d:\dbs.mdb В листинге 22.10 представлен код модуля формы. Алгоритм работы с формой очень простой: при щелчке на кнопке Запись в файл посредством кода процедуры CmdLoad_Click (27-54) создается набор rstNwind в результате вызова метода OpenSchema объекта сп типа Connection (строка 38). После создания его записи помещаются (строки 42-54) в список (рис. 22.22) и сохраняются в XML-файле c:\rstNwindSave.xml (строка 49) методом Save. Набор rstNwind и соединение сп закрываются (строки 58, 59). Листинг 22.10. Использование методов Save и Open объекта Recordset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Dim cn As ADODB.Connection Function ADODB_ConnectedJet() As Boolean ' устанавливает соединение для Jet-провайдера Set cn = New ADODB.Connection On Error GoTo err_not_connection Set cn = New ADODB.Connection cn.Provider = "Microsoft.Jet.OLEDB.4.0" ’ ' cn.Connectionstring = "d:\dbs.mdb" cn.Open ADODB_ConnectedJet = True Exit Function err_not_connection: ADODB_ConnectedJet = False End Function Private Sub CmdExit__Click () Unload Me 632 Глава 22 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44. 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 End Sub i Private Sub CmdLoad_Click() Dim rstNwind As ADODB.Recordset Dim newElement As String, i As Integer If Not ADODB_ConnectedJet() Then * MsgBox "Что-то не сложилось!" Exit Sub End If ' открытие набора с данными о структуре базы данных: Set rstNwind = cn.OpenSchema(adSchemaTables) ' добавление элементов набора в список: Do Until rstNwind.EOF ListBoxl.Additem "Table name: " S _ rstNwind!TABLE_NAME S vbCr S _ "Table type: " S rstNwind!TABLE_TYPE 4 vbCr rstNwind.MoveNext Loop ' запись набора в файл: rstNwind.Save "c:\rstNwindSave.xml", adPersistXML rstNwind.Close ’ закрыть набор cn.Close ' закрыть соединение End Sub Private Sub CmdRead_Click() ' чтение набора из файла Dim rstNwind As New ADODB.Recordset Dim newElement As String, i As Integer ' открытие набора с данными о структуре базы данных: rstNwind.Open "с:\rstNwindSave.xml" ' добавление элементов набора в список: Do Until rstNwind.EOF ListBoxl.Additem "Table name: " & _ rstNwind!TABLE_NAME & vbCr & _ "Table type: " & rstNwind!TABLE_TYPE & vbCr rstNwind.MoveNext Loop rstNwind.Close ' закрыть набор End Sub , , Private Sub CmdClear_Click() f ListBoxl.Clear End Sub Доступ к базам данных из УВА-кода 633 Рис. 22.22 Форма для тестирования приложения с использованием методов ASave и Open объекта Recordset в режиме выполнения Тестирование Recorset.Save , Структура базы d \dbs mdb < Table name MSysAccessObjectsDTable type ACCESS TABLED Table name MSysAccessXMLDTable type ACCESS TABLED Table name MSysACEsDTable type SYSTEM TABLED Table name MSysObjects^Table type SYSTEM TABLED Tbble name MSysQuenesDTable type SYSTEM TABLED j Table name MSysRelatlonshipsDTable type SYSTEM TABLED Table name 3anpoclDTable type VIEWD « Table name ЗапросHDTable type VIEWD Запись в файл Очистить список Выход После загрузки набора в окно списка и файл можно щелкнуть*на кнопке Очистить список для удаления элементов из списка процедурой CmdClear_Click (строки 80-82). В этот момент приложение никак не связано с базой данных, а в файле c:\rstNwindSave.xml хранятся записи ранее используемого набора. На рис. 22.23 часть этого файла показана при помощи приложения Internet Explorer. Рис. 22.23 Так выглядит файл С \rstNwindSave xml в приложении Internet Explorer после записи с использованием методов ASave и Open объекта Recordset Seai ch Favorites Media - 1C VstNwridSave xinl low TABU? НАНЕ- КонтрКАгеитьГ TABLE ГУРЕ - TABLE" ПАН- < SEATED 2ОО2-11-21ТОО:2О:22 DATE- I1ODLI1ED 2003-03-12Т21:26:49 / - rm И ABIE ПАНЬ НаклЗаголовки 1МЧ1 ПРЬ- TABLE LATE: CREATED- 2002-11-21Т00 48’42 ГАТЕ 2002- 12-17T01:58.47 / / iov TADir.HAHE- НаклСпецификации TABLE.JI ffl TABLE DAIIJKIAIID 2002-ll-21T00:25:20 DAI LJIO01T (Lb- 2002-12-17T02:01’41 / z ro ' TABLE ПАНГ- Склады TABLE TYTC- TABLE DAIL MAUD- 2002-ll-17T07:23’18 DAU IKDIHID 2002-12-10T09:21 13 / z row TABLE HAHI - Товары (ABIE ПИ TABLE DATE ( REAIED- 2002-11-17T07.24’27 DA|l I1<*DIHED 2002- 12-10T09:21:21 / I I Кг» ! />1111 Done My Computer Теперь можно щелкнуть на кнопке Чтение из файла. Процедура CmdRe-ad_Click (строки 64-85) откроет набор rstNwind (но уже с использованием в качестве источника файла c:\rstNwindSave.xml) и заполнит окно списка. В этой главе представлена очень малая часть информации о доступе к базам данных из УВА-кода. Заканчиваем главу с надеждой на будущую возможность посвятить этим вопросам гораздо больше времени и книжных страниц. Глсва 23 Работа с SQL Server Как отмечалось в главе 20, «Введение в базы данных», если вы являетесь зарегистрированным пользователем SQL Server, то при помощи Excel-мастера подключения внешних данных и наличии у вас соответствующих полномочий вы можете загрузить в Excel данные из базы, расположенной на SQL Server. В этой главе рассматриваются вопросы, связанные с использованием SQL Server, как обычной сетевой СУБД, к которой вы можете обращаться-посредством своего собственного кода на языке Visual Basic. Рассмотрим некоторые положения, связанные с наиболее популярной реляционной системой управления базами данных типа клиент/сервер SQL Server (впрочем, это относится ко всем клиент/серверным СУБД). На следующем рисунке (подготовлен в Microsoft Visio 2000) представлена компьютерная сеть, состоящая из сервера и трех персональных компьютеров, которые связаны с сервером. В реальной ситуации персональных компьютеров может быть довольно много. Сервер также может быть не один как по количеству, так и по типу. Здесь имеется в виду SQL Server. Причем термины «клиент» и «сервер» относятся и программному, и к аппаратному обеспечению. Программное обеспечение сервера базы данных обрабатывает запросы, инициализируемые программным обеспечением клиента, посылая результат обработки запросов клиенту. Рис. 23.1 Компьютерная сеть, состоящая из сервера и трех персональных компьютеров Программное обеспечение клиента «подсоединяется» к программному обеспечению сервера, делает запрос, получает результат и обрабатывает его, возможно, выводя на экран некоторые из полученных данных. Одним из хороших примеров программного обеспечения клиентской части может служить Microsoft Access, хотя, на самом деле, с использованием языка VBA и драйверов ODBC к SQL Server может «достучаться» любое приложение Microsoft. На компьютере сервера запускается программное обеспечение сервера базы данных SQL Server. Программное обеспечение клиента базы данных SQL Server Работа с SQL Server 635 может быть также запущено с компьютера сервера. На следующем рисунке показано взаимодействие программного обеспечения сервера и клиентов. Компьютер клиента, работающий под управлением какой-либо ОС (Windows 95/98, 2000, Windows NT Server, Windows NT Workstation, Windows 3.1 или MS-DOS), запускает клиентское приложение SQL Server. Это приложение посылает запросы на SQL Server, принадлежащий компьютеру сервера, который работает под управлением ОС Windows 95/98, 2000, Windows NT Server, или Windows NT Workstation и запускает все типы приложений, включая приложение клиента и сервера. Рис. 23.2 Взаимодействие программного обеспечения сервера и клиентов Computer Клиентское приложение SQL-Server SQL Server Пользователей базы данных, которая обслуживается сервером, может быть много. Данные в базе могут быть в целях сохранности и безопасности закрыты частично или полностью (по крайней мере, для обновления) от различных категорий пользователей. Для этого в SQL Server имеются соответствующие механизмы, в том числе так называемые представления и хранимые процедуры, которые, как и таблицы базы данных, могут быть доступны или недоступны определенным группам пользователей. Представления — это своеобразные фильтры, отображающие данные базы. Клиенту можно вообще закрыть всякий доступ к самим таблицам базы и разрешить доступ только посредством представлений. С помощью таких фильтров можно скрыть некоторые данные от клиента. Хранимые процедуры являются программами, которые работают на сервере и вызываются либо приложением клиента, либо правилами, поддерживающими целостность данных, или триггерами. Хранимые процедуры применяют в работе мощные аппаратные решения SQL Server и обеспечивают высокую производительность при обработке данных. Как представления, так и хранимые процедуры пишутся на одном из диалектов языка SQL. Менеджер, работающий с клиентским приложением, должен знать параметры доступа к данным (логическое имя и пароль, зарегистрированные на сервере администратором), которые доступны ему, согласно его функциональным обязанностям. Если менеджеру необходимы дополнительные способы обработки данных, он может обратиться либо к разработчику клиентской, либо разработчику серверной части СУБД. 636 Глава 23 Для приобретения навыков работы с SQL Server ее можно установить на от-, дельный персональный компьютер, создать собственную базу данных и написать для нее клиентское приложение. Зачем пользователю, освоившему VBA для Excel или Word, необходимо научиться работать с SQL Server? Представьте такую ситуацию. Ваша фирма приобрела или уже давно использует вычислительную сеть, в которой некоторые данные хранятся на SQL Server. Сервер обслуживают очень грамотнее и недоступные специалисты, с которыми не так просто установить контакт, особенно, если они работают не на вашей фирме, а выполняют работу по договору. Вы трудитесь на своем компьютере, который при помощи достаточно громоздкой системы управления базой данных «добывает» данные в той форме, какая была предусмотрена при разработке СУБД (назовем ее для важности «большая» СУБД). По мере вашего роста как специалиста (допустим, вы — менеджер или работаете как программист в помощь менеджеру) у вас появилась потребность не только извлечь некоторые данные из базы, но и представить (или даже предварительно переработать!) их так, как не было предусмотрено при разработке «большой» СУБД. Хотя в данный момент времени вы можете не достаточно четко представлять, в какой форме вам нужно получить отчет по тем или иным данным. Какое решение имеет эта гипотетическая проблема? Ответ — очень простое! Необходимо поставить задачу «программисту со стороны серверной части» (если у вас нет доступа к отдельным таблицам всей базы) по извлечению необходимых вам данных, получение же этих данных, их обработку и формирование соответствующих отчетных форм вы можете осуществить, «не покидая» привычный вам Microsoft Office. Если же эта книга попадет в руки начинающему программировать системы управления базами данных при помощи продуктов Microsoft, то эта глава может дать ему некоторые начальные знания по SQL Server, которые пробудят у читателя желание серьезно заняться изучением и применением SQL Server. Начинать работать с SQL Server можно на своем домашнем компьютере, так как версия SQL Server 7.0 (Desktop) предназначена для систем Windows NT и (что более радостно) Windows 95/98 (конечно же, пока еще большинство домашних компьютеров работают под управлением этой системы). Здесь будут рассмотрены задачи построения программ как «со стороны клиента», так и «со стороны сервера». Даже если вы не собираетесь программировать серверные части приложений, знать о том, что это не так уж и сложно (конечно, речь — о простых приложениях), все равно полезно. Вообще, специалист в любой области не должен быть очень «узким», в этом случае ему трудно бывает общаться со специалистом «узким» в другой области, если вдруг им необходимо участвовать в совместной работе. Если вы наотрез отказываетесь программировать с использованием SQL Server, то поймите эту «кухню» хотя бы для того, чтобы грамотно объяснить «серверным» программистам, что вы от них хотите получить. А, вообще-то, если вы еще не поняли, SQL Server здесь «ни причем». Работать из Microsoft Office можно, практически, с любыми системами баз данных. Просто именно сейчас и именно для этой книги в качестве примера было удобнее выбрать SQL Server, тем более, что это — не самая плохая система; скорее — наоборот. Если вы серьезно решили (или это решили за вас) заниматься разработкой баз данных, то можете не задумываться над тем, с чего начать. Устанавливайте на компьютер и начинайте изучать самую современную и одну из мощнейших систем управления базами данных. Она вполне подойдет как для работы на отдельном компьютере, так и в сети — локальной и всемирной. f Установить SQL Server на компьютер очень просто Установка Desktop-версии SQL Server на локальный компьютер не труднее установки программы WinZip и ей подобных. При этом термин «локальный» совсем не означает, что вы не можете установить SQL Server на компьютер, работающий Работа с SQL Server 637 в сети. Было бы даже очень неплохо, если бы вы, имея дома сеть (хотя бы из двух компьютеров), установили SQL Server на один из компьютеров (под Windows 98), азатем «пользовали» его с другого удаленного на всю длину квартиры (или многоквартирного дома) компьютера. Как и при установке многих других продуктов, диалоговые окна, сопровождающие установку, часто не похожи. Но поскольку в данном случае процесс установки не представляет никаких трудностей, не будем подробно на нем останавливаться. При возникновении у вас каких-либо проблем, используйте литературу, специально посвященную SQL Server, например, книгу Тихомирова Ю.В. «Microsoft SQL Server 7.0 — СПб.: БХВ — Санкт-Петербург, 2000». Базы данных в SQL Server Данные в SQL Server хранятся в базах данных. Физическая реализация базы представляет собой несколько файлов на диске, хотя от пользователя данных этот факт скрыт (если пользователь с этим согласен). В SQL Server, кроме пользовательских, имеются несколько встроенных (системных) баз, одними из которых являются master, model, tempdb и msdb. На рис. 23.3 с помощью утилиты SQLServer Enterprise Manager показан состав баз данных SQL Server до того, как пользователь создал свою первую базу. Если при установке указать использование баз-примеров, то в качестве пользовательских можно увидеть и другие базы. Рис. 23.3 Системные базы данных SQL Server 7 ..... ТЧМШЖД—Х] Retort Mew Jools fr» ч ®|ra * x i* q i (5 fe(r I .» О Ж Й 4 Hems ____I Console Foot Ь Microsoft 5QL Servers F, SQL Server Group Г- gg VOVA. (Windows Э5/Э8) г- ♦ U master Л (j model + msdb T tempdb й- Г1 Data Transformation I Management 4, 1 Security + | Support Services Ll........................ J 2J master msdb Как системные, так и пользовательские базы данных в SQL Server располагаются в различных объектах, к основным из которых относятся (рис. 23.4): Таблицы (Tables) Представления (Views) » Хранимые процедуры (Stored Procedures) Расширенные хранимые процедуры (Extended Stored Procedures) Пользователи (Users) Роли (Roles) » Правила (Rules) » Умолчания (Defaults) » Типы данных, определенные пользователем (User Defined Data Types) » Диаграммы базы данных (Database diagrams) 638 Глава 23 Рис. 23.4 Основные объекты базы данных в SQL Server ЯГ SQL Server Enterprise Manager - (Сотой RootXMicrosoft SQL Se... BOE3 . Console Window (Help s I £dron View Tools ' 4 . 1 itpm [SQL Server Gtoupj ___J Lonj.ole Root I liuosoft SQL Servers - ,J-~——— - ВЛАДИМИР (Windows 95/98) - 1 Databases - (J master □ Tables dxf1 Views S Stored Procedures Extended Stored ocedures Users Roles D Rules f””l Defaults C User Defined Data Types + tJ model + msdb + [J tempdb * Data Transformation Services i+ । Management + ____| Security * I Support Services ВЛАДИМИР (Windows 95/98) Таблицы базы данных являются местом хранения бизнес-данных, организованных на этапе проектирования базы в логически связанные между собой двумерные таблицы. Представление — это способ получения данных из базы, результатом которого является (виртуальная) таблица, полученная из (возможно) многих таблиц базы данных. Представление позволяет, кроме защиты данных, представлять данные по-разному для разных пользователей. Хранимая процедура — это подпрограмма, работающая на сервере. Одним из результатов работы хранимой процедуры может быть возвращение таблицы подобно тому, как это делает представление. Как и обычная подпрограмма, хранимая процедура может принимать аргументы. Пользователи — это объекты, которые содержат имена, пароли и другие атрибуты, представляющие пользователей базы данных. Роли — это именованный набор прав в рамках сервера или конкретной базы данных. Правила — это механизм контроля данных при вводе их в базу. Правила позволяют поддерживать порядок работы, принятый в организации, эксплуатирующей базу данных. Умолчания используются для заполнения незаданных полей таблицы при вставках новых записей. Например, вы можете не знать цены на товар, который хотите зарегистрировать заранее. В этом случае можно для поля цены задать нулевое значение по умолчанию и не использовать код для выполнения этой операции, поскольку она будет автоматически выполнена сервером. Пользователи SQL Server могут на основе существующих определять собственные типы данных, называемые типы данных, определенные пользователем. Диаграммы базы данных создаются при помощи утилиты SQL Server Enterprise Manager в диалоговом режиме и позволяют просматривать таблицы базы данных и связи между ними, выполнять модификацию структуры и состав объектов базы данных. Работа с SQL Server 639 Основные этапы работы с SQL Server Работа с SQL Server состоит из непосредственной работы на сервере и написании программного обеспечения так называемой клиентской части, которая будет создавать запросы (обычно с посредством пользовательского интерфейса) для сервера и принимать и представлять полученную информацию. Основные этапы работы непосредственно с сервером можно выполнить при помощи утилиты SQL Server Enterprise Manager или языка T-SQL. Они состоят из: создания базы (или нескольких) данных — набор таблиц; написания представлений и хранимых процедур для обработки данных на сервере; установления прав доступа для каждого элемента базы данных. Основная работа, связанная с построением клиентской части, состоит из создания интерфейса и написания программ для взаимодействия с серверной частью. Создание базы данных при помощи Server Enterprise Manager Конечно, в больших коллективных системах управления базами данных созданием новых баз занимается только администратор, но, вряд ли, ему придется читать данную книгу. И поскольку это издание предназначено для начинающего разработчика баз данных, то ему на своем персональном компьютере можно делать все, что душе угодно, т.е. во много раз больше, чем может позволить себе многоопытный и ответственный администратор баз данных. Создание базы — обычный процесс (конечно, без учета этапа проектирования) описания таблиц и их взаимных связей — в данном случае выполняется, как и во многих других СУБД. При этом можно воспользоваться теми таблицами, которые вы, быть может, ранее применяли в других системах, например, Microsoft Visual FoxPro, Paradox (начиная с версии III), dBase (версии Ш-IV), Microsoft Access и Excel и просто текстовые файлы. С вновь созданной базой при помощи утилиты SQL Server Enterprise Manager можно работать таким же образом, как во многих других оболочках систем управления базами данных. Эта утилита может быть использована почти для всех административных операций с локальными или удаленными базами данных. Для работы с SQL Server Enterprise Manager сначала следует запустить SQL Server Service Manager и щелкнуть на кнопке Start/Continue (рис. 23.5). Теперь можно загрузить Server Enterprise Manager. Рис. 23.5 Для работы с SQL Server Enterprise Manager сначала следует запустить SQL Server Service Manager |fcSQL Seivei Sei vic* Мопдце» Services. [н-.-.QLuer/er Г” Ли(о itart j-ervice when OS starts \W0VA MOSQLSeivei Running Далее щелкните правой кнопкой мыши на компоненте Databases в окне SQL Server Service Manager и из контекстного меню выберите New Database (рис. 23.6). 640 Глава 23 Рис. 23.6 Для создания новой базы данных щелкните правой кнопкой мыши на компоненте Databases в окне SQL Server Service Manager и из контекстного меню выберите New Database Tif Console RootVMicrecaft SQL ServerslSQL Serve* GrocjpWll.. j v/jCton View Joo!5 <<“ ly ryA » 0 iC C8 4 Rems ...,1 Console Root i-д Microsoft SQL Servers - <J SQL Server Group “ gg VOVA [Windows Э5/ЭВ) master ♦ < I Data Tran New Database i J Manageme + ц I Security ..+ Support Se AB Tasks View ..New jwndow fiurn here Refresh В текстовом окне Name диалогового окна Database Properties введите новое имя базы данных, например, УчетТоваров, как на рис. 23.7. Теперь можно щелкать на кнопке ОК, в результате чего вы сразу увидите, что значок новой базы данных отображается в окне SQL Server (рис. 23.8). Рис. 23.7 Диалоговое окно Database Properties для создания новой базы данных Рис. 23.8 Значок новой базы данных в окне SQL Server Enterprise Manager Consol* RootVMicrosoft SQL S«rv«is\SQL 6niu^\VHV ТТ5Г1 ficton Vew look О l (tj ® > * (3 C? i±._^0JjC3 7 Items | Console Root Microsoft SQL Servers H SQL ^wvef Group / a gg VOVA (Windows 95/98J + jESESSSI + I Data Transformation Services j- О Management < + и Security + 2j Support Services d tempdb d J УчетТоваров Vj Dore Работа с SQL Server 641 Создать в базе данных таблицу не сложнее, чем — базу данных. Щелкните правой кнопкой мыши на имени базы в окне SQL Server Enterprise Manager и в контекстном меню выберите сначала New, а затем — Table (рис. 23.9). Рис. 23.9 Создать в базе данных таблицу не сложнее, чем базу данных 7b Console RootVMicrosoft SQL SawrtVSQL Swvar EhoupWOVA (Windows Э5... НЙ Action View £ools Ф5 ftT| Q7[ Й* Q CP фсз On Dias ГП ТаЫИ Viev\ Store (f? User Role A E3 Rule □ Oefc C User &• 2J Data Transit It, } Managemen + I Security — New Database JMew All Tasks View New window horn here delete Refresh Properties Help ineral Tables & Indexes Database User Database Rgle Database Diagran) Tabb. View Stored Procedure rdf- A Ryle Default User Defined Data Txpe Publication Pull Subscription Spa_^j В окне Choose Name (рис. 23.10) введите имя таблицы, например, Товары. Теперь вам ничто не мешает описать каждое поле таблицы подобно тому, как это делается в Microsoft Access, но с немного другими типами данных для полей (рис. 23.11). По окончании формирования таблицы щелкните на значке, расположенном слева от меню Console, и выберите из появляющегося меню команду Close. В дальнейшем вы всегда можете редактировать таблицу, выбрав ее из иерархического меню, щелкнув правой кнопкой мыши на значке таблицы и выбрав из контекстного меню Design Table, как показано на рис. 23.12. Рис. 23.10. В окне Choose Name введите имя таблицы 21 Программирование на VBA 2002 642 Глава 23 Рис. 23.11 Описание структуры таблицы в SQL Server >^2:НешТаЫет'ЦчетТоварое‘оп VOVA' _________ jBISEij й c Column Name | Datatype | Length | Precision | Scale Allow Nul *| КодТовар char 12 0 0 » НаименованиеТовара char 50 0 0 ЦенаОптовая топе/ 8 19 4 7“ ЦенаРозничная money 19 4 Рис. 23.12 В дальнейшем вы всегда можете редактировать таблицу, выполнив команду Design Table ТЬ Consol* RoolKMicrosolt SUL Servois\SUL Soivm GroupWUVA (Wrufom Action yiew Tool* <=> & о ® ca - .J '-НетТоБаров ZZj Diagrams Zj Table; 6тГ views Stored Procedures Users ^2 Roles И Rules ГП Defaults User Defined Data Types + 1 Data Transformation Services +i I Management + 1 Security ZJ sysindexkeys Zj sysmembers ZJ sysobiects ZJ syspermissions ZJ sysprotects ZJ sysreferences ZJ systypes ZJ sysusers Hew Table Design Table Open Table Own₽r Ж1 dbo dbo dbo dbo dbo dbo dbo dbo dbo Full T ext Index Table “II Tasks Copy Delete R ei юте Properties Создать таблицу в вашей базе на SQL Server можно и по-другому: просто импортировав ее из любой ранее созданной базы данных. Это может быть основным способом создания таблиц, если вы, например, решите все свои разработки по базам данных в других СУБД перенести на SQL Server. На рис. 23.13 показано, как Рис. 23.13 Из контекстного меню выбрать операцию импорта таблицы Contote Ro<rt\Micrw*«fl SQL S«vm«\SQL Ssivm br«j*WUVA (Wm4wt Action 2ew Tools New Datafca*© New Import Data. C? □ Й> General AITasfes; New window from here Relate Relie$t Pipperliet --------1..T"UPt<j User . i Data Transfo . I Management 1 Security I Support Serv-es Export Data Maintenance Pla i Generate SQL Scitph Backup Database Restore Database Truncate Log Shirk Datable p-v Ftepbsiuti£unfli f$ x »о ®ca Tables & Indexes Space Allocated УчетТоваров Database ase properties database did yr am shrink database import data owner sa Date 1003 03 created 1 b 35 3u Size 2M0 Space 0 66MB available Database d Работа с SQL Server 643 из контекстного меню выбрать операцию импорта таблицы. После выбора вами Import Data вас «окружит своей заботой» соответствующий «помощник» и перепись таблицы из баз многих форматов покажется вам приятным занятием. В главе 20, «Введение в базы данных», рассмотрен процесс создания базы данных для учета движения товаров на складе. Было бы полезно такую базу поместить на SQL Server, чтобы ее данными имели возможность пользоваться сразу несколько менеджеров. Конечно, эта база слишком проста для того, чтобы приносить много пользы фирме, но достаточно хороша для примера этой книги. Именно эту базу можно импортировать средствами SQL Server Enterprise Manager, тем более, что она уже заполнялась данными (если, конечно, читатель аккуратно создавал эту базу и вводил данные по мере чтения книги). Если вы успели создать таблицу в базе с именем УчетТоваров, удалите ее при помощи контекстного меню (рис. 23.12). Впрочем, можно этого и не делать. Выберите команду Import Data (рис. 23.13). В появившемся окне DTS Import Wizard (рис. 23.14) щелкните кнопку Next (как сами понимаете, других вариантов почти нет). На экране появится окно с более богатым набором элементов управления (рис. 23.15), предназначенное для определения источника, из которого будут взяты таблицы для импорта. В окне комбинированного списка Source выберите Microsoft Access (рис. 23.16). Рис. 23.14 В окне DTS Import Wizard щелкните кнопку Next Рис. 23.15 Окно, предназначенное для определения источника, из которого будут взяты таблицы для импорта 2I 644 Глава 23 OTS Import Wizard Рис. 23.16 В окне комбинированного списка Source выберите Microsoft Access Choose a Data Source Where would you like Io copy data horn? You can copy data from any of the sources listed below Choose one of the following sources Source In Of' sei Serv J Micro ull OLE D8 Provider for SUL Stiver ^Driver para о Microsoft Visual FoxPro S'MediaCatalogDB OLE DB Provider S'MedwCatalogMergedDB OLE DB Provider S MediaCalalog«VebDB OLE DB Provider b Microsoft Access ЛР M icrosoft Access T rerber (’ mdb) Tjj Microsoft Data Link Username Password. £a'abase Ц ^default v] Fehesh | Advanced < gack. |~~ Next> После выбора в окне комбинированного списка Source элемента Microsoft Access диалоговое окно незаметно изменится для того, чтобы можно было в нем указать имя mdb-файла (рис. 23.17). Рис. 23.17 После выбора в окне комбинированного списка Source элемента Microsoft Access диалоговое окно незаметно изменится для того, чтобы можно было в нем указать имя mdb-файла Щелкните кнопку Next в этом окне для перехода к следующему окну; в нем необходимо указать сведения о базе данных, в которую будут записываться импортируемые таблицы (рис. 23.18). Впрочем, если вы начинали работу при помощи контекстного меню с выделенным именем базы данных УчетТоваров, то в этом окне останется только щелкнуть кнопку Next — все остальное будет уже готово. Если процесс импортирования данных пройдет успешно, на экране, наконец, появится сообщение, ради которого стоило все затевать (рис. 23.24) — «Из Microsoft Access в базу Microsoft SQL Server передано 6-ть таблиц». Если данные в базу УчетТоваров будут регулярно записываться (этим или иным способом), то не составит особого труда извлекать их оттуда, для различного рода отчетов. На этом мы завершим краткое описание возможностей SQL Server Enterprise Manager по созданию баз данных. Пока мы не рассмотрели ни вопросы создания представлений, ни — хранимых процедур. Но мы сделаем это позже. Работа с SQL Server 645 Рис. 23.18 В этом окне следует указать базу данных, в которую попадут импортируемые таблицы % DI S Import Wizard Choote a Destination Where would you kke Io copy dale to*7 You can copy data to any of the destinations listed below Choose one of the following destinations Destination Microsoft OLE DB Provider tor SOL Server □ In order to connect to Microsoft SQL Server you must specify the server user name and password pOVA j Г Use Windows NT authentication Use Server authentication Username Password j database | J УчетТоваров •*] fleftesh | Advanced < gack Next > Cancel | Рис. 23.19 В этом окне полезна только кнопка Next Рис. 23.20 Укажите импортируемые таблицы и щелкните кнопку Next V DTS Import Wizard Select Source Tables You can choose one or more tables to copy You can copy the schema and data as it is in the source or click ( ) to transform th* data using ActiveX scripts tabled Source Table ________ № v* Инвентарная_ведом v* КонтрКАгента v* НаклЗаголовки •/ НаклСпецификации | "Destination Table( Transform* !.□ [УчетТоварое].[дЬо][И l2 [УчетТ оваров) [dbo) { 1113 [УчетТoBapo8j.[dbo)[ йШ [УчетТоваровЦдЬо] [Н •у Склады 1Д {У четТ оваров) [dbo] [ j £e»electAII j Preview | < gack Cancel J 646 Глава 23 Рис. 23.21 Для дальнейшей работы щелкните кнопку Next Рис. 23.22 Щелкните кнопку со странным именем Finish Рис. 23.23 Если данных в таблицах очень много, у вас имеется возможность понаблюдать за тем, как оформляют процессы копирования данных профессионалы Microsoft Access Mrnsuft SOL Shi /ег Progress lllllllllllllll Transfer status j Step Name | Status ж Create Table [УчетТоваров] [dbo] [Инвентарная ведим Cor iplete |> Copy Data from Инвентарная_ведомость to [Уч^тТовар Running [0] Create Table [УчетТоваров] [dbo] [КонтрКАгента] Step Complete Copy Data from КонтрКАгента to [У четТоваров] [dbo] [К Waiting Create Table [УчетТоваров] [dbo] [НаклЗаголовки] Step Complete — Copy Data from НаклЗаголовки to [У четТоваров] [dbo] [ Waiting v Create Table [УчетТоваров] [dbo] [НаклСпециФикации] Complete Copy Data from НаклСпециФиг ации to [Учет!оваров] [d Waiting d Cancel Работа с SQL Server 647 Рис. 23.24 Ради этого сообщения и стоило все затевать OTS Wizard Successfully transferred S table(s) from Microsoft Access to Microsoft SQL Server. Создание базы данных посредством кода Создавать и корректировать базу при помощи Server Enterprise Manager легко, в чем вы сами можете убедиться, но это не всегда бывает возможно, а иногда и неудобно. Если вы — не системный администратор, то вряд ли вас «подпустят» к клавиатуре компьютера, на котором находится SQL Server. В лучшем случае на какое-то время вам могут дать права на создание баз данных с удаленного компьютера, да и то, скорее всего, на «пустом» сервере. Если вы работаете с SQL Server на своем компьютере, то создавать базу при помощи Server Enterprise Manager можно также в качестве «разминки». Дело в том, что обычным делом любого «нормального» пользователя компьютера является случайное удаление тех или иных данных, а иногда и полное форматирование жестких дисков. Не всегда у пользователя имеется время на подготовку к переустановке системы. Конечно, никогда не стоит забывать о всевозможных способах дублирования информации, но гораздо удобнее просто написать код для создания баз данных. Это будет самой «твердой» копией пустой (без данных) базы. Если код для создания базы данных включает, кроме описания таблиц, еще определения хранимых (stored) процедур и представлений (views), то процесс восстановления базы на SQL Server (без данных) займет очень мало времени. Конечно, где-то, скорее всего, в некотором внешнем для SQL Server формате должны храниться данные для заполнения базы. После соединения с сервером из клиентской части программного обеспечения можно посылать команды серверу. Несмотря на то, что эти команды посылаются из VBA-приложения (или, например, C++ или Delphi), они, конечно, должны быть командами языка Т-SQL. Поэтому здесь и далее мы рассмотрим некоторые из них. Инструкция создания базы данных на «SQL-диалекте» SQL Server имеет непростой синтаксис, но большая его часть является необязательной и предназначена для очень «тонкой» настройки. Самый простой синтаксис этой инструкции имеет следующий вид: ЧСИНТАКСИС + »< + CREATE DATABASE <database_name> Здесь database_name — имя создаваемой базы данных. Имя должно быть уникальным для данного сервера, отвечать правилам для имен идентификаторов и не превышать по длине 128 символов. Инструкция создания таблицы базы данных на «SQL-диалекте» SQL Server имеет также непростой синтаксис, но большая его часть является необязательной. Самый простой синтаксис этой инструкции имеет следующий вид: синтаксис >. CREATE TABLE (имя таблицы^ ( имя_поля1 тип поля [NIT NULL ] , имя_поля2 тип поля [NIT NULL ] , имя_поляЗ тип поля [NIT NULL ] , . . . ) 648 Глава 23 Для создания таблицы на сервере необходимо передать серверу SQL-инструкцию, например, при помощи метода Execute объекта Connection, например: ' создать новую таблицу в текущей базе данных cn.Execute "CREATE TABLE Т2 " S "(C_KOD VARCHAR(12) NOT NULL, " S " N_SELLO MONEY, " S " N_SELL MONEY, " & * " N_ZAKUP FLOAT " S n J > В главе 20 на рис. 20.28 представлена схема базы данных, которая в этой главе была загружена при помощи SQL Server Enterprise Manager на сервер. Эта схема была создана в системе ERWin, позволяющей не только отображать базу при помощи редактора, но и генерировать код для создания базы данных для различных СУБД, в том числе и для SQL Server. В листинге 23.1 представлен код, сгенерированный для этой цели на языке Т-SQL (диалект SQL Server) в системе ERWin. Листинг 23.1. Код для создания базы данных, сгенерированный в системе ERWin 1 CREATE TABLE Инвентарная ведомость ( 2 КодТовара VARCHAR(12) NOT NULL, 3 4 5 ) КодСклада SMALLINT NOT NULL, ' Количество INTEGER NULL 6 до 7 X 8 9 ALTER TABLE Инвентарная ведомость 10 11 до 12 13 ADD PRIMARY KEY NONCLUSTERED (КодТовара, КодСклада) 14 CREATE 15 16 17 18 ) TABLE Контрагенты ( НаименованиеКАгента SMALLINT NULL, КодКАгента SMALLINT NOT NULL, Адрес varchar(20) NULL 19 до 20 21 22 ALTER 23 24 до 25 26 TABLE Контрагенты ADD PRIMARY KEY NONCLUSTERED (КодКАгента) 27 CREATE 28 29 30 31 TABLE НаклЗаголовки ( КодКАгента SMALLINT NOT NULL, КодСклада SMALLINT NOT NULL, Дата datetime NULL, Номер INTEGER NULL, 32 33 ) ТипНакладной INTEGER NULL 34 до > 35 36 t 37 ALTER TABLE НаклЗаголовки 38 3 9 до 40 41 ADD PRIMARY KEY NONCLUSTERED (КодКАгента, КодСклада) < 42 CREATE : TABLE НаклСпецификации ( 43 Дата datetime NULL, 1 Работа с SQL Server 649 44 КодТовара VARCHAR(12) NOT NULL, 45 Номер INTEGER NULL, 46 Количество int NULL, 47 ЦенаОперации DOUBLE PRECISION NULL 48 ) 4 9 go 50 51 • 52 ALTER TABLE НаклСпецификации 53 ADD PRIMARY KEY NONCLUSTERED (КодТовара) 5 4 go 55 56 57 CREATE : TABLE Склады ( 58 НаименованиеСклада VARCHAR(4 NULL, 59 КодСклада SMALLINT NOT NULL, 60 Адрес char(18) NULL 61 ) 62 go 63 64 65 ALTER TABLE Склады 66 ADD PRIMARY KEY NONCLUSTERED (КодСклада) 67 go 68 69 70 CREATE : TABLE Товары ( 71 НаименованиеТовара VARCHAR(30) NULL, 72 КодТовара VARCHAR(12) NOT NULL, 73 ЦенаОптовая DOUBLE PRECISION NULL, 74 ЦенаРозничная DOUBLE PRECISION NULL 75 ) 7 6 go 77 78 79 ALTER TABLE Товары 80 ADD PRIMARY KEY NONCLUSTERED (КодТовара) 81 go 82 83 84 ALTER TABLE Инвентарная_ведомость 85 ADD FOREIGN KEY (КодСклада) 86 REFERENCES Склады 87 go 88 89 90 ALTER TABLE Инвентарная_ведомость 91 ADD FOREIGN KEY (КодТовара) 92 REFERENCES Товары 93 go 94 95 96 ALTER TABLE НаклЗаголовки 97 ADD FOREIGN KEY (КодКАгента) 98 REFERENCES Контрагенты 99 go 100 101 102 ALTER TABLE НаклЗаголовки 103 ADD FOREIGN KEY (КодСклада) 104 REFERENCES Склады 105 go 106 650 Глава 23 107 108 ALTER TABLE НаклСпецификации 109 ADD FOREIGN KEY (КодТовара) 110 REFERENCES Товары 111 go Для передачи кода, сгенерированного при помощи ERWip, на сервер писать VBA-код не нужно. ERWin имеет диалоговые средства для подключения к SQL Server и передачи на него генерирующего кода. Чтобы отправлять на сервер команды из VBA-кода, необходимо подключиться к серверу. Это можно сделать, зарегистрировав в качестве источника данных ODBC базу данных, хранящуюся на сервере. В этом случае код, рассматриваемый в главе 22 с использованием ODBC, можно без всяких изменений использовать и для SQL Server. В листинге 23.2 для соединения с источником данных, находящемся на SQL Server, используется технология ADO и провайдер для SQL Server. В последних листингах главы 22 для установки соединения применялись функции ADODBCon-nectedODBC (с использованием провайдера для ODBC) и ADODB ConnectedJet (с использованием провайдера для Microsoft Jet). В листинге 23.2 применяется функция ADODB ConnectedSQL, которая использует провайдер для SQL Server. Остальной код, практически, остается тем же. Листинг 23.2. Открытие ADO-соединения с источником SQL Server 1 Dim cn As ADODB.Connection 2 3 Function ADODB_ConnectedSQL() As Boolean 4 ' устанавливает соединение для SQL Server 5 Set cn = New ADODB.Connection 6 7 On Error GoTo err_not_connection 8 9 Set cn - New ADODB.Connection 10 cn.Provider = "SQLOLEDB.l" 11 cn.Connectionstring = _ 12 "0АТАВА5Е=УчетТоваров;SERVER=VOVA;UID=Dmitry;PWD=Dmitry" 13 cn.Open 14 15 ADODB_ConnectedSQL = True 16 Exit Function 17 18 err_not_connection: 19 ADODB_COnnectedSQL = False 20 21 End Function ’ 22 Sub Test_ADODB_Connected() 23 ' тестирует ADODB_ConnectedSQL: устанавливает соединение и 24 1 11 использует данные из таблицы Товары 25 26 27 If ADODB_ConnectedSQL() Then 28 MsgBox "Похоже, соединение установлено..." 29 ' код, использующий установленное соединение: ‘ 30 31 Set rs = New ADODB.Recordset ' 32 rs.CursorType = adOpenDynamic 33 rs.Source = "SELECT * FROM Товары" 34 Set rs.ActiveConnection = cn 35 rs.Open 36 37 MsgBox rs.Fields(l) & " " & rs.Fields(1).Name Работа с SQL Server 651 38 39 cn.Close 1 закрыть соединение 40 Else 41 MsgBox "Что-то не сложилось!" 42 End If 43 44 End Sub Представления и хранимые процедуры Последняя тема книги посвящена одному из интересных (с точки зрения программистов) вопросов — разработке клиент-серверных приложений. Дело в том, что при переходе от mdb-версий баз данных к версиям SQL Server одним переносом самой базы на сервер ограничиваются далеко не все разработчики. Это связано со многими обстоятельствами, в том числе с изменением физических устройств по передаче информации и, быть может, качественного состава пользователей базы. Перспектива передачи информации на большие расстояния (большие, чем в рамках одного компьютера) должна вызывать у разработчика баз данных желание передавать только самую необходимую часть данных, хранящихся на сервере. Например, из тысячи накладных, находящихся в базе данных, нам нужно передать на клиентский компьютер только одну (хотя можно передать все для дальнейшего выбора необходимой из них). В каком-либо контексте многие пользователи, имеющие отношение к программированию баз данных, слышали о программном обеспечении «на стороне сервера», которое обрабатывает запросы клиентского компьютера и возвращает результаты этой обработки клиенту. Этот аппарат, в частности, реализуется при помощи представлений (views) и хранимых процедур (stored procedure), находящихся на сервере вместе с базой данных (рис. 23.4). Для того чтобы разрабатывать представления и хранимые процедуры, необходимо использовать подробную инструкцию по разработке программного обеспечения выбранного сервера баз данных. В этом разделе содержится «рекламная» информация о возможностях, открываемых разработчику VBA-приложений, если он «осмелится» использовать данные, обрабатываемые при помощи представлений и хранимых процедур SQL Server. Представление подобно запросу в базе данных Access; оно не имеет параметров и возвращает набор данных (таблицу). Например, для базы данных УчетТоваров следующее представление (вместе с кодом для его создания) возвращает таблицу из трех полей, содержащую информацию о товарах: CREATE VIEW Прейскурант AS SELECT НаименованиеТовара AS 'Наименование' , ЦенаОптовая AS 'Цена оптовая' FROM Товары Для наглядности структура таблицы, используемой в представлении, приведена на рис. 23.25, а ее содержимое — на рис. 22.6. Инструкция CREATE VIEW представляет собой обычную SQL-инструкцию, подобную той, которая использовалась в окне, показанном на рис. 22.19 для ввода инструкций DELETE и INSERT INTO в главе 22. Так же, как и эти инструкции, ова не возвращает набор и может быть передана на сервер посредством метода Execute объекта Connection. Но в отличие от этих и других инструкций представление, во-первых, навсегда останется на сервере в области хранения информации о базе данных УчетТоваров и, во-вторых, может быть помещено на сервер при помощи SQL Server Enterprise Manager. Для создания представления при помощи SQL Server Enterprise Manager следует раскрыть ветвь УчетТоваров, как показано на рис. 23.27. При этом можно увидеть, где SQL Server хранит все представления этой базы данных. Далее необходимо выбрать Action | New View. 652 Глава 23 Рис. 23.25 Структура таблицы, используемой в представлении Table Prepeilies • Товары 3 Geneial | Owner Товарь Регггг-$юп$ j dbo Create date 10 03 03 22 00 34 Fdegroup Rows PRIMARY 26 Columns КодТовара Наименование! овара ЦенаОптовая ЦенаРозничная Data Ту ptee'] Nulls J Defa nvarchar nvarchar money money 50 8 8 I ...°к................................................................................................................................I Cancel I Рис. 23.26 Содержимое таблицы, используемой в представлении |7ш in Table'Товары* визе! Й* °o □ мн cP ! . (f= 4ц КодТовара |НаименованиеТовара 1 ЦенаОптовая |ЦенаРозничма5-<1 ВДЗД Ш (ЗДДО| (и; Road Rush II 42 49 J 006019170049 (5) Tasmania 30 35 010414114438 (VCD) Патриот 138 161 010415090732 (VCD) Пастырь 111 130 010415090937 (VCD) Шоссе в никуда 120 140 010428144348 (VCD) Доберман 135 158 - 028019100222 (VCD) Голая мишень 90 105 028019095823 (VCD) Dtder Marouani 90 105 028019100018 (VCD) Wham' The best of 105 123 036019164741 (S) Cool Spot 42 49 174500175359 (3DC) Street Fighter 3 Wimpact 750 875 174500175521 (3DC) Star Gladiator 2 750 875 186100175232 (3DC) Super Runabout 750 875 T] 006019165803 (S) Road Rush II 42 49 Рис. 23.27 Здесь SQL Server хранит все представления базы данных УчетТоваров [’Йи Censel» R»at\Micf«t«ft SQL Swv*Ts\SQLS»rv«iGi*up\VGVA(Wi»ihiRi ЭЬ/М№а*аЬыыШ<««гТ Rf"*Q Action View Tools Ф (Xj ГГ • 3 й г X » 0 В 5 20 Items VOVA Endows 95?38| “3 Name Owne 1 Type f Dea*e Dale л ! . 1 Databases CHECK CONSTRAINTS INFORMATI System 1311 98307 17 4 Lj fmans ^COLUMN DOMAIN USAGE informati System 13 11 98 3:07 12 @ master 6V*COLUMN PRIVILEGES INFORMATI System 1311 98 30713 model AT COLUMNS INFORMATI System 13 11 9830712 (jj msdb 6V CONSTRAINT COLUMN US INFORMATI System 13 11 98 30718 tt Q tempdb (g УчетТоваров сЕд Dagrarns (21 Tabtes бхгЩД ^CONSTRAINT TABLEJJSAGE INFORMATI System 1311 9830717 ^DOMAIN CONSTRAINTS INFORMATI System 1311 98307 U ^DOMAINS INFDR MAT! System 1311 98 30711 AT KEY COLUMN USAGE INFORMATI System 1311 98 30715 ^REFERENTIAL CONSTRAINTS INFORMATI System 1311 98 30716 Stored Procedures ^SCHEMATA INFORMATI System 1311 98 30709- Users tfcf sysaDernates dbo System 1311 98 3 0019 Ди Roles sy sconstiants dbo System 1311 98 3 0019 S3 Rules syssegments dbo System 13 11 9830019 I"1 Defaults _ 1 Stable constraints HFORMATI System 1311 98307 10 „1 <1 Г <1 _J 2Г Работа с SQL Server 653 На экране появится окно для ввода нового представления, куда следует ввести SELECT-запрос, как показано на рис. 23.28, то есть без первых слов "CREATE VIEW Прейскурант AS". Рис. 23.28. В окне кода представления введите обычный SQL-запрос Преимуществом создания представления таким способом является возможность проверки кода представления (особенно сложных представлений), так как, щелкнув на кнопке Run, можно проверить правильность написания представления (рис. 23.29). Рис. 23.29. Щелкнув на кнопке Run, можно проверить правильность написания представления 654 Глава 23 Если все — правильно, следует для сохранения представления в базе данных щелкнуть кнопку Save и ввести в окне Save As наименование представления — Прейскурант (рис. 23.30). Рис. 23.30 В этом окне следует ввести имя представления После ввода наименования представления, можно увидеть, что представление Прейскурант заняло свое место в базе данных УчетТоваров (рис. 23.31). й Console Rool\Micro»oft SQL ServcrASQI Snivel GrowpWOVA (Windows □ 9 o ® ca - ___J DafsbaSeS _-*J + finans + Й master + model • + ij +_ U ServiceCenter + (J tempdb (J УчетТоваров £k£| Diagrams ~’| Tables bVJHS Stored Procedures Users 0 Roles ___ И Rules ПП Defaults £2 Usci Defined Dafa Ti ^.i ~ T 1 ±r Name Ormer 1 Type ^DOMAIN CONSTRAINTS INFORMATI System &TDOMAINS INFORMATI System ftTKEY.COLUMN USAGE INFORMATI System AT REFERENTIAL-CONSTRAINTS INFORMATI System AT SCHEMATA INFORMATI System 6?cT sysalternates dbo System bxTsysconstr amts dbo System syssegments dbo System AT TABLE CONSTRAINTS INFORMATI System ftTTA8LE_PRWILEGES INFORMATI System ЙС TABLES INFORMATI System fa* VIE W_C0 LU M N.U SAG E INFORMATI System 6VVIEW_TAEILE_USAGE INFORMATI System fa* VIEWS INFORMATI System Сто'1 Прейскурант dbo User ±L I Create 0 ate *1 1311 Э8 3 07 14 1311 98 3 0714 1311 9830715 13 11 98307 1b 13 11 98307 03 13 11 9830019 1311 9830013 1311 9830019 1311 9830710 1311 9830711 1311 98307 03 1311 38307 20 1311 38307 20 1311 38307 13 31 03 03 20 57 2 V ±J Рис. 23.31. Представление Прейскурант заняло свое место в базе данных УчетТоваров После создания представления его можно редактировать только при помощи SQL Server Enterprise Manager столько раз, сколько это будет необходимо для успешной эксплуатации базы данных. Если доступа к этому средству не имеется, то можно из VBA-кода SQL-инструкцией DROP Прейскурант удалить представление, а затем ввести его новый код из VB-программы. Для демонстрации использования представления Прейскурант в листинге 23.3 приведен код процедуры Test_ADODB_Connected из листинга 22.2, но теперь для передачи в набор данных применен метод Execute с объекта Connection аргументом "SELECT * FROM Прейскурант". Как видно из этой SELECT-инструкции, имя представления используется как имя обычной таблицы, хотя представление может быть довольно сложным запросом. Листинг 23.3. Открытие ADO-соединения с источником SQL Server и использование представления 1 2 3 4 5 1 Sub Test_ADODB_Connected() 2 ' тестирует ADODB_ConnectedSQL: устанавливает соединение 3 ' и использует представление 4 5 Работа с SQL Server 655 6 If ADODB_ConnectedSQL() Then 7 MsgBox "Похоже, соединение установлено..." 8 ' код, использующий установленное соединение: 9 10 ' применение представления: 11 Set rs = cn.Execute("SELECT * FROM Прейскурант") 12 13 MsgBox rs.Fields(1) & " " & rs.Fields(1).Name 14 15 cn.Close 1 закрыть соединение 16 Else 17 MsgBox "Что-то не сложилось!" 18 End If 19 20 End Sub Более гибким средством получения определенных наборов данных с сервера является хранимая процедура, которая в отличие от представления может принимать параметры, влияющие на выбор данных. Как и для разработки представлений, для освоения аппарата хранимых процедур следует хорошо ознакомиться с инструкциями конкретного сервера. Здесь же будет приведен только один пример, с одной стороны, для того, чтобы показать необходимость работы с хранимыми процедурами, с другой — чтобы читатель не подумал, что эта тема для него очень сложная. CREATE PROCEDURE СпецифНакладной @pwhere char(4), @nom_naclad char(7), @datn char(10) AS SELECT b.C_NAMET as 'Наименование', a.N_KOL as 'Кол-во', a.N__SLLD as 'Цена' FROM T1NACL1 a, T2 b WHERE a.C_WHERE = @pwhere and a.N_NOM =@nom_naclad and a.D_DATN=@datn and a.C~KOD=b.C_KOD ORDER BY b.C_NAMET Основным отличием хранимой процедуры от представления является возможность передавать процедуре параметры со всеми вытекающими из этого последствиями: процедура может иметь операторы, влияющие на последовательность выполнения кода, возвращаемые наборы могут зависеть от входных параметров. Кроме того, хранимая процедура может и не возвращать набор. В приведенной выше процедуре с наименованием СпецифНакладной список Spwhere char(4), @nom_naclad char(7), @datn char(10) является списком параметров: @pwhere — текстовый длиной 4 символа, @nom_na-clad — текстовый длиной 7 символов, @datn — текстовый длиной 10 символов. Символ @ также входит в имя параметра. Если хранимая процедура представляет собой единственный SQL-запрос, то параметры используются в предложении WHERE, как в рассматриваемом примере. Код листинга 23.4 использует хранимую процедуру для получения спецификации накладной. Строка strSQL, которая формируется для вызова процедуры СпецифНакладной, имеет следующее значение: "ЕХЕС СпецифНакладной @pwhere='3123' , @nom_naclad=5, @datn='11.02.2003'" Листинг 23,4. Открытие ADO-соединения с источником SQL Server и использование хранимой процедуры 1 2 3 4 5 6 7 8 1 Sub Test_ADODB_Connected2() 2 ' тестирует ADODB_ConnectedSQL: устанавливает соединение 3 ' и использует хранимую процедуру 4 5 Dim strSQL As String 6 7 m_pwhere = "3123" ' код склада 8 m_nom_naclad = 5 ' номер накладной 656 Глава 23 9 m_datn = "11.02.2003" ' дата накладной 10 11 strSQL = "EXEC СпецифНакладной @pwhere='" & m_pwhere & " & 12 " @nom_naclad=" & Str(m_nom_naclad) & ", " & _ 13 " @datn='" & m_datn & ............. 14 15 If ADODB_ConnectedSQL() Then J.6 MsgBox "Похоже, соединение установлено..»" 17 ' код, использующий установленное соединение: 18 19 ' применение хранимой процедуры: 20 Set rs = cn.Execute (strSQL) 21 22 MsgBox rs.Fields(l) & " " & rs.Fields(1).Name 23 '24 cn.Close ' закрыть соединение 25 Else 26 MsgBox "Что-то не сложилось!" 27 End If 28 29 End Sub При написании представления или хранимой процедуры всегда следует помнить, что они выполняются на сервере, а значит должны соответствовать синтаксису SQL-версии СУБД, обеспечивающей сервер В частности, нельзя использовать функции, которые хорошо работали в SQL-инструкциях локального или клиентского компьютера Приложения В данных приложениях собраны справочные сведения, которые могут пригодиться разработчикам VBA-приложений. Для более удобной работы с этими приложениями некоторые материалы содержатся одновременно в нескольких приложениях. Приложение А Справочные таблицы книги Таблица 2.1. Команды меню File (файл) Команда Горячая клавиша Действие Save <project> (сохранить <проект>) Ctrl+S Сохраняет текущий проект VBA на диске, 1 включая все модули и формы. Import File (импорт файла) Ctrl+M Добавляет существующий модуль, форму или класс в текущий проект. Вы можете импортировать только модули, формы или классы, 1 сохраненные ранее командойЕхроН File из другого проекта. Export File (экспорт файла) Ctrl+E Сохраняет текущий модуль, форму или класс в формате текстового файла для импортирования в другой проект или в целях архивиро-1 вания. Remove <item> (удалить <...>) Перманентно удаляет модуль или форму текущего выбора из проекта VBA. Эта команда не доступна, если в Project Explorer не выбран никакой элемент. Print (печать) Ctrl+P Печатает модуль или форму для документирования или с целью архивирования. Close and Return to ... (закрыть и вернуться в ... ) Alt+Q Закрывает Редактор VB и возвращает вас в host-приложение и документ/рабочую книгу, из которых вы открывали Редактор VB. Таблица. 2.2. Команды меню Edit Команда Горячая клавиша Действие Undo (отменить) Ctrl+Z Отменяет самую последнюю команду. Не все команды могут быть отменены. Меню доступно только в случае, если есть, что отменять. Redo (вернуть) Возвращает самую последнюю команду, кото-рую вы отменили. Cut (вырезать) Ctrl+X Вырезает выделенный текст или объект и помещает его в Windows Clipboard. Выделенный текст или объект удаляется из модуля или формы. Сору (копировать) Ctrl+C Копирует выделенный текст или объект и помещает его в Windows Clipboard. Выделенный текст или объект остается неизменным. Справочные таблицы книги 659 Команда Горячая клавиша Действие Paste (вставить) Ctrl+V Вставляет текст или объект из Windows Clipboard в текущий модуль или форму. Clear (очистить) Del Удаляет выделенный текст или объект из модуля или формы. Select АП (выделить все) Ctrl+A Выделяет весь текст в модуле или все объекты в форме. Find (найти) Ctrl+F Подобно команде Find в Word или Excel, позволяет находить указанный текст в модуле. Find Next (найти далее) F3 Повторяет последнюю операцию Find. Replace (заменить) Ctrl+H Подобно команде Replace в Word или Excel, позволяет находить указанный текст в модуле и заменять его другим текстом. Indent (увеличить отступ) Tab Смещает весь выделенный текст вправо на интервал табуляции. Outdent (уменьшить отступ) Shift+ Tab Смещает весь выделенный текст влево на интервал табуляции. List Properties/ Methods (список свойств/ме-тодов) Ctrl+J Открывает список в List Properties/ Methods, отображая свойства и методы объекта, имя которого вы только что ввели. Когда курсор вставки находится на пустом месте в List Properties/ Methods эта команда открывает список глобально доступных свойств и методов. List Constants (список констант) Ctrl+ Shift+J Открывает список в Code Window, отображающий допустимые константы для свойства, которое вы только что ввели с предшествующим знаком Quick Info (сведения) Ctrl+I Открывает всплывающее окно подсказки, отображающее правильный синтаксис для процедуры, функции или метода, который вы только что ввели в Code Window. Parameter Info (параметры) Ctrl+ Shift+I Открывает всплывающее окно подсказки, отображающее параметры (называемые также аргументами) процедуры, функции или оператора, который вы только что ввели в Code Window. Complete Word ^завершить слово) Ctrl+ Space Редактор VB заканчивает слово, которое вы вводите, как только вы введете достаточно символов для того, чтобы VBA распознал ключевое слово. .Bookmarks (закладки) Открывает подменю с пунктами для помещения, удаления или перехода к закладкам, которые вы ранее поместили в ваш модуль. В отличие от закладок в Word, закладки Редактора VB не имеют имен. 660 Приложение А Таблица 2.3. Команды меню View Команда Горячая клавиша Действие Code (программа) F7 Активизирует Code Window для отображения исходного кода VBA, ассоциированного с выбранным модулем или формой. Object (объект) Shift+F7 Отображает объект текущего выбора в Project Explorer. Definition (описание) Shift+F2 Отображает исходный код VBA для процедуры или функции, на которую указывает курсор; отображает Object Browser для объектов в справке VBA. Last Position (вернуться к последней позиции) Ctrl+ Shift+F2 Переходит в последнюю позицию в модуле после использования команды меню Definition или после редактирования кода. Object Browser (просмотр объектов) F2 Открывает Object Browser, позволяющий определять, какие макросы доступны в данный момент. Immediate Window (окно отладки) Ctrl+G Отображает окно отладчика Immediate Window VBA. Locals Window (окно локальных переменных) Отображает окно отладчика Locals Window. Watch Window (окно контрольного значения) Отображает окно отладчика Watch Window (контрольные значения). Call Stack (стек вызова) Ctrl+L Отображает список последовательности вызовов для текущей функции или процедуры VBA. Project Explorer (окно проекта) Ctrl+R Отображает Project Explorer. Properties Window (окно свойств) F4 Отображает Properties Window. Toolbox (панель элементов) Отображает Toolbox. Toolbox используется для добавления элементов управления в пользовательские диалоговые окна. Tab Order (последовательность перехода) Отображает диалоговое окно Tab Order, которое используется при создании пользовательских диалоговых окон. Toolbars (панели инструментов) Отображает подменю, позволяющее показывать или скрывать различные панели инструментов Редактора VB или открывать диалоговое окно для настройки одной из панелей инструментов Редактора VB. Справочные таблицы книги 661 Команда Горячая клавиша Действие <Host application (host-приложение) Alt+Fll Возвращает вас в host-приложение, из которого был запущен Редактор VB, но оставляет Редактор VB открытым. Конкретное , имя этого пункта меню зависит от того, из какого host-приложения VBA вы запустили Редактор VB. Таблица 2.4. Команды меню Insert Команда Действие Procedure (процедура) Вставляет новую процедуру (Sub, Function или Property) в текущий модуль. (Процедура — это еще одно название макроса). UseForm Добавляет новую форму (используется для создания пользовательских диалоговых окон) в проект. Module (модуль) Добавляет новый модуль в проект. Редактор VB дает этому модулю имя в соответствии с правилами, описанными ранее в этой главе. Class Module (модуль класса) Добавляет в проект class module (модуль класса). Модули класса используются для создания пользовательских объектов в проекте. File (файл) Позволяет вставлять текстовый файл, содержащий исходный код VBA, в модуль. Таблица 2.5. Команды меню Format Команда Действие Align (выровнять) Открывает подменю команд, которые позволяют выравнивать выбранные объекты в форме по отношению друг к другу. Здесь можно выравнивать объекты по верхней/нижней, правой/левой границам, по центру или середине создаваемого объекта. Make Same Size (выровнять размер) Открывает подменю команд, позволяющих изменять размер выделенных объектов до размера указанного объекта. Size to Fit (подогнать размер) Одновременно изменяет ширину и высоту объекта до соответствия размеру его содержимого. Size to Grid, (выровнять размер по сетке) Одновременно изменяет ширину и высоту объекта до ближайших меток сетки. При разработке форм Редактор VB отображает в форме сетку, чтобы было легче располагать и изменять размеры объектов в форме. Horizontal Spacing (интервал по горизонтали) Открывает подменю команд, позволяющих устанавливать горизонтальный интервал для выбранных объектов. Здесь можно устанавливать равномерный горизонтальный интервал, уменьшать или увеличивать его или удалять всякий горизонтальный интервал между объектами. 662 Приложение А Команда Действие Vertical Spacing (интервал по вертикали) Открывает подменю команд, позволяющих устанавливать вертикальный интервал для выбранных объектов. Здесь можно устанавливать равномерный вертикальный интервал, уменьшать или увеличивать его или удалять всякий вертикальный интервал между объектами. Center in Form (разместить по центру в форме) Открывает подменю команд, позволяющих изменять положение выбранных объектов, чтобы они были центрированы в форме горизонтально или вертикально. Arrange Buttons (разместить кнопки) Открывает подменю команд, позволяющих автоматически располагать командные кнопки в форме в ряд с равным интервалом по нижнему или правому краю формы. Group (группировать) Связывает несколько выбранных объектов вместе в одну группу, чтобы вы могли перемещать, изменять размер, вырезать или копировать объекты, обращаясь с ними, как с одним целым. Ungroup (разделить) Отменяет группировку объектов, которые перед этим были связаны вместе с помощью команды Group. Order (порядок) Открывает подменю команд, позволяющих изменять упорядочение сверху вниз (называемое z-order ) перекрывающихся объектов в форме. Используйте команду Order, чтобы обеспечить, например, появление текстового окна всегда поверх графического объекта в форме. Таблица 2.6. Команды меню Debug Команда Горячая клавиша Действие Compile <project> (компилировать <про-ект>) Компилирует проект, выбранный в данный момент в Project Explorer. Step Into (шаг с заходом) F8 Выполняет исходный код вашего макроса по одному оператору каждый раз. Step Over (шаг с обходом) Shift+F8 Подобно команде Step Into команда Step Over позволяет выполнять все инструкции в макросе без паузы на каждой отдельной инструкции. Step Out (шаг с выходом) Ctrl+ Shift+F8 Выполняет все остающиеся операторы в макросе без паузы на каждом отдельном операторе. Run to Cursor (выполнить до текущей позиции ) Ctrl+F8 Выполняет операторы исходного кода макроса от оператора, выполняющегося в данный момент, до текущей позиции курсора. Add Watch (добавить контрольное значение) Позволяет указывать переменные или выражения, значения которых можно наблюдать во время выполнения исходного кода VBA. Справочные таблицы книги 663 Команда Горячая клавиша Действие Edit Watch (изменить контрольное значение) Ctrl+W Позволяет редактировать спецификации для наблюдаемых переменных и выражений, которые были созданы ранее с помощью команды Add Watch. Quick Watch (контрольное значение) Shift+F9 Отображает текущее значение выбранного выражения. Toggle Breakpoint (точка останова) F9 Отмечает место (или отменяет отметку) в исходном коде VBA, где необходимо остановить выполнение макроса. Clear All Breakpoints (снять все точки останова) Ctrl+Shift +F9 Удаляет все точки останова в модуле. Set Next Statement (задать следующую инструкцию) Ctrl+F9 Позволяет менять обычное выполнение кода путем указания вручную следующей строки исходного кода, которая должна выполняться. Show Next Statement (показать следующую инструкцию) Приводит к подсветке Редактором VB следующей строки кода, которая будет выполняться. Таблица 2.7. Команды меню Run Команда Горячая клавиша Действие Run Sub/User Form (запуск подпрограм-мы/User Form) F5 Приводит к тому, что VBA запускает макрос, который редактируется в данный момент, то есть VBA запускает макрос, на тексте которого находится курсор вставки. Если какая-либо форма активна, VBA запускает эту форму. Break (прервать) Ctrl+Break Прерывает выполнение вашего кода VBA и приводит к тому, что Редактор VB переходит в режим прерывания (Break mode). (Break mode используется при отладке кода VBA.) Resert <project> (сброс) Устанавливает все переменные модульного уровня и Call Stack (список последовательности вызовов) в исходное состояние. Design Mode (конструктор) Включает и выключает Design mode (режим проектирования или разработки) для 1 проекта. В этом режиме никакой код в вашем проекте не выполняется, и события от элементов управления не обрабатываются. 664 Приложение А Таблица 2.8. Команды меню Tools Команда Действие References (ссылки) Отображает диалоговое окно References, позволяющее устанавливать ссылки на библиотеки объектов, библиотеки типов или другой проект VBA. После установления ссылки объекты, методы, свойства, процедуры и функции в этой ссылке появляются в диалоговом окне Object Browser. Additional Controls (дополнительные элементы) Отображает диалоговое окно Additional Controls, позволяющее настраивать Toolbox (панель элементов) так, чтобы вы могли добавлять элементы управления в формы, помимо встроенных в VBA. Диалоговое окно Additional Controls предназначено для добавления к панели элементов кнопок, которые позволяют добавлять к форме объекты, такие как рабочий лист Excel или документ Word. Macros (макросы) Отображает диалоговое окно Macros, позволяющее создавать, редактировать, выполнять или удалять макросы. Options (параметры) Отображает диалоговое окно Options, позволяющее выбирать различные опции для Редактора VB, такие как число пробелов в интервале табуляции (tab stop), когда VBA проверяет синтаксис ваших операторов, и так далее. <project> Properties (свойства проекта) Отображает диалоговое окно Project Properties, позволяющее устанавливать различные свойства вашего проекта VBA, такие как имя проекта, описание и файл контекстной справки. Это диалоговое окно позволяет также защищать проект, чтобы никто не мог его редактировать без указания пароля. Digital Signature (цифровая подпись) Отображает диалоговое окно Digital Signature, в котором можно задать для проекта сертификат цифровой подписи. Таблица 2.9. Кнопки панели инструментов Standard Кнопка Действие View <host application (вид <host-npuwxHce-ние>) Переключает на host-приложение VBA, из которого вы запустили Редактор VB. Значок этой кнопки изменяется в зависимости от конкретного приложения, из которого вы запускали редактор VB. Insert UserForm (вставить UserForm) Щелкните на кнопке со стрелкой вниз справа от этой кнопки, чтобы отобразить список объектов, которые вы можете вставить в текущий проект: UserForm, Module, Class Module или Procedure. Это можно выполнить и при использовании одноименных команд меню Insert (вставка). Save (сохранить) Сохраняет текущий проект так же, как File | Save. Cut (вырезать) Вырезает выделенный текст или объект и помещает его в Clipboard; так же, как команда Edit | Cut. Справочные таблицы книги 665 Кнопка Действие Сору (копировать) Копирует выделенный текст или объект в Clipboard; так же, как команда Edit | Сору (правка | копировать). Paste (вставить) Вставляет текст или объект из Clipboard в Code Windaw или форму пользователя в позицию курсора; так же, как команда Edit | Paste (правка | вставить). Find (найти) Открывает диалоговое окно Find для нахождения определенного слова или фразы в модуле; так же, как команда Edit | Find (правка | найти). Undo (отменить набор) Отменяет самую последнюю команду, если это возможно (не все действия могут быть отменены); так же, как команда Edit | Undo (правка | отменить набор). Redo (вернуть набор) Возобновляет самую последнюю отмененную команду; так же, как команда Edit | Redo. Run Macro (запуск подпрограммы/UserForm) Запускает текущую процедуру или форму; так же, как команда Run | Sub/UserForm. Break (прервать) Прерывает выполнение кода VBA; так же, как команда Run | Break (запуск | прервать). Reset (сброс) Перезапускает код VBA, как команда Run | Reset (запуск | сброс). Design Mode (конструктор) При нажатии этой кнопки Редактор VB переходит в режим Design (конструктора); так же, как команда Run | Design Mode (запуск | конструктор). Project Explorer (окно проекта) Отображает Окно проекта (Project Explorer); так же, как команда View | Project Explorer) (вид | окно проекта). Properties Window (окно свойств) Отображает Properties Window (окно свойств); так же, как команда View | Properties Window (вид | окно свойств). Object Browser (просмотр объектов) Отображает диалоговое окно Object Browser (просмотр объектов); так же, как команда View | Object Browser (вид | просмотр объектов). Toolbox (панель элементов) Отображает Toolbox (панель элементов); так же, как команда View | Toolbox (вид | панели элементов). Office Assistant (помощник по Office) Отображает окно Справочной системы Microsoft Office для контекстно-зависимой подсказки по текущей задаче. Cursor position (положение курсора) Эта область панели инструментов Standard, фактически, не является командной кнопкой и появляется только тогда, когда курсор находится в Code Window. Эта область показывает, в какой строке модуля и в каком столбце строки находится курсор вставки. More Buttons Позволяет добавлять или удалять кнопки панели. ббб Приложение А Таблица 2.10. Команды панели инструментов Edit Кнопка Действие List Properties/Methods (список свойств/мето-дов) Отображает раскрывающийся список свойств и мето- I дов, принадлежащих объекту, который вы только что ввели; так же, как Edit List Properties/Methods (правка | список свойств/методов). List Constants (список констант) Отображает раскрывающийся список предопределенных констант; так же, как Edit | List Constants (прав- ; ка | список констант). | Quick Info (сведения) Отображает всплывающее окно, показывающее правильный синтаксис для объектного метода; так же, как Edit | Quick Info (правка | сведения). Parameter Info (параметры) Отображает всплывающее окно, показывающее параметры (называемые также аргументами [arguments]) функции или оператора VBA; так же, как Edit | Parameter Info (правка | параметры). Complete Word (завершить слово) Завершает текущее ключевое слово VBA, как только вы введете достаточно символов, чтобы VBA идентифицировал слово, которое вы вводите; так же, как Edit | Complete Word) (правка | завершить слово). Indent (увеличить отступ) Сдвигает выделенный текст вправо на одну позицию табуляции; так же, как Edit | Indent (правка | увеличить отступ). Outdent (уменьшить отступ) Сдвигает выбранный текст влево на одну позицию табуляции; так же, как Edit | Outdent (правка | уменьшить отступ). I Toggle Breakpoint | (точка останова) Устанавливает или отменяет точку прерывания в исходном коде VBA; так же, как Debug | Toggle Breakpoint (отладка | точка останова). Comment Block (закомментировать блок) Превращает выделенный блок текста в Code Window в комментарии, добавляя символ комментария в начало каждой выделенной строки. Эквивалентной команды меню не имеется. Uncomment Block (раскомментировать блок) Удаляет символ комментария из блока выделенного текста в Code Window. Эквивалентной команды меню нет. Toggle Bookmark (закладка) Устанавливает или отменяет закладку в вашем исход- ; ном коде VBA; так же, как Edit | Bookmarks | Toggle Bookmark (правка | закладки | закладка). Next Bookmark (следующая закладка) Перемещает курсор вставки в Code Window к следую- ' щей закладке; так же, как Edit | Bookmarks | Next Bookmark (правка | закладки | следующая закладка). Previous Bookmark (предыдущая закладка) Перемещает курсор вставки в Code Window к предыдущей закладке; так же, как Edit | Bookmarks | Previous । Bookmark (правка | закладки | предыдущая закладка). Clear All Bookmarks (снять все закладки) Удаляет все закладки в модуле; так же, как Edit | Bookmarks | Clear All Bookmarks (правка | закладки | снять все закладки). Справочные таблицы книги 667 Таблица 4.1. Типы данных VBA Название типа Размер в байтах Описание и диапазон значения Byte 1 Для хранения положительного числа от 0 до 255. Boolean 2 Для хранения логическиих значений; может содержать только значения True или False Currency 8 От -922337203685477.5808 до 922337203685477.5807. Date 8 Для хранения комбинации информации о дате и времени. Диапазон дат может быть от 1 января 100 года до 31 декабря 9999 года. Диапазон времени от 00:00:00 до 23:59:59. Decimal 12 Переменные типа Decimal сохраняются как 96-битовые знаковые целые, масштабируемые значением некоторой степени числа 10. Степень десяти определяет число десятичных знаков справа от десятичной точки и может быть в диапазоне от 0 до28. Если степень масштабного коэффициента равна 0, наибольшее число типа Decimal может быть равно ±79,228,162,514,264,337,593,543,950,335. Для степени 28 наибольшее число: ±7.9228162514264337593543950335, а самое меньшее ненулевое значение равно ±0.0000000000000000000000000001. Double 8 Отрицательные числа: рт -1.79769313486232Х10308 до -4.94065645841247Х Ю”324. Положительные числа: от 4.94065645841247Х Ю 324 до 1.79769313486232Х Ю308. Integer 2 Все целые числа от -32768 до 32767. Long 4 Все целые числа от -2147483648 до 2147483647. Object 4 Используется для доступа к любому объекту, распознаваемому VBA. Сохраняет адрес объекта в памяти. Single 4 Отрицательные числа: от -3.402823Х1038 до -1.401298х 10~45 Положительные числа: от 1.401298Х10-45 до 3.402823Х1038 String (переменной длины) 10 байт + длина строки Используется для хранения текста. Может содержать от 0 символов до (приблизительно) 2 миллиардов символов. String (фиксированной длины) Длина строки (один байт на один символ) Используется для хранения текста. Может содержать от одного до (приблизительно) 654000 символов. 668 Приложение А Название типа Размер в байтах Описание и диапазон значения Variant 16 байт, «плюс» 1 байт/ символ Тип Variant может хранить любой другой тип данных. Диапазон для данных типа Variant зависит от фактически сохраняемых данных. В случае текста диапазон соответствует строковому типу; в случае чисел диапазон такой, как у типа Double. Таблица 4.2. Символы определения типа Символ определения Тип ! Single @ Currency # Double $ String % Integer & Long Таблица 5.1. Знаки (обозначения) операций, используемые в арифметических VBA-выражениях Знак Синтаксис Имя/Описание + Nl + N2 Сложение. Прибавляет Nl к N2. - Nl - N2 Вычитание. Вычитает N2 из N1. * Nl * N2 Умножение. Умножает N1 на N2. / Nl/ N2 Деление. Делит N1 на N2. \ Nl\ N2 Целочисленное деление. Делит N1 на N2, отбрасывая любую дробную часть так, чтобы результат был целым числом. Mod Nl Mod N2 Деление по модулю. Делит N1 на N2, возвращая только остаток операции деления. Nl " N2 Возведение в степень. Возводит N1 в степень N2. Таблица 5.2. Знаки (обозначения) операций сравнения Оператор Синтаксис Имя/описание = El = Е2 Равенство. True, если Е1 равно Е2, иначе — False. < El < Е2 Меньше, чем. True, если Е1 меньше, чем Е2, иначе — False. <= Меньше, чем или равно. True, если Е1 меньше или равно Е2, иначе — False. > > Больше, чем. True, если Е1 больше, чем Е2, иначе — False. Справочные таблицы книги 669 Оператор Синтаксис Имя/описание >= >= Больше, чем или равно. True, если Е1 больше или равно Е2, иначе — False. <> о Не равно. True, если Е1 не равно Е2, иначе — False. Is El Is Е2 Оба операнда должны быть значениями типа Object. True, если El ссылается на тот же самый объект, что и Е2, иначе — False. Like El Like Е2 Подобие. Оба операнда должны быть значениями типа String. True, если El совпадает с образцом, содержащимся в Е2, иначе — False. Таблица 5.3. Символы совпадения с образцом для оператора Like Символ образца Соответствие # Любая одиночная цифра от 0 до 9. * Любое количество символов в любой комбинации или отсутствие символов. ? Любой одиночный символ. [list] list — это список определенных символов. Совпадение с любым одиночным символом в списке. [Hist] list — это список определенных символов. Совпадение с любым одиночным символом, не имеющимся в списке. Таблица 5.4. Логические операторы Оператор Синтаксис Имя/Описание And El And E2 Конъюнкция. True, если оба Е1и Е2 имеют значение True, иначе — False. Or El Or E2 Дизъюнкция. True, если одно выражение или оба (Е1 и Е2) являются равными True; иначе — False. Not Not El Отрицание. True, если Е1 имеет значение False; False, если El является равным True. Xor El Xor E2 Исключение. True, если Е1 является равным True или Е2 является равным True; иначе — False. Eqv El Eqv E2 Эквивалентность. True, если Е1 имеет то же самое значение, что и Е2; иначе — False. Imp 1 El Imp E2 Импликация. False, когда Е1 является равным True и Е2 равно False; иначе — True. Таблица 5.5. Иерархия операторов от наивысшего до самого низкого приоритета Оператор Комментарии А Возведение в степень, наивысший приоритет. Унарный минус. 670 Приложение А Оператор „ Ii Комментарии *, / Умножение и деление имеют равные приоритеты; они вычисляются по мере появления в выражении слева направо. \ Mod +, - Сложение и вычитание имеют равный приоритет; они вычисляются по мере появления в выражении слева направо. & Всякая конкатенация строк выполняется после любых арифметических операций в выражении и перед любыми операциями сравнения или логическими операциями. >=, Like=, о, Is Все операторы сравнения имеют равные приоритеты и вычисляются по мере появления в выражении слева направо. Используйте круглые скобки для группирования операторов сравнения в выражениях. Not And Or Xor Eqv Imp Таблица 6.1. Аргументы-константы функции MsgBox Константа Назначение I vbAbortRetrylgnore Отображает командные кнопки Стоп, Повтор, Пропустить (Abort, Retry, Ignore). vbApplicationModal Для продолжения работы с приложением пользователь должен ответить на запрос (или закрыть) этого диалогового окна. Любые другие приложения Windows, работающие в фоновом режиме, продолжают выполняться. vbCritical Отображает в диалоге значок критического предупредительного сообщения (Critical Message) Windows (красный кружок). vbDefaultButtonl Первая командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefaultButton2 Вторая командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefaultButton3 Третья командная кнопка в диалоговом окне является кнопкой по умолчанию. vbDefaultButton4 Четвертая командная кнопка в диалоговбм окне является кнопкой по умолчанию. | vbExclamation Отображает значок ("I") предупреждения (Warning Message); обычно используется для отображения важной информации или предупреждения, не требующего ответа. Справочные таблицы книги 671 Константа Назначение vblnformation Отображает значок ("I") информации (InFormation Message); обычно используется для отображения важной информации, кроме предупреждения. vbMsgBoxHelpButton Добавляет к диалоговому окну кнопку Справка (Help); при щелчке на кнопке Справка открывается файл, который задан в аргументе HelpFile, в разделе, заданном аргументом Context. vbOKCancel Отображает кнопки ОК и Отмена (OK, Cancel). vbOKOnly Отображает только кнопку ОК; то же самое происходит при опускании аргумента Buttons. vbQuestion Отображает значок запроса (Query icon) Windows (“?”); обычно используется, чтобы задать пользователю очень важный вопрос или выдать предупредительное сообщение, требующее ответа. vbRetryCancel Отображает кнопки Повтор и Отмена (Retry, Cancel). vbSystemModal При отображении диалоговое окно остается впереди других окон (даже при переключении на другое приложение), пока не будет закрыто. vbYesNo Отображает кнопки Да и Нет (Yes, No). vbYesNoCancel Отображает кнопки Да, Нет и Отмена (Yes, No, Cancel). Таблица 6.2. Возвращаемые значения-константы функции MsgBox Константа Что означает vbAbort Пользователь выбирает кнопку Стоп (Abort) vbCancel Пользователь выбирает кнопку Отмена (Cancel) vblgnore Пользователь выбирает кнопку Пропустить (Ignore) vbNo Пользователь выбирает кнопку Нет (No) vbOK Пользователь выбирает кнопку ОК vbRetry Пользователь выбирает кнопку Повтор (Retry) vbYes Пользователь выбирает кнопку Да (Yes) Таблица 6.3. Математические функции VBA [функции | (аргументы) Возвращает/действие Abs(N) Возвращает абсолютное значение N. Atn(N) Возвращает арктангенс N как угол в радианах. Cos(N) Косинус угла N, где N — это угол, измеренный в радианах. Exp(N) Возвращает константу е, возведенную в степень N. (е — это основание натуральных логарифмов и она (приблизительно) равна 2,718282). 672 Приложение А Функции (аргументы) Возвращает/действие Fix(N) Возвращает целую часть N. Fix не округляет число, а отбрасывает любую дробную часть. Если N является отрицательным, Fix возвращает ближайшее отрицательное целое большее, чем или равное N. Int(N) Возвращает целую часть N. Int не округляет число, а отбрасывает любую дробную часть. Если N является отрицательным, Int возвращает ближайшее отрицательное целое меньшее, чем или равное N. Log(N) Возвращает натуральный логарифм N. Rnd(N) Возвращает случайное число; аргумент является необязательным. Используйте функцию Rnd только после инициализации VBA-генератора случайных чисел оператором Randomize. Sgn(N) Возвращает знак числа: -1, если N — отрицательное; 1, если N — положительное; 0, если N равно 0. Sin(N) Возвращает синус угла; N — это угол, измеренный в радианах. Sqr(N) Возвращает корень квадратный из N. VBA отображает ошибку времени исполнения, если N — отрицательное. Tan(N) Возвращает тангенс угла; N — угол в радианах. Таблица 6.4. Функции преобразования данных Функция (Аргументы) Возвращает/действие Asc(S) Возвращает число кода символа, соответствующее первой букве строки S. Буква "А", например, имеет код символа 65. Chr(N) Возвращает строку из одного символа, соответствующего коду символа N, который должен быть числом между 0 и 255, включительно. Код символа 65, например, возвращает букву "А". Format(E, S) Возвращает строку, содержащую значение, представленное выражением Е, в формате в соответствии с инструкциями, содержащимися в S. Hex(N) Возвращает строку, содержащую шестнадцатиричное представление N. [ Oct(N) Возвращает строку, содержащую восьмиричное представление N. RGB(N, N, N) Возвращает целое типа Long, представляющее значение основных цветов изображения. N в каждом аргументе должно быть целым в диапазоне 0 — 255, включительно. Аргументы (слева направо) — это значения для красного, зеленого и синего цвета. Str(N) Возвращает строку, эквивалентную численному выражению N. Val(S) Возвращает численное значение, соответствующее числу, представленному строкой S, которая должна содержать только цифры и одну десятичную точку, иначе VBA не может преобразовать ее в число. Если VBA не может преобразовать строку в S, то функция Vai возвращает 0. Справочные таблицы книги 673 Функция (Аргументы) Возвращает/действие CBool(N) Возвращает Boolean-эквивалент численного выражения N. CByte(E) Возвращает численное значение типа Byte (от 0 до 255); Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CCur(E) Возвращает численное значение типа Currency; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CDate(E) Возвращает значение типа Date. Е может быть любым допустимым выражением (строкой или числом), представляющим дату в диапазоне 1/1/100 — 12/31/9999, включительно. CDbl(E) Возвращает численное значение типа Double; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. Cint(E) Возвращает численное значение типа Integer; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CLng(E) Возвращает численное значение типа Long; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CSng(E) Возвращает численное значение типа Single; Е — любое допустимое численное или строковое выражение, которое может быть преобразовано в число. CStr(E) Возвращает значение типа String; Е — любое допустимое численное или строковое выражение. CVar(E) Возвращает значение типа Variant; Е — любое допустимое численное или строковое выражение. Таблица 6.5. Функции даты и времени Функции (аргументы) Возвращает/действие Date Возвращает системную дату. Можно также использовать эту функцию как процедуру для установки системных часов компьютера. Больше информации можно получить в справочной системе VBA. Time Возвращает системное время компьютера как значение типа Date. Можно также использовать эту функцию как процедуру для установки системных часов. Больше информации можно получить в справочной системе VBA. Now Возвращает системную дату и время. Year(D) Возвращает целое, являющееся частью выражения типа Date и содержащее год. Год возвращается как число между 100 и 9999. Month(D) Возвращает целое, являющееся частью выражения типа Date и содержащее месяц. Месяц возвращается как число между 1 и 12, включительно. 22 Программирование на VBA 2002 674 Приложение А 1 Функции (аргументы) Возвращает/действие Day(D) Возвращает целое, являющееся частью выражения типа Date и содержащее день. День возвращается как число между 1 и 31, включительно. Weekday(D) Возвращает целое, содержащее день недели для выражения типа Date. День недели возвращается как число между 1 и 7, включительно; 1 — это воскресенье, 2 — понедельник и так далее. Hour(D) Возвращает целое, содержащее часы как часть времени, содержащегося в выражении типа Date. Часы возвращаются как число между 0 и 23, включительно. Если выражение D не содержит значения времени, то Hour возвращает 0. Minute(D) Возвращает целое, содержащее минуты как часть времени в выражении типа Date. Минуты возвращаются как число между 0 и 59, включительно. Если выражение D не содержит значения времени, Minute возвращает 0. Second(D) Возвращает целое, содержащее секунды как часть времени в выражении типа Date. Секунды возвращаются как число между 0 и 59, включительно. Если выражение D не содержит значения времени, Second возвращает 0. DateAdd(S, N, D) Возвращает Variant-значение, содержащее дату, к которой добавлен некоторый временной интервал. DateDiff(S, DI, D2 [,D3[,D4]]) Возвращает число временных интервалов между двумя заданными датами. DatePart(S, D1[,D2[,D3]]) Возвращает указанную часть заданной даты. DateSerial(Nl, N2, N3) Возвращает значение последовательной даты для заданной даты. Слева направо аргументы представляют год, месяц и день. Аргумент года должен быть целым числом между 100 и 9999, месяца — между 1 и 12, дня — между 1 и 31 (все диапазоны являются включающими). DateValue(E) Возвращает значение типа Date, эквивалентное дате, заданной аргументом Е, который должен быть строкой, числом или константой, представляющей дату. TimeSerial (Nl, N2, N3) Возвращает значение последовательного времени. Слева направо аргументы представляют часы, минуты и секунды. Аргумент часов должен быть целым числом между 0 и 23, аргументы минут и секунд должны оба быть числами 0 и 59 (все диапазоны являются включающими). TimeValue(E) Возвращает значение типа Date, содержащее время, заданное аргументом Е, который может быть строкой, числом или константой, представляющей время. Timer Возвращает число, представляющее количество секунд от полуночи в соответствии с системным временем компьютера. Справочные таблицы книги 675 Таблица 6.6. Строковые функции Функция (аргумент) Возвращает/действие InStr([Nl,] SI, S2[, N2]) Возвращает положение S2 в SI. Nl — начальное положение для поиска; N2 определяет тип сравнения. N1 и N2 необязательны. Если N2 опускается, то для поиска используется текущая установка Option Compare. InStrRev(Sl, S2 [, Nl[, N2]]) Возвращает позицию появления строки S2 внутри S1, в направлении от конца (или N1) к началу строки. N2 определяет тип сравнения. Если N2 опускается, то для поиска используется текущая установка Option Compare. Lcase(S) Возвращает строку (тип String), содержащую копию S со всеми символами верхнего регистра, преобразованными в символы нижнего регистра. Left(S, N) Возвращает строку; копирует N символов из S, начиная с левого крайнего символа S. Len(S) Возвращает число символов в S, включая начальные и конечные пробелы. Ltrim(S) Возвращает копию строки S после удаления символов пробела из левой части строки (начальные пробелы). Mid(S, Nl, N2) Возвращает строку; копирует N2 символов из S, начиная с позиции символа в S, заданной аргументом Nl. N2 является необязательным; если N2 опущен, то Mid возвращает все символы в строке S от позиции N1 до конца строки. Right(S, N) Возвращает значение типа String; копирует N символов из S, начиная с правого крайнего символа S. Например, Rightf’outright", 5) возвращает строку "right". Rtrim(S) Возвращает копию строки S после удаления символов пробела из правой части строки (конечные символы). Space(N) Возвращает строку пробелов длиной N символов. StrComp(Sl, S2, N) Сравнивает SI с S2 и возвращает число, обозначающее результат сравнения: -1, если SI < S2; 0, если SI = S2; 1, если S1 > S2. N является необязательным и указывает, следует ли выполнять сравнение с учетом регистра. Если N опускается, строки сравниваются с использованием текущей установки Option Compare. StrConv(S, N) Возвращает строку, преобразованную в новую форму в зависимости от числового кода, заданного аргументом N. VBA предоставляет внутренние константы для использования с функцией StrConv; наиболее полезными являются: vbProperCase (преобразует строку так, что каждая буква, начинающая слово, становится заглавной), vbLowerCase (преобразует строку в буквы нижнего регистра) и vbUpperCase (преобразует строку в буквы верхнего регистра). String(N, S) Возвращает строку длиной N символов, состоящую из символа, заданного первым символом в S. Например, String (5, "х") возвращает строку "ххххх". 22* 676 Приложение А Функция (аргумент) Возвращает/действие Trim(S) Возвращает копию строки S после удаления начальных и конечных символов пробела из этой строки. Ucase(S) Возвращает S со всеми символами нижнего регистра, преобразованными в символы верхнего регистра. Таблица 6.7. Именованные форматы для использования с функцией Format Именованный формат Действие General Date Форматирует информацию о дате и времени в последовательное число даты, используя установки формата даты и времени для вашего компьютера. То же, что VBA-преобразование по умолчанию последовательных дат в строки. Long Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Long-формата даты. Medium Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Medium-формата даты. Short Date Форматирует в последовательной дате только часть, содержащую дату, используя установки компьютера для Short-формата даты. Long Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Long-формата времени. Medium Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Medium-формата времени. Short Time Форматирует в последовательной дате только часть, содержащую время, используя установки компьютера для Short-формата времени. General Number Форматирует число в строку без каких-либо особых символов. Действие такое же, как VBA-преобразование по умолчанию чисел в строки. Currency Форматирует число с символом денежной единицы, разделителем тысяч и только двумя десятичными разрядами. Символ денежной единицы и десятичный разделитель определяются локальными установками Windows. Fixed Форматирует число так, чтобы всегда была, по крайней мере, одна цифра перед десятичным разделителем и, по крайней мере, две цифры после него. Standard Форматирует число с разделителем тысяч так, чтобы была, по крайней мере, одна цифра перед десятичным разделителем и, по крайней мере, две цифры после него. Справочные таблицы книги 677 Именованный формат Действие Percent Форматирует число как процентное отношение, умножая его на 100 и добавляя символ процента. Например, 0.21 возвращается как 21%. Scientific Форматирует Число в обычный экспоненциальный формат. Yes/No Использование этого формата приводит к тому, что функция Format возвращает строку "Да" ("Yes”), если форматируемое число ненулевое, и возвращает строку "Нет" ("No") для любого нулевого значения. Этот именованный формат наиболее часто используется со значениями типа Boolean. True/False Использование этого формата приводит к тому, что функция Format возвращает строку "Истина" ("True"), если форматируемое число ненулевое, и строку "Ложь" ("False") для любого нулевого значения. Этот именованный формат наиболее полезен со значениями типа Boolean. On/Off Использование этого формата приводит к тому, что функция Format возвращает строку "Вкл" ("On”), если форматируемое число ненулевое, и строку "Выкл" ("Off”) для любого нулевого значения. Наиболее часто используется со значениями Boolean. Таблица 6.8. Символы-заполнители для создания пользовательских форматов Символ-заполнитель Действие 0 Цифровой символ, отображает цифру, если таковая находится в этой позиции, или 0, если — нет. Можно использовать символ 0 для отображения начальных нулей для целых чисел и конечных нулей в десятичных дробях; 00000.000 отображает 1234,5 как 01234,500. # Цифровой символ, отображает цифру, если таковая находится в этой позиции, иначе — не отображает ничего. Символ-заполнитель # эквивалентен 0, кроме того, что начальные и конечные нули не отображаются; #####.### отображает 1234,5 как 1234,5. $ Отображает знак доллара; $###,###.00 отображает 1234,5 как $1 234,50. Десятичный символ-заполнитель, отображает десятичную точку в обозначенной позиции в строке символов-заполнителей 0; #.##.## отображает 1234,5 как 1234,5. % Символ процента, умножает значение на 100 и добавляет знак процента в позицию, указанную символами-заполнителями 0; #.#0.00% отображает число 0.12345 как 12,35% (12,345 округляется до 12,35). , (запятая) Разделитель тысяч, добавляет запятые как разделители тысяч в строках символов-заполнителей 0 и #; ###,###,###.00 отображает 1234,5 как 1 234,50. Е-, е- Отображает значения в экспоненциальном формате со знаком порядка только для отрицательных значений; #.####Е—00 отображает 1,2345Е03; 0,12345 отображается как 1.2345Е-01. 678 Приложение А Символ-заполнитель Действие Е+, е+ Отображает значения в экспоненциальном формате со знаком порядка для положительных и отрицательных значений; #.####Е+00 отображает 1234,5 как 1,2345Е+03. / Отделяет день, месяц и год для форматировайия значений дат. mm/dd/yy отображает 06/06/97. Символы "/” можно заменять на символы дефиса для отображения как 06-06-97. m Указывает, как отображать месяцы в датах; ш отображает 2, mm — 02, mmm — фев, mmmm — Февраль. d Указывает, как отображать дни в датах; d отображает 1, dd отображает 01, ddd — Пт, dddd — пятница. У Отображает день года как число от 1 до 366. УУ Указывает, как отображать годы в датах; уу отображает 99, УУУУ — 1999. q Отображает квартал года как число от 1 до 4. W Отображает день недели как число (1 — это воскресенье). WW Отображает неделю года как число от 1 до 54. :(двоеточие) Отделяет часы, минуты и секунды в значениях формата времени; hh:mm:ss отображает 02:02:02. h Указывает, как отображать часы; для значения времени 02:01:38 h отображает 2, hh отображает 02. И Минутный символ-заполнитель для времени; для значения времени 02:01:08 п отображает 1, а пп отображает 01. S Секундный символ-заполнитель для времени; для значения времени 02:01:08 s отображает 8, и ss отображает 08. АМ/РМ Отображает время в 12-часовом формате времени с добавленными AM и PM; h:nn АМ/РМ отображает 4:00 РМ. Альтернативные форматы включают am/pm, А/P и а/р. @ Символьный заполнитель, отображает пробел, если не имеется соответствующего символа в форматируемой строке. @@@@ отображает строку Hi с двумя начальными пробелами, (порядок заполнения по умолчанию — справа налево). < Отображает все символы в верхнем регистре. > Отображает все символы в нижнем регистре. Таблица 10.1. Общие объекты Excel 2000 Объект Описание Application Само приложение Excel 2000 (host-приложение). Chart Диаграмма в рабочей книге. Font Этот объект содержит атрибуты шрифта и стиля для текста, отображаемого в рабочем листе. Name Заданное имя для диапазона ячеек рабочего листа. Справочные таблицы книги 679 Объект Описание Range Диапазон ячеек (одна или более) или именованный диапазон в рабочем листе. Window Любое окно в Excel; окна используются для отображения рабочих листов, диаграмм и т.д. Workbook Открытая рабочая книга. Worksheet Рабочая таблица в книге. Таблица 10.2. Общие объекты Word 2000 Объект Описание Application Само приложение Word 2000 (host-приложение). Bookmark Отдельная закладка в документе. Document Открытый документ. Font Содержит атрибуты шрифта и стиля для текста, отображаемого в объекте. Paragraph Отдельный параграф в документе. Range Непрерывная область в документе. Style Встроенный или определенный пользователем форматирующий стиль в документе. Table Отдельная таблица в документе. TableOf- Contents Отдельная таблица содержания документа. Template Шаблон документа. Window Любое окно в Windows. Таблица 10.3. Наиболее употребительные свойства объектов в Excel 2000 Свойство Тип/Что означает Где найти ActiveCell Object: активная ячейка в рабочем листе Application, Window ActiveChart Object: активная диаграмма Application, Window, Workbook ActiveSheet Object: активный лист Application, Window, Workbook Address Возвращает координаты ячейки указанного объекта Range Cells Диапазон объекта Range Application, Range, Worksheet Charts Коллекция диаграмм Application, Workbook Count Integer: число объектов в коллекции Все объекты коллекции 680 Приложение А Свойство Тип/Что означает Где найти Fofmula String: формула для ячейки рабочего листа Диапазон Index Integer: число объектов в коллекции Worksheet Name String: имя объекта Application, Workbook и- в других объектах Path String: драйвер и каталог, в котором сохранен объект Addin, Application, Workbook Saved Boolean: сохранялась ли рабочая книга после последних изменений Workbook Selection Object: текущий выделенный фрагмент Application, Window Sheets Коллекция листов рабочей книги Application, W orkbook StatusBar String: сообщение в статусной строке Application ThisWorkBoo k Object: рабочая книга, из которой выполняется текущая процедура Application Type Integer: число, указывающее тип объекта Window, Worksheet, Chart Visible Boolean: отображается или нет объект на экране Application, Worksheet, Range и в других объектах Value (варьируется): действительное значение, отображаемое в ячейке Range Workbooks Коллекция рабочих книг Application Worksheets Коллекция рабочих листов Application, W orkbook Таблица 10.4. Употребительные и полезные свойства объектов Word 2000 Свойство Тип/Значение Имеется в объектах ActiveDocument Object: активный документ Application ActivePrinter String: имя активного принтера Application ActiveWindow Object: активное окно Application, Document Count Long: число объектов в коллекции Во всех объектах коллекций Name String: имя объекта Application, Bookmark, Dictionary, Document и в других Path String: драйвер и путь к папке, в которой сохранен объект Addin, Application, Dictionary, Document и в других , Range Object: часть документа, содержащаяся в указанном объекте Bookmark, Paragraph, Selection, Table и в других Saved Boolean: был ли сохранен текст после последнего изменения Document, template Справочные таблицы книги 681 Свойство Тип/Значение Имеется в объектах Selection Object: текущий выделенный фрагмент Application, Pane, Window StatusBar String; сообщение строки состояния Application Visible Boolean: отображается объект на экране или нет * Application, Border Таблица 10.5. Общеупотребительные и полезные методы объектов Excel 2000 Метод Назначение Имеется в объектах Activate Активизирует объект Window, Workbook, Worksheet, Range и в других объектах Calculate Выполняет вычисления в открытой рабочей книге, рабочем листе или диапазоне Application, Range, Worksheet Clear Удаляет данные, сохраненные в указанном объекте Range Close Закрывает указанный объект Window, Workbook, Workbooks Justify Выравнивает текст, сохраненный в указанном объекте Range Run Выполняет указанную процедуру или функцию Application, Range Save Сохраняет файл рабочей книги Application, Workbook SaveAs Сохраняет указанный объект в другом файле Workbook, Worksheet Select Выбирает указанный объект Range, Sheets, Worksheets SendKeys Пересылает нажатия клавиши в диалоговые окна в host-приложении Application Volatile Регистрирует функцию как изменяющуюся (см. гл. 6) Application Таблица 10.6. Наиболее употребительные и полезные методы объектов Word 2000 Метод Назначение Имеется в этих объектах Activate Активизирует объект Window, Document, Pane и в других объектах CheckSpelling Проверяет орфографию указанного документа или диапазона Document, Range Close Закрывает указанный объект Window, Document 682 Приложение А Метод Назначение Имеется в этих объектах Delete Удаляет указанный объект или удаляет символы и слова Bookmark, Range и в других объектах GoTo Перемещает курсор в начальное положение элемента, такого как страница, закладка или иоле; возвращает объект Range Document, Range, Selection * Printout Печатает указанный объект Application, Document, Envelope, Window Run Выполняет указанную процедуру или функцию Application Save Сохраняет указанный объект Document, Template SaveAs Сохраняет документ в другом файле Document Select Выбирает указанный объект Bookmark, Document, Field и в других объектах Таблица 10.7. Общие коллекции Excel 2000 Коллекция Назначение Addins Коллекция надстроек приложения. Charts Коллекция всех таблиц (Chart sheets) в рабочей книге. ChartObjects Коллекция всех объектов Chart в рабочем листе. Dialogs Коллекция всех диалогов в приложении. Windows Коллекция всех окон в приложении, независимо от того, отображается ли окно на экране. Workbooks Коллекция всех открытых в данных момент рабочих книг в приложении. Worksheets Коллекция всех рабочих листов в рабочей книге. Таблица 10.8. Общие коллекции Word 2000 Коллекция Назначение Addins Коллекция надстроек приложения. Bookmarks Коллекция всех закладок в документе, разделе или диапазоне (в зависимости от контейнера). Characters Коллекция всех символов в документе, разделе или диапазоне (в зависимости от контейнера). Каждый элемент в коллекции Characters является объектом Range, содержащим один символ. Comments Коллекция всех комментариев документа. Dialogs Коллекция диалогов приложения. Documents Коллекция всех открытых в данный момент документов. Справочные таблицы книги 683 Коллекция Назначение Paragraphs Коллекция объектов Paragraph в документе, разделе или диапазоне (в зависимости от контейнера). Sections Коллекция разделов в документе, разделе или диапазоне (в зависимости от контейнера). Styles Коллекция описаний стилей в документе для встроенных , и определенных пользователем стилей. Templates Коллекция всех шаблонов приложения. Windows Коллекция всех окон в приложении или коллекция всех окон (отображающих документ в зависимости от контейнера). Таблица 13.1. Функции, методы и операторы управления файлами Имя Категория Назначение ChDir Оператор Изменяет текущий каталог (папку). ChDrive Оператор Изменяет текущий драйвер диска. CurDir Функция Возвращает текущий каталог (папку). Dir Функция Возвращает имя каталога или файла, совпадающее с определенным именем файла (включая символы универсального сопоставления), передаваемым как строковый аргумент. Предназначена для нахождения одного или нескольких файлов на диске. FileCopy Оператор Копирует файл. FileDateTime Функция Возвращает значение типа Date, содержащее дату и время, когда этот файл был изменен последний раз. FileLen Функция Возвращает длину файла в байтах. GetAttr Функция Возвращает число, представляющее объединенные атрибуты файла или каталога диска, такие как System, Hidden и так далее. GetOpenFile-Name Метод Отображает Excel-диалоговое окно Open и возвращает имя файла, выбранное пользователем. В Word не имеется. GetSaveAsFile-Name Метод Отображает Excel-диалоговое окно (Save As) и возвращает имя файла, выбранное пользователем. В Word не имеется. Kill Оператор Удаляет файлы с диска. MkDir Оператор Создает каталог диска (папку). Name Оператор Переименовывает или перемещает файл. RmDir Оператор Удаляет каталог диска (папку). SetAttr Оператор Устанавливает атрибуты файла. 684 Приложение А Таблица 13.2. Константы атрибутов файла Visual Basic for Applications Константа VBA Значение Что означает vbNormal 0 Normal vbReadOnly 1 Read-Only vbHidden 2 Hidden vbSystem 4 System vbVolume 8 Volume Label vbDirectory 16 Каталог или подкаталог диска. vbArchive 32 Archive. Если установлен, указывает, что этот файл был изменен со времени последнего резервирования. vbAlias 64 Указанное имя файла является алиасным. Доступна только в Macintosh. Таблица 13.3. Возвращаемые значения метода Display Числовое значение Что означает -2 Диалоговое окно было закрыто с помощью кнопки Close (Закрыть). -1 Диалоговое окно было закрыто щелчком кнопки ОК или эквивалентной ей (Open (Открыть) в диалоговых окнах wdDialogFileOpen и wdDialogFileSaveAs). ° Диалоговое окно было отменено. > 0 Командная кнопка; 1 — для первой командной кнопки, 2 — для второй и так далее. Таблица 14.1. Наиболее часто используемые свойства объектов UserForm Свойство Описание ActiveControl Возвращает объектную ссылку на элемент управления, находящийся в фокусе в данный момент. Только для чтения. BackColor Целое типа Long определяет цвет фона формы. Самый простой способ установить это свойство — использовать Properties Window; чтобы выбрать желаемый цвет (если необходимо), можно скопировать номер цвета из Properties Window в свою программу. Caption Текст, выводимый в качестве заголовка формы. Запись/Чтение. Controls Возвращает коллекцию всех элементов управления формы. Только для чтения. Cycle Определяет, должно ли нажатие клавиши табуляции вызывать последовательный выбор всех элементов управления во всех группах и на каждой странице многостраничных элементов управления или только в пределах текущей группы или страницы. Может содержать одну из двух встроенных констант: fmCycleAllForms или fmCycleCurrentForm. Чтение/Запись. Справочные таблицы книги 685 Свойство Описание Enabled Содержит значение типа Boolean, указывающее, доступна ли форма. Если его значение равно False, ни один из элементов управления формы не доступен. Чтение/Запись. Font Возвращает ссылку на объект Font, посредством которого вы можете выбрать параметры шрифта формы или элемента управления. ForeColor То же самое, что и свойство BackColor, но устанавливает цвет, используемый для переднего плана (обычно — это цвет текста) объекта формы. Таблица 14.2. Наиболее часто используемые методы для объектов UserForm Метод Назначение Сору Копирует выделенный в элементе управления текст в буфер обмена Windows. Cut Вырезает выделенный в элементе управления текст и помещает его в буфер обмена Windows. Hide Скрывает UserForm, не выгружая ее из памяти, сохраняя значения элементов управления формы и всех переменных, объявленных в модуле класса формы. Paste Вставляет содержимое буфера обмена Windows в текущий элемент управления. PrintForm Выводит на используемый в Windows по умолчанию принтер изображение формы, включая все данные, введенные в элементы управления. Repaint Перерисовывает форму, выведенную на экран. Используйте этот метод, если хотите перерисовать форму, не ожидая, когда она будет перерисована через обычный период времени. Show Выводит форму на экран. Если форма еще не загружена в память, то данный метод сначала ее загружает. Таблица 14.3. События объектов UserForm Событие Синтаксис заголовка процедуры обработки события Описание Activate Private Sub ob/ect_Activate() Инициируется всякий раз, когда окно формы становится активным. Используйте это событие для обновления содержимого диалоговых элементов управления, чтобы отразить любые изменения, которые произошли, пока окно формы было неактивным. Click Private Sub object_Click(index As Long) Инициируется всякий раз, когда по форме (любой ее части, не занятой элементами управления) щелкают мышью. 686 Приложение А Событие Синтаксис заголовка процедуры обработки события Описание DblClick Private Sub ob/ect_DblClick(index As Long, By Vai Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда по форме (любой ее части, не занятой элементами управления) дважды щелкают мышью. Deactivate Private Sub obyect_Deactivate() Инициируется всякий раз, когда форма] перестает быть активной. Initialize Private Sub ob/ect_Initialize() Инициируется всякий раз, когда форма впервые загружается в память посредством выполнения оператора Load или с помощью метода Show. Используйте это событие для инициализации элементов управления формы при ее появлении на экране. Resize Private Sub UserF orm_Resize() Инициируется при изменении размеров формы. Terminate Private Sub ob/ect_Terminate() Инициируется всякий раз, когда форма выгружается из памяти. Используйте это событие для осуществления любых специальных служебных задач, которые необходимо выполнить прежде, чем переменные формы будут выгружены. Таблица 14.4. Стандартные элементы управления, включенные в VBA Элемент управления Назначение Label (надпись, метка) Позволяет создавать заголовки элементов управления, которые не имеют собственных встроенных заголовков. Используйте этот элемент для того, чтобы поместить на форму статический текст, например, инструкции, советы по заполнению других диалоговых элементов управления. TextBox (текстовое поле) Окно редактируемого текста свободной формы для ввода дан-1 ных. Может быть одно- или многострочным. ComboBox (поле со списком) Этот элемент управления объединяет окно редактирования и окно списка. Используйте, когда хотите предложить пользователю выбрать значение, но при этом дать ему возможность ввести данные, отсутствующие в списке. Вы можете также ограничить выбор только теми значениями, которые появляются в ComboBox для эмуляции ниспадающего списка. ListBox (список) Отображает список значений, из которых пользователь может сделать выбор. Окна списка можно использовать, чтобы дать возможность пользователю выбрать только одно значение или же несколько. CheckBox (флажок) Стандартный флажок (квадратное окно, содержащее, если элемент выбран, «галочку»). Используйте флажки для выбора вариантов, которые не являются взаимоисключающими. Справочные таблицы книги 687 Элемент управления Назначение i OptionButton (переключатель) Стандартная кнопка-переключатель (круглое окно, при выборе в центре него находится черная точка). Используйте OptionButton, когда пользователю необходимо сделать выбор между «включено/выключено», «истина/ложь». Кнопки-переключатели, как правило, объединяются вместе при помощи рамки для создания группы переключателей. ToggleButton (выключатель) Выключатели служат для той же цели, что и флажки, но выводят установки в виде кнопки находящейся в «нажатом» или «отжатом» состоянии. Frame (рамка) Визуально и логически объединяет некоторые элементы управления (особенно флажки, переключатели и выключатели). Используйте Frame, чтобы показать пользователю, какие элементы управления в диалоговом окне связаны между собой, или чтобы выделить группу элементов управления, отделяя ее от остальных элементов управления, находящихся в диалоговом окне. CommandButton (кнопка) Используйте кнопки для выполнения таких действий как Cancel (Отмена), Save (Сохранить), ОК и так далее. Когда пользователь щелкает по кнопке, выполняется VBA-процедура, закрепленная за данным элементом управления. TabStrip (набор вкладок) Этот элемент управления состоит из области, в которую вы помещаете другие элементы управления (такие как текстовые поля, флажки и так далее) и полосы кнопок табуляции. Используйте элемент управления TabStrip для создания диалоговых вкладок, отображающих одни и те же данные в различных категориях. MultiPage (набор страниц) Этот элемент управления состоит из нескольких страниц. Вы можете выбрать любую из них, щелкнув по соответствующей вкладке. Используйте элемент управления MultiPage для создания диалоговых окон с вкладками, такими, например, как диалоговое окно, появляющееся при выборе команды Tools | Options (панели инструментов | настройка). ScrollBar (полоса прокрутки) Элемент управления ScrollBar позволяет выбирать линейное значение, аналогично тому, как это можно сделать при помощи счетчика. SpinButton (счетчик) Элемент управления SpinButton является специальной разновидностью текстового поля. Обычно счетчики используются для того, чтобы ввести число, дату или какие-либо иные последовательные величины, которые заведомо находятся в опреде- ленном интервале значений. Щелчок по указывающей вверх стрелке счетчика увеличивает значение в окошке, а щелчок по стрелке, направленной вниз, соответственно уменьшает его. Image (рисунок) / Элемент управления Image позволяет вывести на форме графическое изображение. Используйте Image для вывода графических изображений в любом из следующих форматов: *.bmp, *.cur, *.gif, *.ico, *.jpg, или *.wmf. Вы можете обрезать и масштабировать графическое изображение, чтобы подобрать размер элемента Image, но только не редактировать графическое изображение. Можно даже написать специальную VBA-процедуру, выполняющуюся, если пользователь щелкнет по элементу управления Image. 688 Приложение А Таблица 14.5. Наиболее часто используемые свойства стандартных элементов управления Свойство Где применяется Описание Accelerator Checkbox, Tab, CommandButton, Label, Page, OptionButton, ToggleButton Содержит символ, используемый, в качестве быстрой клавиши вызова, элемента управления. При нажатии АИ+<клавиша быстрого вызова> происходит выбор элемента управления. BackColor Все элементы Число, представляющее определенный цвет фона элемента управления. Caption CheckBox, CommandButton, Frame, Label, OptionButton, ToggleButton, Page, Tab, UserForm Для надписи — текст, отображаемый, элементом управления. Для других элементов управления — надпись, которая появляется на кнопке или вкладке или рядом с рамкой, флажком или переключателем. Cancel CommandButton Задает кнопку отмены диалогового окна. При нажатии на эту кнопку или клавишу Esc диалоговое окно исчезает. Только одна кнопка формы может иметь данное свойство. ControlTipText Все элементы управления Устанавливает текст, который отображается в виде всплывающей подсказки (ControlTip, называемой также ToolTip), когда указатель мыши помещается на элемент управления. Default CommandButton Определяет заданную по умолчанию кнопку. Когда пользователь нажимает в процессе диалога клавишу Enter, эта кнопка ведет себя так, как если бы по ней щелкнули мышью. Enabled Все элементы управления Хранит значение типа Boolean, определяющее доступен или нет элемент управления. Если Enabled имеет значение False, то элемент управления продолжает отображаться в диалоговом окне, но не может быть выбран. ForeColor Все элементы управления То же самое, что и BackColor, но устанавливает цвет для переднего плана элемента управления, как правило, символов текста. List ComboBox Массив типа Variant (одно- или многомерный), представляет список содержащийся в элементе управления. Используйте индекс Value как нижний индекс в коллекции List, чтобы получить текст для выбранного пункта списка. Используйте методы элемента управления Additem и Removeitem для добавления или удаления пунктов списка. Справочные таблицы книги 689 Свойство Где применяется Описание Мах ScrollBar, SpinButton Переменная типа Long, определяющая максимальное значение счетчика, или значение, при котором полоса прокрутки находится в самом верху (для вертикальной полосы) или справа (для горизонтальной). Min ScrollBar, SpinButton Переменная типа Long, определяющая минимальное значение счетчика, или значение, при котором полоса прокрутки находится в самом низу (для вертикальной полосы) или слева (для горизонтальной). Name Все элементы управления Содержит имя элемента управления. Вы можете установить данное свойство только с помощью Properties Window. RowSource ComboBox Задает источник, из которого ListBox берет список объекта. В Excel VBA RowSource обычно использует диапазон рабочего листа. Selected ListBox Возвращает массив значений типа Boolean для списка, который допускает множественный выбор. Каждый элемент массива содержит по одному элементу, соответствующему каждому пункту списка. Если значение элемента в массиве Selected равно True, то соответствующий пункт списка выбран. Tabindex Все элементы управления Число, указывающее положение элемента управления в порядке табуляции (может иметь значение от 0 до значения, равного количеству элементов управления на форме). TabStop Все элементы управления Значение типа Boolean, указывающее может ли элемент управления быть выбран клавишей Tab. Если значение TabStop равно False вы, тем не менее, можете щелкнуть на элементе и таким образом его выбрать. Value Все элементы управления I Значение текущих установок элемента управления: текст в текстовом поле, какие выбраны флажки и переключатели, индекс выбранного раздела списка или число, указывающее текущее положение полосы прокрутки или счетчика. J Visible Все элементы управления Значение типа Boolean, указывающее, является ли элемент управления видимым. Таблица 14.6. Наиболее часто используемые события объектов управления Событие Синтаксис процедуры обработки Описание AddControl См. приложение Е Инициируется всякий раз, когда к форме (или элементам Frame, Page, MultiPage) добавляется какой-либо элемент управления. 690 Приложение А Событие Синтаксис процедуры обработки Описание AfterUpdate Private Sub object_AfterUpdate() Инициируется после обновления значения элемента управления. BeforeUpdate Private Sub obj ect_BeforeUpdate( By Vai Cancel As MSForms.ReturnBoolean) Инициируется после того, как было изменено значение элемента управления, но перед тем, как был обновлен сам элемент управления. t Change Private Sub object_Change() Инициируется всякий раз, когда изменяется значение элемента управления. Click Private Sub object_Click() Инициируется всякий раз, когда по элементу управления щелкают мышью. Используйте данное событие для того, чтобы выполнить действие при помощи кнопки. DblClick Private Sub object_DblClick(ByVal Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда по элементу управления дважды щелкают мышью. Используйте данное событие для вывода дополнительных форм. Enter Private Sub object_Enter() Инициируется всякий раз, когда выделяется элемент управления. Exit Private Sub object_Exit( ByVai Cancel As MSForms.ReturnBoolean) Инициируется всякий раз, когда с элемента управления снимается выделение. Error Private Sub obj ect_Error( Index As Long, ByVai Number As integer, ByVai Description As MSForms .Returnstring) Инициируется всякий раз, когда элемент управления обнаруживает ошибку и не может возвратить информацию об ошибке в вызывающую программу. KeyDown Private Sub object_KeyDown(ByVal KeyCode As MSForms.Returninteger, ByVai Shift As fmShiftState) Инициируется при нажатии пользователем какой-либо клавиши в тот момент, когда форма выполняется и имеет фокус. KeyPress Private Sub object KeyPress(ByVal KeyANSI As MSForms. Returninteger) Инициируется, когда пользователь нажимает алфавитно-цифровую клавишу. Ke у Up Private Sub object_KeyUp(ByVal KeyCode As MSForms. Returninteger, ByVai Shift As fmShiftState) Инициируется, когда пользователь отпускает клавишу. Layout Private Sub object_Layout() Инициируется, когда изменяются размеры элемента Frame (или MultiPage). Справочные таблицы книги 691 Событие Синтаксис процедуры обработки Описание MouseDown, MouseUp См. приложение Е Инициируются при щелчке мышью: MouseDown, когда пользователь нажимает на клавишу мыши; MouseUp, когда пользователь отпускает клавишу мыши. MouseMove См. приложение Е Инициируется, когда пользователь перемещает мышь. SpinDown, SpinUp Private Sub object_SpinDown() Private Sub object_SpinUp() Событие SpinDown инициируется, когда пользователь щелкает стрелку «вниз» (или «влево») кнопки счетчика. Событие SpinUp инициируется, когда пользователь щелкает стрелку «вверх» (или «вправо») кнопки счетчика. Zoom Private Sub object_Zoom(index As Long, Percent As Integer) Инициируется при изменении свойства Zoom. Таблица 16.1. Встроенные константы WdUnits Константа Описание wdCell Ячейка таблицы. wdCharacter Символ, включая скрытые и непечатаемые символы. wdColumn Столбец таблицы. wdLine Строка текста. Вы можете использовать данную константу только для аргумента Unit, если используемый метод применяется к объекту Selection. wdParagraph Абзац. Абзац ограничивается символом конец абзаца (1|). Символ конца абзаца не отображается на экране пока вы не щелкните кнопку Показать все символы (Show АП) панели инструментов Word. wdRow Строка таблицы. wdSection Раздел документа. wdSentence Предложение. Предложение ограничивается знаками пунктуации, такими как точка (.), знак вопроса (?), и восклицательный знак (!). wdStory Область документа. wdTable Таблица. wdWord Слово. Слово ограничено пробелами и символами пунктуации. Таблица 16.2. Встроенные константы WdGoToItem Константа Описание wdGoToBookmark Закладка. wdGoToField Поле, например поле даты или номера страницы. 692 Приложение А Константа Описание wdGoToHeading Заголовок, то есть текст отформатированный с помощью одного из стилей заголовка: Заголовок!, Заголовок2 и так далее. wdGoToLine Строка документа. wdGoToPage Страница документа. wdGoToPercent Местоположение в документе, выраженное в процентах от длины документа. Таблица 17.1. Типы классов для часто используемых объектов Объект Тип класса 1-2-3 Worksheet 123Worksheet Приложение Microsoft Access Access.Application.10 Приложение Microsoft Excel Excel. Application. 10 Диаграмма Microsoft Excel Excel.Chart Лист Microsoft Excel Excel.Sheet Приложение Microsoft Graph MSGraph .Application Приложение MS PowerPoint PowerPoint. Application Приложение Microsoft Word Word. Application. 10 Документ Microsoft Word Word.Document Таблица 17.2.а Значения ClassType (ClassName) для ActiveX Controls Значение аргумента ClassType (ClassName) Создаваемый элемент управления Forms.Ch eckBox. 1 CheckBox Forms.ComboBox. 1 ComboBox Forms.CommandButton.! CommandButton Forms.Frame. 1 Frame Forms.Image. 1 Image Forms.Label.1 Label Forms.ListBox. 1 ListBox Forms.MultiPage.l MultiPage Forms.OptionButton. 1 OptionButton Forms.ScrollBar. 1 ScrollBar Forms.SpinButton. 1 SpinButton Forms.TabStrip. 1 TabStrip Forms.TexBox.l TexBox Forms.ToggleButton.l ToggleButton Справочные таблицы книги 693 Таблица 17.2.Ь Значения ClassType (ClassName) для объектов Microsoft Access Значение аргумента ClassType (ClassName) Создаваемый объект Access. Application Application Access.CodeData, Access.CurrentDat a CurrentData Access. CodeProj ect, Access. CurrentPrоj ect CurrentProject Access.DefaultWebOptions Def aultW ebOptions Таблица 17.2.С Значения ClassType (ClassName) для объектов Microsoft Excel Значение аргумента ClassType (ClassName) Создаваемый объект Excel. Application Application Excel. Addin Workbook Excel. Chart Workbook Excel.Sheet Workbook Таблица 17.2.d Значение ClassType (ClassName) для объекта Microsoft Outlook Значение аргумента ClassType (ClassName) Создаваемый объект Outlook. Application Application Таблица 17.2.е Значение ClassType (ClassName) для объекта Microsoft PowerPoint Значение аргумента ClassType (ClassName) Создаваемый объект PowerPoint .Application Application Таблица 17.2.f Значения ClassType (ClassName) для объектов Microsoft Word Значение аргумента ClassType (ClassName) Создаваемый объект Word. Application Application Word.Document, Word.Template Document Word.Global Global Таблица 17.3. Некоторые свойства OLE-объектов Свойство Приложение Объект-носитель Назначение Anchor Word Shape Объект Range указывает диапазон документа, с которым связывается объект Shape. 694 Приложение А Свойство Приложение Объект-носитель Назначение AutoUpdate Excel, Word, PowerPoint LinkFormat Имеет значение True, если связанный OLE-объект автоматически обновляется, когда изменяются данные приложения-сервера. BottomRightCell Excel Shape Возвращает объект Range, определяющий ячейку рабочего листа под правым нижним углом объекта Shape. Height Excel, Word, PowerPoint Shape Устанавливает или возвращает высоту объекта Shape, измеряемую в точках. Left Excel, Word, PowerPoint Shape Устанавливает или возвращает позицию левого края объекта относительно левого края рабочего листа или документа (в точках). Line Excel, Word, PowerPoint Shape Возвращает объект LineFormat, свойства которого управляют видом рамки OLE-объекта. LinkFormat Excel, Word, PowerPoint Shape Возвращает объект LinkFormat, свойства которого сохраняют информацию о связанном OLE-объекте. Name Excel, Word, PowerPoint Shape Имя объекта. Используйте это свойство, чтобы вернуть имя OLE-объекта или переименовать OLE-объект. Object Excel, Word, PowerPoint OLEFormat Возвращает Automation-объект, связанный с объектом. OLEFormat Excel, Word, PowerPoint Shape Возвращает объект OLEFormat, свойства которого содержат информацию как о связанных, так и о внедренных объектах. OnAction Excel Shape Вы можете использовать это свойство в Excel, чтобы установить или вернуть имя процедуры события для данного объекта Shape. Progid Excel, Word, PowerPoint OLEFormat Возвращает строку, содержащую тип класса OLE-объекта. Shadow Excel, Word, PowerPoint Shape Возвращает ссылку на объект ShadowFormat, который сохраняет информацию о состоянии тени, отбрасываемой объектом: видима она или — нет, ее цвет, величину сдвига относительно объекта и т.д. Справочные таблицы книги 695 Свойство Приложение Объект-носитель Назначение Тор Excel, Word, PowerPoint » Shape Устанавливает или возвращает позицию верхнего края объекта относительно верхнего края рабочего листа или документа (в точках). TopLeftCell Excel Shape Возвращает объект Range, определяющий ячейку рабочего листа, расположенную под верхним левым углом объекта Shape. Используйте TopLeftCell и Bottom-RightCell для поиска ячеек, перекрытых объектом Shape. Туре Excel, Word, PowerPoint Shape Возвращает численное значение, указывающее тип объекта Shape. Используйте встроенные константы MsoShapeType для определения типа Shape. Visible Excel, Word, PowerPoint Shape Установите это свойство в состояние False, чтобы скрыть объект, или в состояние True, чтобы сделать его видимым. Width Excel, Word, PowerPoint Shape Устанавливает или возвращает ширину объекта Shape (в точках). Таблица 18.1. Встроенные константы VBA для аргумента WindowStyle функции Shell WindowStyle Вид окна vbHide Скрытое, с фокусом vbNormalFocus Нормальный размер, с фокусом vbMinimizedFocus Минимизированное, с фокусом vbMaximizeFocus Максимизированное, с фокусом vbNormalNoFocus Нормальный размер, без фокуса vbMinizedNoFocus Минимизированное, без фокуса Таблица 18.2. Строки, используемые в качестве аргумента String в методе SendKeys Клавиши Коды BACKSPACE {BACKSPACE}, {BS} или {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL или DELETE {DELETE}или{DEL} 696 Приложение А Клавиши Коды DOWN ARROW {DOWN} END {END} ENTER {ENTER} или - ESC {ESC} HELP {HELP} HOME {HOME} INS или INSERT {INSERT} или {INS} LEFT ARROW {LEFT} NUM LOCK {NUMLOCK} PAGE DOWN {PGDN} PAGE UP {PGUP} PRINT SCREEN {PRTSC} RIGHT ARROW {RIGHT} SCROLL LOCK {SCROLLLOCK} TAB {TAB} UP ARROW {UP} F1-F16 {F1}-{F16} Таблица 18.3. Коды для клавиш Alt, Ctrl и Shift клавиша знак SHIFT + CTRL ALT % Таблица 19.1. Часто используемые события объектов Excel Событие Относится к Когда происходит Activate Chart, Workbook, Worksheet Когда объект активизируется VBA-кодом или действиями пользователя. Addininstall Workbook Когда рабочая книга устанавливается как надстройка (add-in). AddinUninstall Workbook Когда выгружается рабочая книга-надстройка. BeforeClose Workbook Перед тем, как закрывается рабочая книга и перед тем, как пользователю выдается запрос о сохранении изменений. Справочные таблицы книги 697 Событие Относится к Когда происходит BeforeDoubleClick Chart, Worksheet При выполнении двойного щелчка внедренной диаграммы или рабочего листа, но перед заданным по умолчанию ответным действием на двойной щелчок. BeforePrint Workbook Перед печатью рабочей книги или ее частью. BeforeRightClick Chart, Worksheet При выполнении правого щелчка внедренной диаграммы или рабочего листа, но перед заданным по умолчанию ответным действием на правый щелчок. BeforeSave Workbook Перед сохранением рабочей книги. Calculate Chart, Worksheet После того как рабочий лист повторно вычислен или после рисования диаграммы по новым или обновленным данным. Change Worksheet Когда свойство Value ячейки изменяется либо кодом VBA, либо в результате действий пользователя. Deactivate Chart, Workbook, Worksheet Когда объект деактивизируется либо кодом VBA, либо в результате действий пользователя. NewSheet Workbook При создании в рабочей книге нового листа (диаграммы или рабочего листа). NewWorkbook Application Когда создается новая рабочая книга. < Open Workbook Когда открывается рабочая книга. SelectionChange Worksheet При изменении выделенного фрагмента в рабочем листе. SheetActivate Application, Workbook Когда активизируется любой лист. SheetBeforeDoubleClick Application, Workbook При выполнении двойного щелчка рабочего листа, но до ответного действия по умолчанию на двойной щелчок. SheetBeforeRightClick Application, Workbook При выполнении правого щелчка рабочего листа, но до ответного действия по умолчанию на правый щелчок. SheetCalculate Application, Workbook Когда рабочий лист перерасчитывается или изменяются данные на диаграмме. Sheetchange Application, Workbook Когда ячейка в рабочем листе изменяется пользователем или внешней связью. SheetDeactivate Application, Workbook Когда лист (рабочий лист или диаграмма) деактивизируется. SheetSelectionChange Application, Workbook При изменении выделенного фрагмента в рабочем листе. Window Activate 1 Application, Workbook Когда активизируется любое окно рабочей книги. 698 Приложение А Событие Относится к Когда происходит WindowDeactivate Application, Workbook Когда деактивизируется любое окно рабочей книги. WindowResize Application, Workbook При изменении размеров любого окна рабочей книги. WorkbookActivate Application При активизации любой рабочей книги. W orkbook Addininstall Application Когда любая рабочая книга устанавливается как надстройка (add-in). WorkbookAddinUninstall Application Когда выгружается любая рабочая книга-надстройка. WorkbookBeforeClose Application Непосредственно перед закрытием любой рабочей книги. WorkbookBeforePrint Application Непосредственно перед печатью любой рабочей книги (или ее части). WorkbookBeforeSave Application Непосредственно перед сохранением любой открытой рабочей книги. WorkbookDeactivate Application Когда любая открытая книга деактивизируется. WorkbookNewSheet Application При создании в любой открытой рабочей книге нового листа (рабочего листа или диаграммы). WorkbookOpen Application При открытии рабочей книги. Таблица 19.2. Текстовые строки, использующиеся для аргумента Key метода ОпКеу Клавиша Строка BACKSPACE {BACKSPACE}, {BS} или {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL или DELETE {DELETE} или {DEL} DOWN ARROW {DOWN} END {END} ENTER {ENTER} или - ESC {ESC} HELP {HELP} HOME {HOME} INS или INSERT {INSERT} или {INS} LEFT ARROW {LEFT} NUM LOCK {NUMLOCK} PAGE DOWN {PGDN} Справочные таблицы книги 699 Клавиша Строка PAGE UP {PGUP} PRINT SCREEN {PRTSC} RIGHT ARROW {RIGHT} SCROLL LOCK {SCROLLLOCK} TAB {TAB} UP ARROW {UP} F1-F16 {F1}-{F16} Таблица 19.4. События Word-объекта Application Событие Когда происходит DocumentBeforeClose Перед тем, как закрывается любой документ. DocumentBeforePrint Перед тем, как печатается любой открытый документ. DocumentBeforeSave Перед тем, как сохраняется любой открытый документ. Documentchange Когда изменяется открытый документ. DocumentOpen Когда открывается документ. EPostageinsert, EPostageProperty Dialog, MailMergeAf terMerge, MailMergeAfterRecordMerge, MailMergeBeforeMerge, MailMergeBeforeRecordMerge, MailMergeDataSourceLoad, MailMergeDataSourceValidate, MailMergeDataSourceValidate, MailMergeWizardSendToCustom, MailMergeWizardStateChange При возникновении событий, связанных с использованием аппарата рассылки писем. i NewDocument При создании нового документа. Quit Когда пользователь завешает работу с Word. WindowActivate Когда любое окно документа становится активным. WindowBeforeDoubleClick Когда в редактируемой области окна документа выполняется двойной щелчок, перед выполнением действия по умолчанию. WindowBeforeRightClick Когда в редактируемой области окна документа выполняется правый щелчок, перед выполнением действия по умолчанию. WindowDeactivate Когда любое окно документа перестает быть активным. WindowSelectionChange I Когда в окне активного документа изменяется выделенный фрагмент. 700 Приложение А Событие Когда происходит WindowSize Когда окно приложения изменяется в размерах или перемещается. Таблица 19.5. События Word-объекта Document Событие Когда происходит Close Когда закрывается документ. New Когда новый документ создается на основе шаблона. Open При открытии документа. Приложение Б Приоритеты операций в Visual Basic * В следующей таблице приведены операции языка Visual Basic в порядке их приоритетов (сначала следуют операции с более высоким приоритетом). Обозначение Наименование Обозначение Наименование * возведение в степень О неравенство + унарный «плюс» < меньше чем - унарный «минус» <= меньше либо равно * умножение > больше чем / деление >= меньше либо равно \ деление без остатка Like шаблонное сравнение Mod деление по модулю Is ссылочное сравнение + сложение Not логическое отрицание - вычитание And логическое «И» & конкатенация Or логическое включающее «ИЛИ» равенство Xor логическое исключающее «ИЛИ» ел О Wr Операторы в VBA AppActivate Активизирует окно приложения (application window). Синтаксис AppActivate title], wait] Оператор AppActivate имеет следующие именованные аргументы: title Обязательный. Строковое выражение, определяющее строку заголовка для окна активизируемого приложения. ID-задачи, возвращаемый функцией Shell, может использоваться в качестве параметра для title. wait Необязательный. Тип Boolean. Значение, определяющее, должно ли вызывающее приложение иметь фокус перед активизацией другого приложения. Если этот параметр равен значению False (по умолчанию), указанное приложение немедленно активизируется, даже если вызывающее приложение не имеет фокуса. Если этот параметр равен значению True, вызывающее приложение ожидает получение фокуса, после чего активизируется указанное приложение. Оператор AppActivate переносит фокус на именованное приложение или окно, но не воздействует на их максимизацию или минимизацию. Для запуска приложения (которое затем можно активизировать) можно использовать функцию Shell. Shell запускает исполняемую программу и возвращает значение, представляющее ID-задачи, если запуск выполнен успешно, или нуль — в противном случае. В процессе определения того, какое приложение следует активизировать, аргумент title сравнивается со строкой заголовка каждого выполняющегося приложения. Если точного совпадения нет, то активизируется любое приложение, строка заголовка которого начинается с title. Если одновременно выполняются несколько экземпляров приложения с заголовком title, активизируется один из них, выбранный произвольно. Пример Sub Call_Excel() ' ' в качестве аргумента оператора AppActivate можно использовать ' возвращаемое значение функции Shell MyAppID = Shell( "e:\Program Files\Microsoft Office\OfficelO\EXCEL.EXE", 1) AppActivate MyAppID End Sub Beep Выдает звуковой сигнал посредством встроенного динамика. Синтаксис Веер Операторы в VBA 703 Частота и длительность сигнала зависят от оборудования и программного обеспечения компьютера. Пример Function MyBeep(n As Integer) ' n - "длительность" звучания For I - 1 То n Веер Next End Function Call Передает управление (вызывает) Sub-процедуре, Function-процедуре или процедуре DLL-библиотеки. Синтаксис [Call] name [argumentlist] Синтаксис оператора Call состоит из элементов: Call Необязательный; (ключевое слово). Если указан, список аргументов argumentlist необходимо заключать в круглые скобки. | name Обязательный. Имя вызываемой процедуры. argumentlist Необязательный. Список разделенных запятыми переменных, массивов или выражений для передачи вызываемой процедуре в качестве аргументов. Компоненты списка argumentlist могут включать ключевые слова ByVai или ByRef для описания способа передачи аргументов (по значению или по ссылке) процедуре. При вызове процедуры ключевое слово Call использовать необязательно. Но, если вы используете Call для вызова процедуры, которая принимает аргументы, необходимо список аргументов заключать в круглые скобки. Если ключевое слово Call не используется, скобки вокруг списка аргументов также не нужны. Пример В этом примере описаны три процедуры (с именами a_sub, b_sub и c_sub). Процедура a_sub вызывает процедуру b_sub и передает ей в качестве аргумента строку. Процедура b_sub вызывает процедуру c_sub и передает ей в качестве аргумента принятую от процедуры a_sub строку. Процедура c_sub с помощью MsgBox выводит содержимое переданной из b_sub строки. Sub a_sub() Call Ь("Привет от процедуры а!") End Sub , Sub b_sub(StrMy As String) c_sub (StrMy) End Sub I Sub c_sub(StrMy As String) MsgBox StrMy End Sub 704 Приложение В ChDir Изменяет текущий каталог или папку. Синтаксис ChDir path Обязательный аргумент path — строковое выражение, которое определяет новый текущий каталог или папку. Аргумент path может включать имя драйвера. Если имя*Драйвера не указывается, используется текущий драйвер. Оператор ChDir изменяет каталог по умолчанию, но не драйвер по умолчанию. Например, если драйвер по умолчанию — F, следующий оператор изменит каталог по умолчанию на драйвере Е, но F останется драйвером по умолчанию: ChDir "E:\TMP" Пример ChDir "MYDIR" ChDir "D:\WIN2000\SYSTEM" ChDrive Изменяет текущий драйвер. Синтаксис ChDrive drive Обязательный аргумент drive — строковое выражение, определяющее имеющийся драйвер. Если аргумент drive — строка из нескольких символов, оператор ChDrive использует только первую букву. Пример ChDrive "F" Close Закрывает ввод/вывод для файла, открытого с использованием оператора Open. Синтаксис Close [filenumberlist] Необязательный аргумент filenumberlist может быть списком номеров файлов (file numbers) со следующим синтаксисом (filenumber — допустимый номер файла): [[#]filenumber] [, [#]filenumber] . . . Если filenumberlist не указан, оператор Close закрывает все активные файлы, открытые оператором Open. Когда вы закрываете файлы, открытые для Output или Append, окончательный буфер вывода записывается в буфер операционной системы для этого файла. Все буферное пространство, связанное с этим файлом, удаляется, и связь файла с его файловым номером прекращается. Пример В этом примере в цикле For...Next открываются три файла для записи (Output), в каждый файл записывается текстовая строка; после окончания цикла при помощи оператора Close файлы закрываются. Sub Close'Iest () Dim I, FileName For I = 1 To 3 , Операторы в VBA 705 FileName = "TEST" & I ' создать имя файла Open FileName For Output As #1 ' открыть файл Print #1, "запись в файл " & FileName ' записать строку в файл Next I Close ' закрыть все три файла End Sub Const Объявляет константы. Синтаксис [Public I Private] Const constname [As type] = expression Синтаксис оператора Const включает три элемента: Public Необязательный. Ключевое слово, используемое на уровне модуля для объявления констант, которые доступны всем процедурам во всех модулях. Нельзя использовать в процедурах. Private Необязательный. Ключевое слово, используемое на уровне модуля для объявления констант, которые доступны только в том модуле, в котором объявлены. Нельзя использовать в процедурах. constname Обязательный. Имя константы; должно отвечать стандартным соглашениям об именовании переменных. type Необязательный. Тип (данных) константы; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String или Variant. expression Обязательный. Литерал, другая константа или любая комбинация, включающая все арифметические или логические операции, кроме Is. Константы по умолчанию являются закрытыми. В процедурах константы всегда являются закрытыми; их «видимость» не может быть изменена. В стандартных модулях видимость по умолчанию констант модульного уровня может быть изменена с использованием ключевого слова Public. Однако в модулях классов константы могут быть только закрытыми, их видимость нельзя изменить ключевым словом Public. Константы, объявляемые в Sub-, Function- или Property-процедурах, локальны для этих процедур. Константы, объявленные вне процедуры, «видимы» в модуле, в котором объявлены. Для объединения нескольких объявлений констант на одной строке следует отделять их друг от друга запятыми. Примеры Const IntMyVarl = 429 Public Const StrMyVarl = "Word" Private Const IntMyVar2 As Integer = 15 Const StrMyVarl = "Excel", DblPi As Double = 3.14 Date Устанавливает системную текущую дату. Синтаксис Date = date 23 Программирование на VBA 2002 706 Приложение В Для системы Microsoft Windows 9Х обязательный элемент синтаксиса date может быть в диапазоне от 1 января 1980 года до 13 декабря 2099 года. Для Microsoft Windows NT этот диапазон имеет верхнюю границу 31 декабря 2079 года. Для Macintosh date может принимать значения от 1 января 1904 года до 5 февраля 2040 года. Пример В следующем примере объявляется константа DateMy и переменная DateNow для сохранения текущей системной даты. С помощью функции Now в переменной запоминается текущая дата. Затем оператор Date (с аргументом DateMy) изменяет системную дату, a MsgBox выдает в диалоговом окне подтверждение выполнения оператора Date. Далее оператор Date с аргументом DateNow восстанавливает системную дату, a MsgBox в диалоговом окне дает возможность убедиться в «восстановлении справедливости» по отношению к системной дате. Sub DateTest () Const DateMy = #2/11/1986# Dim DateNow DateNow = Now() ' запомнить текущую дату (и время) Date = DateMy ' установить новую дату MsgBox Now () ' проверить изменение даты на новую Date = DateNow ' восстановить правильную дату MsgBox Now() ' проверить изменение даты сохраненную End Sub Declare Используется на уровне модуля для объявления ссылок на внешние процедуры в DLL-библиотеке. Синтаксис 1 [Public I Private] Declare Sub пате Lib <libname> [Alias <aliasname>] [([arglist])] Синтаксис 2 [Public | Private] Declare Function name Lib <libname> [Alias <aliasname>] [([arglist])] [As type] Синтаксис оператора Declare включает следующие элементы: Public Необязательный. Используется для объявления процедур, которые доступны всем другим процедурам во всех модулях. Private Необязательный. Используется для объявления процедур, которые доступны только внутри модуля, содержащего эти объявления. Sub Необязательный (должно быть либо Sub, либо Function). Указывает, что процедура не возвращает значения. । Function Необязательный (должно быть либо Sub, либо Function). Указывает, что процедура возвращает значение, которое может быть использовано в каком-либо выражении. name Обязательный. Любое допустимое имя процедуры. Lib Обязательный. Указывает, что DLL- или код-источник содержит процедуру, которая объявляется. hbname Обязательный. Имя DLL- или код-источника, который содержит объявляемую процедуру. Операторы в VBA 707 Alias Необязательный. Указывает, что вызываемая процедура имеет другое имя в DLL. Это полезно, когда имя внешней процедуры совпадает с ключевым словом или когда имя DLL-процедуры совпадает с public-переменной, константой или именем другой процедуры в той же области действия. Alias также используется, если некоторые символы в имени DLL-процедуры недопустимы стандартными соглашениями об DLL-именовании. aliasname Необязательный. Имя процедуры в DLL- или код-источнике. Если первый символ не является символом #, aliasname — имя точки входа в процедуру в DLL. Если # — первый символ, все последующие символы указывают порядковый номер точки входа в процедуру. arglist Необязательный. Список переменных, представляющих аргументы, передаваемые в процедуру при вызове. type Необязательный. Тип значения, возвращаемого Function-процедурой; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), Variant, типом, определенным пользователем, или объектным типом. Синтаксис аргумента arglist состоит из следующих элементов: [Optional] [ByVai | ByRef] [ParamArray] varname[( )] [As type] Optional Необязательный. Указывает, что аргумент — необязательный. Если используется, все последующие аргументы в arglist должны быть также необязательными и объявляться с ключевым словом Optional. Если используется ParamArray слово Optional не может использоваться ни для какого аргумента. ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Указывает, что аргумент передается по ссылке (в Visual Basic по умолчанию). ParamArray Необязательный. Используется только в качестве последнего аргумента в списке arglist для указания того, что последний аргумент является Optional-массивом Variant-элементов. Ключевое слово ParamArray позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, передаваемой процедуре; должно удовлетворять стандартным соглашениям об именовании переменных. () Обязательны для переменных-массивов. Указывают, что varname —массив. type Необязательный. Тип аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), Object, Variant, типом, определенным пользователем, или объектным типом. Для Function-процедур тип данных процедуры определяет тип возвращаемого значения. Пустые скобки указывают, что Sub- или Function-процедура не имеет аргументов. Если процедура имеет список аргументов, их тип и количество проверяются при вызове процедуры. 23' 708 Приложение В Deftype Используется на уровне модуля для определения типа по умолчанию переменных, аргументов, передаваемых процедурам, и возвращаемого типа Function-и Property Get-процедур, имена которых начинаются с определенных символов. Синтаксис DefBool letterrange[, letterrange] DefByte letterrange[, letterrange] Deflnt letterrange[, letterrange] . DefLng letterrange], letterrange] . DefCur letterrange], letterrange] . DefSng letterrange[, letterrange] . DefDbl letterrange[, letterrange] . DefDec letterrange[, letterrange] . DefDate letterrange[, letterrange] DefStr letterrange[, letterrange] . DefObj letterrange[, letterrange] . DefVar letterrange], letterrange] . Обязательный аргумент letterrange имеет следующий синтаксис: let ter1[-letter2] Аргументы letterl и letter2 определяют диапазон имен, для которого устанавливается тип данных по умолчанию. Каждый аргумент представляет первый символ имени переменной, аргумента, Function- или Property Get-процедуры и может быть любым алфавитным символом. Имя оператора определяет тип данных: оператор тип данных оператор тип данных DefBool Boolean DefDbl Double DefByte Byte DefDate Date Deflnt Integer DefStr String DefLng Long DefObj Object DefCur Currency DefVar Variant DefSng Single Если в коде указывается буквенный диапазон, он обычно определяет тип да-ных для переменных, которые начинаются с букв первых 128-и символов символьного набора. Однако когда задается буквенный диапазон А-Z, устанавливается значение по умолчанию на определенный тип данных для всех переменных, включая переменные, которые начинаются с международных символов из расширенной части символьного набора (128-255). После того как диапазон А-Z определен, можно в дальнейшем переопределять любой поддиапазон переменных, используя операторы Defti/pe. Если в следующем операторе Defti/pe окажется символ из ранее используемого диапазона, это вызовет ошибку. Однако при этом можно, используя оператор Dim со спецификатором As type, явно указать для некоторой переменной ее тип. Например, если вы указали, что переменные, начинающиеся с символов диапазона i-n, по умолчанию будут иметь тип Integer (именно эти символы очень часто используются для именования переменных циклов For...Next), для конкретной переменной iTaxRate можно указать тип Double: Deflnt A-Z Dim TaxRate As Double Операторы в VBA 709 Оператор Deftype не оказывает воздействия на элементы типов, определенных пользователем, поскольку эти элементы должны объявляться явно. Пример De fl nt I-К DefStr L-Z DeleteSetting Удаляет секцию или ключевую настройку (key setting) из раздела приложения в Windows-реестре. Синтаксис DeleteSetting appname, section[, key] Синтаксис оператора DeleteSetting включает следующие именованные аргументы: appname Обязательный. Строковое выражение, содержащее наименование приложения или проекта (project), для которого предназначена эта секция или ключевая настройка. section Обязательный. Строковое выражение, содержащее наименование секции или ключевой настройки для удаления. Если указываются и appname, и section, то удаляется заданная секция и все связанные с ней настройки. key Необязательный. Строковое выражение, содержащее наименование ключевой настройки для удаления. Пример Далее приведены две процедуры, одна из которых (TestSave) создает секцию и ключевые настройки в Реестре, а другая (TestDelete) удаляет всю секцию. Выполните первую процедуру и запустите программу Regedit.exe (из меню Пуск). Найдите секцию МуАрр и посмотрите установленные ключи. Затем запустите процедуру TestDelete и убедитесь в том, что секция МуАрр действительно удалена. Sub TestSave() ' поместить некоторые настройки в Реестр SaveSetting appname:="МуАрр", Section:="Startup", _ Кеу:="Тор", setting:=75 SaveSetting "МуАрр", "Startup", "Left", 50 End Sub Sub TestDelete() ' удалить секцию из Реестра DeleteSetting "МуАрр" End Sub Dim Объявляет переменные и резервирует память. Синтаксис Dim [WithEvents] varname[([subscripts])] [As [New] type] [, [WithEvents] varname[([subscripts])] [As [New] type]] ... Синтаксис оператора Dim включает следующие элементы: 710 Приложение В WithEvents Необязательный. Ключевое слово, которое указывает, что varname — объектная переменная, используемая для реакции на событие, инициированное ActiveX-объектом. WithEvents допускается только в модулях класса. Отдельных переменных с использованием ключевого слова WithEvents можно объявлять столько, сколько необходимо, но массив, используя его, создавать нельзя. Также нельзя использовать ключевое слово New при наличии WithEvents. varname Обязательный. Имя переменной; должно соответствовать стандартным соглашениям об именовании переменных. subscripts Необязательный. Размерность переменной-массива; объявить можно до 60 размерностей. Аргумент subscripts использует следующий синтаксис: [lower То] upper [, [lower То] upper] ... lower — нижний предел допустимых индексов массива; upper — верхний предел (является обязательным) для индексов массива. При наличии в операторе Dim только upper нижний предел определяется в зависимости от установки оператора Option Base. New Необязательный. Ключевое слово, позволяющее неявно создать объект. Если вы используете New при объявлении объектной переменной, создается новый экземпляр объекта, поэтому нет необходимости использовать оператор Set для назначения объекту ссылки. Type Необязательный. Тип данных переменной; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), String * length (для строк фиксированной длины), Object, Variant, типом, определенным пользователем, или объектным типом. Переменные, объявляемые оператором Dim на уровне модуля, доступны всем процедурам этого модуля. На уровне процедуры переменные доступны только внутри этой процедуры. Оператор Dim следует использовать на уровне модуля или процедуры для объявления типа переменной. Например, следующая переменная объявляется как String: Dim StrName As String Оператор Dim можно использовать и для объявления переменной объектного типа. В следующем примере объявляется новый экземпляр объекта Worksheet: Dim WorkShNew As New Worksheet Если ключевое слово New не используется при объявлении объектной переменной, то переменной, которая ссылается на объект, должна быть присвоена ссылка на существующий объект с использованием оператора Set. До тех пор, пока этого не сделано, объектная переменная будет иметь значение Nothing, которое указывает, что объектная переменная не ссылается ни на какой конкретный экземпляр объекта. Оператор Dim можно использовать с пустыми круглыми скобками для объявления динамического массива. Используя затем оператор ReDim, можно указать размерность и число элементов массива. Do...Loop Повторяет блок операторов до тех пор, пока некоторое условие имеет значение True или пока оно не станет равным True. Операторы в VBA 711 Синтаксис Do [(While I Until} condition] [statements] [Exit Do] [statements] Loop или Do [statements] [Exit Do] [statements] Loop [(While | Until} condition] Синтаксис оператора Do Loop включает следующие элементы: condition Необязательный. Численное или строковое выражение, имеющее значение True или False. Если condition имеет значение Null, оно интерпретируется как False. statements Один или более операторов, которые повторяются, пока condition — True, или до тех пор пока оно не станет равным True. В теле оператора (цикла) может быть любое количество операторов Exit Do, которые являются дополнительными средствами для окончания цикла (выхода из оператора Do...Loop). Оператор Exit Do часто используется внутри Do...Loop с применением оператора If...Then, который проверяет некоторое дополнительное условие для выхода из цикла. End Заканчивает процедуру или блок. Синтаксис End End Function End If ' End Property End Select End Sub End Type End With Синтаксис оператора End имеет следующие формы: End Немедленно прекращает выполнение. He является обязательным, но может располагаться в любом месте процедуры для окончания работы этой процедуры, закрытия файлов, открытых оператором Open и «очистки» переменных. End Function Обязателен для окончания Function-процедуры. End If Обязателен для окончания блока оператора If...Then...Else. End Property Обязателен для окончания Property Let-, Property Get- или Property Set-процедуры. End Select Обязателен для окончания оператора Select Case. End Sub Обязателен для окончания Sub-процедуры. 712 Приложение В End Type Обязателен для окончания определения пользовательского типа (оператора Туре). End With Обязателен для окончания оператора With. При выполнении оператор End «переустанавливает» все переменные уровня модуля и все статические локальные переменные во всех модулях. Чтобы сохранить значения этих переменных используйте оператор Stop. Оператор End останавливает выполнение кода аварийно, без вызова событий (и соответствующих им программ обработки) Unload, QueryUnload или Terminate, а также какого-либо другого кода. Объекты, созданные с помощью модулей класса, уничтожаются, файлы, открытые оператором Open, закрываются, память, используемая программой, освобождается. Пример В этом примере при загрузке формы с помощью функции InputBox запрашивается пароль. Если пароль введен неправильно, программа завершает работу. Конечно, этот пример следует использовать только в учебных целях, так как пароль, находящийся рядом с кодом его запроса, легко извлечь. Sub Form_Load Dim strPassword, StrPw strPassword = "Привет Шишкину1" StrPw = InputBox("Введите пароль:") If StrPw <> strPassword Then MsgBox "К сожалению, пароль неверен1" End End If ' полезные операторы процедуры: End Sub Enum Объявляет тип для перечисления. Синтаксис [Public | Private] Enum name membername [= constantexpression] membername [= constantexpression] End Enum K, Синтаксис оператора Enum включает следующие элементы: Public Необязательный. Указывает, что тип Enum является видимым во всем проекте. Типы Enum являются Public по умолчанию. Private Необязательный. Указывает, что тип Enum является видимым только внутри модуля, в котором он определяется. пате Обязательный. Имя типа Enum. Имя должно быть допустимым для Visual Basic идентификатором. membername Обязательный. Допустимый для Visual Basic идентификатор, определяющий имя, посредством которого будет известен составной элемент типа Enum. Операторы в VBA 713 constantexpression Необязательный. Значение элемента (приводится к Long). Если constantexpression не указан, этому значению присваивается либо ноль (если это первый membername), либо на единицу больше, чем значение непосредственно предыдущего membername. Переменные перечисления — это переменные, объявленные при помощи оператора Enum. В качестве типа Enum могут быть объявлены как переменные, так и аргументы. Элементы типа Enum инициализируется константными значениями. Эти значения не могут быть изменены в режиме исполнения программы и могут включать как положительные, так и отрицательные значения. Оператор Enum можно использовать только на уровне модуля. Сразу после описания Enum-типа этот тип можно использовать для объявления переменных, параметров процедур или типов данных, возвращаемых процедурами. Public Enum-типы в модуле класса не являются членами этого класса, хотя они записываются в библиотеку типов1. Типы Enum, определенные в стандартных модулях2, записываются в библиотеки типов. Типы Public Enum с одним и тем же именем не могут определяться и в стандартном, и модуле класса, поскольку они совместно используют (разделяют) одно и то же пространство имен. Если два типа Enum в различных библиотеках типов имеют одно и то же имя, но различные элементы, ссылка на переменную типа зависит от того, какая библиотека типов имеет более высокий приоритет в References. Erase Повторно инициализирует элементы фиксированного массива и освобождает память, занимаемую элементами динамического массива. Синтаксис Erase arraylist Обязательный аргумент arraylist — один (или более разделенных запятыми) массив. Оператор Erase действует по разному для массивов фиксированного и переменного размера (динамических). Массивы фиксированного размера не уничтожаются: занимаемая ими память не освобождается. Оператор Erase устанавливает элементы массивов фиксированного размера следующим образом: Тип массива Действие оператора Erase Фиксированный массив чисел Устанавливает каждый элемент массива в ноль. Фиксированный массив строк (переменной длины) Присваивает каждому элементу массива значение строки нулевой длины (""). Фиксированный массив строк (фиксированной длины) Устанавливает каждый элемент массива в ноль. Фиксированный Variant-массив Устанавливает каждый элемент массива в Empty. 1 Файл или компонент внутри другого файла, который содержит стандартное описание объявленных объектов, свойств и методов, доступных для Automation. 2 Модуль, содержащий только процедуру, тип и объявления данных н определения. Объявления и определения модульного уровня в стандартном модуле по умолчанию являются открытыми (Public). 714 Приложение В Тип массива Действие оператора Erase Массив данных определенных пользователем типов Устанавливает каждый элемент, как будто это — отдельная переменная. Массив объектов Присваивает каждому элементу значение Nothing. Оператор Erase освобождает память, занимаемую динамическим массивом. Прежде чем ваша программа сможет снова ссылаться на динамический массив, необходимо снова объявить массив с использованием оператора ReDim. Error Моделирует появление ошибки. 1 Синтаксис Error errornumber Обязательный аргумент errornumber может быть любым допустимым номером ошибки. Оператор Error поддерживается для обратной совместимости. При разработке нового кода (особенно при создании объектов) для генерации run-time-ошибок используйте метод Raise объекта Err. Если errornumber указывается, оператор Error вызывает обработчик ошибок (error handler) после того, как свойства Err-объекта принимают следующие значения по умолчанию: Number Значение, определенное как аргумент для оператора Error. Может быть любым допустимым номером ошибки. Source Наименование текущего проекта Visual Basic. Description Строковое выражение, относящееся к возвращаемому значению функции Error для определенного Number, если эта строка существует. Если строка не существует, Description содержит строку нулевой длины (""). HelpFile Драйвер, путь и имя соответствующего Help-файла Visual Basic. HelpContext ID соответствующего Help-файла Visual Basic. LastDLLError Ноль. Event Объявляет определенное пользователем событие. Синтаксис [Public] Event procedurename [(arglist)] Синтаксис оператора Event включает следующие элементы: Public Необязательный. Определяет «видимость» события во всем проекте (используется по умолчанию). procedurename Обязательный. Имя события; должно соответствовать стандартным соглашениям об именовании переменных. Операторы в VBA 715 Аргумент arglist имеет следующий синтаксис: [ByVai | ByRef] varname[( )] [As type] ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Необязательный. Указывает, что аргумент передается по ссылке (по умолчанию). varname Обязательный. Имя переменной — аргумент, передаваемый процедуре; должно соответствовать стандартным соглашениям об именовании переменных. Type Необязательный. Тип (данных) аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), Object, Variant, типом, определенным пользователем, или объектным типом. После объявления события для его инициализации используется оператор RaiseEvent: Event LogonCompleted (UserName as String) Sub RaiseEvent LogonCompleted("AntoineJan") End Sub Аргументы для событий можно создавать так же, как это делается для обычных процедур, хотя имеются следующие исключения: события не могут иметь именованные аргументы, Optional-аргументы или РагатАггау-аргументы. События не возвращают значение. Exit Прерывает выполнение блока Do...Loop, For...Next, Function-, Sub- или Property-кода. , Синтаксис Exit Do Exit For Exit Function Exit Property Exit Sub Синтаксис оператора Exit имеет следующие формы: Exit Do Предназначен для прекращения работы оператора Do...Loop и может использоваться только внутри этого оператора. Оператор Exit Do «передает управление» выполнением программы оператору, следующему за словом Loop оператора Do...Loop. Если Exit Do используется во вложенных операторах Do...Loop, то «управление передается» во внешний Do...Loop по отношению к тому, в котором встретился оператор Exit Do. Exit For Обеспечивает способ выхода из цикла For. Может использоваться в циклах For...Next или For Each...Next. Оператор Exit For «передает управление» выполнением программы оператору, следующему за словом Next. При использовании внутри вложенного цикла For оператор Exit For «передает управление» во внешний For-цикл по отношению к тому, в котором встретился оператор Exit For. 716 Приложение В । Exit Do Предназначен для прекращения работы оператора Do...Loop и может использоваться только внутри этого оператора. Оператор Exit Do «передает управление» выполнением программы оператору, следующему за словом Loop оператора Do...Loop. Если Exit Do используется во вложенных операторах Do...Loop, то «управление передается» во внешний Do...Loop по отношению к тому, в котором встретился оператор Exit Do. Exit Function Немедленно прекращает выполнение Function-процедуры, в которой встречается. «Управление передается» оператору, следующему за тем, который вызвал Function-процедуру. Exit Property Немедленно прекращает выполнение Property-процедуры, в которой встречается. «Управление передается» оператору, следующему за тем, который вызвал Property-процедуру. Exit Sub Немедленно прекращает выполнение Sub-процедуры, в которой встречается. «Управление передается» оператору, следующему за тем, который вызвал Sub-процедуру. Не следует путать Exit и End операторы. Оператор Exit не определяет конец структуры. Пример Sub ExitStatementTest() , Dim I, MyNum , Do For I = 1 To 1000 MyNum = Int(Rnd * 1000) Select Case MyNum Case 7: Exit For Case 29: Exit Do Case 54: Exit Sub End Select Next I Loop End Sub FileCopy Копирует файл. Синтаксис FileCopy source, destination Синтаксис оператора FileCopy включает следующие именованные аргументы: Source Обязательный. Строковое выражение, определяющее имя файла, который будет копироваться; может включать каталог (папку) и драйвер диска. Destination, Обязательный. Строковое выражение, определяющее имя файла, в который будет производиться копирование. | Оператор FileCopy нельзя использовать для текущего открытого файла. Пример FileCopy "Filer', "File2" Операторы в VBA 717 For Each...Next Повторяет группу операторов для каждого элемента массива или коллекции. Синтаксис For Each element In group ' [statements!] [Exit For] [statements2] Next [element] Синтаксис оператора For...Each...Next включает следующие элементы: element Обязательный. Переменная, используемая для итерации по элементам коллекции или массива. Для коллекций element может быть только Variant-переменной, обобщенной объектной переменной или определенной объектной переменной. Для массива element может быть только Variant-переменной. group Обязательный. Имя коллекции объектов или массива (исключая массив типов, определенных пользователем). statements Необязательный. Один или более операторов, которые выполняются для каждого элемента в group. Блок For...Each выполняется, если в group имеется, по крайней мере, один элемент. Все операторы цикла выполняются для каждого элемента в group. После этого «управление передается» оператору, следующему за ключевым словом Next. Пример Sub ForEachtest() Dim а() As Integer, i As Integer, j As Integer i = 1 Do While Not i = 0 i = Int (InputBox("Введите целое число")) If i > 0 Then ReDim Preserve a(i) For ] = 1 To i a(l) = 1 Next Call PrintArray(a) End If Loop End Sub ' , Sub PrintArray(aa) 1 для печати массива aa не нужно знать его размер For Each dd In aa Debug.Print dd Next Debug.Print "------------" End Sub For...Next Повторяет группу операторов определенное число раз. Синтаксис For counter = start То end [Step step] [statements!] > 718 Приложение В [Exit For] [statements2] Next [counter] Синтаксис оператора The For...Next содержит следующие элементы: counter Обязательный. Числовая переменная, используемая в качестве счетчика цикла (loop counter). Тип этой переменной не может быть 1 типом Boolean или элементом массива. start Обязательный. Начальное значение для counter. end Обязательный. Конечное значение для counter. step Необязательный. Шаг изменения значения counter после каждого цикла. Если не указывается, по умолчанию используется значение 1. statements Необязательный. Один или более операторов, выполняемых определенное число раз. Аргумент step может быть как положительным, так и отрицательным. После выполнения всех операторов в цикле значение step добавляется к значению counter. После этого либо все операторы цикла выполняются снова, либо цикл прекращается и «управление передается» следующему за словом Next оператору. Не следует пытаться изменять значение counter внутри цикла. Это может затруднить чтение и отладку кода. В качестве альтернативных выходов их цикла For...Next можно внутри цикла располагать любое количество операторов Exit For. Пример Sub Fortest() Dim a (33) As Integer, j As Integer For ] = 1 To 33 aU) - ] Next End Sub Function Объявляет имя, аргументы и код тела Function-процедуры. Синтаксис [Public ] Private | Friend] [Static] Function name [(arglist)] [As type] [statements!] > [name = expression!] [Exit Function] [statements.?] [name = expressions] End Function Синтаксис оператора Function включает следующие элементы: Public Необязательный. Указывает, что Function-процедура доступна всем другим процедурам во всех модулях. Если используется в модуле, который содержит Option Private, процедура недоступна вне этого проекта. Private Необязательный. Указывает, что Function-процедура доступна другим процедурам только в модуле, в котором объявлена. Операторы в VBA 719 Friend Необязательный. Используется только в модуле класса. Указывает, что Function-процедура доступна всем модулям проекта. Static Необязательный. Указывает, что локальные переменные Function-процедуры сохраняются между вызовами процедуры. Атрибут Static не действует на переменные, объявленные вне Function, даже если они используются в коде процедуры. name Обязательный. Имя Function-процедуры; должно отвечать стандартным соглашениям об именовании переменных. arglist Необязательный. Список переменных, представляющих передаваемые процедуре аргументы. type Необязательный. Тип данных, возвращаемый Function-процедурой; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String, Object, Variant или типом, определенным пользователем. statements Необязательный. Любая группа операторов, которая выполняется при вызове Function-процедуры. expression Необязательный. Возвращаемое значение Function-процедуры. Аргумент arglist должен соответствовать следующему синтаксису: [Optional] [ByVai | ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue] Optional Необязательный. Указывает, что аргумент необязательный. Если используется, все последующие аргументы в arglist должны быть * также необязательными и объявляться с ключевым словом Optional. Если применяется ParamArray, слово Optional не может использоваться ни для какого аргумента. ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Необязательный. Указывает, что аргумент передается по ссылке. Используется по умолчанию. ParamArray Необязательный. Используется только в качестве последнего аргумента в списке arglist для указания того, что последний аргумент является Optional-массивом Variant-элементов. Ключевое слово ParamArray позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, передаваемой процедуре; должно удовлетворять стандартным соглашениям об именовании переменных. type Необязательный. Тип аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), Object, Variant или определенным объектным типом. Если параметр не описан как Optional, может быть указан тип, определенный пользователем. defaultvalue Необязательный. Любая константа или константное выражение. Допускается только для аргументов, описанных как Optional. Если типом является Object, то явное значение по умолчанию может быть только значением Nothing. 720 Приложение В Если явно не определено использование Public, Private или Friend, Function-процедура является Public по умолчанию. Если не используется Static, значения локальных переменных не сохраняются между вызовами. Ключевое слово Friend может быть использовано только в модулях класса. Однако Friend-процедуры могут быть доступны процедурам в любом модуле проекта. Function-процедуры могут быть рекурсивными. Это означает, что они могут вызывать сами себя. Иногда в результате рекурсивных вызовов может происходить переполнение программного стека. Ключевое слово Static обычно не используется при описании рекурсивных Function-процедур. Весь выполняемый код помещается в теле Function-процедуры. Нельзя определить Function-процедуру внутри другой Function-, Sub- или Property-процедуры. Оператор Exit Function приводит к немедленному завершению Function-процедуры. При этом программа продолжает выполняться с оператора, следующего за тем, который вызвал Function-процедуру. В качестве альтернативных выходов внутри Function-процедуры может встречаться любое количество операторов Exit Function. Подобно Sub-процедуре Function-процедура — это отдельная процедура, которая может принимать аргументы, выполнять ряд операторов и изменять значения ее аргументов. Однако в отличие от Sub-процедуры выражение с вызовом Function-процедуры может появляться в правой части операции присваивания в составе некоторого выражения. Например, как функции Chr, Cos и так далее. Для вызова функции используется ее имя, за которым в круглых скобках помещаются значения аргументов функции. Чтобы функция возвращала значение, необходимо в теле (любом месте) функции поместить оператор, присваивающий это значение имени функции. Причем таких операторов может быть несколько. Если имени функции не присваивается внутри функции никакого значения, функция возвращает значение по умолчанию: функция, объявленная как числовая, возвращает 0, строковая функция — строку нулевой длины, Variant-функция — значение Empty, а объектная функция — значение Nothing. Пример В этом примере приведена функция проверки наличия файла на диске (IsDiskFile) и процедура, тестирующая эту функцию. Function IsDiskFile(fName As String) As Boolean ' возвращает Истина (True), если файл на диске найден, ' иначе - Ложь (False) If (Dir(fName) о "") Then IsDiskFile = True Else IsDiskFile = False End If \ End Function i Sub TestlsDiskFile() Dim namefun As String namefun = InputBox("Введите имя файла") If IsDiskFile(namefun) Then MsgBox ("Файл на диске!") Else MsgBox ("Файл на диске не найден!") End If End Sub •' Операторы в VBA 721 Get , Считывает данные из открытого файла на диске и помещает их в переменную. Синтаксис Get [#]flienumber, [recnumber], varname Синтаксис оператора Get включает следующие элементы: filenumber Обязательный. Любое допустимое имя файла. recnumber Необязательный. Variant (Long). Номер записи (record number) [для режима Random] или номер байта (byte number) [для режима Binary], с которого начинается чтение данных. varname Обязательный. Допустимое имя переменной, в которую считываются данные. Данные, считываемые оператором Get, обычно предварительно записываются посредством оператора Put. Первая запись (или байт) в файле находится в позиции 1, вторая — в позиции 2 и так далее. Если аргумент recnumber опускается, происходит считывание следующей записи (или байта) после той, с которой использовались операторы Get или Put (или указанной функцией Seek). Не следует забывать, что для пропуска аргумента нужно использовать две запятые: Get #2,,StrBuffer Для файлов, открытых в Random-режиме, применяются следующие правила: Если длина считываемых данных меньше, чем длина, указанная в опции Len оператора Open, Get считывает последующие записи на границах длин записей. Пространство между концом одной записи и началом следующей записи заполняется имеющимся содержимым файлового буфера. Если считываемая переменная является строкой переменной длины, оператор Get сначала считывает 2-байтовый дескриптор (descriptor), содержащий длину строки, а затем — сами данные, которые помещаются в переменную. Поэтому длина записи (record), определяемая опцией Len в операторе Open, должна быть, по крайней мере, на 2 байта больше, чем действительная длина строки. Если считываемая переменная — Variant числового типа, Get считывает 2 байта, идентифицирующие VarType, а затем — сами данные, которые помещаются в переменную. Длина записи, определяемая опцией Len в операторе Open, должна быть, по крайней мере, на 2 байта больше, чем действительное число байтов, необходимое для сохранения переменной. Если считываемая переменная — Variant, значение VarType которой равно 8 (String), оператор Get считывает 2 байта, идентифицирующие VarType, 2 байта, указывающие длину строки, а затем — сами строковые данные. Длина записи, определяемая опцией Len в операторе Open, должна быть, по крайней мере, на 4 байта больше, чем действительная длина строки. Если считываемая переменная — динамический массив, оператор Get считывает дескриптор, длина которого равна 2 «плюс» 8, умноженное на число размерностей массива (2 + 8 * NumberOfDimensions). Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна сумме количества байтов, необходимых для хранения массива, и длины дескриптора. Например, объявленный ниже массив требует при записи на диск 218 байтов — 18 (2 + 8 * 2) байтов занимает дескриптор и 200 (5 * 20 * 2) необходимо для хранения массива: Dim MyArray(l То 5,1 То 20) As Integer 722 Приложение В Если считываемая переменная — массив фиксированного размера, оператор Get считывает только данные. Если считываемая переменная — переменная любого другого типа (не строка переменной длины или Variant), Get считывает только данные. Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна длине считываемых данных. Оператор Get считывает элементы типов, определенных пользователем, как если бы они считывались отдельно, за исключением того, что между ними нет заполняющих элементов. На диске динамический массив определенного пользователем типа (записанный оператором Put) предваряется дескриптором, длина которого равна 2 «плюс» 8, умноженное на число размерностей: 2 + 8 * NumberOfDimensions. Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна сумме всех байтов, необходимых для чтения отдельных элементов, включая любые массивы и их дескрипторы. Для файлов, открытых в Binary-режиме, применяются все Random-правила, за исключением: Len-опция (параметр) оператора Open не действует. Оператор Get считывает все переменные с диска непрерывно, т.е. без заполняющих символов между записями. Для любого массива, кроме массива пользовательского типа, Get считывает только данные. Дескриптор не читается. Get считывает строки переменной длины, которые не являются элементами пользовательских типов, без дескриптора 2-байтовой длины. Число считываемых байтов равно числу символов, имеющихся в строке. Пример В следующем примере описывается пользовательский тип данных (Record), процедура записи (TestPut) данных в файл и процедура чтения (TestGet) данных из файла. Type Record 1 Определенный пользователем тип ID As Integer FirstName As String * 20 LastName As String * 20 End Type Sub TestPut () ' Тестирование Put Dim MyRecord As Record, RecordNumber Kill "TESTFILE" Open "TESTFILE" For Random As #1 Len = Len(MyRecord) MyRecord.FirstName = "Петр" MyRecord.LastName = "Петров" MyRecord.ID = 333 Put #1, 2, MyRecord MyRecord.FirstName = "Сидор" MyRecord.LastName = "Сидоров" MyRecord.ID = 111 Put #1, 3, MyRecord v MyRecord.FirstName = "Иван" MyRecord.LastName = "Иванов" MyRecord ID = 222 Put #1, 1, MyRecord Операторы в VBA 723 Close #1 End Sub Sub TestGetO , ' тестирование Get Dim MyRecord As Record, Position Open "TESTFILE" For Random As #1 Len = Len(MyRecord) For i = 1 To 3 Get #1, i, MyRecord Debug.Print MyRecord.FirstName & " : " & MyRecord.ID Next Close #1 End Sub GoSub...Return Передает (и возвращает) управление выполнением процедуры подпрограмме (subroutine) внутри процедуры. Синтаксис GoSub line [statements of procedure] line [statements of subroutine] Return Аргумент line может быть любой строковой или числовой меткой. Операторы GoSub и Return можно использовать в любом месте процедуры, но GoSub и соответствующий ему оператор Return должны быть в одной и той же процедуре. Подпрограмма может иметь более одного оператора Return. Пример В этом примере (практически, бессмысленном с математической точки зрения) приведена процедура, внутри которой для большей наглядности имеются две подпрограммы (именно подпрограммы с общими переменными!). Обратите внимание на то, что после оператора Return выполняется оператор Debug.Print Num. Sub GosubDemo3() Dim Num Num = InputBox("Введите целое число") Select Case Num Case Is > 0 GoSub MyRoutinel Case Is < 0 GoSub MyRoutine2 ' End Select , Debug.Print Num Exit Sub MyRoutinel: Debug.Print "значение/2:" Num = Num / 2 Return MyRoutine2: Debug.Print "(100+значение)/2" Num = 100 + Num Num = Num / 2 Return End Sub 724 Приложение В GoTo Приводит к безусловной передаче управления выполнением программы на указанную строку внутри процедуры. Синтаксис GoTo line Обязательный аргумент line может быть любой строковой или числовой меткой. Оператор GoTo передает управление только на строку в процедуре, в которой этот оператор описан. С точки зрения структурного программирования этот оператор является «вредным», наносящим ущерб читабельности, создающим определенные трудности для отладки и сопровождения программного кода. Практика программирования показывает, что без этого оператора можно вполне обходиться. Чаще всего в VB этот оператор используется в программах обработки ошибок. If...Then...Else Выполняет группу операторов в зависимости от значения некоторого условия. Синтаксис 1 If condition Then [statements] [Else elsestatements] Синтаксис 2 If condition Then [statements!] [Elself condition-n Then [else!fstatements] ... [Else [elsestatements?]] *-• End If Оператор If...Then...Else состоит из следующих элементов: condition Обязательный. Одно или более выражений следующих двух типов. Численное или строковое выражение, которое приводится к значениям True или False. Если значение condition — Null, интерпретируется как False. statements Необязательный в блочной форме (block form); обязательный в однострочной форме (single-line form), которая не имеет ветви Else. Один или более операторов; выполняются, если condition имеет значение True. condition-n Необязательный. То же, что и condition. elseifstatements Необязательный. Один или более операторов, выполняемых, если соответствующее condition-n имеет значение True. elsestatements Необязательный. Один или более операторов, выполняемых, если ни одно из предыдущих выражений condition или condition-n не равны значению True. Самая простая форма оператора — однострочная. Например', следующая строка кода приводит к выводу диалогового окна с текстом "а больше, чем d", если в момент выполнения дтой строки значение переменной а больше, чем значение переменной d: If а > d Then MsgBox "а больше, чем d" Операторы в VBA 725 Если необходимо выполнить более одного оператора в однострочной структуре, можно записать их все в одной строке, используя в качестве разделителя символ двоеточия. Блочная структура обеспечивает большую гибкость, чем однострочная форма, и обычно легче читается и отлаживается. Следующие строки эквиваленты предыдущей строке кода: If а > d Then • MsgBox "а больше, чем d" - End If Пример В этой процедуре обработки события — выбор кнопки-переключателя — Public-переменной пр присваивается тип подразделения. Далее вызывается функция загрузки наименований подразделений выбранного типа, например, в окно списка. Private Sub OptionCklad__Click () If OptionCklad.Value Then np = 2 ' тип подразделения - СКЛАД Else np = 4 ' тип подразделения - ОПТОВЫЙ МАГАЗИН End If t = ListBoxlLoad(np) End Sub Implements Определяет интерфейс (interface) или класс (class), внедряемый в модуль класса, в котором используется этот оператор. Синтаксис Implements [InterfaceName I Class] Обязательный аргумент InterfaceName или Class — имя интерфейса или класса в библиотеке типов (type library), методы которого внедряться соответствующими методами в VB-классе. Интерфейс — коллекция прототипов, представляющая те члены (методы и свойства), которые инкапсулирует интерфейс; это означает, что он содержит только объявления для процедур-членов (member procedures). Класс обеспечивает реализацию (implementation) всех методов и свойств одного или более интерфейсов. Классы обеспечивают код, используемый при вызове любой функции контроллером (controller) класса. В Visual Basic любой член, который не является явно членом внедренного (implemented) интерфейса, — неявно член интерфейса по умолчанию. Input # Считывает данные из открытого файла последовательного доступа и присваивает их переменным. Синтаксис Input #flienumber, varlist Синтаксис оператора Input # состоит из следующих элементов: filenumber Обязательный. Любой допустимый файловый номер. varlist Обязательный. Список разделенных запятыми переменных, которым присваиваются значения, считываемые из файла — массив или объектная переменная. 726 Приложение В Данные, считываемые с помощью оператора Input #, — обычно то, что записано в этот файл оператором Write #. Используйте этот оператор только для файлов, открытых в режимах Input или Binary. При чтении стандартной строки или числовых данных результат присваивается переменной без преобразования данных. В следующей таблице показано, как интерпретируются другие входные данные: данные значение, назначаемое переменной Ограничивающая запятая или пустая строка Empty #NULL# Null #TRUE# или #FALSE# True или False #yyyy-mm-dd hh:mm:ss# Дата и/или время, представленное выражением. #ERROR errornumber# errornumber (переменная — Variant, помеченная как ошибка). Двойные кавычки во входных данных игнорируются. Пример Чтобы выполнить следующий пример, необходимо предварительно создать файл с именем "IWFILE" и при помощи оператора Write # занести в него данные в формате: <строка>,<число>. Sub Testinput() Dim StrMy, NumberMy Open "IWFILE" For Input As #1 ' открыть файл Do While Not EOF(l) 1 цикл до конца файла Input #1, StrMy, NumberMy 1 считать данные в две переменные MsgBox StrMy & " : " & NumberMy ' результат -> на экран Loop Close #1 1 закрыть файл End sub Kill Удаляет файлы с диска. Синтаксис Kill pathname Обязательный аргумент pathname — строковое выражение, которое определяет одно или более файловых имен для удаления. Аргумент pathname может включать каталог (или папку) и имя драйвера. В Microsoft Windows оператор Kill поддерживает использование символов множественной подстановки * или ?. Пример Kill "TestFile.TXT" ' Kill "*.ВАК" г Let Присваивает значение выражения переменной или свойству. Операторы в VBA 727 Синтаксис [Let] varname = expression Синтаксис оператора Let состоит из следующих элементов: Let Необязательный. Явное использование ключевого слова Let — это оригинальный стиль, который обычно не применяется. varname Обязательный. Имя переменной или свойства; должен соответствовать стандартным соглашениям об именовании переменных. expression Обязательный. Значение, присваиваемое переменной или свойству. Значение выражения может быть присвоено переменной или свойству, если только оно имеет тип данных, совместимый с типом переменной. Нельзя присвоить строковое выражение (string expression) числовой переменной (numeric variable); нельзя присвоить числовое выражение строковой переменной. Переменные типа Variant могут присваиваться строчным или числовым переменным. Однако обратное не всегда верно. Строковой переменной может быть присвоена любая Variant-переменная, кроме Null, но числовой переменной может быть присвоена только та Variant-переменная, значение которой может интерпретироваться как число. Для определения того, может ли Variant-переменная преобразована в число, можно использовать функцию IsNumeric. Пример Dim StrMy, IntMy Let StrMy = "Опять — весна..." Let IntMy = 25 Line Input # Считывает одну строку из файла последовательного доступа и присваивает эту строку String-переменной. Синтаксис Line Input #fllenumber, varname Синтаксис оператора Line Input # состоит из следующих элементов: filenumber Обязательный. Допустимый файловый номер. varname Обязательный. Допустимое имя переменной типа Variant или String. Данные, считываемые оператором Line Input #, обычно записываются в файл оператором Print #. Оператор Line Input # считывает из файла по одному символу, пока не встретит символ «возврата каретки» (Chr(13)) или последовательность «возврат каретки» — «перевод строки» (Chr(13) + Chr(10)). Последовательность «возврат каретки» — «перевод строки» (carriage return-linefeed) не добавляется к считываемой символьной строке. Пример - В качестве примера приведены две процедуры: для записи данных в файл (TestPrint) и для чтения данных из файла (Testinput). Запустите на выполнение первую процедуру. Затем откройте в Редакторе VB окно Immediate и выполните вторую процедуру для просмотра содержимого тестового файла. 728 Приложение В Sub TestPrint() ' запись данных в файл TESTFILE Dim TextLine Open "TESTFILE" For Output As #1 Print #1, "А теперь мне жизнь - могила,” Print #1, "Белый свет душе постыл," Print #1, "Грустен лес, поток уныл..." Print #1, "Хлоя - другу изменила!.." » Print #1, "Я для милой... уж не мил!.." Print #1, Print #1, Tab(10); "А.С. Пушкин" Close #1 End Sub Sub Testinput() ' чтение данных из файла TESTFILE Dim TextLine Open "TESTFILE" For Input As #1 Do While Not EOF(l) Line Input #1, TextLine Debug.Print TextLine Loop Close #1 End Sub Load Загружает, но не показывает объект. Синтаксис Load object Шаблон object представляет объектное выражение (object expression), которое преобразуется к объекту в Applies То list. При загрузке объект помещается в память, но остается невидимым. Чтобы объект стал видимым, необходимо выполнить его метод Show. Если объект остается невидимым, с невозможно «общаться». Пример Private Sub UserForm_Initialize() Load UserForm2 UserForm2.Show End Sub i Lock, Unlock Управляет доступом ко всему или части файла, открытого с использованием оператора Open. Синтаксис Lock [#]filenumber[, recordrange] Unlock [#]filenumber[, recordrange] Синтаксис оператора Lock (и Unlock) состоит из следующих элементов: filenumber Обязательный. Любой допустимый файловый номер. recordrange Необязательный. Диапазон записей для открытия (закрытия) доступа. Операторы в VBA 729 Аргумент recordrange имеет следующий синтаксис: recnumber | [start] То end recnumber Номер записи (файл в режиме Random) или номер байта (файл в режиме Binary), на который устанавливается или отменяется доступ. start Номер первой записи (или байта) для открытия или закрытия доступа. end Номер последней записи (или байта) для открытия или закрытия доступа. Операторы Lock и Unlock используются в среде, где к одному и тому же файлу необходим доступ из нескольких процессов (processes), и всегда используются вместе. Аргументы этих операторов должны точно совпадать. Первая запись (или байт) в файле находится в позиции 1, вторая запись (или байт) — в позиции 2 и т.д. Если указывается (в операторах Lock, Unlock) только одна запись, то только к этой записи будет открыт или закрыт доступ. Если определяется диапазон записей и опускается начальная запись (start), режим доступа задается для всех записей с первой до указанной последней записи (end). Использование Lock (Unlock) без аргумента recnumber управляет доступом ко всему файлу. LSet Выполняет левое выравнивание строки внутри строковой переменной или копирует переменную одного пользовательского типа в другую переменную пользовательского типа, отличного от первого. Синтаксис LSet stringvar = string LSet varnamel = varname2 Синтаксис оператора LSet состоит из следующих элементов: stringvar Обязательный. Имя строковой переменной. string Обязательный. Строковое выражение, которое будет выравниваться внутри stringvar. varnamel Обязательный. Имя переменной пользовательского типа, в которое будет производиться копирование. varname2 Обязательный. Имя переменной пользовательского типа, из которого будет производиться копирование. Оператор LSet заменяет все левые символы в stringvar пробелами. Если string длиннее, чем stringvar, LSet помещает в stringvar только «наиболее левые» символы из string, количество которых равно длине строки stringvar. Пример (см. пример для RSet) Dim StrMyVar StrMyVar = "0123456789" ' инициализация для задания длины строки LSet StrMyVar = "<-Left" ' StrMyVar теперь: "<-Left ". 730 Приложение В Mid Выполняет замену указанного числа символов в Variant-переменной (String) на символы другой строки. Синтаксис » Mid(stringvar, start], length]) — string Синтаксис оператора Mid состоит из следующих элементов: stringvar Обязательный. Имя строчной переменной для модификации. start Обязательный; Variant (Long). Позиция символа в stringvar, с которой начинается заменяемая часть строки. length Необязательный; Variant (Long). Число заменяемых символов. string Обязательный. Строковое выражение для замены. Число заменяемых символов всегда меньше или равно числу символов с stringvar. Не следует путать оператор Mid с функцией Mid, которая возвращает значение [тип Variant (String)], содержащее указанное число символов из строки, и имеет похожий синтаксис. Примеры Dim StringMy StringMy = "Мама Катю мыла" Mid(StringMy, 5, 3) = "Сашу" Mid(StringMy, 5) = "Катю" Mid(StringMy, 5) = "кашу варила" 1 функция Mid возвращает значение SMidWords = Mid(StringMy, 1, 9) & ' StringMy = "Мама Сашу мыла" ' StringMy = "Мама Катю мыла" ' StringMy = "Мама кашу варила" 'Мама кашу не варила': " не " & Mid(StringMy, 11, 6) MkDir Создает новый каталог (или папку). Синтаксис MkDir path Обязательный аргумент path — строковое выражение, определяющее создаваемый каталог (или папку). Аргумент path может включать драйвер. Если драйвер не указывается, MkDir создает новый каталог (или папку) на текущем драйвере. Пример MkDir "NewDir" ' создать каталог на текущем драйвере Name Переименовывает дисковый файл, каталог (папку). Синтаксис Name oldpathname As newpathname , Синтаксис оператора Name состоит из следующих элементов: oldpathname Обязательный. Строковое выражение, определяющее текущее имя и местонахождение файла; может включать каталог (папку) и драйвер диска. Операторы в VBA 731 newpathname Обязательный. Строковое выражение, определяющее новое имя и местонахождение файла; может включать каталог (папку) и драйвер диска. Оператор Name переименовывает файл и перемещает его в другой каталог (папку). Оператор Name может перемещать файл с одного драйвера (диска) на другой, но он может переименовать только существующий каталог (папку), если в обоих аргументах указан один и тот же драйвер. Оператор Name не может создать новый файл, каталог (папку). Использование оператора Name с открытым файлом вызовет ошибку. Аргументы оператора Name не могут включать символ множественной подстановки (*) и одиночной подстановки (?). Пример Dim StrOldName As String, StrNewName As String StrOldName = "OLDFILE" StrNewName = "NEWFILE" Name StrOldName As StrNewName On Error Делает доступным обработчик ошибок и определяет его положение внутри процедуры; используется также и для запрета обработки ошибок. Синтаксис On Error GoTo line On Error Resume Next On Error GoTo 0 Синтаксис оператора On Error имеет следующие формы: On Error GoTo line Делает доступным обработчик ошибок, который начинается со строки, определенной аргументом line. Аргумент line может быть меткой или числом. При возникновении ошибки управление выполнением программы передается на строку кода с меткой line. Таким образом происходит активизация обработчика ошибок. Метка line должна находиться в той же процедуре, что и оператор On Error. On Error Resume Next Указывает на то, что при возникновении ошибки управление выполнением программы передается на оператор, следующий непосредственно за тем, в котором произошла ошибка. Этот оператор позволяет продолжить выполнение программы, несмотря на возникновение run-time-ошибки. Оператор On Error Resume Next становится неактивным при вызове другой процедуры. On Error GoTo 0 Отключает пользовательский обработчик ошибок в данной процедуре. Этот оператор не указывает метку 0 в качестве начала обработчика ошибки, даже если в процедуре действительно имеется такая метка. Без этого оператора обработчик ошибок «отключается» автоматически после окончания работы процедуры. Пользовательские обработчики ошибок являются составной частью «дружественного» интерфейса. Если во время работы пользователя с вашим приложением 732 Приложение В возникает непредвиденная вами ситуация, то в любом случае не стоит оставлять пользователя «наедине» с системой VBA, не настолько дружественной, как хороший разработчик приложений. VBA «знает» очень мало о том, в каких местах вашего программного кода и какие могут возникать ошибки. Разработчик же приложения должен знать все «тонкие» места в коде и ожидать те или иные ошибки. Даже если приложение просто пытается открыть файл, который нечаянно «убили», VBA-сообщение об отсутствии файла не так информативно, как могло бы быть сообщение разработчика, которое не только должно сообщить об отсутствии файла, но и предложить возможные пути его восстановления или замены этого файла его старой копией. Следует различать состояния «доступность» («enabled») и «активность» («active») обработчика ошибок. Обработчик доступен, если оператор On Error выполнен, но ошибка еще не возникла. Обработчик активен, когда им выполняется обработка некоторой возникшей ошибки. Если ошибка возникает, когда обработчик активен (обрабатывает ранее возникшую ошибку), эта ошибка не обрабатывается и управление передается в вызывающую процедуру. Если вызывающая процедура имеет обработчик ошибок, находящийся в состоянии «enabled», он переходит в состояние «active» (т.е. обработки ошибки). Если обработчик вызывающей процедуры находится в состоянии «active», то управление передается предыдущей вызывающей процедуре с обработчиком в состоянии «enabled», но не «active». Т.е. в цепочке вызывающих процедур ищется обработчик ошибок в состоянии «enabled», готовый обработать ошибку. Обычно в процедурах обработки ошибок для определения причины ошибки используется свойство Number объекта Err. Сообщение об ошибке (довольно «скупое»), связанное с Err.Number, содержится в Err.Description. Поэтому обычно на стадии отладки после метки, на которую передается управление выполнением программы в случае возникновения (ожидаемой) ошибки, помещается следующий оператор: MsgBox "Error " & Err & & Err.Description Следующая функция использует On Error и предназначена для создания базы данных на SQL Server. Если подключение по каким-либо причинам невозможно, функция выдаст (при помощи функции MsgBox) сообщение, из которого можно будет понять причину неудачи. Function DataBaseCreate(DataBaseName As String) As Boolean ' простая Функция создания базы данных на SQL Server ' DataBaseName - имя базы f Dim wrk As Workspace, cnn As Connection, strConnect As String On Error GoTo Err_DataBaseCreate ' строка подключения strConnect = "ODBC;DSN=finan;UID=sa;PWD=" Set wrk = DBEngine.CreateWorkspace("NewODBCDirect", _ "sa", dbUseODBC) ' устанавливаем тип драйвера курсора как wrk.DefaultCursorDriver = dbUseClientBatchCursor ' открываем соединение Set cnn = wrk.OpenConnection("finan", dbDriverNoPrompt, _ False, strConnect) ' создать, наконец, указанную базу на сервере ' cnn.Execute "CREATE DATABASE " & DataBaseName cnn.Execute "CREATE TABLE T2 " & "(C_KOD VARCHAR(12) NOT NULL, " & Операторы в VBA 733 "C_NAMET VARCHAR(30) )" Exit_DataBaseCreate: cnn. Close Exit Function Err_DataBaseCreate: If Err.Number = 3146 Then ' такой номер выдается при попытке создать уже имеющуюся базу MsgBox "Проверьте наличие такой базы на сервере" Else ' вывод номера и описания ошибки MsgBox "Error " & Err.Number & " & Err.Description End If Resume Exit_DataBaseCreate End Function В следующей процедуре используется On Error Resume Next для того, чтобы при определении отсутствия в системе экземпляра приложения Excel программа не завершалась с ошибкой. * Sub TestError() Dim xlApp As Object Dim xlSheet As Object On Error Resume Next Set xlApp = Nothing Set xlApp = GetObject(, "Excel.Application") If Err.Number <> 0 Then Set xlApp = CreateObject("Excel.Application") End If Err.Clear Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook.Worksheets(1) xlSheet.Application.Visible = True End Sub On...GoSub, On...GoTo «Передают управление» выполнением программы на одну из нескольких определенных строк кода в зависимости от значения некоторого значения. Синтаксис On expression GoSub destinationlist On expression GoTo destinationlist Синтаксис операторов On...GoSub и On...GoTo включает следующие элементы: Expression Обязательный. Любое численное выражение, которое приводится к целому числу в диапазоне от 0 до 255, включительно. Если expression — не является целым, оно предварительно округляется. destinationlist Обязательный. Список номеров строк (line numbers)1 или строковых меток (line labels)1 2, разделенных запятыми. 1 Используется для идентификации единственной строки кода. Номер строки может быть любой комбинацией цифр, которая уникальна внутри модуля, где используется этот номер. Номера строк должны начинаться в первой колонке. 2 Используется для идентификации единственной строки кода. Метка строки может быть любой комбинацией символов, которая начинается с буквы и завершается двоеточием (:). Метки строк нечувствительны к регистру и должны начинаться в первой колонке. 734 Приложение В Значение expression определяет, на какую строку в списке destinationlist выполняется переход. Если значение expression меньше чем 1, или больше чем число элементов в списке, то происходит следующее: если expression ТО равно 0 «Управление передается» на оператор, рледующий за операторами On...GoSub и On...GoTo. больше числа элементов в списке «Управление передается» на оператор, следующий за операторами On...GoSub и On...GoTo. отрицательно Инициируется ошибка. больше, чем 255 Инициируется ошибка. В одном списке можно смешивать номера строк и строковые метки. Можно использовать неограниченное количество номеров строк и строковых меток. Пример Sub OnGosubGotoDemo() Dim Number, MyString Number = 2 On Number GoSub Subl, Sub2 ' On...GoSub. On Number GoTo Linel, Line2 Exit Sub Subl : MyString = "In Subl" : Return Sub2 : MyString = "In Sub2" : Return Linel: MyString = "In Linel" Line2: ' MyString = "In Line2" End Sub Open Открывает файл для ввода/вывода. Синтаксис Open pathname For mode [Access access] [lock] As [#]f lienumber [Len=reclength] • Синтаксис оператора Open состоит из следующих элементов: pathname Обязательный. Строковое выражение, которое определяет имя файла; может включать каталог (папку) и драйвер. mode Обязательный. Ключевое слово, определяющее режим файла: Append, Binary, Input, Output или Random. access Необязательный. Ключевое слово, определяющее операции, выполняемые с фалом: Read, Write или Read Write. Lock Необязательный. Ключевое слово, определяющее ограничения для других процессов: Shared, Lock Read, Lock Write и Lock Read Write. Операторы в VBA 735 Filenumber Обязательный. Допустимый файловый номер в диапазоне от 1 до 511, включительно. Для получения следующего допустимого файлового номера следует использовать функцию FreeFile. reclength Необязательный. Число, меньшее или равное 32767 (байтов). Для файлов, открытых в режиме прямого доступа (mode — Random), это значение равно длине записи. Для последовательного доступа это значение равно числу буферизованных символов. Перед выполнением файловых операций чтения/записи файл необходимо открыть. Оператор Open выделяет буфер ввода/вывода для файла и определяет режим доступа к этому буферу. Если файл, указанный аргументом pathname, не существует, он создается для режимов Append, Binary, Output или Random. Опция Len при mode со значением Binary игнорируется. Пример Sub OpenTestO Dim I, FileName For I = 1 To 3 FileName = "TEST" & I ' создать имя файла Open FileName For Output As #1 ' открыть файл Print #1, "запись в файл " & FileName ' записать строку в файл Next I Close ' закрыть все три файла End Sub Option Base Используется на модульном уровне для объявления нижней границы массива по умолчанию. Синтаксис Option Base {0 | 1} По умолчанию нижняя граница массива — это значение 0. При использовании этого оператора необходимо располагать его в модуле до объявления процедур. Оператор Option Base может появляться в модуле только один раз и предшествовать объявлению массивов. При этом он воздействует только на нижнюю границу (может быть определена при помощи функции LBound) массивов в модуле, в котором он определен. Option Compare Используется на модульном уровне для объявления метода по умолчанию при сравнении строчных данных. Синтаксис Option Compare {Binary | Text I Database} Оператор Option Compare следует располагать в модуле перед определением процедур. Оператор Option Compare определяет метод сравнения строк (string comparison) (Binary, Text или Database) для модуля. Если модуль не содержит оператор Option Compare, по умолчанию при текстовом сравнении используется метод Binary. 736 Приложение В При использовании Option Compare Binary сравнение строк основывается на двоичном представлении символов, т.е. на порядке расположения символов в таблице двоичного представления. В Microsoft Windows порядок расположения символов определяется кодовой страницей. Для Option Compare Text двоичный эквивалент для каждого символа не используется. При этом буквы верхнего регистра эквивалентны буквам нижнего регистра. Option Compare Database может использоваться только в Microsoft Access. При этом сравнение строк основывается на параметре, определенном локальным ID базы данных, где возникают эти сравнения. Option Explicit Используется на модульном уровне для обязательного явного объявления всех переменных в модуле. Синтаксис Option Explicit Оператор Option Explicit должен располагаться в модуле до объявления процедур. При использовании оператора Option Explicit необходимо явно объявлять все переменные с помощью операторов Dim, Private, Public, ReDim или Static. Если этого не сделать, возникнет ошибка времени компиляции. Если оператор Option Explicit не используется, все необъявленные переменные имеют тип Variant. Пример Option explicit Dim VarMy IntMy =103 ' эта строка вызовет ошибку VarMy = 101 1 эта строка не вызовет ошибку Option Private При использовании в host-приложениях, которые допускают ссылки на множество проектов, Option Private Module препятствует ссылкам на содержимое модуля из внешней среды этого проекта. В host-приложениях, которые не допускают таких ссылок, например, отдельные версии Visual Basic, оператор Option Private не действует. Синтаксис Option Private Module v Оператор Option Private на модульном уровне должен появляться перед описанием процедур. Если модуль включает оператор Option Private Module, public-элементы, переменные, объекты и определяемые пользователем типы, объявленные на модульном уровне, остаются доступными внутри проекта, содержащего этот модуль, но недоступными другим приложениям или проектам. Пример Option private Module Print # Записывает отформатированные для отображения данные в файл с последовательным доступом. Операторы в VBA 737 Синтаксис Print #filenumber, [outputlist] Синтаксис оператора Print # включает следующие элементы: Filenumber Обязательный. Любой допустимый файловый номер. outputlist Необязательней. Выражение или список выражений для печати. Аргумент [{Spc(n) outputlist следующий синтаксис: ТаЬ[(л)]}] {expression] [charpos] Spc(n) Используется для вставки в вывод символов пробела; п — это число вставляемых символов пробелов. Tab(n) Используется для позиционирования точки (курсора) вставки в определенную колонку, где п — номер колонки. Использование Tab без аргументов приводит к позиционированию точки вставки в начало следующей зоны печати (print zone). expression Численные или строковые выражения для печати. \ charpos Определяет точку вставки для следующего символа. Чтобы позиционировать точку вставки сразу после последнего отображенного символа, используйте точку с запятой. Для позиционирования точки вставки в определенную колонку используйте Tab(n). Использование Tab без аргументов приводит к позиционированию точки вставки в начало следующей зоны печати. Если charpos опускается, очередной символ печатается на следующей строке. Данные, записываемые оператором Print #, обычно считываются из файла при помощи операторов Line Input # или Input. Если outputlist не используется, а после filenumber включается разделитель списка, в файл записывается пустая строка. Несколько записываемых в файл выражений (на одной строке кода) могут разделяться либо пробелами, либо двоеточиями. Пример Sub TestPrint() ' запись данных в файл TESTFILE Dim TextLine Open "TESTFILE" For Output As #1 Print #1, "В Академии наук" Print #1, "Заседает князь Дундук." Print #1, "Говорят, не подобает " Print #1, "Дундуку такая честь;" Print #1, "Почему ж он заседает?" Print #1, "Потому что есть чем сесть Print #1, Print #1, Tab(10); "А.С. Пушкин" Close #1 End Sub Private Используется на модульном уровне для объявления private-переменных и выделения для них памяти. 24 Программирование на VBA 2002 738 Приложение В Синтаксис Private [WithEvents] varname[([subscripts])] [As [New] type] [,[WithEvents] varname[([subscripts])] [As [New] type]] Синтаксис оператора Private включает следующие элементы: WithEvent s Необязательный. Ключевое слово, которое определяет varname — объектная переменная для реакции на события, вызываемые ActiveX-объектом. WithEvents допускается только в модулях класса. Это ключевое слово нельзя использовать при объявлении массивов. Нельзя использовать ключевое слово New с ключевым словом WithEvents. varname Обязательный. Имя переменной. subscripts Необязательный. Размерности массива-переменной; можно объявлять до 60 размерностей. Аргумент subscripts имеет следующий синтаксис: [lower То] upper [,[bower То] upper] ... Если явно не указывается lower, то нижняя граница массива определяется оператором Option Base. Если же оператор Option Base в коде не используется, значение нижней границы по умолчанию равняется 0. New Необязательный. Ключевое слово, позволяющее создание объекта. Использование New при объявлении объектной переменной приводит к созданию нового экземпляра объекта и ссылки на него, поэтому в операторе Set (назначает ссылку на объект) для этого объекта нет необходимости. Type Необязательный. Тип (данных) переменной; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), String * length (только фиксированной длины), Object, Variant, типом, определенным пользователем, или объектным типом. Оператор Private используется для объявления переменных (объектных переменных), доступных только в модуле, в котором они объявлены. Например, в следующей строке объявлены переменная целого типа j и объектная переменная типа Table с именем newT. Private 3 As Integer, newT As New Table Если при объявлении объектной переменной ключевое слово New не используется, то оператор Private не создает новый экземпляр объекта, а создает, практически, ссылочную переменную, которая пока не ссылается ни на какой конкретный объект (участок памяти). Чтобы таким образом объявленная объектная переменная ссылалась на объект, необходимо оператором Set указать этот объект. До тех пор, пока этого не сделано, объектная переменная имеет специальное значение Nothing, которое указывает на то, что переменная не ссылается ни на какой объект. Если при объявлении переменных (объектных переменных) тип переменной не указывается, VB умолчанию объявляет для нее тип Variant. Из синтаксиса оператора Private следует, что с его помощью можно объявлять массивы (динамические — в том числе). Property Get ' Объявляет имя, аргументы и код, формирующие Property-процедуру, которая считывает (извлекает) значение свойства (property). Операторы в VBA 739 Синтаксис [Public | Private I Friend] [Static] Property Get name [(arglist)] [As type] [statements] [name = expression] [Exit Property] [statements] [name = expression^ End Property Значение элементов синтаксиса оператора Property Get: Public Необязательный. Указывает на то, что процедура Property Get доступна всем другим процедурам во всех модулях. Если используется в модуле, содержащем оператор Option Private, эта процедура не доступна вне проекта. Private Необязательный. Указывает на то, что процедура Property Get доступна другим процедурам в модуле, в котором она объявлена. Friend Необязательный. Используется только в модуле класса. Указывает на то, что процедура Property Get видима во всем проекте. Static Необязательный. Указывает на то, что локальные переменные Property Get-процедуры сохраняют свои значения между вызовами. Static-атрибут не оказывает действия на переменные, которые объявляются вне процедуры Property Get, даже если они используются в этой процедуре. name Обязательный. Имя процедуры Property Get; должно соответствовать стандартным соглашениям об именовании переменных, за исключением того, что в одном модуле имя может быть таким же, как и в процедуре Property Let или Property Set. arglist Необязательный. Список разделенных запятыми переменных, представляющих аргументы, передаваемые процедуре Property Get при ее вызове. Имя и тип каждого аргумента в процедуре Property Get должны быть теми же, что и в соответствующей процедуре Property Let (если она имеется). type Необязательный. Тип (данных) значения, возвращаемого процедурой Property Get; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (кроме фиксированной длины), Object, Variant, пользовательским типом и массивом. Возвращаемый тип процедуры Property Get должен быть тем же, что и тип последнего аргумента в соответствующей процедуре Property Let (если она имеется), которая определяет значение, присваиваемое свойству. statements Необязательный. Любая группа операторов, которая выполняется в теле процедуры Property Get. expression Необязательный. Значение свойства, возвращаемое процедурой, определяемой оператором Property Get. Аргумент arglist имеет следующий синтаксис: [Optional] [ByVai I ByRef] [ParamArray] varname]( )] [As type] [= defaultvalue] 24* 740 Приложение В Optional Необязательный. Указывает, что аргумент является необязательным. Если используется, все последующие аргументы в arglist должны быть необязательными и объявляться с использованием слова Optional. By Vai Необязательный. Указывает, что аргумент передается по значению (by value). ByRef Необязательный. Указывает, что аргумент передается по ссылке (by reference). В Visual Basic ByRef используется по умолчанию. ParamArray Необязательный. Используется только как последний аргумент в arglist для указания того, последний аргумент — это Optional-массив Variant-элементов. Ключевое слово Par am Array позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, представляющей аргумент; должно соответствовать стандартным соглашениям об именовании переменных. type Необязательный. Тип аргумента, передаваемого процедуре; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (фиксированной длины), Object, Variant или объектным типом. Если параметр — не Optional, может быть указан также пользовательский тип. defaultvalue Необязательный. Любая константа или константное выражение. Допустима только для Optional-параметров. Если тип — Object, явным значением по умолчанию может быть только Nothing. Если явно не указано использование Public, Private или Friend, процедура Property является Public по умолчанию. Если не используется Static, локальные переменные не сохраняют свои значения между вызовами процедуры. Ключевое слово Friend можно использовать только в модуле класса. Однако Friend-процедура может быть доступна любой процедуре модуля проекта. При программировании классов некоторые данные класса (обычно они называются свойствами) можно защитить от прямого обновления и даже считывания. Пользователь класса (в качестве которого выступают программы) может не иметь непосредственного доступа к данным класса, но может обращаться к ним посредством интерфейсных процедур. В качестве таких процедур в VB используются процедуры с наименованиями Property Let и Property Let. Особенно важным является возможность проверки корректности данных, записываемых в закрытые элементы класса при помощи кода процедур Property Let. Пример Пусть, например, необходимо разработать класс, в котором будут содержаться такие сведения о накладной: дата, номер накладной, код отправителя товара, код получателя товаров. Код для описания данных (в модуле класса в разделе объявлений) может иметь вид: Private Dm_Date As Date Private Im_Num As Integer Private Cm_Sou As String Private CmWne As String Для получения значения закрытой переменной Dm_Date как общедоступного свойства D_Date можно написать следующий код: Операторы в VBA 741 Public Property Get D_Date() As Date D_Date = Dm_Date End Property Точно так же можно написать код для получения остальных свойств объекта класса: Public Property Get I_Num() As Integer I_Num = Im_Num End Property / Public Property Get C_Sou() As String C_Sou = Cm_Sou End Property Public Property Get C_Wne() As String C_Wne = Cm_Wne End Property Property Let Объявляет имя, аргументы и код, формирующие Property Let процедуру, которая присваивает значение свойству. Синтаксис [Public I Private | Friend] [Static] Property Let name ([arglist,] value) [statements] [Exit Property] [statements] End Property Значения элементов синтаксиса оператора Property Let: Public Необязательный. Указывает на то, что процедура Property Let доступна всем другим процедурам во всех модулях. Если используется в модуле, содержащем оператор Option Private, эта процедура недоступна вне проекта. Private Необязательный. Указывает на то, что процедура Property Let доступна другим процедурам в модуле, в котором она объявлена. Friend Необязательный. Используется только в модуле класса. Указывает на то, что процедура Property Let видима во всем проекте. Static Необязательный. Указывает на то, что локальные переменные Property Let-процедуры сохраняют свои значения между вызовами. Static-атрибут не оказывает действия на переменные, которые объявляются вне процедуры Property Let, даже если они используются в этой процедуре. i name Обязательный. Имя процедуры Property Let; должно соответствовать стандартным соглашениям об именовании переменных, за исключением того, что в одном модуле имя может быть таким же как и в процедуре Property Get или Property Set. arglist Обязательный. Список разделенных запятыми переменных, представляющих аргументы, передаваемые процедуре Property Let при ее вызове. Имя и тип каждого аргумента в процедуре Property Let должны быть теми же, что и в соответствующей процедуре Property Get (если она имеется). 742 Приложение В Public Необязательный. Указывает на то, что процедура Property Let доступна всем другим процедурам во всех модулях. Если используется в модуле, содержащем оператор Option Private, эта процедура недоступна вне проекта. value Обязательный. Переменная, значение которой присваивается свойству. При вызове процедуры этот аргумент появляется в правой части вызывающего выражения. Тип переменной value должен совпадать с типом возвращаемого значения соответствующей Property Get-процедуры. statements Необязательный. Любая группа операторов, которая выполняется в теле процедуры Property Let. Аргумент arglist имеет следующий синтаксис: [Optional] [ByVai | ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue] Optional Необязательный. Указывает, что аргумент является необязательным. Если используется, все последующие аргументы в arglist должны быть необязательными и объявляться с использованием слова Optional. ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Необязательный. Указывает, что аргумент передается по ссылке. В Visual Basic ByRef используется по умолчанию. ParamArray Необязательный. Используется только как последний аргумент в arglist для указания того, последний аргумент — это Optional-массив Variant-элементов. Ключевое слово ParamArray позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, представляющей аргумент; должно соответствовать стандартным Соглашениям об именовании переменных. type Необязательный. Тип аргумента, передаваемого процедуре; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (фиксированной длины), Object, Variant или объектным типом. Если параметр — не Optional, может быть указан также пользовательский тип. defaultvalue Необязательный. Любая константа или константное выражение. Допустима только для Optional-параметров. Если тип — Object, явным значением по умолчанию может быть только Nothing. Каждый оператор Property Let должен определять, по крайней мере, один аргумент процедуры, которую этот оператор описывает. Этот аргумент (или последний, если их несколько) содержит значение, которое присваивается свойству при вызове процедуры, определенной оператором Property Let. Если явно не указано использование Public, Private или Friend, процедура Property является Public по умолчанию. Если не используется Static, локальные переменные не сохраняют свои значения между вызовами процедуры. Ключевое слово Friend можно использовать только в модуле класса. Однако Friend-процедура может быть доступна любой процедуре модуля проекта. Операторы в VBA 743 Оператор Exit Property (их может более одного в процедуре) приводит к немедленному выходу из Property Let-процедуры. Выполнение программы продолжается с оператора, следующего за тем, который вызвал Property Let-процедуру. Подобно Function- и Property Get-процедурам, Property Let-процедура — это отдельная процедура, которая может принимать аргументы, выполнять набор операторов и изменять значения своих аргументов. Однако в отличие от Function-и Property Get-процедур, которые возвращают значение, Property Let-процедуры можно располагать только в левой части выражения присваивания свойства или оператора Let. Пример Для класса из примера оператора Property Get можно написать следующие процедуры Property Let: Public Property Let D_Date(ByVai DatNew As Date) ' 1 код для проверки корректности даты ' можно, например, исключить выходные и праздники Dm_Date = DatNew End Property Public Property Let I_Num(ByVal NumNew As Integer) ' код для проверки корректности номера накладной Im_Num = NumNew End Property Public Property Let C_Sou(ByVai SouNew As String) y < ' код для проверки корректности кода источника 1 если такой код в базе данных отсутствует, функция ' может об этом сообщить Cm_Sou = SouNew End Property Public Property Let C_Wne(ByVai WneNew As String) ' код для проверки корректности кода приемника ' если такой код в базе данных отсутствует, функция ' может об этом сообщить Cm_Wne = WneNew End Property i Property Set Объявляет имя, аргументы и код, формирующие Property-процедуру, которая устанавливает ссылку на объект. Синтаксис > [Public | Private I Friend] [Static] Property Set name ([arg-list,] reference) [ statements] [Exit Property] [statements] End Property 744 Приложение В Синтаксис оператора Property Set состоит из следующих элементов: Public Необязательный. Указывает на то, что процедура Property Set доступна всем другим процедурам во всех модулях. Если используется в модуле, содержащем оператор Option Private, эта процедура недоступна вне проекта. Private Необязательный. Указывает на то, что процедура Property Set доступна другим процедурам в модуле, в котором она объявлена. Friend Необязательный. Используется только в модуле класса. Указывает на то, что процедура Property Set видима во всем проекте. Static Необязательный. Указывает на то, что локальные переменные Property Set-процедуры сохраняют свои значения между вызовами. Static-атрибут не оказывает действия на переменные, которые объявляются вне процедуры Property Set, даже если они используются в этой процедуре. name Обязательный. Имя процедуры Property Set; должно соответствовать стандартным соглашениям об именовании переменных, за исключением того, что в одном модуле имя может быть таким же, как и в процедуре Property Get или Property Let. arghst Обязательный. Список разделенных запятыми переменных, представляющих аргументы, передаваемые процедуре Property Set при ее вызове. reference Обязательный. Переменная, содержащая объектную ссылку, используемую в правой части присвоения объектной ссылки. statements Необязательный. Любая группа операторов, которые должны выполняться в процедуре. Аргумент arglist имеет следующий синтаксис: [Optional] [ByVai I ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue] Optional Необязательный. Указывает, что аргумент является необязательным. Если используется, все последующие аргументы в arghst должны быть необязательными и объявляться с использованием слова Optional. ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Необязательный. Указывает, что аргумент передается по ссылке. В Visual Basic ByRef используется по умолчанию. ParamArra У Необязательный. Используется только как последний аргумент в arglist для указания того, что последний аргумент — это Optional-массив Variant-элементов. Ключевое слово ParamArray позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, представляющей аргумент; должно соответствовать стандартным соглашениям об именовании переменных. Операторы в VBA 745 Optional Необязательный. Указывает, что аргумент является необязательным. Если используется, все последующие аргументы в arghst должны быть необязательными и объявляться с использованием слова Optional. Tz/pe Необязательный. Тип аргумента, передаваемого процедуре; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (фиксированной длины), Object, Variant или объектным типом. Если параметр — не Optional, может быть указан также пользовательский тип. defaultvalue Необязательный. Любая константа или константное выражение. Допустима только для Optional-параметров. Если тип — Object, явным значением по умолчанию может быть только Nothing. Каждый оператор Property Set должен определять, по крайней мере, один аргумент процедуры, которую этот оператор описывает. Этот аргумент (или последний, если их несколько) содержит объектную ссылку для свойства при вызове процедуры, определенной оператором Property Set. Это — reference в предыдущем синтаксисе. Может быть Optional. Если явно не указано использование Public, Private или Friend, процедура Property является Public по умолчанию. Если не используется Static, локальные переменные не сохраняют свои значения между вызовами процедуры. Ключевое слово Friend можно использовать только в модуле класса. Однако Friend-процедура может быть доступна любой процедуре модуля проекта. Весь исполняемый код должен быть в процедуре. Нельзя определять процедуру Property Set внутри другой Property-, Sub- или Function-процедурьк Оператор Exit Property (их может более одного в процедуре) приводит к немедленному выходу из Property Set-процедуры. Выполнение программы продолжается с оператора, следующего за тем, который вызвал Property Set-процедуру. Подобно Function- и Property Get-процедурам, Property Set-процедура — это отдельная процедура, которая может принимать аргументы, выполнять набор операторов и изменять значения своих аргументов. Однако в отличие от Function-и Property Get-процедур, которые возвращают значение, Property Set-процедуры можно располагать только в левой части выражения присваивания свойства или оператора Set. Public Используется на модульном уровне для объявления public-переменных и выделения памяти для них. Синтаксис Public [WithEvents] varname[([subscripts])] [As [New] type] [,[WithEvents] varname[([subscripts])] [As [New] type]] ... Синтаксис оператора Public содержит следующие элементы: WithEvents Необязательный. Ключевое слово, которое указывает, что varname — объектная переменная, используемая для реакции на событие, инициированное ActiveX-объектом. WithEvents допускается только в модулях класса. Отдельных переменных с использованием ключевого слова WithEvents можно объявлять столько, сколько необходимо, но массив, используя его, создавать нельзя. Также нельзя использовать ключевое слово New при наличии WithEvents. 746 Приложение В I varname Обязательный. Имя переменной; должно соответствовать стандартным соглашениям об именовании переменных. subscripts ) I Необязательный. Размерность переменной-массива; можно объявить до 60 размерностей. Аргумент subscripts использует следующий синтаксис: [lower То] upper [, [lover То] upper] .... lower — нижний предел допустимых индексов массива; upper — верхний предел (является обязательным) для индексов массива. При наличии в операторе Dim только upper нижний предел определяется в зависимости от установки оператора Option Base. New Необязательный. Ключевое слово, позволяющее неявно создать объект. Если вы используете ключевое слово New при объявлении объектной переменной, создается новый экземпляр объекта, поэтому нет необходимости использовать оператор Set для назначения объекту ссылки. type Необязательный. Тип данных переменной; может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), String * length (для строк фиксированной длины), Object, Variant, типом, определенным пользователем, или объектным типом. Переменные, объявляемые оператором Public доступны всем процедурам всех модулей во всех приложениях, если используется оператор Option Private Module, при действии которого переменные имеют статус Public только в том проекте, в котором они находятся. Оператор Public нельзя применять в модуле класса для объявления переменной-строки фиксированной длины. Оператор Public можно использовать для объявления типа переменной. Например, следующий оператор объявляет переменную типа Integer: Dim IntName As Integer Оператор Public можно использовать также для объявления переменной объектного типа: Dim WorkShNew As Worksheet ИЛИ Dim WorkShNew As New Worksheet Если при объявлении объектной переменной ключевое слово New не используется, то, чтобы объектная переменная ссылалась на объект, необходимо оператором Set указать этот объект. До тех пор, пока этого не сделано, объектная переменная имеет специальное значение Nothing, которое указывает на то, что переменная не ссылается ни на какой объект. Оператор Public можно использовать (вместо оператора Dim) и для объявления массивов. После объявления динамического массива (при помощи пустых круглых скобок) следует для указания размерности массива применять оператор ReDim. Put Записывает данные из переменной в файл диска. Синтаксис Put [#] filenumber, [recnumber], varname Операторы в VBA 747 Синтаксис оператора Put включает следующие элементы: Filenumber Обязательный. Любой допустимый файловый номер. recnumber Необязательный. Variant (Long). Номер записи (для режим доступа Random) или номер байта (для режим доступа Binary) для записи. varnarrte Обязательный. Имя переменной, содержащей записываемые в файл данные. Данные, записанные оператором Put, обычно можно прочитать оператором Get. Первая запись (или байт) в файле находится в позиции 1, вторая запись (или байт) — в позиции 2 и т.д. Если аргумент recnumber не указывается, номер записи (или байта) определяется как результат работы последнего оператора Get (или Put) или функции Seek. Для файлов, открытых в Random-режиме, применяются следующие правила: Если длина записываемых данных меньше, чем длина, указанная в опции Len оператора Open, Put записывает последующие записи на границах длин записей. Пространство между концом одной записи и началом следующей записи заполняется имеющимся содержимым файлового буфера. Если записываемая переменная является строкой переменной длины, оператор Put записывает сначала 2-байтовый дескриптор (descriptor), содержащий длину строки, а затем — переменную. Поэтому длина записи, определяемая опцией Len в операторе Open, должна быть, по крайней мере, больше на 2 байта, чем действительная длина строки. Если записываемая переменная — Variant числового типа, Put записывает 2 байта, идентифицирующие VarType переменной Variant, а затем — само значение переменной. Длина записи (record), определяемая опцией Len в операторе Open, должна быть, по крайней мере, на 2 байта больше, чем действительное число байтов, необходимое для сохранения переменной. Если записываемая переменная — Variant, значение VarType которой равно 8 (String), оператор Put записывает 2 байта, идентифицирующие VarType, 2 байта, указывающие длину строки, а затем — сами строковые данные. Длина записи, определяемая опцией Len оператора Open, должна быть, по крайней мере, на 4 байта больше, чем действительная длина строки. Если записываемая переменная — динамический массив, оператор Put записывает дескриптор, длина которого равна 2 «плюс» 8, умноженное на число размерностей массива (2 + 8 * NumberOfDimensions). Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна сумме количества байтов, необходимых для записи массива, и длины дескриптора. Например, объявленный ниже массив требует при записи на диск 218 байтов — 18 (2 + 8 * 2) байтов занимает дескриптор и 200 (5 * 20 * 2) необходимо для хранения массива: Dim MyArray(l То 5,1 То 20) As Integer Если записываемая переменная — массив фиксированного размера, оператор Put записывает только данные. • Если записываемая переменная — переменная любого другого типа (не строка переменной длины или Variant), Put записывает только данные. Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна длине записываемых данных. Оператор Put записывает элементы типов, определенных пользователем, как если бы они записывались отдельно, за исключением того, что между ними нет заполняющих элементов. На диске динамический массив определенного пользователем типа (записанный оператором Put) предваряется дескриптором, дли 748 Приложение В на которого равна 2 «плюс» 8, умноженное на число размерностей: 2 + 8 * NumberOfDimensions. Длина записи, определяемая опцией Len в операторе Open, должна быть больше или равна сумме всех байтов, необходимых для чтения отдельных элементов, включая любые массивы и их дескрипторы. Для файлов, открытых в Binary-режиме, применяются все Random-правила, кроме: Len-опция (параметр) оператора Open не действует. Оператор Put записывает все переменные на диск непрерывно, т.е. без заполняющих символов между записями. Для любого массива, кроме массива пользовательского типа, Put записывает только данные. Дескриптор не записывается. » Put записывает строки переменной длины, которые не являются элементами пользовательских типов, без дескриптора 2-байтовой длины. Число записываемых байтов равно числу символов, имеющихся в строке Пример В следующем примере описывается пользовательский тип данных (Record) и процедура записи (TestPut) данных в файл. Type Record 1 Определенный пользователем тип ID As Integer FirstName As String * 20 LastName As String * 20 End Type Sub TestPut() ' Тестирование Put Dim MyRecord As Record, RecordNumber Kill "TESTFILE" Open "TESTFILE" For Random As #1 Len = Len(MyRecord) MyRecord.FirstName = "Петр" MyRecord.LastName = "Петров" MyRecord.ID = 333 Put #1, 2, MyRecord MyRecord.FirstName = "Сидор" MyRecord.LastName = "Сидоров" MyRecord.ID = 111 Put #1, 3, MyRecord MyRecord.FirstName = "Иван" MyRecord.LastName = "Иванов" MyRecord.ID = 222 Put #1, 1, MyRecord ' Close #1 End Sub RaiseEvent Инициирует событие, объявленное на модульном уровне в классе (class), форме (form) или документе (document). Синтаксис RaiseEvent eventname [(argumentlist)] Обязательный аргумент eventname — имя события, объявляемого внутри модуля; должно соответствовать стандартным соглашениям об именовании переменных. Операторы в VBA 749 Синтаксис оператора RaiseEvent включает следующие элементы: eventname Обязательный. Имя события. argumentlist Необязательный. Разделяемый запятыми список аргументов, в качестве которых могут использоваться переменные, массивы или выражения. Если аргументов нет, скобки не должны использоваться. Randomize Инициализирует генератор случайных чисел. Синтаксис Randomize [number] ' . . Необязательный аргумент number — значение типа Variant или любое числовое выражение. Оператор Randomize использует number для инициализации генератора случайных чисел функции Rnd (см. Приложение Г), задавая новое seed-значение. Если аргумент number опускается, то в качестве нового seed-значения используется значение системного таймера. Пример Следующий код генерирует строку из случайных чисел в диапазоне от 1 до 6. Dim MyValue, MyString As String Randomize MyString = "" For I = 0 To 9 MyValue = Int((6 * Rnd) + 1) MyString = MyString & " " & MyValue Next ReDim Используется на уровне процедуры для переопределения размеров динамический массивов. Синтаксис ReDim [Preserve] varname(subscripts) [As type] [, varname(subscripts) [As type]] ... Синтаксис оператора ReDim состоит из следующих элементов: Preserve Необязательный. Ключевое слово, используемое для сохранения данных в существующем массиве при изменении последней размерности. | varname Обязательный. Имя переменной. subscripts Обязательный. Размерности массива-переменной; можно объявлять до 60 размерностей. Аргумент subscripts имеет следующий синтаксис: [lower То] upper [,[lower То] upper] ... Если lower явно не указан, нижняя граница массива определяется оператором Option Base. Если в коде не используется оператор Option Base, нижняя граница считается равной нулю. 750 Приложение В type Необязательный. Тип (данных) переменной (массива); может быть Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (для строк переменной длины), String * length (для строк фиксированной длины), Object, Variant, определенным пользователем типом или объектным типом. Оператор ReDim используется для определения и переопределения размера динамического массива, который перед этим уже был формально объявлен при помощи операторов Private, Public или Dim с пустыми скобками (вместо указания размерностей). Оператор ReDim можно применять повторно для изменения числа элементов и размерностей массива. Однако нельзя при помощи оператора ReDim изменить тип массива (не для Variant-массива). Если массив содержит данные типа Variant, тип его элементов можно изменить (предложением As type)-, это не относится к оператору ReDim, в котором используется ключевое слово Preserve, не допускающее изменения типа данных. При использовании ключевого слова Preserve можно изменить размер только последней размерности; количество самих размерностей изменить нельзя. Пример Dim MyArrayO As Integer ' объявление динамического массива Redim MyArray(lO) ' выделение памяти для массива Redim Preserve MyArray(25) ' добавление 15-ти элементов Rem Используется для включения в код комментариев. Синтаксис Rem commen t Можно также использовать следующий синтаксис: ' comment Необязательный аргумент comment — текст комментария. Между ключевым словом Rem и comment обязательно следует помещать пробел. Reset Закрывает все файлы на диске, которые были открыты с использованием оператора Open. Синтаксис Reset Оператор Reset закрывает все активные файлы, открытые оператором Open, и записывает содержимое всех файловых буферов на диск. Resume Возобновляет выполнение кода после того, как заканчивает работу процедура обработки ошибки. Операторы в VBA 751 Синтаксис Resume [0] Resume Next Resume line Синтаксис оператора Resume может быть одной из следующих форм: Resume Если ошибкгС возникла в той же самой процедуре, в которой находится обработчик ошибок, выполнение кода возобновляется с того же оператора, который вызвал ошибку. Если ошибка возникла в вызванной процедуре, выполнение кода возобновляется с оператора, который последним вызвал процедуру, содержащую обработчик ошибок. Resume Next Если ошибка возникла в той же самой процедуре, в которой на- > ходится обработчик ошибок, выполнение кода возобновляется с оператора, находящегося сразу за тем, который вызвал ошибку. Если ошибка возникла в вызванной процедуре, выполнение кода возобновляется с оператора, непосредственно следующего за тем, который последним вызвал процедуру, содержащую обработчик ошибок (или оператор On Error Resume Next). Resume line Выполнение кода возобновляется со строки line, заданной в качестве аргумента. Аргумент line — метка или номер строки в той же самой процедуре, где находится обработчик. Примеры Далее приведены примеры на все упомянутые в таблице формы оператора Resume. Private Sub Test_Resumel() ' Использование в обработчике оператора Resume Dim z, у As Integer On Error GoTo Err у = InputBox("Введите число") z = у + 10 MsgBox z ‘MsgBox "Спасибо!" Exit Sub Err: If Err.Number = 13 Then MsgBox ("Просили же Вас ввести число!") Resume End If * End Sub Private Sub Test_Resume2() ' Использование в обработчике оператора Resume Next Dim z, у As Integer On Error GoTo Err у = InputBox("Введите число") z = у + 10 MsgBox z MsgBox "Спасибо!" Exit Sub Er r: If Err.Number = 13 Then MsgBox ("С Вашего разрешения введем 9999") 752 Приложение В у = 9999 Resume Next End If End Sub Public co As Integer Private Sub Test_Resume3() ' Использование в обработчике оператора Resume line» Dim z, у As Integer On Error GoTo Err у = InputBox("Введите число") z = у + 10 Debug.Print z Debug.Print "Спасибо’" Exit Sub err_exit: Debug.Print "Что-то у Вас не получается" Exit Sub Err: If Err.Number = 13 Then If co = 2 Then Resume err_exit Else co = co + 1 Debug.Print ("У Вас осталось " & _ (3 - co) & " попытки") Resume End End Sub End If If Private Sub Form_Load() co = 0 End Sub ' Обработчик ошибок в одной из процедур Private Sub Test_Resume4() Call A End Sub Sub A() On Error GoTo Err Call В Debug.Print "В любом случае процедура а завершается" Exit Sub Err: Debug.Print "Где-то произошла ошибка!" Resume Next End Sub Sub B() Call C End Sub Sub C() Dim d As Integer d = 1 / 0 End Sub Операторы в VBA 753 RmDir Удаляет существующий каталог (или папку), не содержащий файлов. Синтаксис > , . RmDir path , Обязательный аргумент path — строковое выражение, которое определяет удаляемый каталог (или папку). Путь может включать драйвер (по умолчанию — текущий). Если каталог содержит файлы (т.е. — не пустой), при выполнении оператора возникает ошибка, которую можно «перехватить» и обработать оператором On Error; обработчик, например, может дать пользователю возможность либо удалить файлы каталога (оператором Kill), либо отказаться от удаления каталога, если пользователь «поспешил»). Пример1 RmDir "WINDOWS" ' пользователь не любит WINDOWS RSet Выполняет правое выравнивание в строковой переменной. Не может быть использован с типами, определенными пользователем. Синтаксис RSet stringvar = string Синтаксис оператора RSet состоит из следующих элементов: stringvar Обязательный. Имя строковой переменной. string Обязательный. Строковое выражение, которое выравнивается внутри stringvar. Если stringvar длиннее, чем string, оператор RSet заменяет все символы с левой стороны строки stringvar пробелами. Пример (см. пример для LSet) Dim StrMyVar StrMyVar = "0123456789" ' инициализация для задания длины строки Rset StrMyVar = "Right->" ' StrMyVar теперь: ” Right->" SaveSetting Сохраняет или создает элемент настройки (ключевую настройку) определенного приложения в Windows-реестре. Синтаксис SaveSetting аррпате, section, key, setting Синтаксис оператора SaveSetting имеет следующие именованные аргументы: appname Обязательный. Строковое, содержащее имя приложения или проекта, настройки которого предназначены настройки. 1 Не стоит выполнять этот пример, хотя из-за того, что каталог не пуст, оператор просто вызовет ошибку. 754 Приложение В section Обязательный. Строковое выражение, содержащее наименование секции, в которой сохраняется ключевая настройка. | key Обязательный. Строковое выражение, содержащее имя настройки. | setting Обязательный. Выражение, содержащее значение ключевой настройки. | Seek Устанавливает позицию для следующей операции чтения/записи в открытом (при помощи оператора Open) файле. Синтаксис V Seek [#)filenwnber, position Синтаксис оператора Seek состоит из следующих элементов: Filenumber Обязательный. Любое допустимое число. position Обязательный. Число в диапазоне 1-2,147,483,647, включительно, которое указывает, номер элемента (записи) для операции чтения/записи. Пример В следующем примере описывается пользовательский тип данных (Record), процедура записи (TestPut) данных в файл и процедура чтения (TestSeek) данных из файла. Type Record ' Определенный пользователем тип ID As Integer FirstName As String * 20 LastName As String * 20 End Type Sub TestPut () ' Тестирование Put Dim MyRecord As Record, RecordNumber Open "TESTFILE" For Random As #1 Len = Len(MyRecord) MyRecord.FirstName = "Петр" MyRecord.LastName = "Петров" MyRecord.ID = 333 Put #1, 2, MyRecord t MyRecord.FirstName = "Сидор" MyRecord.LastName = "Сидоров" MyRecord.ID - 111 Put #1, 3, MyRecord MyRecord.FirstName = "Иван" MyRecord.LastName = "Иванов" MyRecord.ID = 222 Put #1, 1, MyRecord Close #1 End Sub Sub TestSeek() ' тестирование Get Операторы в VBA 755 Dim MyRecord As Record, MaxSize As Integer ' чтение записей без Seek: Open "TESTFILE" For Random As #1 Len = Len(MyRecord) For i = 1 To 3 Get #1, i, MyRecord Debug.Print MyRecord.FirstName & " : " & MyRecord.ID Next Close #1 ' чтение c Seek: Open "TESTFILE" For Random As #1 Len = Len(MyRecord) ' определить число записей в файле: MaxSize = LOF(l) \ Len(MyRecord) ' чтение (и печать) записей в цикле в обратном порядке For RecordNumber = MaxSize То 1 Step -1 Seek #1, RecordNumber ' Установка позиции Get #1, , MyRecord ' чтение записи Debug.Print MyRecord.FirstName & " : " & MyRecord.ID Next RecordNumber Close #1 End Sub Select Case Выполняет одну или несколько групп операторов, в зависимости от выражения. Синтаксис Select Case testexpression [Case express!onlist-n [statements-n] ) ... [Case Else [eisestatements) ) End Select Синтаксис оператора Select Case состоит из следующих элементов: testexpression Обязательный. Любое числовое или строковое выражение. expressionlist-n / Обязателен в случае использования Case. Список (с разделителями) из одной или более следующих форм: expression expression То expression Is comparisonoperator expression Ключевое слово To определяет диапазон значений, в котором меньшее значение должно быть перед ключевым словом То. Ключевое слово Is следует использовать с операторами сравнения (кроме, Is и Like) для указания диапазона значений. Если этот аргумент не используется, автоматически поставляется ключевое слово Is. statements-n Необязательный. Один или более операторов, выполняемых, если testexpression совпадает с любым значением из expressionlist-n. eisestatements Необязательный. Один или более операторов, выполняемых, если testexpression не совпадает ни с каким Case-предложением. Если testexpression совпадает с любым из Case-выражений expressionlist, выполняются операторы statements, следующие за этим Case-предложением (до еле- 756 Приложение В дующего Case-предложения или последнего Case-предложения — до End Select). Управление выполнением программы передается оператору, следующему за предложением End Select. Если testexpression совпадает с expressionlist в нескольких Case-предложениях, выполняются операторы, соответствующие первому совпадению. Предложение Case Else используется для указания группы операторов elsestatements, которые следует выполнять, если ни в одном Case-предложении не нашлось совпадений. Конструкция Select Case допускает вложения. SendKeys Посылает одно или более нажатий клавиш активному окну, как будто они выполнены с клавиатуры. Синтаксис SendKeys string [, wait] Синтаксис оператора SendKeys включает следующие именованные аргументы: string Обязательный. Строковое выражение, определяющее посылаемые нажатия клавиш. wait Необязательный. Значение типа Boolean, определяющее режим ожидания (wait mode). Если — False (по умолчанию), управление возвращается процедуре немедленно после передачи клавиш. Если — True, нажатия клавиш должны быть обработаны прежде, чем управление будет возвращено процедуре. Каждая клавиша представляет один или более символов. Для указания одиночного символа клавиатуры используйте сам символ. Например, для представления символа N используйте строку "N". Для представления нескольких символов используйте строку, например, "ABCD". Знаки "плюс" (+), "каре" ('), "процент" (%), "тильда" (-), "парные скобки" () имеют для функции SendKeys специальные значения. Для указания любого из этих символов заключайте их в фигурные скобки ({}). Например, для определения знака "плюс” используйте строку "{+}”. Квадратные скобки ([ ]) не имеют специального значения для функции SendKeys, но их также следует заключать в фигурные скобки. Для указания символов, которые не отображаются при нажатии на них (ENTER или TAB), и символов, которые представляют действие, а не символ, используйте следующие коды: Клавиши Коды BACKSPACE {BACKSPACE}, {BS} или {BKSP} BREAK {BREAK} CAPS LOCK {CAPSLOCK} DEL or DELETE {DELETE} или {DEL} DOWN ARROW {DOWN} END {END} ENTER {ENTER} или - | ESC {ESC} Операторы в VBA 757 Клавиши Коды HELP {HELP} НОМЕ {HOME} INS or INSERT {INSERT} или {INS} LEFT ARROW {LEFT} NUM LOCK {NUMLOCK} PAGE DOWN {PGDN} PAGE UP {PGUP} PRINT SCREEN {PRTSC} RIGHT ARROW {RIGHT} SCROLL LOCK {SCROLLLOCK} TAB {TAB} UP ARROW {UP} Fl {Fl} F2 {F2} F3 {F3} F4 {F4} F5 {F5} F6 {F6} F7 {F7} F8 {F8} F9 {F9} F10 {F10} Fll {Fll} Fl 2 {F12} F13 {F13} F14 {F14} F15 {F15} F16 {F16} Для определения комбинаций клавиш с клавишами SHIFT, CTRL и ALT предваряйте код клавиши следующими знаками: Клавиша Знак SHIFT + CTRL ALT % 758 Приложение В Для указания того, что некоторая комбинация клавиш SHIFT, CTRL и ALT остается нажатой в то время, как нажимаются другие клавиши, заключайте коды этих клавиш в скобки. Например, чтобы указать, что при нажатой клавише SHIFT «нажимаются» клавиши Е и Я, следует использовать строку ”+(ЕЯ)". А чтобы указать, что при нажатой клавише SHIFT нажимается клавиша Е, а затем — только Я (без SHIFT), следует использовать строку "+ЕЯ". Для определения повторяющихся клавиш используйте следующую форму {клавиша число}. Например, {LEFT 43} означает нажатие клавиши LEFT ARROW (стрелка влево) 43 раза; {Y 12} означает нажатие клавиши Y 12 раз. Пример В этом примере с использованием функции Shell запускается приложение Microsoft Outlook и «нажимается» кнопка Send/Receive сочетанием клавиш Alt и С. Sub TestSendKeys() ' Запустить почтовую программу ReturnValue = Shell("OUTLOOK.EXE", 1) ' Нажать на кнопку Send/Receive SendKeys "%С", True End Sub Set Присваивает объекту ссылку на переменную или свойство. Синтаксис Set objectvar = {[New] ebjectexpression | Nothing) Синтаксис оператора Set состоит из следующих элементов: objectvar Обязательный. Имя переменной или свойства; должно соответствовать стандартным соглашениям об именовании переменных. New Необязательный. New обычно используется для неявного создания объекта. Если New используется вместе с Set, создается новый экземпляр класса. Если objectvar содержал ссылку на некоторый объект, эта ссылка удаляется, когда присваивается новая. Ключевое слово New нельзя использовать для создания нового экземпляра встроенного типа данных. objectexpression Обязательный. Выражение, состоящее из имени объекта, другой объявленной переменной того же объектного типа или функции (метода), которая возвращает объект того же типа. Nothing Необязательный. Прекращение связи objectvar с любым указанным объектом. Переменная objectvar должна быть объектного типа, совместимого с объектом, который ей присваивается. Операторы Dim, Private, Public, ReDim и Static только объявляют переменную, которая ссылается на объект. Действительное присваивание ссылки на определенный объект выполняет оператор Set. Пример Dim xlBook As Object Dim xlSheet As Object Set xlApp = CreateObject("Excel.Application") Set xlBook = xlApp.Workbooks.Add Set xlSheet = xlBook.Worksheets(1) Операторы в VBA 759 SetAttr Устанавливает информацию об атрибутах для файла. Синтаксис SetAttr pathname, attributes Синтаксис оператора SetAttr включает следующие именованные аргументы: pathname Обязательный. Строковое выражение, определяющее имя файла (может включать каталог и драйвер диска). attributes Обязательный. Константное или числовое выражение, которое представляет сумму определенных атрибутов. Аргумент attributes может принимать следующие значения: Константа Значение Назначение VbNormal 0 Normal (по умолчанию) [обычный]. VbReadOnly 1 Read-only [для чтения/записи]. VbHidden 2 Hidden [скрытый]. VbSystem 4 System [системный] файл. | VbArchive 32 Файл изменялся со времени последней архивации. Пример SetAttr "С:\Мои документы^.TESTFILE", vbHidden SetAttr "С:\Мои документы\ТЕЗТГ1ЬЕ", vbHidden + VbSystem Static Используется на уровне процедуры для объявления переменных и выделяет для них память. Переменные, объявляемые при помощи оператора Static, сохраняют свои значения в течение всего времени выполнения программы. Синтаксис Static varname[([subscripts])] [As [New] type] [, varname[([subscripts])] [As [New] type]] . . . Синтаксис оператора Static включает следующие элементы: varname Обязательный. Имя переменной; должно соответствовать стандартным соглашениям об именовании переменных. subscripts Необязательный. Необязательный. Размерность переменной-массива; можно объявить до 60 размерностей. Аргумент subscripts использует следующий синтаксис: [lower То] upper [,[lower То] upper] ... lower — нижний предел допустимых индексов массива; upper — верхний предел (является обязательным) для индексов массива. При наличии в операторе Dim только upper нижний предел определяется в зависимости от установки оператора Option Base. 760 Приложение В New Необязательный. Ключевое слово, позволяющее неявно создать объект. Если вы используете New при объявлении объектной переменной, создается новый экземпляр объекта, поэтому нет необходимости использовать оператор Set для назначения объекту ссылки. type Необязательный. Тип данных переменной; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), String * length (для строк фиксированной длины), Object, Variant, типом, определенным пользователем, или объектным типом. Во время выполнения кода модуля переменные, объявленные оператором Static, сохраняют свои значения до «сброса» или перезапуска модуля. Переменные, объявленные оператором Static в модуле класса, сохраняют свои значения в каждом экземпляре класса до удаления экземпляра. Переменные, объявленные оператором Static в модуле формы, сохраняют свои значения до закрытия формы. Stop Останавливает выполнение кода. Синтаксис Stop Для приостановки выполнения кода (в целях отладки) можно помещать оператор Stop в любом месте программы. Использование этого оператора подобно использованию точки прерывания (breakpoint). Оператор Stop останавливает выполнение программы, но в отличие от оператора End этот оператор не закрывает файлы и не очищает переменные (за исключением компилированных исполняемых файлов). Пример Sub Teststop() Dim I For I = 1 To 10 Debug.Print I & " Для продолжения выполните Run|Continue" Stop Next I End Sub Sub Объявляет имя, аргументы и код тела Sub-процедуры. Синтаксис [Private I Public I Friend] [Static] Sub name [(arghst)] [s tatements] [Exit Sub] [statements] End Sub Синтаксис оператора Sub включает следующие элементы: Public Необязательный. Указывает, что Sub-процедура доступна всем другим процедурам во всех модулях. Если используется в модуле, который содержит оператор Option Private, эта процедура недоступна вне проекта. Операторы в VBA 761 Private Необязательный. Указывает, что процедура доступна другим процедурам только того модуля, в котором она объявлена. Friend Необязательный. Используется только в модуле класса. Указывает, что Sub-процедура видима во всем проекте. Static Необязательный. Указывает, что локальные переменные процедуры сохраняют свои значения между вызовами. пате Обязательный. Имя Sub-процедуры; должно соответствовать стандартным соглашениям об именовании переменных. \ arglist Необязательный. Список переменных, представляющих аргументы, передаваемые процедуре при ее вызове. [statements Необязательный. Любой набор операторов, которые будут выполняться при вызове процедуры. Синтаксис параметра arglist имеет вид и включает: [Optional] [ByVai | ByRef] [ParamArray] varname]( )] [As type] [= defaultvalue] Optional Необязательный. Ключевое слово, указывающее, что аргумент является необязательным. Если используется, все последующие аргументы в arglist должны быть также необязательными и объявляться с ключевым словом Optional. Если применяется ParamArray, слово Optional не может использоваться ни для какого аргумента. ByVai Необязательный. Указывает, что аргумент передается по значению. ByRef Необязательный. Указывает, что аргумент передается по ссылке. Используется по умолчанию. ParamArray Необязательный. Используется только в качестве последнего аргумента в списке arglist для указания того, что последний аргумент является Optional-массивом Variant-элементов. Ключевое слово ParamArray позволяет использовать переменное число аргументов и не может применяться с ByVai, ByRef или Optional. varname Обязательный. Имя переменной, передаваемой процедуре; должно удовлетворять стандартным соглашениям об именовании переменных. type Необязательный. Тип аргумента, передаваемого процедуре; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), Object, Variant или объектным типом. Если параметр не описан как Optional, может быть указан тип, определенный пользователем. defaultvalue Необязательный. Любая константа или константное выражение. Допускается только для аргументов, описанных как Optional. Если типом является Object, то явное значение по умолчанию может быть только значение Nothing. Sub-процедуры — это основные программные единицы на языке Visual Basic. Они обеспечивают функционирование диалоговых форм, выполняют действия общего характера, вызывая при необходимости другие Sub-процедуры и Function-процедуры, обеспечивают работу с экземплярами классов. 762 Приложение В Если явно не определено использование Public, Private или Friend, Sub-процедура является Public по умолчанию. Если не используется Static, значения локальных переменных не сохраняются между вызовами. Ключевое слово Friend может быть использовано только в модулях класса. Однако Friend-процедуры могут быть доступны процедурам в любом модуле проекта. Sub-процедуры могут быть рекурсивными. Это означает, что они могут вызывать сами себя. Иногда в результате рекурсивных вызовов может происходить переполнение программного стека. Ключевое слово Static обычно не используется при описании рекурсивных Sub-процедур. Весь выполняемый код помещается в теле процедуры. Нельзя определить Function-процедуру внутри другой Function-, Sub- или Property-процедуры. Оператор Exit Sub приводит к немедленному завершению Sub-процедуры. При этом программа продолжает выполняться с оператора, следующего за тем, который вызвал Sub-процедуру. В качестве альтернативных выходов внутри Sub-процедуры может встречаться любое количество операторов Exit Sub. Подобно Function-процедуре Sub-процедура — это отдельная процедура, которая может принимать аргументы, выполнять ряд операторов и изменять значения ее аргументов. Однако в отличие от Function-процедуры имя Sub-процедуры не может появляться в правой части операции присваивания в составе некоторого выражения. Time Устанавливает системное время. Синтаксис Time = time Обязательный аргумент time — любое числовое, строковое выражение или любая комбинация, представляющая время. Если time — строка, оператор Time «пытается» преобразовать ее во время, используя разделители времени, которые определены в вашей системе. Пример TimeMy = #4:30:20 PM# Time = TimeMy Type Используется на уровне модуля для определения типа данных пользователя. Синтаксис [Private I Public] Type varname elementname [([subscripts])] As type [elementname [([subscripts])] As type] End Type Синтаксис оператора Type включает следующие элементы: Public Необязательный. Используется для объявления пользовательских типов, доступных всем процедурам во всех модулях всех проектов. Private Необязательный. Используется для объявления пользовательских типов, доступных только в модуле, где они объявляются. Операторы в VBA 763 varname Обязательный. Имя определенного пользователем типа; должно соответствовать стандартным соглашениям об именовании переменных. elementname Обязательный. Имя элемента пользовательского типа. Имена элементов также должны соответствовать стандартным соглашениям об именовании переменных. subscripts Если аргумент lower явно не указывается, нижняя граница массива определяется оператором Option Base. Нижняя граница равна 0, если оператор Option Base не используется. type ( Обязательный. Тип данных элемента; может быть типом Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String (только переменной длины), String * length (для строк фиксированной длины), Object, Variant, типом, определенным пользователем, или объектным типом. После того как с использованием оператора Туре (можно использовать только на модульном уровне) описан пользовательский тип, вы можете объявлять переменные этого типа в любом месте внутри области действия описания типа. При этом следует использовать операторы Dim, Private, Public, ReDim или Static. В стандартных модулях и модулях класса типы пользователя являются public-типами по умолчанию, что легко изменить, используя ключевое слово Private. Пример Type Record ’ Определенный пользователем тип ID As Integer FirstName As String * 20 LastName As String * 20 End Type Unload Удаляет объект из памяти. Синтаксис Unload object Обязательный аргумент object является объектным выражением, которое вычисляется до объекта в Applies То list. Пример Private Sub CanselCommand_Click() Unload me ' удалить из памяти текущий диалог End Sub While...Wend Выполняет серию операторов, пока некоторое условное выражение является равным True. Синтаксис ' While condition [statements] Wend 764 Приложение В Синтаксис оператора While...Wend включает следующие элементы: condition Обязательный. Числовое или строковое выражение, результатом вычисления которого являются значения True или False. Если condition — Null, то оно интерпретируется как False. statements Необязательный. Один или более операторов; выполняемых, если условие является равным значению True. Если condition является равным значению True, выполняются все операторы между словами While и Wend. Управление выполнением программы передается в начало структуры While...Wend и значение condition снова проверяется. Если оно остается равным значению True, процесс повторяется, иначе управление передается на оператор, следующий за словом Wend. Оператор While...Wend допускает вложения. Пример Sub TestWhileWend() Dim i As Integer i = 10 , ' ' While i < 20 ’ ' i = i + 2 J ” 1 MsgBox i Wend MsgBox "Последнее выданное значение должно быть равно 20" End Sub Width # Устанавливает ширину выводимой в файл строки (файл открывается оператором Open). Синтаксис Width #filenumber, width Синтаксис оператора Width # включает следующие элементы: filenumber Обязательный. Любой допустимый файловый номер. j width Обязательный. Числовое выражение в диапазоне 0-255, включительно, которое указывает количество символов, появляющихся в строке перед началом новой строки (т.е. количество символов в строке). Если значение width равно 0, то длина строки не имеет ограничений. По умолчанию значение width является равным 0. | With Выполняет несколько операторов для единственного объекта или пользовательского типа. Синтаксис With object 4 [statements] End With Операторы в VBA 765 Синтаксис оператора With включает следующие элементы: object Обязательный. Имя объекта или пользовательского типа. statements Необязательный. Один или более операторов, которые должны быть выполнены. Оператор With позволяет выполнить несколько операторов для определенного объекта без повторного указания имени объекта. Так, например, удобно сразу изменить несколько свойств некоторого объекта, как это показано в следующем примере. Пример Этот пример получен при помощи макрорекордера записью действий при форматировании выделенного участка абзаца в Word. Sub Масгоб() 1 Масгоб Macro ' Macro recorded 01.12.01 by Владимир With Selection.Font .Name = "Times New Roman" .Size = 10 .Bold = False .Italic = False .Underline = wdUnderllneNone .Underlinecolor = wdColorAutomatic .StrikeThrough = False .DoubleStrikeThrough = False .Outline = False .Emboss = False .Shadow = False Hidden = False SmallCaps = False .AllCaps = False .Color = wdColorAutomatic Engrave = False Superscript = False •’ • * Subscript = True .Spacing = 0 Scaling = 100 .Position = 0 Kerning = 0 ' .Animation = wdAnimationNone End With End Sub Write # z Записывает данные в файл с последовательным доступом. Синтаксис Write # filenumber, [outputlist] Синтаксис оператора Write # состоит из следующих элементов: jilenumber Обязательный. Любой допустимый файловый номер. outputlist Необязательный. Одно или более (разделенных запятыми) числовых или строковых выражений для записи в файл. 766 Приложение В Данные, которые записываются в файл оператором Write #, обычно считываются оператором Input #. Если аргумент outputlist не используется, а после filenumber помещается запятая, в файл записывается пустая строка. Чтобы при использовании оператора Write # для записи в файл данные корректно считывались оператором Input #, выполняются следующие правила: Числовые данные всегда записываются с использованием точки в качестве десятичного разделителя. * Для данных типа Boolean печатается либо #TRUE#, либо #FALSE#. Данные типа Date записываются в файл с использованием универсального формата даты. Если компонента даты или времени отсутствует или нулевая, в файл записывается только предоставленная часть. В файл ничего не записывается, если значение outputlist имеет значение Empty. Однако для Null-данных записывается #NULL#. Для Error-данных в файле появляется #ERROR errorcode#. В отличие от оператора Print # оператор Write # вставляет запятые между элементами и кавычки вокруг строк. Вам не нужно использовать явно разделители в списке. Оператор Write# вставляет символ новой строки, т.е. Chr(13) + Chr(10), после того, как в файл будет записан последний символ из outputlist. Пример Sub TestPrint() ' запись данных в файл TESTFILE Dim TextLine Open "TESTFILE" For Output As #1 Write #1, "По синим волнам океана," Write #1, "Лишь звезды блеснут в небесах," Write #1, "Корабль одинокий несется," Write #1, "Несется на всех парусах" Write #1, Write #1, Iab(10); "М.Ю. Лермонтов" Close #1 End Sub Sub Testinput () Dim StrMy Open "TESTFILE" For Input As #1 ' открыть файл Do While Not EOF(l) ' цикл до конца файла Input #1, StrMy ' считать данные Debug.Print StrMy 1 результат -> на экран Loop Close #1 ' закрыть файл End Sub Приложение Г Функции в VBA В этом приложении приведены функции, которые вы можете использовать в своих программах. Данная информация предназначена для разработчиков VBA-приложений. Abs Возвращает абсолютное значение своего аргумента. (Абсолютное значенце числа — это его значение без знака.) Синтаксис Abs(number) Обязательный аргумент number может быть любым допустимым арифметическим выражением. Если number содержит Null, возвращается также Null; если — неинициализированная переменная, то возвращается нулевое значение. Array Возвращает Variant-массив, значениями которого являются элементы аргумента-списка. Синтаксис Array(argl1st) Обязательный аргумент arglist—это разделенный запятыми список значений, которые назначаются элементам массива. Значение нижней границы (индекса) массива определяется опцией оператора Option Base. Примеры Dim A As Variant ' объявление А как типа Variant А = Array(10,20,30) ' теперь А — массив В = А(2) ' в В записывается значение А (2) Asc J. Возвращает числовой (тип Integer) код первого символа строки-аргумента. Синтаксис Asc(string) , Обязательный аргумент string —любое допустимое строковое выражение. Если аргумент не содержит ни одного символа, вызывается ошибка времени исполнения. Диапазон возвращаемых значений: 0-255 для не DBCS-систем и -32768 -32767 для DBCS-систем. Примеры Dim MyNumber MyNumber = Asc("В") ‘ возвращает 66 MyNumber = Asc("a") ' возвращает 97 MyNumber - AscCABCD") ’ возвращает 65 768 Приложение Г Atn Возвращает арктангенс (тип Double) заданного аргумента. Синтаксис Atn(number) Обязательный аргумент number —переменная типа Double или любое допустимое арифметическое выражение. Функция Atn (обратная функции Tan) принимает отношение двух сторон прямоугольного треугольника и возвращает значение соответствующего угла в радианах (в диапазоне от — pi/2 до pi/2). Пример pi = 4 * Atn(l) ' pi CallByName Выполняет метод некоторого объекта или устанавливает или возвращает свойство объекта. Синтаксис CallByName(object, procname, calltype,[args()1) Функция CallByName принимает следующие именованные аргументы: Аргумент Назначение object Обязательный; тип — Variant (Object). Имя объекта, для которого вызывается функция. ргоспате Обязательный; тип — Variant (String). Строка с именем свойства или метода объекта. calltype Обязательный; Константа типа vbCallType, представляющая тип вызываемой процедуры. args( ) Необязательный: тип — Variant (Array). Для проверки работы этой функции поместите на форме три кнопки с именами, которые Редактор VB задаст им по умолчанию, и напишите простые программы обработки событий: Private Sub CommandButtonl_Click() MsgBox "Свойство Enabled кнопки: " & _ CallByName(CommandButton2, "Enabled", VbGet) \ End Sub Private Sub CommandButton3_Click() If CallByName(CommandButton2, "Enabled", VbGet) Then CallByName CommandButton2, "Enabled", VbLet, False Else CallByName CommandButton2, "Enabled", VbLet, True End If End Sub Когда вы запустите это приложение (командой Run | Run Sub/UserForm), кнопка с именем CommandButtonl позволит вывести на экран свойство Enabled кнопки CommandButton2. А кнопка с именем CommandButton3 будет последовательно изменять свойство Enabled кнопки CommandButton2. Обратите внимание на различие в синтаксисе функции при установке и считывании свойства. Функции в VBA 769 Функции преобразования типов Синтаксис CBool(expression) CByte(expression) CCur(expression) CDate(expression) CDbl(expression) CDec(expression) CInt(expression) CLng(expression) CSng(expre s s i on) CStr(expression) CVar(expression) Функции преобразуют данные из одних типов в другие. Обязательный аргумент expression —любое строковое или численное (арифметическое) выражение. Возвращаемые типы Тип возвращаемых данных определяется именем функции: Функция Тип возвращаемых данных CBool Boolean CByte Byte CCur Currency CDate Date CDbl Double CDec Decimal CInt Integer CLng Long CSng Single CStr String CVar Variant Обычно функции преобразования типов данных используются разработчиком VBA-приложения для документирования преобразований в коде, поскольку преобразования, выполняемые по умолчанию, могут быть не понятны при чтении кода. Choose Выбирает и возвращает значение из списка аргументов. Синтаксис Choose(index, choice-1 [, choice-2, ... [, choice-n]]) Функция Choose принимает следующие аргументы: Аргументы Назначение index Обязательный. Численное выражение, результатом которого является значение от 1 до числа возможных вариантов для выбора. 25 Программирование на VBA 2002 770 Приложение Г j Аргументы Назначение choice Обязательный. Variant-выражение, содержащее один из возможных выборов. Пример Dim Ind As Integer • Ind = 2 ' функция MsgBox выдаст диалоговое окно с "United" MsgBox Choose(Ind, "Speedy", "United", "Federal") Chr Возвращает String-значение (строку), содержащее символ, код которого указан в качестве аргумента. Синтаксис ( Chr(charcode) Обязательный аргумент charcode — это Long-значение кода символа. Диапазон значений аргумента: 0-255. Однако в DBCS-системах1 этот диапазон: от -32768 до 65535. Cos Возвращает значение (тип Double) косинуса угла-аргумента. Синтаксис Cos (number) *' Обязательный аргумент number —допустимое численное выражение, представляющее угол в радианах. CreateObject Создает и возвращает ссылку на ActiveX-объект. Синтаксис CreateObject{class,[servername]) Функция CreateObject имеет следующие аргументы: Аргумент Назначение class Обязательный; тип Variant (String). Имя приложения и класс объекта для создания. servername Необязательный; тип Variant (String). Имя сервера сети, где должен быть создан объект. Если servername — пустая строка («»)> используется локальная машина. Аргумент class использует синтаксис appname.objecttype, где: Здесь набор символов использует 1 или 2 байта для представления символа. Функции в VBA 771 Элемент Назначение |i аррпате Обязательный; тип Variant (String). Имя приложения, предоставляющего объект. || objecttype Обязательный; тип Variant (String). Тип или класс объекта для создания. | Любое приложение, поддерживающее Automation, предоставляет, по крайней мере, один тип объекта. Например, приложение текстового процессора может предоставить объект Application, Document и Toolbar. Чтобы создать ActiveX-объект, присвойте объект, возвращаемый функцией CreateObject, объектной переменной: Dim Excel_Sheet As Object Set Excel_Sheet - CreateObject("Excel.Sheet") Объявление объектной переменной при помощи As Object создает переменную, содержащую ссылку на объект любого типа. Связывание этой ссылки с конкретным объектом происходит при выполнении программы (позднее связывание). Чтобы создать объектную переменную при помощи раннего связывания, объявляйте объектную переменную как определенный ID-класс. Например: Dim xlApplication As Excel.Application Dim xlBook. As Excel. Workbook Dim xlSheet As Excel.Worksheet Set xlApplication = CreateObject("Excel.Application") Set xlBook = xlApplication.Workbooks.Add Set xlSheet = xlBook.Worksheets(1) CurDir Возвращает значение типа Variant (String), содержащее текущий путь (current path). Синтаксис CurDir[(drive)] Необязательный аргумент drive — строковое выражение, определяющее драйвер. Если этот аргумент не задан или является пустой строкой ('"'), функция CurDir возвращает путь для текущего драйвера. Пример Dim My_Path My_Path = CurDir ' Returns "C:\WIN2000\SYSTEM". My_Path = CurDir("C") ' Returns "C:\WIN2000\SYSTEM". My.Path = CurDir("D") ' Returns "D:\WORD". CVErr Возвращает значение (тип Variant) подтипа Error, содержащее номер ошибки, определенный пользователем. Синтаксис CVErr(errornumber) Обязательный аргумент errornumber — любое допустимое error-число. Функцию CVErr следует использовать для описания ошибок в пользовательских процедурах. Например, если вы создали функцию с несколькими аргумента- 25* 772 Приложение Г ми, то можно при этом написать вспомогательную функцию, которая проверяет количество передаваемых аргументов и нахождение значений аргументов в допустимых диапазонах. В случае нарушения правил передачи параметров вы можете использовать функцию CVEr, для возвращения номера возникшей ошибки, который вы сами и зададите. * Date Возвращает значение [тип Variant (Date)], содержащее текущую системную дату. Синтаксис Date Можно также использовать эту функцию как процедуру для установки системных часов компьютера. DateAdd Возвращает значение [тип Variant (Date)], содержащее дату, к которой добавлен заданный интервал времени. Синтаксис DateAdd(interval, number, date) Функция DateAdd принимает следующие именованные аргументы: Аргумент Назначение interval Обязательный. Строковое выражение, определяющее вид интервала, который необходимо использовать. number Обязательный. Числовое выражение, определяющее количество добавляемых интервалов. Может быть как положительным, так и отрицательным. date Обязательный. Значение [Variant (Date)], определяющее дату, к которой добавляется временной интервал. Аргумент interval может принимать следующие значения: Значение Описание Значение Описание УУУУ Year (год) W Weekday (день недели) q Quarter (квартал) WW Week (неделя) m Month (месяц) h Hour (час) У Day of year (день года) n Minute (минута) d Day (день) s Second (секунда) Функция DateAdd может использоваться для добавления (или вычитания) определенного временного интервала к указанной дате (из указанной даты). Например, с использованием функции DateAdd можно узнать значение даты через 40 дней после текущей даты или время через 50 секунд от текущего времени. Функции в VBA 773 DateDiff Возвращает значение [тип Variant (Long)] числа временных интервалов между двумя определенными датами. Синтаксис DateDiff(interval, datel, date2[, firstdayofweek[, firstweekofyear]]) Функция DateDiff принимает следующие именованные аргументы: Аргумент Назначение interval Обязательный. Строковое выражение, которое является временным интервалом (единицей измерения). datel, date2 Обязательный; Variant (Date). Две даты для вычисления. firstdayofweek Необязательный. Константа, которая определяет первый день недели (день по умолчанию зависит от национальных настроек). firstweekofyear Необязательный. Константа, которая определяет первую неделю года. Если не указана, первой неделей считается неделя, в которой имеется дата 1 января. Значения аргумента interval приведены в таблице для функции DateAdd. Значения аргумента firstdayofweek могут быть следующими: Константа Значение Описание vbUseSystem 0 Использовать национальные языковые [National Language Support (NLS)] API-настройки vbSunday 1 Sunday (Воскресенье) vbMonday 2 Monday (Понедельник) vbTuesday 3 Tuesday (Вторник) vb Wednesday 4 Wednesday (Среда) vbThursday 5 Thursday (Четверг) vbFriday 6 Friday (Пятница) vbSaturday 7 Saturday (Суббота) Значения аргумента firstweekofyear могут быть следующими: Константа Значение Описание vbUseSystem 0 Использовать NLS API-настройки. vbFirstJanl 1 Начинать с недели, в которой имеется дата 1 января. (по умолчанию). vbFirstFourDays 2 Начинать с первой недели, которая имеет, по крайней мере, четыре дня в новом году. vbFirstFullWeek 3 Начинать с первой полной недели года. Функция DateDiff используется для определения количества указанного вида (дней, недель и т.д.) временных интервалов между двумя датами. При этом следует учитывать значение последнего аргумента. 774 Приложение Г Date Part Возвращает определенную часть [тип Variant (Integer)] заданной даты. Синтаксис DatePart(interval, date[,firstdayofweek[, firstweekofyear]]) Функция DatePart принимает следующие именованные аргументы: Part Description interval Обязательный. Строковое выражение с обозначением необходимого интервала. date Обязательный. Тип Variant (Date). Значение даты. firstdayofweek Необязательный. Константа, задающая первый день недели. Значение по умолчанию определяется национальными настройками системы. firstweekofyear Необязательный. Константа, задающая первую неделю года. Если не задается, первая неделя считается той, в которой имеется дата 1 января. Значения аргумента interval приведены в таблице для функции DateAdd. Значения аргумента firstdayofweek приведены в таблице для функции DateDiff. Аргумент firstweekofyear может принимать следующие значения: Константа Значение Описание vbUseSystem 0 Использовать настройку NLS API. vbFirstJanl 1 Начинать с той недели, в которой будет первое января (по умолчанию). ' vbFirstFourDays 2 Начинать с первой недели, которая имеет, по меньшей мере, четыре дня в новом году. vbFirstFull W eek 3 Начинать с первой полной недели года. Функция DatePart может быть использована для вычисления некоторой даты и интервала времени. Например, вы можете вычислить день недели или текущий час. Пример Dim DateVar As Date ' DateVar = InputBox("Введите дату:") MsgBox "Квартал: " & DatePart("q", DateVar) Если в диалоговом окне функции InputBox ввести, например, 22/09/2001, то в диалоговом окне MsgBox будет выведена строка "Квартал: 3". DateSerial Возвращает значение даты [тип Variant (Date)] для заданных года, месяца и дня. Синтаксис DateSerial(year, month, day) Функция DateSerial принимает следующие именованные аргументы: Функции в VBA 775 Part Description year Обязательный; тип Integer. Число (арифметическое выражение) в интервале от 100 до 9999. month Обязательный; тип Integer. Любое арифметическое выражение. day Обязательный? тип Integer. Любое арифметическое выражение. Пример Следующая строка имеет результатом диалоговое окно с текстом "12.02.01". MsgBox DateSerial(2001, 2, 12) DateValue Возвращает значение типа Date, эквивалентное дате, заданной аргументом, который должен быть строкой, числом или константой, представляющей дату. Синтаксис DateValue(date) Обязательный аргумент date — обычно строковое выражение, представляющее дату от 1 января 100 года до 31 декабря 9999 года. Этот аргумент может быть также любым выражением, которое вычисляется до значения даты. Если date является строкой, включающей только числа, разделенные так называемыми разделителями даты (date separators), DateValue распознает месяц, день и год в соответствии с форматом Short Date, который определен для вашей системы. DateValue также распознает строку, которая содержит дату с полным или коротким именем месяца (например, "февраль 12, 1969"). Day Возвращает значение [тип Variant (Integer)] (между 1 и 31 включительно), представляющее день месяца. Синтаксис Day (da te) Обязательный аргумент date — любое значение TnnaVariant, численное выражение, строковое выражение или их комбинация, которая представляет дату. Если аргумент содержит значение Null, функция возвращает Null. Возвращаемое значение зависит от значения свойства Calendar в вашей системе. DDB Возвращает значение (Double) амортизации (depreciation) активов за определенный период времени с использованием балансового метода «двойного списания» (double-declining) или другого (вами указанного) метода. Синтаксис DDB(cost, salvage, life, periodl, factor]) Именованные аргументы функции DDB: 776 Приложение Г Аргумент Назначение cost Обязательный. Тип Double. Определяет начальную стоимость активов. ‘ salvage Обязательный. Тип Double. Определяет стоимость активов в конце периода амортизации (остаточная стоимость). life Обязательный. Тип Double. Определяет длительность периода амортизации собственности. period Обязательный. Тип Double. Определяет период, для которого вычисляется амортизация активов. factor Необязательный. Тип Variant. Определяет норму снижения стоимости (амортизации). Если аргумент отсутствует, используется значение 2 (метод «двойного списания»). Аргументы life и period должны выражаться в одних и тех же единицах, например, если life задается в месяцах, то и period также должен быть задан в месяцах. Все аргументы должны быть положительными числами. Функция DDB использует следующую формулу для вычисления амортизации за заданный период: Амортизация / period = ((cost - salvage) * factor) / life Dir Возвращает значение типа String, представляющее имя файла (каталога или папки), которое совпадает с шаблоном, файловым атрибутом или меткой тома драйвера. Синтаксис Dir[(pathname[, attributes])] Функция Dir имеет следующие аргументы: Аргумент Назначение Pathname Необязательный. Строковое выражение, которое определяет имя файла. Может включать каталог (папку) и имя драйвера диска Если функция не находит pathname, возвращается строка нулевой длины (""). Attributes Необязательный. Константа или числовое выражение, являющееся суммой атрибутов файла. Аргумент attributes принимает следующие значения: Константа Значение Описание vbNormal 0 Обычный (Normal) (по умолчанию) — файлы без атрибутов. vbReadOnly 1 Только на чтение (Read-only). vbHidden 2 Скрытый (Hidden). VbSystem 4 Системный файл (System file). vb Volume 8 Метка тома (Volume label); если указаны любые другие атрибуты, vbVolume игнорируется. Функции в VBA 777 Константа Значение Описание vbDirectory 16 Каталог или папка. vbAlias 64 Алиасное имя (на Macintosh). В Microsoft Windows Dir поддерживает использование символов (*) и (?) для поиска множества файлов. В первом вызове функции Dir следует обязательно задавать аргумент pathname, иначе будет сгенерирована ошибка. Аргумент pathname также должен использоваться, если указываются атрибуты файлов. Dir возвращает первое имя файла, которое совпадает с pathname. Для получения следующих файлов, совпадающих с pathname, следует вызвать функцию Dir снова, но без аргументов. После того как функция в последних вызовах возвратит все совпавшие файлы, функция возвратит пустую строку (""). В связи с этим удобно записывать имена файлов, возвращаемых функцией Dir, в массив и в дальнейшем, например, сортировать его. Environ Возвращает значение типа String, связанное с переменной среды операционной системы. На Macintosh не работает. Синтаксис Environ({envstring | number}) Функция Environ принимает следующие именованные аргументы: Аргумент Назначение | envstring Необязательный. Строковое выражение, содержащее имя переменной среды. 1 number Необязательный. Числовое выражение, соответствующее номеру строки в таблице переменных среды. Если значение аргумента envstring не может быть найдено в таблице переменных среды, функция возвращает строку нулевой длины («»). Иначе функция возвращает текст, присвоенный определенному параметру envstring, текст, который следует за знаком равенства (=) в таблице переменных среды для определенной переменной. EOF • Z Возвращает значение True при достижении конца файла, открытого для прямого или последовательного доступа. Синтаксис EOF(f21епumber) Обязательный аргумент filenumber является Integer-значением, содержащим допустимый номер файла. Эту функцию следует использовать перед попыткой доступа к концу файла. Пока конец файла (открытого для Random- или Binary-доступа) не достигнут, функция возвращает значение False. При этом из файла можно получать данные. Если файл был открыт для Binary-доступа, попытка чтения записей из него функцией Input при условии, что EOF возвращает значение True, приведет к гене 778 Приложение Г рации ошибки. Используйте функции LOF и Loe вместо EOF при чтении бинарных файлов функцией Input или используйте GET с функцией EOF. С файлами, открытыми для Output, функция EOF всегда возвращает True. Error Возвращает еггог-сообщение, соответствующее заданному номеру ошибки. Синтаксис Error[(errornumber)] Необязательный аргумент errornumber может быть любым допустимым еггог-номером. Если errornumber — допустимый error-номер, но не определен, функция возвращает сообщение "Application-defined or object-defined error." Если аргумент отсутствует, возвращается сообщение, относящееся к последней run-time-ошибке. Если же errornumber равен 0, функция возвращает строку нулевой длины (""). Ехр Возвращает значение (тип Double), определяющее число е (основание натурального логарифма), возведенное в степень. Синтаксис Exp(number) Обязательный аргумент number — Double- или любое допустимое численное выражение. Если значение аргумента превышает число 709.782712893, возникнет ошибка. Константа е равна приблизительно 2.718282. FileAttr Возвращает значение (тип Long), представляющее файловый режим для файла, открытого с использованием оператора Open. Синтаксис FileAttr(filenumber, returntype) Функция FileAttr имеет следующие именованные аргументы: Аргумент Назначение filenumber Обязательный; тип Integer. Любой допустимый файловый номер. returntype Обязательный; тип Integer. Число, указывающее на тип возвращаемой информации. Для определения файлового режима следует задать значение 1. Для получения дескриптора файла операционной системы укажите значение 2 (только для 16-битной системы!). При значении аргумента returntype равном 1, можно получить следующие результаты: Режим Значение Input 1 Output 2 Функции в VBA 779 Режим Значение Random 4 Append 8 Binary 32 FileDateTime Возвращает значение [тип Variant (Date)], которое указывает дату и время создания или последней модификации файла. Синтаксис FileDateTime(pathname) Обязательный аргумент pathname является строковым выражением, определяющим имя файла, которое может включать каталог (папку) и драйвер. Пример Следующая строка приводит к выдаче в окне MsgBox информации о времени создания файла "TESTFILE". MsgBox FileDateTime("TESTFILE") FileLen Возвращает значение (тип Long) длины (размера) файла в байтах. Синтаксис FileLen(pathname) Обязательный аргумент pathname является строковым выражением, определяющим имя файла, которое может включать каталог (папку) и драйвер. Если указанный в аргументе файл открыт при вызове функции FileLen, возвращаемое значение имеет отношение к длине файла непосредственно перед открытием. Чтобы получить длину открытого файла, используйте функцию LOF. Пример Следующая строка приводит к выдаче в окне MsgBox информации о длине файла "TESTFILE". MsgBox FileLen ("TESTFILE") Filter Возвращает массив (начинающийся с нулевого индекса), содержащий поднабор строчного массива на основе заданного критерия. Синтаксис Filter(sourcesrray, match[, include!, compare]]) Функция Filter имеет следующие именованные аргументы: Аргумент Назначение sourcearray Обязательный. Одномерный массив, в котором производится поиск. match Обязательный. Строка для поиска. 780 Приложение Г Аргумент Назначение include Необязательный. Значение типа Boolean, определяющее, какое значение возвращать: включающее или не включающее шаблон match. Если include — True, функция Filter возвращает поднабор массива, который содержит match как подстроку. Если include — False, Filter возвращает поднабор массива, который не содержит match как подстроку. compare Необязательный. Численной значение, указывающее тип сравнения. Аргумент compare может иметь следующие значения: Константа Значение Назначение vbUseCompareOption -1 Выполнять сравнение с использованием настроек оператора Option Compare. vbBinaryCompare 0 Выполнять бинарное сравнение. vbTextCompare 1 Выполнять текстовое сравнение. vbDatabaseCompare 2 Только для Microsoft Access. Выполнять сравнение, основанное на информации в базе данных. Если ни одного совпадения с шаблоном match в sourcearray не обнаруживается, функция Filter возвращает пустой массив. Если sourcearray — Null или — неодномерный массив, возникает ошибка. Fix Возвращает целую часть числа. Синтаксис Fix(number) Обязательный аргумент number имеет тип Double или является допустимым численным выражением. Если number — Null, возвращается Null. И функция Int, и функция Fix удаляют дробную часть аргумента number и возвращают целое значение. Отличаются эти функции при работе с отрицательным аргументом: Int возвращает ближайшее меньшее отрицательное число, a Fix — ближайшее большее отрицательное число. Примеры Dim My_Number as Integer My_Number = Int(19.8) My_Number = Fix(19.2) ' результат ’ результат 19 19 My_Number = Int(-19.8) ’ результат -20 My_Number = Fix(-19.8) ’ результат -19 My_Number = Int(-19.2) ' результат -20 My_Number = Fix(-19.2) ’ результат -19 Функции в VBA 781 Format Возвращает строку [тип Variant (String)], содержащую значение, отформатированное согласно инструкциям, находящимся в format-выражении. Синтаксис Format(expression[, fornfat], firstdayofweek], firstweekofyear]]]) Функция Format принимает следующие аргументы: Аргумент Назначение expression Обязательный. Любое допустимое выражение. format Необязательный. Допустимое выражение именованного или определенного пользователем формата. | firstdayofweek Необязательный. Константа, которая определяет первый день | недели. firstweekofyear Необязательный. Константа, которая определяет первую неделю года. Аргумент firstdayofweek может принимать следующие значения: Константа Значение Описание vbUseSystem 0 Использовать настройку NLS API. Vb Sunday 1 Sunday vbMonday 2 Monday vbTuesday 3 Tuesday । vb Wednesday 4 Wednesday vbThursday 5 Thursday vbFriday 6 Friday vbSaturday 7 Saturday Аргумент firstweekofyear может принимать следующие значения: Константа Значение Описание vbUseSystem 0 Использовать настройку NLS API. vbFirstJanl 1 Начинать с недели, в которой имеется дата первое января. vbFirstFourDays 2 Начинать с первой недели, в которой имеется, по крайней мере, четыре дня года. vbFirstFuIl Week 3 Начинать с первой полной недели года. Если вы пытаетесь форматировать число, не определяя format, функция Format обеспечивает функциональность, подобную функциональности Str. Однако положительные числа, форматируемые как строки с использованием функции Format, не включают лидирующего пробела, резервируемого для знака значения. 782 Приложение Г Символ Диапазон | D 1-30 Dd 1-30 WW 1-51 ттт Отображать полное наименование месяца (Юлианские наименования месяцев не имеют сокращений). У 1-355 УУУУ 100-9666 Formatcurrency Возвращает выражение, отформатированное как денежное (валютное) выражение с использованием значения, заданного на вкладке Денежная единица окна Свойства: Язык и стандарты, доступного из Панели управления. Синтаксис Formatcurrency(Expression[, NumDigitsAfterDecimal [, IncludeLeadingDigit [, UseParensForNegativeNumbers [, GroupDigits]]]]) Функция Formatcurrency принимает следующие аргументы: Аргумент Назначение Expression Обязательный. Выражение для форматирования. NumDigitsAfterDecimal Необязательный. Численное значение, определяющее количество отображаемых знаков справа от десятичной точки. Значение по умолчанию для этого аргумента равно -1, что означает использование региональных настроек. IncludeLeadingDigit Необязательный. Константа трех состояний, определяющая, следует ли отображать ведущий ноль для дробных чисел. UseParensForNegative- Numbers Необязательный. Константа трех состояний, определяющая, следует ли помещать отрицательные значения внутри круглых скобок. GroupDigits Необязательный. Константа трех состояний, определяющая, группировать ли цифры с помощью ограничителей, заданных региональными настройками. Аргументы IncludeLeadingDigit, UseParensForNegativeNumbers и GroupDigits могут принимать следующие значения: Константа Значение Описание vbTrue -1 True vbFalse 0 False vbUseDefauIt -2 Использовать региональные настройки компьютера. Когда один или более необязательных аргументов пропускается, значения для пропущенных аргументов используются из региональных настроек компьютера. Функции в VBA 783 FormatDateTime Возвращает выражение, отформатированное, как дата или время. Синтаксис FormatDateTime(Date[,NamedFormat]) Функция FormatDateTime принимает следующие аргументы: Аргумент Назначение Date Обязательный. Дата для форматирования. NamedFormat Необязательный. Численное значение, указывающее, необходимый формат. Если опущен, используется vbGeneralDate. Аргумент NamedFormat может принимать следующие значения: Константа Значение Описание vbGeneralDate 0 Отображать дату и/или время. Если в аргументе Date имеется часть даты, дата отображается в коротком формате. Если в аргументе Date имеется часть времени, она отображается в длинном формате. vbLongDate 1 Отображать дату с использованием длинного формата, установленного на компьютере в региональных настройках. vbShortDate 2 Отображать дату с использованием короткого формата, установленного на компьютере в региональных настройках. vbLongTime 3 Отображать время с использованием временного формата, установленного на компьютере в региональных настройках. vbShortTime 4 Отображать время с использованием формата 24-hour (hh:mm). FormatNumber Возвращает выражение, отформатированное, как число. Синтаксис FormatNumber{Expression[,NumDigitsAfterDecimal [,IncludeLeadingDigit [, UseParensForNegativeNumbers [,GroupDigits]]]]) Функция FormatNumber принимает следующие аргументы: Аргумент Назначение Expression Обязательный. Выражение для форматирования. NumDigitsAf terDecimal Необязательный. Численное значение, определяющее количество отображаемых знаков справа от десятичной точки. Значение по умолчанию для этого аргумента равно -1, что означает использование региональных настроек. 784 Приложение Г Аргумент Назначение IncludeLeadingDigit Необязательный. Константа трех состояний, определяющая, следует ли отображать ведущий ноль для дробных чисел. UseParensForNegativeNumbers Необязательный. Константа трех состояний, определяющая, следует ли помещать отрицательные значения внутри круглых скобок. GroupDigits Необязательный. Константа трех состояний, определяющая, группировать ли цифры с помощью ограничителей, заданных региональными настройками. Аргументы IncludeLeadingDigit, UseParensForNegativeNumbers и GroupDigits могут принимать следующие значения: Константа Значение Описание vbTrue -1 True vbFalse 0 False vbUseDefault -2 Использовать региональные настройки компьютера. Когда один или более необязательных аргументов пропускается, значения для пропущенных аргументов используются из региональных настроек компьютера. FormatPercent Возвращает выражение, отформатированное, как процентное отношение (умноженное на 100) с конечным знаком процента (%). Синтаксис FormatPercent(Expression[,NumDigitsAft erDecimal [,IncludeLeadingDigit [,UseParensForNegativeNumbers [,GroupDigits]]]]) Функция FormatPercent имеет следующие аргументы: Аргумент Назначение Expression Обязательный. Выражение для форматирования. NumDigitsAf terDecimal у Необязательный. Численное значение, определяющее количество отображаемых знаков справа от десятичной точки. Значение по умолчанию для этого аргумента равно -1, что означает использование региональных настроек. IncludeLeadingDigit Необязательный. Константа трех состояний, определяющая, следует ли отображать ведущий ноль для дробных чисел. UseParensForNegative- Numbers Необязательный. Константа трех состояний, определяющая, следует ли помещать отрицательные значения внутри круглых скобок. GroupDigits Необязательный. Константа трех состояний, определяющая, группировать ли цифры с помощью ограничителей, заданных региональными настройками. Функции в VBA 785 Когда один или более необязательных аргументов пропускается, значения для пропущенных аргументов используются из региональных настроек компьютера: Константа Значение Описание vbTrue -1 True vbFalse 0 False vbUseDefault -2 Использовать региональные настройки компьютера. Когда один или более необязательных аргументов пропускается, значения для пропущенных аргументов используются из региональных настроек компьютера. FreeFile Возвращает значение (тип Integer), представляющее следующий файловый номер1, доступный для использования оператором Open. Синтаксис FreeFile [ (rangenumber) ] • Необязательный аргумент rangenumber (тип Variant) определяет диапазон для возвращаемых файловых номеров. Если этот аргумент задается нулевым (по умолчанию), то возвращается файловый номер в диапазоне 1-255, включительно. Для диапазона 256-511 используется значение 1. * ' А FV Возвращает будущее значение (тип Double) ежегодных поступлений (annuity) на базе периодических, фиксированных платежей (fixed payments) и фиксированной процентной ставки (fixed interest rate). Синтаксис ' FV(rate, nper, pmt[, pv[, type]]) Функция FV имеет следующие именованные аргументы: Аргумент Назначение rate Обязательный. Тип Double. Процентная ставка за период. Например, если вы получаете ссуду на покупку машины из расчета 10 процентов годовых [annual percentage rate (APR)] и вносите ежемесячные платежи, то ставка за период должна составлять 0.1/12 или 0.0083. прег Обязательный. Тип Integer. Общее число периодов платежей в ежегодных поступлениях (annuity). Например, если вы вносите ежемесячные платежи в счет погашения четырехлетней ссуды на покупку автомашины, в вашей ссуде будет всего 4 * 12 (или 48) периодов платежей. pmt Обязательный. Тип Double. Платеж, который должен быть внесен за каждый период. Платежи обычно состоят из основного платежа (principal) и платежа по процентам (interest), которые не изменяются на протяжении выплаты взноса. 1 Файловый номер (file number) — число, используемое в операторе Open для открытия файла. 786 Приложение Г Аргумент Назначение pv Необязательный. Тип Variant. Настоящая величина [или твердая (lump sum)] ряда будущих платежей. Например, когда вы берете в долг деньги, чтобы купить автомобиль, сумма займа (loan amount) — это настоящая величина для кредитора ежемесячных платежей за автомобиль, которые вы будете вносить. Если аргумент отсутствует, то он подразумевается равным 0. type Необязательный. Тип Variant. Определяет, когда должен производиться платеж. Используется 0, если платеж должен производиться в конце периода платежа или 1, если срок платежа наступает в начале периода платежа. Если отсутствует, подразумевается 0. Ежегодные поступления, аннуитет (annuity) — это ряд фиксированных наличных платежей, вносимых в течение некоторого периода времени. Поступления могут быть ссудой, такой как ипотека (home mortgage) или инвестицией, такой как план ежемесячных накоплений (monthly savings plan). Аргументы rate и прег должны вычисляться с использованием периодов платежей, выраженных в одних и тех же единицах. Например, если rate вычисляется с использованием месяцев, прег должен также вычисляться в месяцах. Для всех аргументов наличные платежи, такие как депозиты (deposits to savings) представляются отрицательными числами; наличные поступления, такие как дивиденды, представляются положительными числами. GetAllSettings Возвращает список ключевых настроек и их значения в Windows реестре (или файле инициализации приложения на Macintosh). Синтаксис GetAllSettings(appname, section) Функция GetAllSettings принимает следующие именованные аргументы: Аргумент Назначение аррпате Обязательный. Строковое выражение, содержащее имя приложения или проекта, ключевые установки которого требуются. section Обязательный. Строковое выражение, содержащее имя секции, ключевые настройки которой необходимо получить. Функция возвращает двумерный массив строк, содержащий все ключевые настройки в указанной секции и соответствующие им значения. Функция GetAllSettings возвращает неинициализированное Variant-значение, если не задан либо аргумент appname, либо section. GetAttr Возвращает значение (тип Integer), представляющее атрибуты файла, каталога или папки. Синтаксис GetAttr(pathname) Функции в VBA 787 Обязательный аргумент pathname является строковым выражением, которое определяет имя файла, которое может включать каталог (или папку) и драйвер. Значения, возвращаемые функцией GetAttr, представляют собой сумму следующих значений атрибутов: Константа Значение Описание vbNormal 0 Обычный (Normal). vbKeadOnly 1 Только на чтение (Read-only). vbHidden 2 Скрытый (Hidden). vbSystem 4 Системный файл (System file) vbDirectory 16 Каталог или папка (Directory or folder). vbArchive 32 Файл изменился с момента архивации (недоступен на Macintosh). vbAlias 64 Определяет имя файла как алиасное (Specified file name is an alias). Только для Macintosh. Чтобы определить установленные атрибуты, необходимо использовать оператор And для побитового сравнения возвращаемого функцией значения и некоторого шаблона с указанием конкретного атрибута. Если результатом сравнения будет нулевое значение, это означает, что атрибут не установлен. GetObject Возвращает ссылку на объект, поддерживаемый ActiveX-компонентом. Синтаксис GetObject([pathname] [, class]) Функция GetObject принимает следующие именованные аргументы: Аргумент Назначение । pathname Необязательный; тип Variant (String). Полный путь и имя фай- 1 ла, содержащего объект. Если pathname опускается, необходимо указывать аргумент class. class Необязательный; тип Variant (String). Строка — класс объекта. Аргумент class использует следующий синтаксис appname.objecttype и имеет две составляющие: Аргумент Назначение аррпате Обязательный; тип Variant (String). Имя приложения, обеспечивающего объектом. objecttype Обязательный; тип Variant (String). Тип или класс объекта. Используйте функцию GetObject для доступа к ActiveX-объекту из файла и назначайте объект объектной переменной. Оператор Set применяйте для присваивания объектной переменной возвращаемого функцией GetObject значения. Например: Dim CObject As Object Set CObject = GetObject("C:\CAD\SCHEMA.CAD") 788 Приложение Г Если pathname является строкой нулевой длины функция GetObject возвращает экземпляр нового объекта указанного типа. Если аргумент pathname опускается, GetObject возвращает текущий активный объект указанного типа. Если ни одного указанного объекта не существует, возникает ошибка. Пример В следующей процедуре функция GetObject используется для того, чтобы определить наличие в системе экземпляра приложения Excel. Sub Test GetObject() Dim xlApp As Object Dim xlSheet As Object On Error Resume Next Set xlApp - Nothing ' Set xlApp = GetObject(, "Excel.Application") If Err.Number <> 0 Then Set xlApp = CreateObject("Excel.Application") End If Err.Clear Set xlBook = xlApp.Workbooks-Add Set xlSheet - xlBook.Worksheets(1) xlSheet.Application.Visible = True End Sub GetSetting Возвращает значение ключевой настройки определенного приложения в Windows-реестре. Синтаксис GetSetting(аррпате, section, keyf, default]) Функция GetSetting принимает следующие именованные аргументы: 1 Аргумент Назначение appname Обязательный. Строковое выражение, содержащее имя приложения или проекта, настройки которого необходимы. I section Обязательный. Строковое выражение, содержащее наименование секции, в которой следует искать ключевую настройку. key Обязательный. Строковое выражение, содержащее имя настройки. i default Необязательный. Выражение, содержащее возвращаемое значение, если в настройке не установлено никакого значения. Если этот параметр опускается, используется строка нулевой длины Если какой-либо из элементов, указанных в аргумента функции GetSetting, не существует, функция возвращает default. Hex Возвращает строку, представляющую шестнадцатиричное значение числа. Синтаксис Hex (number) Функции в VBA 789 Обязательный аргумент number является любым допустимым числовым (или строковым) выражением. Если number не является целым числом, сначала выполняется округление до целого. если number функция возвращает Null Null Empty Ноль (0) Примеры Му_Нех = Hex(5) ' Returns 5 Му_Нех = Hex(10) 1 Returns A Му_Нех = Hex (459) ' Returns 1CB Му__Нех = Hex (4 59.4) ' Returns 1CB Му_Нех = Hex (459.7) ' Returns ICC Hour Возвращает значение [TnnVariant (Integer)], определяющее целое число в диапазоне от 0 до 23, включительно, представляющее час дня. Синтаксис Hour(time) Обязательный аргумент time — любое значение типа Variant, численное выражение, строковое выражение или любая их комбинация, представляющая время. Для аргумента time, содержащего Null, функция возвращает Null. Ilf Возвращает значение одного из двух своих аргументов в зависимости от оцениваемого выражения. Синтаксис Ilf(ехрг, truepart, falsepart) Функция Ilf имеет следующие (все обязательные) именованные аргументы: аргумент назначение expr Оцениваемое выражение. truepart Значение или выражение, которое возвращается, если ехрг имеет значение True. falsepart Значение или выражение, которое возвращается, если ехрг имеет значение False. Пример х = 200 MsgBox Ilf(х > 1000, "Много", "Мало") ' выдача слова "Мало" 790 Приложение Г Input Функция String возвращает строку символов из файла, открытого в режиме Input или Binary. Синтаксис Input(number, [#]filenumber) * Функция Input имеет следующие (обязательные) аргументы: аргумент назначение Number Любое допустимое выражение (возвращающее число), определяющее число возвращаемых символов. Filenumber Допустимый номер файла. Данные, считываемые функцией Input, предварительно должны быть записаны в файл посредством функции Print # или Put. В отличие от оператора Input # функция Input возвращает все прочитанные символы, включая запятые, символы возврата каретки, перехода на другую строку, кавычки и ведущие пробелы. Пример В этом примере открывается текстовый файл и в цикле происходит посимвольное считывание и вывод в окно Immediate . Open "F:\ZZ\WWW.TXT" For Input As #1 ' открыть файл Do While Not EOF(l) ' цикл до конца файла CharOne = Input (1, #1) ' считать символ 1 Debug.Print CharOne ' отобразить в Immediate-окне Loop Close #1 ' закрыть файл InputBox Отображает запрос в диалоговом окне, ожидает ввода пользователем строки (или щелчка на кнопке окна), а затем возвращает строку из поля ввода окна. Синтаксис InputBox (prompt [, title] [, default] [, iqaos] [, ypos] [, helpfile, context]) Функция InputBox принимает следующие именованные аргументы: аргумент назначение prompt Обязательный. Любое строковое выражение, отображаемое в качестве подсказки. Максимальная длина этой строки примерно 1024 символа (в зависимости от используемой ширины символов). Если необходимо, чтобы prompt-аргумент содержал более одной строки, следует использовать символы разделения строк: символ возврата каретки (Chr(13)) и символ перехода на другую строку (Chr(10)) или комбинацию этих символов (Chr(13) & Chr(10)). title Необязательный. Строка, используемая в качестве заголовка для окна ввода. Если этот аргумент опускается, в качестве заголовка выводится наименование приложения, в котором вызывается функция. Функции в VBA 791 аргумент назначение default Необязательный. Является любым строковым выражением и используется как значение по умолчанию для пользовательского ввода. Если опускается, строка ввода в окне отображается пустой. xpos Необязательный. Численное значение, определяющее (в твипах) горизонтальное расстояние от левого края окна до верхнего левого угла диалогового окна. Если этот аргумент не указан, диалоговое окно центрируется горизонтально. ypos Необязательный. Численное значение, определяющее (в твипах) вертикальное расстояние от верхнего края окна до верхней границы диалогового окна. Если этот аргумент не указывается, диалоговое окно позиционируется по вертикали примерно на одну треть от нижней части экрана. helpfile Необязательный. Строковое выражение, которое содержит имя справочного Windows-файла для обеспечения контекстной справки. Если этот аргумент используется, необходимо включать и аргумент context. context Необязательный. Численное выражение, которое указывает раздел в справочном файле, относящийся к отображаемому окну. InStr Возвращает значение [тип Variant (Long)], определяющее позицию первого вхождения одной строки внутри другой. Синтаксис InStr([start, ]stringl, string2[, compare]) Функция InStr принимает следующие аргументы: Аргумент назначение start Необязательный. Числовое выражение, задающее начальную позицию для поиска. Если аргумент не указывается, то поиск начинается с первого символа. Если аргумент start содержит значение Null, возникает ошибка. Аргумент start является обязательным, если указывается аргумент compare. stringl Обязательный. Строковое выражение, в котором выполняется поиск. string2 Обязательный. Строковое выражение, поиск положения которого выполняет функция. compare Необязательный. Определяет тип сравнения строк. Если не опускается, то используется сравнение согласно оператору Option Compare. Аргумент compare может принимать следующие значения: константа значение описание vbUseCompareOption -1 Выполняется сравнение согласно установкам посредством оператора Option Compare. vbBinaryComp are 0 Выполняется двоичное сравнение. 792 Приложение Г константа значение описание vbTextCompare 1 Выполняется двоичное сравнение. vbDatabaseCompare 2 Только для Microsoft Access. Выполняется сравнение, основанное на информации в вашей базе данных. Возвращаемые значения если InStr возвращает stringl имеет нулевую длину 0 string 1 — Null Null string2 имеет нулевую длину start 1 string2 — Null Null string2 не найдена 0 string2 найдена в stringl Позиция, в которой произошло совпадение. start > string2 0 InStrRev Возвращает позицию появления одной строки внутри другой, начиная с конца строки. Синтаксис InstrRev(stringcheck, stringmatch[, start], compare]]) Функция InstrRev принимает следующие именованные аргументы: аргумент Назначение stringcheck Обязательный. Строка, в которой выполняется поиск. stringmatch Обязательный. Строковое выражение, поиск которого выполняется. i start Необязательный. Численное выражение, устанавливающее начальную позицию для поиска. Если не указывается, используется значение -1, что означает начало поиска с последнего символа строки. Значение Null вызывает появление ошибки. compare Необязательный. Численное значение, задающее тип сравнения. Если не указывается, выполняется двоичное сравнение. Аргумент compare может принимать следующие значения: константа значение описание vbUseCompareOption -1 Выполняется сравнение согласно установкам посредством оператора Option Compare. vbBinaryCompare 0 Выполняется двоичное сравнение. vbTextCompare 1 Выполняется двоичное сравнение. Функции в VBA 793 константа значение описание vbDatabaseCompare 2 Только для Microsoft Access. Выполняется сравнение, основанное на информации в вашей базе данных. Функция InStrRev возвращает следующие значения: если InStrRev возвращает stringcheck имеет нулевую длину 0 stringcheck — Null Null stringmatch имеет нулевую длину start stringmatch — Null Null stringmatch не найдена 0 stringmatch найдена в stringcheck Позиция, в которой произошло совпадение. start > Lenfstringmatch) 0 Int Возвращает целую часть числа. Синтаксис Fix(number) Обязательный аргумент number — число (тип Double) или допустимое числовое выражение. Если number содержит Null, функция возвращает Null. IPmt Возвращает значение (тип Double) платежей по процентам для данного периода ежегодных поступлений на базе периодических, фиксированных платежей и фиксированной процентной ставки. Синтаксис IPmt(rate, per, nper, pv[, fv[, type]]) Именованные аргументы функции IPmt: аргумент назначение rate Обязательный. Тип Double. Процентная ставка за период. Например, если вы берете заем для покупки автомобиля из расчета 10 процентов годовых (annual percentage rate, APR) и делаете ежемесячные платежи, ставка за период составляет 0.1/12, или 0.0083. per Обязательный. Значение типа Double. Период платежа в диапазоне 1 - nper. nper Обязательный. Значение типа Double. Общее число периодов платежей в ежегодных поступлениях (annuity). Например, если вы вносите ежемесячные платежи в счет погашения четырехлетней ссуды, ваша ссуда имеет всего 4 * 12 (или 48) периодов платежа. 794 Приложение Г аргумент назначение ри Обязательный. Значение Double. Текущая стоимость или общая сумма всех будущих платежей с настоящего момента. Например, когда вы получаете заем, чтобы купить автомобиль, сумма займа — это текущее значение (present value) для кредитора. fv Необязательный. Значение Variant. Будущее значение (future value) или баланс наличности (cash balance), которого необходимо достичь после того, как вы внесете окончательный платеж. Например, будущая величина ссуды равна $0, потому что это ее величина после окончательного платежа. Однако если вы хотите накопить $50,000 за 18 лет, то $50,000 — это будущее значение. Если аргумент отсутствует, то он предполагается равным 0. type Необязательный. Значение Variant. Определяет, когда должен производиться платеж. Используется 0, если срок платежа наступает в конце периода платежа или используется 1, если срок платежа наступает в начале периода. Если аргумент отсутствует, он предполагается равным 0. Ежегодные поступления (annuity) — это ряд фиксированных наличных платежей (fixed cash payments), внесенных в течение некоторого периода времени. Поступления могут быть ссудой, такой как ипотека (home mortgage) или инвестиции (investment), такие как план ежемесячных накоплений (monthly savings plan). Аргументы rate и прег должны вычисляться с использованием периодов платежей, выраженных в одних и тех же единицах. Например, если rate вычисляется с использованием месяцев, прег также должен вычисляться в месяцах. Для всех аргументов выплаченные наличные платежи, такие как депозиты (deposits to savings) представляются отрицательными числами; прибыли, такие как дивиденды (dividend checks), представляются положительными числами. IRR Возвращает (значение типа Double) внутреннюю скорость оборота для серии периодических операций с наличными. Синтаксис IRR(values О [, guess]) Именованные аргументы функции IRR: аргумент назначение valuesQ Обязательный. Массив (тип Double) со значениями, для которых определяется внутренняя скорость оборота средств. Массив должен содержать, по меньшей мере, одно отрицательное значение (выплата) и одно — положительное (поступление). guess ' Необязательный. Ваша оценка (тип Variant) возвращаемого функцией результата. Если отсутствует, то полагается равным значению 0.1 (10%). Функция IRR использует порядок значений массива для интерпретации порядка денежных выплат или поступлений, поэтому следует внимательно указывать этот порядок. Функции в VBA 795 IsArray Возвращает значение (тип Boolean), указывающее, является ли переменная массивом. Синтаксис t IsArray (varname) Обязательный аргумент varname — идентификатор, определяющий переменную. Функция IsArray возвращает значение True, если переменная-аргумент является массивом. В противном случае возвращается значение False. Примеры Dim Arrayl(1 То 5) As Integer, Array2, Rez Array2 = Array (1, 2, 3) Rez = IsArray(Arrayl) 1 True Rez = IsArray(Array2) 1 True IsDate Возвращает значение (тип Boolean), указывающее, может ли выражение-аргумент быть конвертировано в дату. Синтаксис IsDate(expression) Обязательный аргумент expression — значение (тип Variant), содержащее выражение даты или любое строковое выражение, распознаваемое как дата или время. Функция IsDate возвращает значение True, если выражение-аргумент является датой или может быть представлен как дата; иначе возвращается значение False. Примеры Dim DateExpl, DateExp2, NoDate, Rez DateExpl= "February 12, 1969" DateExp2= #2/12/69# NoDate = " " Rez = IsDate(NoDate) 1 False Rez = IsDate(DateExpl) ' True Rez = IsDate(DateExp2) 1 True IsEmpty Возвращает значение (тип Boolean ), указывающее, была ли переменная-аргумент инициализирована. Синтаксис IsEmpty(expression) Обязательный аргумент expression — значение (тип Variant), содержащее численное или строковое выражение. Но поскольку функция IsEmpty используется для определения того, инициализирована ли отдельная переменная, аргумент expression — чаще всего имя единственной переменной. Функция IsEmpty возвращает значение True, если переменная инициализирована или ей явно было присвоено значение Empty; иначе — функция возвращает 796 Приложение Г значение False. Значение False также возвращается всегда, когда expression содержит более одной переменной. Примеры , Dim My_Var, Rez MyCheck = IsEmpty(My_Var) ' True * My_Var = Null MyCheck = IsEmpty(My_Var) ' False My_Var = Empty MyCheck = IsEmpty(My_Var) ' True z IsError Функция возвращает значение (тип Boolean), указывающее, является ли выражение значением ошибки (еггог-значением). Синтаксис IsError(expressi on) Обязательный аргумент expression может быть любым допустимым выражением. Error-значения создаются преобразованием действительных чисел в error-значения с использованием функции CVErr. Функция IsError используется для определения того, представляет ли числовое выражение ошибку. IsError возвращает значение True, если аргумент expression указывает на ошибку, и — False в противном случае. IsMissing Возвращает значение (тип Boolean), указывающее, был ли необязательный аргумент (типа Variant) передан в процедуру (указан ли при вызове). Синтаксис IsMissing(argname) Обязательный аргумент argname содержит имя необязательного аргумента процедуры. Используйте функцию IsMissing для определения того, были ли определены при вызове процедуры необязательные аргументы. Функция IsMissing возвращает значение True, если для указанного аргумента не было при вызове процедуры указано никакого значения; иначе — возвращается значение False. Если функция IsMissing возвращает значение True для некоторого аргумента, использование отсутствующего аргумента в коде может вызвать определенную пользователем ошибку. IsNull Возвращает значение (тип Boolean), которое указывает, содержит ли выражение недопустимые данные (Null). Синтаксис IsNull(expression) Обязательный аргумент expression — (тип Variant) численное или строковое выражение. функции в VBA 797 Функция IsNull возвращает значение True, если expression — Null; иначе — IsNull возвращает False. Если expression содержит более одной переменной, Null в любой переменной приводит к тому, что для всего выражения функция возвращает значение True. Значение Null указывает, что Variant содержит недопустимые данные. Null — это не то же самое, что Empty, которое указывает на то, что переменная еще не была инициализирована. Это — также не то же самое, что строка нулевой длины (”"). Обычно следует использовать функцию IsNull для определения того, содержит ли выражение значение Null. Примеры Dim MyVar, Rez Rez = IsNull(My_Var) 'False My_Var = Null Rez = IsNull(My_Var) 'True My__Var = "" Rez = IsNull(My_Var) 'False IsNumeric Возвращает значение (тип Boolean), указывающее, является ли результатом вычисления выражения численное значение. Синтаксис IsNumeric(expression) Обязательный аргумент expression — значение (тип Variant), содержащее численное или строковое выражение. Функция IsNumeric возвращает значение True, если все expression распознается как число, иначе —возвращается значение False. Если expression является датой, функция возвращает значение False. Примеры В этом примере используется функция IsNumeric для определения, может ли переменная быть оценена как число. StrVar =,"763" BooleanVar = IsNumeric(StrVar) 'возвращает True IsObject Возвращает значение (тип Boolean), указывающее, представляет ли идентификатор объектную переменную. Синтаксис IsObject(identifier) Обязательный аргумент identifier — имя переменной. Функция IsObject возвращает значение True, если аргумент identifier является переменной, объявленной как Object-тип или как тип любого допустимого класса, или если identifier — Variant-переменная VarType vbObject, или объект типа, определенного пользователем; иначе — возвращается значение False. Функция IsObject возвращает значение True, даже если переменной было присвоено значение Nothing. 798 Приложение Г Join Возвращает строку, объединяя несколько подстрок, находящихся в массиве. Синтаксис Join(sourcearray[, delimiter]) ' Функция Join принимает следующие именованные аргументы: аргумент назначение sourcearray Обязательный. Одномерный массив, содержащий подстроки, которые следует объединить. delimiter Необязательный. Символ, используемый для разделения подстрок в возвращаемой строке. Если параметр опускается, используется символ пробела (" "). Если этот аргумент является строкой нулевой длины (""), подстроки объединяются без разделителя. Примеры Dim array_str(3) array_str(l) = "Первый" array_str(2) = "Второй" array—str(3) = "Третий" MsgBox Join(array_str, 'вывод: "Первый:Второй:Третий " LBound Функция возвращает значение (тип Long), содержащее наименьшее значение индекса массива. Синтаксис LBound(arrayname[, dimension]) Функция LBound принимает следующие аргументы: аргумент назначение аггаупатпе Обязательный. Имя переменной-массива. dimension Необязательный; тип Variant (Long). Целое число, определяющее, границу какой из размерностей следует возвратить. Для первой размерности указывайте значение 1, для второй — 2, и так далее. Если аргумент dimension опускается, он предполагается равным 1. Функцию LBound можно использовать совместно с функцией UBound для определения размера массива, поскольку последняя возвращает наибольшее значение индекса массива. Пример Dim Rez Dim A (4 To 100, 0 To 3, -5 To 4) Rez = LBound(A, 1) 'возвращает 4 Rez = LBound(A, 2) 'возвращает 0 Rez = LBound(A, 3) 'возвращает -5 Функции в VBA 799 LCase Возвращает значение (тип String), которое преобразовано к нижнему регистру. Синтаксис LCase(string) Обязательный аргумент string — любое допустимое строковое выражение. Если string содержит Null, возвращается Null. К нижнему регистру преобразуются только символы верхнего регистра. Остальные символы остаются без изменений. Пример Dim Ustring, Lstring Ustring = "Hello Nike-2" Lstring = LCase (Ustring) ' возвращает "hello nike-2". Left Возвращает значение [тип Variant (String)], содержащее указанное количество символов с левой стороны строки. Синтаксис Left(string, length) Функция Left принимает следующие именованные аргументы: аргумент назначение string Обязательный. Строковое выражение, из которого возвращается указанное количество символов. Если аргумент string содержит Null, возвращается также Null. length Обязательный; тип Variant (Long). Численное выражение, определяющее количество возвращаемых символов строки. Если это значение равно 0, возвращается строка нулевой длины (””). Если аргумент больше или равен длине строки, возвращается вся строка. Примеры Dim StrMY StrMY = Left("Hello World", 2) StrMY = Left("Hello World", 6) StrMY = Left("Hello World", 20) 'возвращает "He" 'возвращает "Hello " 'возвращает "Hello World" Len Возвращает значение (тип Long), содержащее количество символов (длину) строки или число байт, необходимых для сохранения переменной. Синтаксис Len(string | varname) Функция Len принимает следующие аргументы: 800 Приложение Г аргумент назначение string Любое допустимое строковое выражение. Если аргумент содержит Null, функция возвращает Null. varname Любое допустимое имя переменной. Если varname содержит Null, функция возвращает Null. Если varname — Variant, функция Len «рассматривает» его как строку и возвращает число символов в аргументе. Loc Возвращает значение (тип Long), определяющее текущую позицию чтения/за-писи в открытом файле. Синтаксис Loc(filenumber) Обязательный аргумент filenumber — любой допустимый файловый номер (тип Integer). В следующей таблице приведены режимы файлового доступа и соответствующие им возвращаемые значения функции Loc. режим возвращаемое значение Random Номер последней записи, которая считывалась из файла или записывалась в файл. Sequential Текущая байтовая позиция в файле, деленная на число 128. Binary Позиция последнего считанного или записанного байта. Примеры В этом примере открывается текстовый файл и в цикле происходит посимвольное считывание и вывод в окно Immediate считанного символа и номера текущей байтовой позиции в файле. Open "F:\ZZ\WWW.TXT" For Input As #1 Do While Not EOF(l) CharOne = Input(1, #1) MyLocation = Loc(l) Debug.Print CharOne; MyLocation Loop Close #1 'открыть файл 'цикл до конца файла 'считать символ 'текущая позиция 'отобразить в Immediate-окне 'закрыть файл t LOF Возвращает значение (тип Long), представляющее размер (в байтах) файла, открытого с использованием оператора Open. Синтаксис LOF(filenumber) Обязательный аргумент filenumber — число (тип Integer), содержащее допустимый номер файла. В качестве примера см. код для функции Loc. функции в VBA 801 Log Возвращает значение (тип Double), определяющее натуральный логарифм числа. Синтаксис * hog(number) Обязательный аргумент number — число (тип Double) или допустимое численное выражение, большее нуля. Натуральный логарифм — это логарифм с основанием е , где константа е равна примерно 2.718282. LTrim Функция возвращает значение [тип Variant (String)], содержащее копию указанной строки без ведущих (leading) пробелов. Синтаксис LTrim(string) Обязательный аргумент string — любое допустимое строковое выражение. Если аргумент содержит Null, функция возвращает Null. Mid Возвращает значение [тип Variant (String)], содержащее указанное число символов из строки. Синтаксис Mid(string, start], length]) Функция Mid принимает следующие именованные аргументы: аргумент назначение string Обязательный. Строковое выражение (тип String), из которого возвращается определенное число символов. Если аргумент string содержит Null, функция возвращает Null. start Обязательный; тип Long. Символьная позиция в строке string, с которой следует начинать выделение строки. Если значение аргумента start больше длины заданной строки, функция возвращает строку нулевой длины. length Необязательный; тип Variant (Long). Число возвращаемых из строки символов. Если опускается или если символов в строке меньше, чем length, включая символ в позиции start, функция возвращает все символы с позиции start до конца строки. Примеры SFirstWord = Mid("Mid Function Example", 1, 3) ' "Mid" SLastWord = Mid("Mid Function Example", 14 ) ' "Example" SMidWords = Mid("Mid Function Example", 5, 8) ' "Function" 26 Программирование на VBA 2002 802 Приложение Г Minute Функция возвращает [тип Variant (Integer)] целое число от 0 до 59, включительно, которое представляет минуты часа. Синтаксис . Minute(time) Обязательный аргумент time — численное (тип Variant) выражение, строковое выражение или любая комбинация, представляющая время. Если аргумент time содержит Null, функция возвращает Null. Примеры DTime = #4:35:17 PM# DMinute = Minute(DTime) ' возвращаемое значение - 35 , 1 MIRR Возвращает (тип Double) модифицируемую внутреннюю скорость оборота для ряда периодических операций с наличными. Синтаксис MIRR(values(), finance_rate, reinvest_rate) Именованные аргументы функции MIRR: аргумент назначение ualues() Обязательный. Массив (тип Double) со значениями, для которых определяется внутренняя скорость оборота средств. Массив должен содержать, по меньшей мере, одно отрицательное значение (выплата) и одно — положительное (поступление). finance_rate Обязательный. Норма прибыли (тип Double), выплачиваемой за денежные средства, находящиеся в наличном обороте. reinvest_rate Обязательный. Норма прибыли (тип Double), получаемой за денежные средства, находящиеся в наличном обороте при инвестировании. Функция MIRR учитывает как стоимость инвестиций, так и доход от реинвестирования, и использует порядок значений массива для интерпретации порядка денежных выплат или поступлений. Следует внимательно указывать этот порядок. Month Возвращает целое значение [тип Variant (Integer)] в диапазоне от 1 до 12, включительно, представляющее месяц года. Синтаксис Month(date) Обязательный аргумент date — (тип Variant) численное выражение, строковое выражение или любая комбинация, которая представляет дату. Если аргумент date содержит Null, функция возвращает Null. Возвращаемое значение функции зависит от значения свойства Calendar. Функции в VBA 803 Примеры DDateMy = #February 12, 1969# DMonthMy = Month(MyDate) ' возвращает 2 MonthName Возвращает строку, указывающую определенный месяц. Синтаксис MonthName(month[, abbreviate]) Функция MonthName имеет следующие аргументы: аргумент назначение month Обязательный. Числовое представление месяца. Например, Январь (January) — это 1, Февраль (February) — 2 и т.д. abbreviate Необязательный. Тип Boolean. Значение, которое указывает, следует ли использовать сокращение для отображения имени месяца. Если аргумент опущен, то по умолчанию принимается значение False, которое означает, сокращение не используется. MsgBox Отображает сообщение в диалоговом окне, ожидает нажатия на кнопку пользователем и возвращает значение (тип Integer), указывающее, какую кнопку выбрал пользователь. Синтаксис MsgBox(prompt[, buttons] [, title] [, helpfile, context]) Функция MsgBox имеет следующие именованные аргументы: аргумент назначение prompt Обязательный. Строковое выражение, отображаемое в диалоговом окне. Строка может содержать примерно 1024 символа (в зависимости от используемой ширины символов). Если необходимо, чтобы выражение prompt состояло из нескольких строк, можно для разделения строк использовать символы возврата каретки (Chr(13)), перехода на другую строку (Chr(10)) или комбинацию этих символов (Chr(13) & Chr(10)). buttons Необязательный. Числовое выражение, являющееся суммой значений, которые определяют количество и тип кнопок для отображения, используемый значок, кнопку по умолчанию и модальность диалогового окна Если не используется, принимается равным значению 0. title Необязательный. Строковое выражение для заголовка диалогового окна. Если не используется, в заголовке отображается наименование приложения. helpfile Необязательный. Строковое выражение, которое идентифицирует Help-файл для обеспечения контекстно-зависимой помощи. Если этот аргумент используется, context также должен использоваться. context Необязательный. Числовое выражение, указывающее раздел (в справочном файле), относящийся к отображаемому диалоговому окну. 804 Приложение Г Аргумент buttons может принимать следующие значения (константы): константа значение описание vbOKOnly 0 Отображать только кнопку ОК. vbOKCancel 1 Отображать кнопки ОК и Cancel. vbAbortRetrylgnore 2 Отображать кнопки Abort, Retry и Ignore. vbYesNoCancel 3 Отображать кнопки Yes, No и Cancel. vbYesNo 4 Отображать кнопки Yes и No. vbRetryCancel 5 Отображать кнопки Retry и Cancel. vbCritical 16 Отображать значок Critical Message. vbQuestion 32 Отображать значок Warning Query. vbExclamation 48 Отображать значок Warning Message. vblnformation 64 Отображать значок Information Message. vbDefaultButtonl 0 Первая кнопка — кнопка по умолчанию. vbDefaultButton2 256 Вторая кнопка — кнопка по умолчанию. vbDefaultButton3 512 Третья кнопка — кнопка по умолчанию. vbDefaultButton4 768 Четвертая кнопка — кнопка по умолчанию. vbApplicationModal 0 Приложение — модальное; пользователь должен сначала «ответить» на диалоговое окно, прежде чем сможет продолжить работу с текущим приложением. vbSystemModal 4096 Система — модальная; все приложения ожидают «ответа» на диалоговое окно. vbMsgBoxHelpButton 16384 Добавляет кнопку Help к диалоговому окну. VbMsgBoxSet-Foreground 65536 Определяет диалоговое окно как окно переднего плана. vbMsgBoxRight 524288 Текст выравнивается по правой границе. В этой таблице первая группа констант (0-5) описывает типы кнопок, отображаемых в диалоговом окне; следующая группа (16, 32, 48, 64) — стили значков; третья группа (0, 256, 512) определяет кнопку умолчания (кнопка, которая будет «срабатывать» при нажатии на клавишу Enter); четвертая группа (0, 4096) задает модальность диалогового окна. Возвращаемые значения функции MsgBox: константа значение выбранная кнопка vbOK 1 OK vbCancel 2 Cancel vbAbort 3 Abort vbRetry 4 Retry vblgnore 5 Ignore vbYes 6 Yes vbNo 7 No функции в VBA 805 Если используются оба аргумента helpfile и context, для вызова справочного файла, связанного с диалоговым окном MsgBox, достаточно нажать на клавиатуре клавишу F1. Если диалоговое окно содержит кнопку Cancel, то вместо щелчка на этой кнопке можно нажимать на клавишу Esc на клавиатуре. Now Возвращает текущую дату и время [тип Variant (Date)], используя системные дату и время компьютера. Синтаксис Now NPer Возвращает количество (тип Double) периодов выплаты для данного вклада на основе периодических фиксированных выплат и фиксированной процентной ставки. Синтаксис NPer (rate, pint, pv[, fv[, type]]) Функция NPer имеет следующие именованные аргументы: аргумент назначение rate Обязательный. Ставка (тип Double) — процентная ставка за период. Например, если вы получаете заем для покупки автомашины из расчета 10 процентов годовых (APR) и вносите ежемесячные платежи, то ставка за период составит 0.1/12 или 0.0083. pmt Обязательный. Выплата (тип Double), производимая в каждый период. Выплаты обычно состоят из основного платежа и платежа по процентам и не изменяются в течение срока займа. pv Обязательный. Тип Double. Текущее значение или величина сегодня всех будущих платежей или поступлений. Например если вы получаете заем для покупки автомашины, сумма займа является текущим значением для кредитора ежемесячных платежей, которые вы будете вносить. f» Необязательный. Значение типа Variant. Будущее значение или баланс наличности, который необходимо достичь после последнего платежа. Например, будущее значение займа равно $0 поскольку это — его значение после внесения последнего платежа. Однако если вы хотите накопить $50,000 в течение 18 лет на образование вашего ребенка, то $50,000 будет будущим значением. Если аргумент опущен, предполагается равным 0. type Необязательный. Значение типа Variant, обозначающее, когда должна производиться выплата. Используется 0, если срок платежа наступает в конце периода платежа, или 1, если выплата должна производиться в начале периода платежа. Если аргумент опущен, предполагается равным 0. Ежегодные поступления (по займу и т.д., аннуитет) — это ряд фиксированных наличных платежей в течение периода времени. Аннуитет может быть ссудой, та 806 Приложение Г кой как ипотека (home mortgage) или вкладами, такими как план ежемесячной экономии (monthly savings plan). Для всех аргументов наличные выплаты, такие как вклады (deposits to savings) представляются отрицательными числами, наличные поступления, такие как дивиденды (dividend checks) представляются положительными числами. Функция NPV Возвращает значение типа Double, определяющее чистый текущий объем вклада на базе ряда периодических операций с наличностью (платежей и поступлений) и учетной ставки (discount rate). Синтаксис NPV(rate, valuesO) Именованные аргументы функции NPV: аргумент назначение rate Обязательный. Тип Double, определяет учетную ставку за период. valuesO Обязательный. Массив типа Double. Определяет значения операций с наличностью. Массив должен содержать, по меньшей мере, одно отрицательное значение (платеж) и одно положительное значение (поступление). Чистый текущий объем вклада — это текущее значение ряда будущих платежей и поступлений. Функция NPV использует порядок значений в массиве для определения порядка платежей и поступлений. Убедитесь, что значения ваших платежей и поступлений введены в правильной последовательности. Инвестиция, значение которой вычисляет функция NPV, начинается за один период до даты первой наличной операции (денежного взноса) и заканчивается последним значением наличной операции (денежного взноса) в массиве. Вычисление чистого текущего значения вклада основывается на будущих наличных операциях (денежных взносах). Если ваш первый денежный взнос производится в начале первого периода, то первое значение следует добавить к значению, возвращаемому функций NPV, но не включать в список аргументов values(). Функция NPV аналогична функции PV (текущее значение), за исключением того, что функция PV допускает, чтобы денежные взносы производились либо в конце, либо в начале периода. В отличие от переменных значений денежных взносов в функции NPV, значения денежных взносов функции PV должны быть фиксированными в течение всего периода инвестиции. Oct Возвращает значение [тип Variant (String)], являющееся восьмеричным представлением числа.. Синтаксис Oct(number) Обязательный аргумент number — любое допустимое численное или строковое выражение. Если аргумент number не является целым числом, его значение округляется до целого, а затем производится преобразование к восьмеричному представлению. Функции в VBA 807 если number функция Oct возвращает Null Null Empty Нуль (0) Любое другое число Восьмеричные цифры Примеры OctRep = Oct(4) ' 4 OctRep = Oct(9) ' 11 OctRep = Oct(459) ' 713 Partition Возвращает значение [тип Variant (String)], показывающее диапазон (из серии диапазонов), внутри которого находится заданное число. Синтаксис Partition(number, start, stop, interval} Функция Partition принимает следующие именованные аргументы: аргумент назначение number Обязательный. Целое число, которое необходимо оценить относительно диапазонов. start Обязательный. Целое число — начало всего диапазона чисел. Это число не может быть меньше нуля. stop Обязательный. Целое число — конец всего диапазона чисел. Это число не может быть равным или меньшим, чем start. Каждый диапазон создается с использованием аргументов start, stop и interval. Функцию Partition удобно использовать в запросах (queries). Вы можете создать select-запрос, который покажет, как много заказов попадает в различные диапазоны, например, значения заказов от 1 до 1000, от 1001 до 2000 и т.д. Если любой из аргументов функции — Null, функция Partition возвращает Null. Примеры Var = Partition(3, 1, 20, 5) Var = Partition(14, 1, 20, 5) Var = Partition(14, 1, 20, 10) 'возвращает 1:5 'возвращает 11:15 'возвращает 11:20 Pmt Возвращает значение типа Double. Вычисляет величину выплаты по ссуде на основе периодических, фиксированных платежей и фиксированной процентной ставки. Синтаксис ₽mt(rate, nper, pv[, fv[, type]]) Именованные аргументы функции Pmt: 808 Приложение Г аргумент назначение rate Обязательный. Тип Double. Процентная ставка за период. Например, если вы получаете заем на покупку автомашины из расчета 10 процентов годовых (APR) и вносите ежемесячные платежи, ставка за период составляет 0.1/12, или 0.0083. прег Обязательный. Значение типа Integer. Общее число периодов выплат ежегодных поступлений (аннуитет). Например, если вы делаете ежемесячные выплаты по четырехлетнему займу, ваш заем имеет в сумме 4 * 12 (or 48) периодов выплат. pv Обязательный. Тип Double. Текущее значение (или общая сумма), которое составит ряд будущих платежей. Например, если вы берете в долг деньги для покупки автомашины, сумма займа является текущим значением для кредитора выплат, которые вы будете вносить. fv Необязательный. Тип Variant. Будущая сумма или баланс наличности, которого необходимо достичь, после того как вы внесете последний платеж. Например, будущее значение займа равно $0, потому что это его значение после последней выплаты. Однако если вы хотите накопить $50,000 в течение 18 лет на образование вашего ребенка, то будущей суммой является $50,000. Если опущен, то предполагается равным 0. type Необязательный. Тип Variant. Определяет, когда должна производиться выплата. Используется 0, если платеж должен производиться в конце периода, или 1, если платеж должен производиться в начале периода. Если опущен, предполагается равным 0. Ежегодные поступления (annuity) — это ряд фиксированных наличных платежей, производимых в течение периода времени. Аннуитет может быть ссудой, такой как ипотека (home mortgage), или инвестицией, такой как план ежемесячных накоплений (monthly savings plan). Аргументы rate и прег должны вычисляться с использованием периодов выплат, выраженных в одних и тех же единицах. Например, если, rate вычисляется с использованием месяцев, прег также должен вычисляться с использованием месяцев. Для всех аргументов наличные выплаты, такие как депозиты и накопления, представляются отрицательными числами; наличные поступления, такие как дивиденды-чеки (dividend checks), представляются положительными числами. PPmt ’ Возвращает значение типа Double. Величина основного платежа на данный период займа на основе периодических, фиксированных платежей и фиксированной процентной ставки. Синтаксис PPmt(rate, per, прег, pv[, fv[, type]]) Именованные аргументы функции PPmt: Функции в VBA 809 аргумент назначение rate Обязательный. Тип Double. Процентная ставка за период. Например, если вы получаете заем на покупку автомашины из расчета 10 процентов годовых (APR) и вносите ежемесячные платежи, ставка за период равна 0.1/12, или 0.0083. per Обязательный. Тип Integer. Задает период в интервале 1 - прег. прег Обязательный. Тип Integer. Это — общее число периодов выплат годовой ссуды. Например, если вы вносите ежемесячные платежи в счет погашения четырехлетней ссуды на автомашину, ваш заем имеет всего 4 * 12 (или 48) периодов платежей. pv Обязательный. Тип Double. Это — текущее значение или значение сегодня ряда будущих платежей или поступлений. Например, если вы берете заем для покупки автомашины, сумма займа является текущим значением для кредитора. fv Необязательный. Тип Variant. Это — будущая сумма или баланс наличности, которого необходимо достичь после того, как вы внесете последний платеж. Например, будущая сумма ссуды равна $0, таково ее значение после последнего платежа. Однако если вы хотите накопить $50,000 в течение 18 лет на образование вашего ребенка, то будущим значением является $50,000. Если опущен, предполагается равным 0. type Необязательный. Тип Variant, определяет, когда должен производиться платеж. Используется 0, если платеж должен производиться в конце периода, или используется 1, если делать выплату необходимо в начале периода. Если опущен, предполагается равным 0. Ежегодные поступления (annuity) — это ряд фиксированных наличных платежей, производимых в течение периода времени. Аннуитет может быть ссудой, такой как ипотека (home mortgage), или инвестицией, такой как план ежемесячных накоплений (monthly savings plan). Аргументы rate и прег должны вычисляться с использованием периодов выплат, выраженных в одних и тех же единицах. Например, если, rate вычисляется с использованием месяцев, прег также должен вычисляться с использованием месяцев. Для всех аргументов наличные выплаты, такие как депозиты и накопления, представляются отрицательными числами; наличные поступления, такие как дивиденды-чеки (dividend checks), представляются положительными числами. PV Возвращает значение типа Double, определяющее текущий объем вклада (займа) на основе будущих периодических, фиксированных платежей и фиксированной процентной ставки. Синтаксис PV(rate, прег, pmt[, fv[, type]]) Именованные аргументы функции PV: 810 Приложение Г аргумент назначение rate Обязательный. Тип Double. Процентная ставка за период. Например, если вы получаете ссуду на покупку автомашины из расчета 10 процентов годовых (APR) и вносите ежемесячные платежи, то процентная ставка за период равна 0.1/12, или 0.0083. nper Обязательный. Тип Integer. Это — общее число периодов платежей годовой ссуды. Например, если вы вносите ежемесячные платежи в счет погашения четырехлетней ссуды, ваша ссуда имеет всего 4 * 12 (или 48) периодов. pmt Обязательный. Тип Double. Это — платеж, производимый в каждый период. Платежи обычно включают основные платежи и платежи по процентам, которые не изменяются за все время годовых поступлений. । fv Необязательный. Тип Variant, обозначает будущее значение или наличный баланс, которого необходимо достичь после того, как будет внесен последний платеж. Например, будущая стоимость займа равна $0, потому что таково его значение после последней выплаты. Однако если вы хотите накопить $50,000 за 18 лет на образование вашего ребенка, то будущее значение равняется $50,000. Если опущен, предполагается равным 0. type Необязательный. Тип Variant, обозначает, когда должен производиться платеж. Используется 0, если платеж должен производиться в конце периода, или 1, если платеж должен производиться в начале периода. Если опущен, предполагается равным 0. Ежегодные поступления (annuity) — это ряд фиксированных наличных платежей, производимых в течение периода времени. Аннуитет может быть ссудой, такой как ипотека (home mortgage), или инвестицией, такой как план ежемесячных накоплений (monthly savings plan). Аргументы rate и nper должны вычисляться с использованием периодов выплат, выраженных в одних и тех же единицах. Например, если, rate вычисляется с использованием месяцев, nper также должен вычисляться с использованием месяцев. Для всех аргументов наличные выплаты, такие как депозиты и накопления, представляются отрицательными числами; наличные поступления, такие как дивиденды-чеки (dividend checks), представляются положительными числами. QBColor Возвращает значение (тип Long) кода RGB-цвета. Синтаксис QBColor(color) Обязательный аргумент color — целое число в диапазоне 0-15: ЧИСЛО цвет число цвет । 0 Black (черный) 8 Gray (серый) 1 Blue(Голубой) 9 Light Blue (светло голубой) 2 Green (зеленый) 10 Light Green Функции в VBA 811 ЧИСЛО цвет ЧИСЛО цвет 3 Cyan (бирюзовый) 11 Light .Cyan 4 Red (красный) 12 Light Red 5 Magenta (малиновый) 13 Light Magenta 6 Yellow (желтый) 14 Light Yellow 7 White (белый) 15 Bright White Аргумент color представляет значение цвета, используемого ранними версиями системы Basic (такими как Microsoft Visual Basic for MS-DOS и Basic Compiler). Начиная с младшего значащего байта, возвращаемое значение определяет red-, green- и blue-значения, используемые для установки соответствующего цвета в RGB-системе для Visual Basic for Applications. Примеры Sub ChangeBackColor (IntColorCode As Integer, FormMy As Form) FormMy.BackColor = QBColor (IntColorCode) End Sub Процедура в этом примере позволяет менять свойство формы BackColor. Имя формы (как и код цвета) передается как параметр. Rate Возвращает значение типа Double, определяющее процентную ставку за период при выплате годовых поступлений (annuity). Синтаксис Rate(прег, pmt, pv[, fv[, type], guess]]]) Полное описание аргументов прег, pmt, pv, fv и type см. в справке по функции PV. Именованные аргументы функции Rate : аргумент назначение прег Обязательный. Значение типа Double, обозначает общее число периодов выплат годовых поступлений. Например, если вы вносите ежемесячные платежи по четырехлетнему займу на покупку автомашины, то ваш заем имеет всего 4 * 12 (или 48) периодов платежей. pmt Обязательный. Тип Double. Это — платеж, вносимый в каждый период. Платежи обычно состоят из основного платежа и платежа по процентам и не меняются в течение всего периода выплат. pv Обязательный. Тип Double. Это — текущее значение или сумма сегодня ряда будущих платежей или поступлений. Например, когда вы берете заем для покупки автомашины, сумма займа является настоящим значением для кредитора. fv Необязательный. Тип Variant. Это — будущее значение или баланс наличности, которого необходимо достичь после последнего платежа. Например, будущее значение для займа равняется $0. Если аргумент fv опущен, то он предполагается равным 0. 812 Приложение Г аргумент назначение type Необязательный. Тип Variant. Число 0, если платеж должен производиться в конце периода, или 1, если платеж должен производиться в начале периода. Если аргумент опущен, он предполагается равным 0. guess Необязательный. Тип Variant. Это — предполагаемая величина нормы, возвращаемая функцией Rate. Если аргумент guess опущен, то он предполагается равным 0.1 (10 процентам). Ежегодные поступления (annuity) — это ряд фиксированных наличных платежей, производимых в течение периода времени. Аннуитет может быть ссудой, такой как ипотека (home mortgage), или инвестицией, такой как план ежемесячных накоплений (monthly savings plan). Для всех аргументов наличные выплаты, такие как депозиты и накопления, представляются отрицательными числами; наличные поступления, такие как дивиденды-чеки (dividend checks), представляются положительными числами. Rate вычисляется методом последовательного приближения и может не иметь решения или иметь несколько решений. Начиная со значения guess, функция Rate выполняет циклически вычисления до тех пор, пока результат не будет в пределах 0.00001 процента. Если после 20 итераций Rate не может найти результат, функция заканчивается неуспешно. Если ваше значение guess равно 10 процентам и функция Rate заканчивается неуспешно, попробуйте использовать другие значения для guess. Replace Возвращает строку, в которой определенная подстрока заменена на другую подстроку указанное число раз. Синтаксис Replace(expression, find, replace[, start[, count[, compare]]]) Функция Replace принимает следующие именованные аргументы: аргумент назначение expression Обязательный. Строковое выражение, содержащее подстроку для замены. find Обязательный. Подстрока, которую необходимо найти. replace Обязательный. Строка для замены. start Необязательный. Позиция внутри expression, с которой начинается поиск подстроки. Если опускается, используется значение 1. count Необязательный. Необходимое число подстановок подстроки. Если опускается, по умолчанию используется число -1, означающее выполнение всех возможных подстановок. compare Необязательный. Числовое значение, определяющее тип сравнения. См. следующую таблицу. Функции в VBA 813 Аргумент compare может принимать следующие значения: константа значение описание vbUseCompareOption -1 Выполнять сравнение с использованием установки оператора Option Compare. vbBinaryCompare 0 Выполнять двоичное сравнение. vbTextCompare 1 Выполнять текстовое сравнение. vbDatabaseCompare 2 Только для Microsoft Access. Выполнять сравнение, основываясь на информации в некоторой базе данных. Функция Replace возвращает следующие значения: если функция Replace возвращает expression — нулевой длины Строку нулевой длины (""). expression — Null Ошибку. find — нулевой длины Копию строки expression. replace — нулевой длины Копию строки expression со всеми удалениями строки find. start > Len(expression) Строку нулевой длины. count — 0 Копию строки expression. Возвращаемое значение функции Replace — строка с выполненными подстановками. Пример vexpression = "Привет всем, кто добрый, и ничего всем, кто не добрый" vFind = "добрый" vReplace = "хороший" 'замена всех слов "добрый" на слово "хороший": MsgBox Replace(vexpression, vFind, vReplace) vReplace = "" 'удаление всех слов "добрый" MsgBox Replace(vexpression, vFind, vReplace) RGB Возвращает целое число (тип Long), представляющее значение RGB-цвета. Синтаксис RGB(red, green, blue) Функция RGB принимает следующие именованные аргументы: аргумент назначение red Обязательный; тип Variant (Integer). Число в диапазоне 0-255, включительно, которое представляет красную (red) компоненту цвета. green Обязательный; тип Variant (Integer). Число в диапазоне 0-255, включительно, которое представляет зеленую (green) компоненту цвета. 814 Приложение Г аргумент назначение blue Обязательный; Variant (Integer). Число в диапазоне 0-255, включительно, которое представляет голубую (blue) компоненту цвета. Значение RGB-цвета определяет относительную интенсивность красного, зеленого и голубого для получения необходимого цвета, который будет отображаться на экране. Если значение некоторого аргумента функции RGB превышает 255, оно заменяется на значение 255. В следующей таблице приведены стандартные цвета и соответствующие им значения красного, зеленого и голубого цветов. цвет Red-значение Green-значение Blue-значение Black 0 0 0 Blue 0 0 255 Green 0 255 0 Cyan 0 255 255 Red 255 0 0 I Magenta 255 0 255 Yellow 255 255 0 White 255 255 255 Значения RGB-цветов, возвращаемых функцией, совместимы с используемыми в операционной системе Macintosh. Они могут использоваться в контексте Microsoft-приложения для Macintosh, но не могут применяться, когда взаимодействующие цвета меняются непосредственно для операционной системы Macintosh. Right Возвращает строку [тип Variant (String)], содержащую определенное количество символов правой части указанной строки. Синтаксис Right(string, length} Функция Right принимает следующие именованные аргументы: аргумент назначение string Обязательный. Строковое выражение, из правой части которого возвращаются символы. Если string содержит Null, функция возвращает Null. length Обязательный; тип Variant (Long). Численное выражение, указывающее число возвращаемых символов. Если этот аргумент равен значению 0, функция возвращает строку нулевой длины (""). Если length содержит значение, равное или большее, чем длина строки, возвращается вся строка. Для определения длины строки (аргумента string) следует использовать функцию Len. Функции в VBA 815 Примеры В этом примере используется функция Right для возвращения указанного числа символов от правого конца строки. Dim StringAny, StrRez StringAny = "Hello World" StrRez = Right(StringAny, 1) ' возвращает "d" StrRez = Right(StringAny, 6) 'возвращает " World” StrRez = Right(StringAny, 20) 'возвращает "Hello World" Rnd Возвращает значение (тип Single), содержащее случайное число. Синтаксис Rnd[(number) ] Необязательный аргумент (тип Single) number — любое допустимое числовое выражение. Возвращаемые значения функции: если number функция Rnd возвращает меньше нуля Одно и то же число каждый раз, используя number для инициализации генератора случайных чисел. больше нуля Следующее случайное число в последовательности случайных чисел. равно нулю Самое последнее сгенерированное число. । ) не используется Следующее случайное число в последовательности случай- | ных чисел. 1 Функция Rnd возвращает значение, меньшее 1, большее или равное 0. Значение аргумента number определяет способ генерации функцией случайного числа: для любого заданного числа-инициализатора последовательности случайных чисел (seed) генерируется одна и та же последовательность, поскольку каждый последующий вызов функции Rnd использует предыдущее число как инициализатор для генерации следующего случайного числа. Перед вызовом функции Rnd следует использовать оператор Randomize (см. Приложение Д) без аргументов для инициализации генератора случайных чисел, использующего системное время в качестве числа-инициализатора. Иногда бывает необходимо получать последовательность случайных чисел в некотором числовом диапазоне. Для этого можно использовать следующую формулу: Int((upperbound - lowerbound +1) * Rnd + lowerbound) Здесь upperbound — наибольшее число диапазона, lowerbound — наименьшее число диапазона. Примеры Dim MyValue, MyString As String Randomize MyString = "" For I = 0 To 9 MyValue = Int ((6 * Rnd) + 1) MyString = MyString & " " & MyValue Next 816 Приложение Г Приведенный код генерирует строку из случайных чисел в диапазоне от 1 до 6. Результатом работы этого кода могут быть, например, следующие строки: "1526555554 1"; "5613546143" Round Возвращает число, округленное до определенного количества десятичных знаков. Синтаксис Round(expression [,numdecimalplaces]) Функция Round принимает следующие аргументы: аргумент назначение expression Обязательный. Численное выражение, которое округляется. numdecimalplaces Необязательный. Число, указывающее, до скольки десятичных знаков (справа от десятичной точки) следует выполнять округление. Если этот аргумент опускается, функция Round возвращает целое число. Rtrim Функция возвращает значение [тип Variant (String)], содержащее копию указанной строки без конечных (trailing) пробелов. Синтаксис RTrim(string) Обязательный аргумент string — любое допустимое строковое выражение. Если аргумент содержит Null, функция возвращает Null. Second Возвращает значение [тип Variant (Integer)], определяющее целое число между 0 и 59, включительно, представляющее секунды в минуте. Синтаксис ' Second(time) Обязательный аргумент time — любое Variant-, численное, строковое выражение или любая их комбинация, которое представляет время. Если аргумент time содержит Null, функция также возвращает Null. Пример Timel = #3:45:20 PM# MySecond = Second (Timel) 1 переменная получает значение 20 Seek Возращает значение (тип Long), определяющее текущую позицию чтения/за-писи в файле, открытом с использованием оператора Open. Функции в VBA 817 Синтаксис Seek(flienumber) Обязательный аргумент filenumber — допустимый файловый номер (тип Integer). Функция Seek возвращает значения между 1 и 2147483647 (что эквивалентно 231 - 1), включительно. В следующей таблице описаны возвращаемые значения для каждого режима файлового доступа. режим возвращаемое значение Random Номер следующей записи (record) для чтения или записи. Binary, Output, Append, Input Позиция байта, для которой имеет место следующая операция. Первый байт в файле имеет позицию 1, второй байт — позицию 2 и т.д. ___________ Sgn Возвращает значение [тип Variant (Integer)], указывающее знак числа. Синтаксис Sgn(number) Обязательный аргумент number может быть любым допустимым численным выражением. Возвращаемые значения если number функция возвращает больше нуля 1 равно нулю 0 меньше нуля -1 Обратите внимание: знак аргумента определяет знак возвращаемого значения функции. Shell Запускает исполняемую программу и возвращает значение [тип Variant (Double)], представляющее ID-задачи, если запуск выполнен успешно, или нуль — в противном случае. Синтаксис Shell(pathname[,windowstyle]) Функция Shell принимает следующие именованные аргументы: 27 Программирование на VBA 2002 818 Приложение Г аргумент назначение pathname Обязательный; тип Variant (String). Наименование (имя) программы, которую следует запустить, и необходимые аргументы и ключи; можно включать каталог или папку и драйвер диска. На Macintosh можно использовать функцию MacID для определения сигнатуры приложения вместо его имени. Например, так на Macintosh можно с помощью сигнатуры запустить Microsoft Word: Shell MacID(«MSWD») windowstyle Необязательный; тип Variant (Integer); соответствует стилю окна, в котором запускается приложение. Если аргумент windowstyle опускается, программа «стартует» минимизированной (если такое состояние в ней предусмотрено) с фокусом. На Macintosh (System 7.0 и более поздняя) аргумент windowstyle определяет, получает ли запускаемое приложение фокус. Аргумент windowstyle может иметь следующие значения: константа значение описание vbHide 0 Окно скрыто, фокус передается на скрытое окно. На платформе Macintosh эта константа не используется. | vbNormalFocus 1 Окно имеет фокус и восстановлено до оригинальных размеров и положения на экране. vbMinimizedFocus 2 Окно отображается как значок с фокусом. vbMaximizedFocus 3 Окно максимизировано и с фокусом. vbNormalNoFocus 4 Окно восстановлено к его предыдущим размерам и положению на экране. Текущее активное окно остается быть активным. vbMinimizedN oFocus 6 Окно отображается как значок. Текущее активное окно остается быть активным. Если функция Shell успешно запускает исполняемый файл, она возвращает ID запущенной программы — уникальный номер, который идентифицирует выполняемую программу. Если функция Shell не может запустить программу, возникает ошибка. По умолчанию функция Shell запускает другие программы асинхронно. Это означает, что программа, запущенная этой функцией, не должна завершаться перед той, из которой была выполнена функция Shell. Пример Так, например, можно запустить Windows-программу «Лазерный проигрыватель» (переменная ReVai может получить при этом значение, например, -532327): ReVai = Shell("С:\WINDOWS\cdplayer.EXE", vbNormalFocus) Sin Возвращает значение (тип Double) синуса угла (в диапазоне от -1 до 1). Синтаксис Sin(number) : Функции в VBA 819 Обязательный аргумент number — Double- или любое численное выражение, которое представляет значение угла в радианах. SLN Возвращает значение типа Double, обозначающее величину непосредственной амортизации имущества за один период. Синтаксис SLN(cost, salvage, life) Именованные аргументы функции SLN: аргумент назначение cost Обязательный. Тип Double, обозначает начальную стоимость имущества. salvage Обязательный. Тип Double. Это — стоимость имущества в конце периода амортизации. life Обязательный. Тип Double. Это — продолжительность периода использования (амортизации). Замечания Период снижения стоимости (depreciation period ) должен выражаться в одних и тех же единицах, что и аргумент life. Все аргументы должны быть положительными числами. Space Возвращает строку [тип Variant (String)], содержащую указанное количество пробелов. Синтаксис Space(number) Обязательный аргумент number — это необходимое количество пробелов в возвращаемой строке. Функция Space полезна при форматировании выходных данных и очистке строк фиксированной длины. Пример 1 MsgBox = "ПрЮвет"4 Space(5) & "зайцу1" Spc Используется с оператором Print # или методом Print (в окне Immediate) для позиционирования выходных данных. Синтаксис ' Spc(n) Обязательный аргумент п — это количество пробелов для вставки перед следующим отображаемым на экране или печатаемым выражением в списке. 820 Приложение Г Если п меньше, чем ширина выходной строки, информация выводится сразу за указанным количеством пробелов. Если п больше, чем ширина выходной строки, функция Spc вычисляет следующую позицию для печати, используя формулу: текущая_позиция + (п Mod ширина) Например, если текущая позиция для печати — 25, ширина выходной строки длина — 75, и вы определяете Spc(90), выдача данных начнется с позиции (текущая позиция + остаток от 90/75). Если разность между текущей позицией и шириной выходной строки меньше, чем п (или п Mod ширина), функция Spc выполняет переход к началу следующей строки и генерирует число пробелов, равное п - (ширина - текущая_позиция). При использовании метода с пропорциональным шрифтом ширина символов пробела с использованием функции Spc — это всегда среднее значение ширины всех символов для выбранного шрифта. Однако нет никакой связи между числом печатаемых символов и количеством колонок фиксированной ширины, которые эти символы занимают. Например, символ W занимает больше места, чем колонка фиксированной ширины, а символ 1 — меньше. Split Возвращает одномерный массив (индексируемый с нуля), содержащий определенное число подстрок. Синтаксис Split(expression[, delimiter!, limit!, compare]])) Функция Split принимает следующие именованные аргументы: аргумент назначение expression Обязательный. Строковое выражение, содержащее подстроки и ограничители. Если expression — строка нулевой длины (""), функция Split возвращает пустой массив, не содержащий ни элементов, ни данных. delimiter Необязательный. Строковый символ, используемый в качестве разделителя подстрок. Если этот аргумент не указан, в качестве разделителя используется символ пробела. Если delimiter — строка нулевой длины, функция возвращает массив из одного элемента, содержащего всю строку, заданную аргументом expression. limit Необязательный. Число возвращаемых подстрок.; -1 указывает на необходимость вернуть все подстроки. compare Необязательный. Числовое значение, определяющее тип сравнения при оценке подстрок. (См. следующую таблицу.) Аргумент compare может иметь следующие значения: константа значение описание vbUseCompareOption -1 Выполнять сравнение с использованием настройки оператора Option Compare. vbBinaryCompare 0 Выполнять бинарное сравнение. I vbTextCompare 1 Выполнять текстовое сравнение. vbDatabaseCompare 2 Только для Microsoft Access. Выполнять сравнение, основанное на информации базы данных. Функции в VBA 821 Возвращает значение (тип Double), определяющее корень квадратный из числа-аргумента. Синтаксис Sqr(number) Обязательный аргумент number — Double- или любое допустимое числовое выражение, большее или равное нулю. Пример Sqr3 = Sqr(O) 'возвращает О Sqrl = Sqr(9) 'возвращает 3 Sqr2 = Sqr(23) 'возвращает 4.79583152331272 Sqr4 = Sqr(-9) 'генерируется ошибка времени исполнения Str Возвращает строку [тип Variant (String)], представляющую число. Синтаксис Str(number) Обязательный аргумент number — значение (тип Long ), содержащее любое допустимое числовое выражение. При преобразовании числа в строку всегда резервируется ведущий пробел для знака числа. Если number — положительное число, возвращается строка с ведущим пробелом. Для преобразования числовых значений в форматированные строки (в даты, время, валюты и т.д.) следует использовать функцию Format, которая в отличие от Str не включает в строку ведущий пробел для знака числа. Примеры MyString = Str(975) MyString = Str(-449.63) MyString = Str(479.011) 'возвращает строку " 975" 'возвращает строку "-449.63" 'возвращает строку " 479.011" StrComp Возвращает значение [тип Variant (Integer)] с результатом строкового сравнения. Синтаксис , StrComp(stringl, string2[, compare]) Функция StrComp принимает следующие именованные аргументы: аргумент назначение stringl Обязательный. Любое допустимое строковое выражение. string2 Обязательный. Любое допустимое строковое выражение. compare Необязательный. Определяет тип строкового сравнения. Если compare — Null, генерируется ошибка. Если compare не указывается, тип сравнения определяется настройкой оператора Option Compare. 822 Приложение Г Аргумент compare может принимать следующие значения: константа значение описание vbUseCompareOption -1 Выполнять сравнение с использованием настройки оператора Option Compare. vbBinaryCompare 0 Выполнять бинарное сравнение. vbTextCompare 1 Выполнять текстовое сравнение. vbDatabaseCompare 2 Только для Microsoft Access. Выполнять сравнение, основанное на информации базы данных. Возвращаемые значения Функция StrComp возвращает следующие значения: если StrComp возвращает stringl меньше, чем string2 -1 stringl эквивалентна string2 0 stringl больше, чем string2 1 stringl или string2 — Null Null Примеры Dim Strl, Str2, RezComp Strl = "BCDF" Str2 = "bcdf" RezComp = StrComp(Str2, Strl) ' 1 RezComp = StrComp(Strl, Str2, 1) ' 0 RezComp = StrComp(Strl, Str2, 0) ' -1 StrConv Возвращает значение [тип Variant (String)], конвертированное указанным способом. Синтаксис StrConv(string, conversion, LCID) Функция StrConv принимает следующие именованные аргументы: аргумент назначение String Обязательный. Конвертируемое строковое выражение. Conversion Обязательный. Тип Integer. Суммарное значение, определяющее тип преобразования. LCID Необязательный. LocalelD, если отличается от системного LocalelD (по умолчанию). Аргумент conversion может принимать следующие значения: константа значение описание vbUpperCase 1 Конвертировать строку в символы верхнего регистра. Функции в VBA 823 константа значение описание vbLowerCase 2 Конвертировать строку в символы нижнего регистра. vbProperCase 3 Конвертирует первый символ каждого слова строки в символ верхнего регистра. vbUnicode 64 Конвертирует строку в Unicode, используя кодовую страницу системы по умолчанию (Не для Macintosh). vbFrom-Unicode 128 Конвертирует строку из Unicode в кодовую страницу системы по умолчанию (Не для Macintosh). StrReverse Возвращает строку с обратным порядком символов по сравнению с оригинальной строкой. Синтаксис StrReverse(expression) Аргумент expression. — строка, символы которой должны изменить порядок следования. Если expression является строкой нулевой длины («»), функция также возвращает строку нулевой длины. Если expression — Null, возникает ошибка. String Возвращает строку [тип Variant (String)], содержащую определенной длины строку повторяющихся символов. Синтаксис String(number, character) Функция String принимает следующие именованные аргументы: аргумент назначение number Обязательный; тип Long. Длина возвращаемой строки. Если number содержит Null, функция также возвращает Null. character Обязательный; тип Variant. Код символа или строковое выражение, первый символ которого используется для построения возвращаемой строки. Если character содержит Null, функция возвращает Null. Если character содержит код, больший чем 255, функция String предварительно преобразует это значение в следующей формуле: character Mod 256 Примеры Stringl = String (5, "*") ' String2 = String(5, 42) ' String3 = String(10, "BCd")' String4 = String (5, 299) ' возвращает "*****" возвращает возвращает "AAAAAAAAAA" возвращает "+++++" 824 Приложение Г Switch * Оценивает список выражений и возвращает значение (тип Variant) или выражение, связанное с первым выражением в списке, равным значению True. Синтаксис Switch(expr-1, value-l[, expr-2, value-2 [, expr-n,value-n]]) Функция Switch принимает следующие аргументы аргумент назначение ехрг Обязательный. Variant-выражение, которое необходимо оценить. value Обязательный. Значение или выражение, которое возвращается, если соответствующее выражение равно значению True. Список аргументов функции Switch содержит пары выражений и значений. Выражения оцениваются слева направо, и значение, соответствующее первому выражению, которое оценивается как True, возвращается. Функция Switch возвращает Null, если ни одно из выражений не равно значению True или если первое из выражений, равное значению True, имеет соответствующее ему значение Null. SYD Возвращает значение годовой амортизации активов за определенный период. Синтаксис SYD(cost, salvage, life, period} Функция SYD имеет следующие (все обязательные, тип Double) именованные аргументы: аргумент назначение cost Начальная стоимость имущества. salvage Остаточная стоимость имущества в конце периода амортизации (useful life). life Время эксплуатации (период амортизации). period Период, за который вычисляется амортизация. Аргументы life и period должны выражаться в одних и тех же единицах, например, если life задается в месяцах, то и period также должен быть задан в месяцах. Все аргументы должны быть положительными числами. Tab Используется с оператором (statement) Print # или методом Print для позиционирования выходных данных. Синтаксис ’ , ТаЬ[(п)] Функции в VBA 825 Необязательный аргумент п — число колонок, на которые необходимо сместить начало вывода информации на экране или принтере. Если аргумент отсутствует, функция Tab перемещает курсор вставки в начало следующей зоны печати. Это позволяет использовать функцию Tab вместо запятой там, где запятая применяется как десятичный разделитель. Если текущая позиция печати на текущей строке больше, чем п, функция Tab пропускает n-ую колонку на* следующей строке вывода. Если п меньше, чем 1, функция Tab продвигает позицию печати к первой колонке. Если значение аргумента п больше, чем ширина выходной строки, следующая позиция печати вычисляется по формуле: п Mod width Tan Возвращает значение (тип Double) тангенса угла. Синтаксис Tan(number) Обязательный аргумент number — Double- или любое допустимое числовое выражение, которое представляет значение угла в радианах. Примеры Angle = 1.-3 ' значение угла в радианах Cotangent = 1 / Tan(Angle) ' значение котангенса , Time Возвращает значение [тип Variant (Date)] системного времени. Синтаксис Time 1 Пример TimeSystem = Time ' возвращает системное время Timer Возвращает значение (тип Single), представляющее число секунд, прошедших с начала суток. Синтаксис Timer В Microsoft Windows функция Timer возвращает дробные части секунд. TimeSerial Возвращает значение [тип Variant (Date)], содержащее время для указанных часа, минут и секунд. Синтаксис TimeSerial(hour, minute, second) Функция TimeSerial принимает следующие именованные аргументы: 826 Приложение Г аргумент назначение hour Обязательный; тип Variant (Integer). Число между 0 (12:00 А.М.) и 23 (11:00 Р.М.), включительно, или числовое выражение. minute Обязательный; тип Variant (Integer). Любое числовое выражение в диапазоне от 0 до 59, включительно. second Обязательный; тип Variant (Integer). Любое числовое выражение в диапазоне от 0 до 59, включительно. Примеры Timel = TimeSerial(1, 30, 17) 'значение для Timel 10:30:17 TimeValue Возвращает значение [тип Variant (Date)], содержащее время. Синтаксис TimeValue(time) Обязательный аргумент time — это обычно строковое выражение, представляющее время от 0:00:00 (12:00:00 А.М.) до 23:59:59 (11:59:59 Р.М.), включительно. Если time содержит Null, функция возвращает Null. Примеры Msg = "Московское время: " S TimeValue("5:30:17 РМ") В этом примере переменная Msg получает значение ‘Московское время: 17:30:17’. Trim Функция возвращает значение [тип Variant (String)], содержащее копию указанной строки без ведущих и конечных пробелов. Синтаксис Trim(string) Обязательный аргумент string — любое допустимое строковое выражение. Если аргумент содержит Null, функция возвращает Null. TypeName Возвращает Строку (тип String), которая содержит информацию о типе переменной. Синтаксис TypeName(varname) Обязательный аргумент varname — имя переменной. Строка, содержащая возвращаемое функцией TypeName, может иметь следующее значение: возвращаемая строка переменная object type Объект с типом objecttype Byte Байтовое значение Функции в VBA 827 возвращаемая строка переменная Integer Целое Long Длинное целое Single Число с плавающей запятой одинарной точности Double Число с плавающей запятой двойной точности Currency Значение валюты Decimal Десятичное значение Date Значение даты String Строка Boolean Логическое значение Error Значение ошибки Empty Неинициализированная переменная Null Нет допустимых данных Object Объект Unknown Объект с неизвестным типом Nothing Объектная переменная, которая не ссылается на объект Если varname — массив, функция возвращает строку с типом элементов массива и двумя круглыми скобками. Примеры Dim NullVar, VarType Dim StrVar As String Dim IntVar As Integer Dim CurVar As Currency Dim IntArray (1 To 25) As Integer NullVar = Null VarType = TypeName(StrVar) ' возвращает VarType = TypeName(IntVar) ' возвращает VarType = TypeName(CurVar) ' возвращает VarType = TypeName(IntArray) ' возвращает VarType = TypeName(NullVar) 1 возвращает "String" "Integer" "Currency” "Integer()" "Null" UBound Возвращает значение (тип Long), содержащее наибольшее значение индекса для указанной размерности массива. Синтаксис UBound(arrayname[, dimension]) Функция UBound имеет следующие аргументы: аргумент назначение аггаупате Обязательный. Имя переменной-масива. dimension Необязательный; Тип Variant (Long). Целое число, указывающее размерность, для которой определяется верхняя граница индекса. Для первой размерности используется число 1, для второй — 2 и т.д. Если аргумент не указывается, по умолчанию используется значение 1. | 828 Приложение Г Функция UBound обычно используется с функцией LBound для определения размера массива, поскольку LBound позволяет найти наименьшее значение индекса указанной размерности. Примеры Dim IntArray(1 То 12, 5 То 17, 10 To 20) ' Declare array variables Dim DouArray(13) IntUpper = UBound(DouArray) * возвращает 13 IntUpper = UBound(IntArray, 1) ’возвращает 12 IntUpper = UBound(IntArray, 2) ’возвращает 17 UCase Возвращает значение [тип Variant (String)], содержащее заданную строку, символы которой преобразованы к верхнему регистру. Синтаксис UCase(string) Обязательный аргумент string — любое допустимое строковое выражение. Если string содержит Null, функция возвращает Null. Примеры Dim LowerCase, Uppercase StringLowerCase = "Hello World!" 'Следующий оператор возвращает строку 'HELLO WORLD!' StringUpperCase = UCase(StringowerCase) Vai Возвращает число, содержащееся в строке. Синтаксис Vai(string) Обязательный аргумент string — любое допустимое строковое выражение. Функция Vai прекращает чтение строки на первом символе, который не распознается как часть символа. Такие символы, как символ доллара, запятая, не распознаются. Однако функция распознает символы основания системы счисления &0 (для восьмеричной) и &Н (для шестнадцатиричной). Пробелы, знаки табуляции отсекаются. Примеры IntValue = Vai("9459") ' возвращается 9459 IntValue - Val(" 9 45 9") ' возвращается 9459 IntValue = Vai("124 and 537") ' возвращается 24 VarType Возвращает целое, указывающее подтип переменной. Синтаксис VarType (varname) Обязательный аргумент varname — значение (тип Variant), содержащее любую переменную, исключая переменные типов, определенных пользователем. Функции в VBA 829 Возвращаемые значения константа значение описание vbEmpty 0 Empty (не инициализирована) vbNull 1 Null (недопустимые данные) vblnteger 2 Целое vbLong 3 Длинное целое vbSingle 4 С плавающей точкой одинарной точности vbDouble 5 С плавающей точкой двойной точности vbCurrency 6 Значение валюты vbDate 7 Значение даты vbString 8 Строка vbObject 9 Объект vbError 10 Значение ошибки vbBoolean 11 Логическое значение vbVariant 12 Variant (используется только с variant-массивами) vbDataObject 13 Объект для доступа к данным vbDecimal 14 Десятичное значение vbByte 17 Байтовое значение vbUserDefinedType 36 Variant-данные пользовательского типа vbArray 8192 Массив Функция VarType никогда не возвращает значение для vbArray «само по себе». Оно всегда добавляется к некоторому другому значению для указания на массив определенного типа. Константа vbVariant возвращается только в конъюнкции с vbArray для индикации того, что аргумент функции VarType является массивом типа Variant. Примеры IntVar = 159 DateVar = #2/11/73# StrVar = "Random number generator" MyRez = VarType(IntVar) ' возвращает 2 (vblnteger) MyRez = VarType(DateVar) ' возвращает 7 (vbDate) MyRez = VarType(StrVar) ' возвращает 8 (vbString) Weekday Возвращает значение типа Variant (Integer), являющееся частью аргумента (типа Date) и содержащее день недели. Синтаксис Weekday(date, !firstdayofweek]) Функция Weekday принимает следующие именованные аргументы: 830 Приложение Г аргумент назначение date Обязательный. Тип Variant. Численное, строковое выражение или их комбинация, представляющая дату. Если date содержит Null, функция возвращает Null. firstdayofweek Необязательный. Константа, которая задает первый день недели; если не указан, по умолчанию используется vbSunday или vbMonday (в зависимости от национальных настроек). В качестве аргумента firstdayofweek следует использовать следующие константы: константа значение назначение vbUseSystem 0 Использовать настройки NLS API. vbSunday 1 Sunday vbMonday 2 Monday vbTuesday 3 Tuesday vb Wednesday 4 Wednesday vbThursday 5 Thursday vbFriday 6 Friday vbSaturday 7 Saturday Функция Weekday возвращает следующие значения: константа значение назначение vbSunday 1 Sunday vbMonday 2 Monday vbTuesday 3 Tuesday vbWednesday 4 Wednesday vbThursday 5 Thursday vbFriday 6 Friday vbSaturday 7 Saturday Результат функции зависит от значения свойства Calendar. Пример My_Date = #February 13, 1969# My_Week_Day = Weekday(My_Date) ' My_Week_Day содержит 5 WeekdayName Возвращает строку с наименованием дня недели, используя номер дня недели. Синтаксис WeekdayName(weekday, abbreviate, firstdayofweek) Функция WeekdayName-принимает следующие аргументы: Функции в VBA 831 аргумент назначение weekday Обязательный. Числовое обозначение дня недели. Численное значение каждого дня недели зависит от значения firstdayofweek. abbreviate Необязательный. Тип Boolean. Указывает на необходимость использовать сокращенное название дня недели. По умолчанию — False, что означает использовать полное название. firstdayofweek Необязательный. Численное значение, определяющее первый день недели. Аргумент firstdayofweek может принимать следующие значения: константа значение назначение vbUseSystem 0 Использовать национальные языковые [National Language Support (NLS)] API-настройки. vbSunday 1 Sunday (Воскресенье) vbMonday 2 Monday (Понедельник) vbTuesday 3 Tuesday (Вторник) vbWednesday 4 Wednesday (Среда) vbThursday 5 Thursday (Четверг) vbFriday 6 Friday (Пятница) vbSaturday 7 Saturday (Суббота) Пример MsgBox WeekdayName(2) ' в диалоговом окне — "Вторник MsgBox WeekdayName(2, True) ' в диалоговом окне — "Вт" MsgBox WeekdayName(2, True, vbSunday) ' в диалоговом окне — "Пн" Year Возвращает значение типа Variant (Integer), являющееся частью аргумента (типа Date) и содержащее год. Синтаксис Year(date) . Обязательный аргумент date — любое выражение (Variant, численное, строковое или любая комбинация), представляющее дату. Если аргумент If date содержит Null, функция возвратит Null. Результат функции зависит от значения свойства Calendar. Пример Dim My_Date, My_Year My_Date = #February 11, 1960# My_Year = Year(My_Date) ' My_Year содержит 1960 Приложение Д Константы в VBA В этом приложении приведены все константы, которые можете использовать в своих программах. Данная информация предназначена для разработчиков VBA-приложений. Календарные (Calendar) константы Константа Значение Описание vbCalGreg 0 Указывает на использование Григорианского календаря. vbCalHijri 1 Указывает на использование Юлианского календаря. Константы типов вызова (CallType) Константа Значение Описание vbMethod 1 Указывает на используемый метод. vbGet 2 Указывает на процедуру Property Get. vbLet 4 Указывает на процедуру Property Let. vbSet 8 Указывает на процедуру Property Set. Константы цветовые (Color) Константа Значение Описание vbBlack 0x0 Черный (Black) vbRed OxFF Красный (Red) vb Green OxFFOO Зеленый (Green) vbYellow OxFFFF Желтый (Yellow) vbBlue OxFFOOOO Голубой (Blue) vbMagenta OxFFOOFF Малиновый (Magenta) vbCyan OxFFFFOO Бирюзовый (Cyan) vb White OxFFFFFF Белый (White) Константы в VBA 833 Константы типов сравнений (Comparison) Константа Значение Описание vbU seCompareOption -1 Выполняется сравнение, использующее установки оператора Option Compare. vbBinaryCompare 0 Выполняется бинарное сравнение. vbTextCompare 1 Выполняется текстовое сравнение. vbDatabaseCompare 2 Для Microsoft Access: выполняется сравнение, базирующееся на информации из вашей базы данных. Константы компиляции (Compiler) Константа Значение Описание Для 16-битных платформ: winie True Указывает на 16-битную среду разработки. Win32 False Указывает, что среда разработки — не 32-битная. Для 32-битных платформ: Vba6 True Указывает, что среда разработки — Visual Basic for Applications, версия 6.0. Vba6 False Указывает, что среда разработки — не Visual Basic for Applications, версия 6.0. Winl6 False Указывает, что среда разработки — не 16-битная. Win32 True Указывает на 32-битную среду разработки. Mac False Указывает, что среда разработки — не Macintosh. WinlG False Указывает, что среда разработки — не 16-битная. Константы дат (Date) Константа Значение Описание Аргумент firstdayofweek может принимать следующие значения vbUseSystem 0 Использовать настройку NLS API. vbSunday 1 Sunday vbMonday 2 Monday vbTuesday 3 Tuesday vb W ednesday 4 Wednesday vbThursday 5 Thursday vbFriday 6 Friday vbSaturday 7 Saturday 834 Приложение Д Константа Значение Описание Аргумент firstdayofyear может принимать следующие значения vbUseSystem 0 Использовать настройку NLS API. VbUseSystem DayOfWeek 0 Использовать день недели, заданный установками вашей системы для первого дня недели. VbFirstJanl 1 Начинать с той недели, в которой будет первое января (по умолчанию). vbFirstFourDays 2 Начинать с первой недели, которая имеет, по меньшей мере, четыре дня в новом году. 1 vbFirstFull W eek 3 Начинать с первой полной недели года. Возвращаемые значения vbSunday 1 Sunday vbMonday 2 Monday vbTuesday 3 Tuesday vb Wednesday 4 Wednesday vbThursday 5 Thursday vbFriday 6 Friday vbSaturday 7 Saturday Константы формата дат (Date Format) Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. Константа Значение Описание vbGeneralDate • 0 Отображать дату и/или время. Для действительных чисел отображать дату и время. Если дробная часть отсутствует, отображать только дату. Если отсутствует целая часть, отображать только время. Вид отображения даты и времени определяется настройками компьютерной системы. vbLongDate 1 Отображать дату с использованием «длинного» (long) формата, определенного региональными установками компьютерной системы. vbShortDate 2 Отображать дату с использованием «короткого» (short) формата, определенного региональными установками компьютерной системы. vbLongTime 3 Отображать время с использованием «длинного» (long) формата, определенного региональными установками компьютерной системы. vbShortTime 4 Отображать время с использованием «короткого» (short) формата, определенного региональными установками компьютерной системы. Константы в VBA 835 Константы функций Dir, GetAttr и SetAttr Константа Значение Описание vbNormal 0 Обычный (Normal) (по умолчанию для Dir и SetAttr], vbReadOnly 1 Только на чтение (Read-only). vbHidden 2 Скрытый (Hidden). vbSystem 4 Системный файл (System file). vb Volume 8 Метка тома (Volume label). vbDirectory 16 Каталог или папка. vbArchive 32 Файл изменен после последнего резервирования. vbAlias 64 Алиасное имя (на Macintosh). Для Macintosh доступны только VbNormal, vbReadOnly, vbHidden и vbAlias. Константы типов драйверов (DriveType) Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. Константа Значение Описание Unknown 0 Тип драйвера не может быть определен. Removable 1 Устройство со съемным носителем. Включает все флоппи-драйверы и много других разновидностей устройств хранения данных. Fixed 2 Устройство с несъемным носителем. Включает все «жесткие» диски. Remote 3 Сетевые драйверы. CDROM 4 CD-ROM. Не различаются read-only и read/write. RAMDisk 5 Драйвер — блок Random Access Memory (RAM) на локальном компьютере. По своему «поведению» подобен дисковому драйверу. Константы атрибутов файлов (File Attribute) Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. Константа Значение Описание Normal 0 Обычный файл Readonly 1 Файл только для чтения Hidden 2 Скрытый файл System 4 Системный файл Volume 8 Метка тома дискового драйвера 836 Приложение Д Константа Значение Описание Directory 16 Папка или каталог Archive 32 Файл изменился, после последней архивации Alias 64 Ссылка или ярлык Compressed 128 Упакованный файл Константы файлового ввода/вывода (File Input/Output) Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. Константа Значение Описание ForReading 1 Файл открывается только для чтения. Запись в этот файл невозможна. For Writing 2 Файл открывается для записи. Если файл с таким именем уже существует, предыдущее его содержимое теряется. ForAppending 8 Файл открывается для дозаписи (в конец файла). Константы форм (Form) Константа Значение Описание vbModeless 0 UserForm — немодальная vbModal 1 UserForm — модальная (modal) Константы Dir, GetAttr и SetAttr Константа Значение Описание vbNormal 0 Обычный (Normal) vbReadOnly 1 Только на чтение (Read-only) vbHidden 2 Скрытый (Hidden) vbSystem 4 Системный файл (System file) vbVolume 8 Метка тома (Volume label) vbDirectory 16 Каталог или папка (Directory or folder) vb Archive 32 Файл изменился, после последней архивации (File has changed since last backup) vbAlias 64 Ha Macintosh (идентифицирует алиас) Константы VbNormal, vbReadOnly, vbHidden и vbAlias доступны только при работе в системе Macintosh. Константы в VBA 837 Константы ключевых кодов (Keycode) Константа Значение Описание vbKeyLButton 0x1 Левая кнопка мыши (Left mouse button) vbKeyRButton 0x2 Правая кнопка мыши (Right mouse button) vbKeyCancel 0x3 Клавиша CANCEL (CANCEL key) vbKeyMButton 0x4 Средняя кнопка мыши (Middle mouse button) vbKeyBack 0x8 Клавиша BACKSPACE (BACKSPACE key) vbKeyTab 0x9 Клавиша TAB (TAB key) vbKeyClear OxC Клавиша CLEAR (CLEAR key) vbKeyReturn OxD Клавиша ENTER (ENTER key) vbKeyShift 0x10 Клавиша SHIFT (key) vbKeyControl 0x11 Клавиша CTRL (CTRL key) vbKeyMenu 0x12 Клавиша MENU (MENU key) vbKeyPause 0x13 Клавиша PAUSE (PAUSE key) 1 vbKeyCapital 0x14 Клавиша CAPS LOCK (CAPS LOCK key) 1 vbKeyEscape OxlB Клавиша ESC (ESC key) vbKeySpace 0x20 Клавиша SPACEBAR (SPACEBAR key) vbKeyPageUp 0x21 Клавиша PAGE UP (PAGE UP key) vb KeyPageDown 0x22 Клавиша PAGE DOWN (PAGE DOWN key) j vbKeyEnd 0x23 Клавиша END (END key) | vbKeyHome 0x24 Клавиша HOME (HOME key) vbKeyLeft 0x25 Клавиша LEFT ARROW (LEFT ARROW key) vbKeyUp 0x26 Клавиша UP ARROW (UP ARROW key) vbKeyRight 0x27 Клавиша RIGHT ARROW (RIGHT ARROW key) vbKeyDown 0x28 Клавиша DOWN ARROW (DOWN ARROW key) vbKeySelect 0x29 Клавиша SELECT (SELECT key) vbKeyPrint 0x2A Клавиша PRINT SCREEN (PRINT SCREEN key) vbKeyExecute 0x2B Клавиша EXECUTE (EXECUTE key) vbKeySnapshot 0x2C Клавиша SNAPSHOT (SNAPSHOT key) vbKeylnsert 0x2D Клавиша INSERT (INSERT key) vbKeyDelete 0x2E Клавиша DELETE (DELETE key) | vbKeyHelp 0x2F Клавиша HELP (HELP key) | vbKeyNumlock 0x90 Клавиша NUM LOCK (NUM LOCK key) 838 Приложение Д Клавиши от А до Z имеют следующие константы и ASCII-значения: Константа Значение Клавиша Константа Значение Клавиша vbKeyA 65 A vbKeyM 77 M vbKeyB 66 В vbKeyN 78 N vbKeyC 67 С vbKeyO 79 О vbKeyD 68 D vbKeyP 80 P vbKeyE 69 E vbKeyQ 81 Q vbKeyF 70 F vbKeyR 82 R vbKeyG 71 G vbKeyS 83 S vbKeyH 72 H vbKeyT 84 T vbKeyl 73 I vbKeyU 85 и vbKeyJ 74 J vbKeyV 86 V vbKeyK 75 К vbKeyW 87 w vbKeyL 76 L vbKeyX 88 X Клавиши от 0 до 9 имеют следующие константы и ASCII-значения: Константа Значение Клавиша vbKeyO 48 0 vbKeyl 49 1 vbKey2 50 2 vbKey3 51 3 vbKey4 52 4 vbKey5 53 5 vbKey6 54 6 vbKey7 55 7 vbKey8 56 8 vbKey9 57 9 Константы, соответствующие клавишам на числовом поле клавиатуры: Константа Значение Клавиша vbKeyNumpadO 0x60 0 vbKeyN umpadl 0x61 1 vbKeyNumpad2 0x62 2 vbKeyN umpad3 0x63 3 vbKeyNumpad4 0x64 4 vbKeyN umpad5 0x65 5 vbKeyN umpad6 0x66 6 Константы в VBA 839 Константа Значение Клавиша vbKeyNumpad7 0x67 7 vbKeyNumpad8 0x68 8 vbKeyNumpad9 0x69 9 vbKeyMultiply 0x6A MULTIPLICATION SIGN (*) vbKeyAdd 0x6B PLUS SIGN (+) vbKeySeparator 0x6C ENTER vbKeySubtract 0x6D MINUS SIGN (-) vbKeyDecimal 0x6E DECIMAL POINT (.) vbKeyDivide 0x6F DIVISION SIGN (/) Константы для представления функциональных клавиш: Константа Значение Клавиша Константа Значение Клавиша vbKeyFl 0x70 Fl vbKeyF9 0x78 F9 vbKeyF2 0x71 F2 vbKeyFlO 0x79 F10 vbKeyF3 0x72 F3 vbKeyFll 0x7A Fll vbKeyF4 0x73 F4 vbKeyF12 0x7B F12 vbKeyF5 0x74 F5 vbKeyF13 0x7C F13 vbKeyF6 0x75 F6 vbKeyF14 0x7D F14 vbKeyF7 0x76 F7 vbKeyF15 0x7E F15 vbKeyF8 0x77 F8 vbKeyF16 0x7F F16 Смешанные константы (Miscellaneous Constants) Константа Значение Описание vbCrLf Chr(13) + Chr(10) Комбинация символов «возврат карет -ки-перевод строки» (Carriage return-linefeed combination). vbCr Chr(13) Символ «возврата каретки» (Carriage return character). vbLf Chr(10) Символ «перевода строки» (Linefeed character). vbNewLine Chr(13) + Chr(10) или Chr(13) на Macintosh Зависящий от «платформы» символ «новой строки». vbNullChar Chr(0) Символ нулевого значения (Character having value 0). vbNullString Строка, имеющая нулевое значение (String having value 0) Не то же самое, что строка нулевой длины (""); используется при вызове внешних процедур. 840 Приложение Д Константа Значение Описание vbObjectError -2147221504 Определяемые пользователем error-числа должны быть больше этого значения. Например: Err.Raise Number = vbObjectError + 1000 vbTab Chr(9) Символ табуляции (Tab character). vbBack Chr(8) Backspace-символ (Backspace character). Константы функции MsgBox Аргументы-константы функции MsgBox Константа Значение Описание vbOKOnly 0 Вывод только кнопки ОК (по умолчанию). vbOKCancel 1 Вывод кнопок ОК и Cancel. vbAbortRetrylgnore 2 Вывод кнопок Abort, Retry и Ignore. vbYesNoCancel 3 Вывод кнопок Yes, No и Cancel. vbYesNo 4 Вывод кнопок Yes и No. vbRetryCancel 5 Вывод кнопок Retry и Cancel. vbCritical 16 Critical-сообщение. vbQuestion 32 Warning-запрос. vbExclamation 48 W arning-сообщение. vblnformation 64 Information-сообщение. vbDefaultButtonl 0 Кнопка по умолчанию — первая (по умолчанию). vbDefaultButton2 256 Кнопка по умолчанию — вторая. vbDefaultButton3 512 Кнопка по умолчанию — третья. vbDefaultButton4 768 Кнопка по умолчанию — четвертая. vbApplicationModal 0 Модальное окно сообщения приложения (по умолчанию) (Application modal message box). vbSystemModal 4096 Модальное окно сообщения системы (System modal message box). vbMsgBoxHelpButton 16384 Добавляет кнопку Help к окну сообщения. VbMsgBoxSet-Foreground 65536 Определяет окно сообщения как фоновое (Specifies the message box window as the foreground window). vbMsgBoxRight 524288 Текст выравнивать по правой границе. vbMsgBoxRtlReading 1048576 Определяет, что должен появляться справа-налево, как в Hebrew- и Arabic-системе. Константы в VBA 841 Возвращаемые значения функции MsgBox Константа Значение Выбрана кнопка vbOK 1 OK vbCancel 2 . Cancel vbAbort 3 Abort vbRetry 4 Retry vblgnore 5 Ignore vbYes 6 Yes vbNo 7 No QueryClose-константы Константа Значение Описание vbFormControlMenu 0 Пользователь выбирает команду Close из меню Control на форме. vbFormCode 1 Оператор Unload вызывается из кода. vbApp Windows 2 Текущий сеанс Microsoft Windows заканчивается. vbAppTaskManager 3 Windows Task Manager закрывает приложение. Константы Shell Константа Значение Описание vbHide 0 Окно становится скрытым, фокус устанавливается на скрытое окно. vbN ormalFocus 1 Окно принимает фокус и восстанавливается до оригинальных размеров и положения на экране. vbMinimizedFocus 2 Окно отображается как значок с фокусом. vbMaximizedFocus 3 Окно «максимизируется» с фокусом. vbNormalNoFocus 4 Окно восстанавливается до его последних размеров и положения на экране. Текущее активное окно остается активным. vbMinimizedN oFocus 6 Окно отображается как значок. Текущее активное окно остается активным. Константы специальных папок (SpecialFolder) Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. 842 Приложение Д Константа Значение Описание WindowsFolder 0 Папка Windows содержит файлы, установленные операционной системой Windows. SystemFolder 1 Папка System содержит библиотеки, шрифты и драйверы устройств. TemporaryFolder 2 Папка Тетр используется для хранения временных файлов. Путь (path) к ней находится в переменной среды ТМР. Константы преобразования строк (StrConv) Константа Значение Описание vbUpperCase 1 Конвертирует строку в символы верхнего регистра. vbLowerCase 2 Конвертирует строку в символы нижнего регистра. vbProperCase 3 Конветрирует первый символ каждого слова в строке в верхний регистр. vbUnicode 64 Конвертирует строку в Unicode, используя кодовую страницу системы по умолчанию (Не для Macintosh). vbFromUnicode 128 Конвертирует строку из Unicode в кодовую страницу системы по умолчанию (Не для Macintosh). Константы системных цветов (System Color) Константа Значение Описание vbScrollBars 0x80000000 Цвет линейки прокрутки vbDesktop 0x80000001 Цвет элемента Desktop vbActiveTitleBar 0x80000002 Цвет строки заголовка активного окна ! vblnactiveTitleBar 0x80000003 Цвет строки заголовка неактивного окна vbMenuBar 0x80000004 Цвет фона меню vbWindow- Background 0x80000005 Цвет фона окна (Window) vbWindowFrame 0x80000006 Цвет рамки окна (Window frame color) 1 vbMenuText 0x80000007 Цвет текста меню (Color of text on menus) vbWindowText 0x80000008 Цвет текста в окнах (Color of text in windows) vbTitleBarText 0x80000009 Цвет текста в заголовке (caption) vbActiveBorder 0x8000000A Цвет границы активного окна (Border color of active window) Константы в VBA 843 Константа Значение Описание vblnactiveBorder 0x8000000В Цвет границы неактивного окна (Border color of inactive window) vbApplication-Workspace 0x8000000C Цвет фона приложений с многодокументным интерфейсом [Background color of multiple-document interface (MDI) applications] vbHighlight 0x8000000D Цвет фона выделенных частей элемента управления (Background color of items selected in a control) vbHighlightText 0x8000000E Цвет текста выделенных частей элемента управления (Text color of items selected in a control) vbButtonFace 0x8000000F Цвет затенения командной кнопки (Color of shading on the face of command buttons) vbButton Shadow 0x80000010 Цвет затенения на контуре командной кнопки (Color of shading on the edge of command buttons) vbGrayText 0x80000011 Текст на элементе, недоступном для выбора vbButtonText 0x80000012 Цвет текста на «нажатой»кнопке (Text color on push buttons) vblnactiveCaption-Text 0x80000013 Цвет текста неактивного заголовка (Color of text in an inactive caption) vb3DHighlight 0x80000014 Цвет выделения для трехмерных элементов (Highlight color for 3-D display elements) vb3DDKShadow 0x80000015 Самый темный цвет тени для трехмерных элементов (Darkest shadow color for 3-D display elements) vb3DLight 0x80000016 Второй по яркости после vb3DHighlight цвет для трехмерных элементов (Second lightest 3-D color after vb3Dhighlight) vblnfoText 0x80000017 Цвет текста для элемента ToolTip vblnfoBackground 0x80000018 Цвет фона для элемента ToolTip Tristate-константы Эти константы доступны только в том случае, когда ваш проект имеет явную ссылку на соответствующую библиотеку, в которой константы определены. Константа Значение Описание vbTrue -1 True vbFalse 0 False vbUseDefault -2 Использовать установку по умолчанию 844 Приложение Д VarType-константы Константа Значение Описание vbEmpty 0 He инициализирована (по умолчанию) vbNull 1 Содержит недопустимые данные vblnteger 2 Целое (Integer) vbLong 3 Длинное целое (Long integer) vbSingle 4 Число с плавающей запятой одинарной точности (Single-precision floating-point number) vbDouble 5 Число с плавающей запятой двойной точности (Double-precision floating-point number) vbCurrency 6 Currency vbDate 7 Date vbString 8 String vbObject 9 Object vbError 10 Error vbBoolean 11 Boolean vbVariant 12 Variant (используется только для Variant-массивов) vbDataObject 13 Объект для доступа к данным (Data access object) vbDecimal 14 Decimal vbByte 17 Byte vbUserDefinedType 36 Данные пользовательских типов vbArray 8192 Array Приложение I События объектов UserForm Для всех синтаксических выражений object - допустимый объект, объектное выражение, которое вычисляется до объекта (ссылки на объект). Activate Инициируется всякий раз, когда окно формы становится активным. Синтаксис Private Sub object Activate() Пример Следующий код использует две формы UserForm: UserForml и UserForm2. Скопируйте эти две процедуры в модуль UserForml, затем добавьте UserForm2. Заголовок UserForml создается в процедуре события Activate. Когда пользователь щелкает мышью на клиентской области UserForml, UserForm2 загружается и отображается, запуская событие Deactivate формы UserForml, изменяющее заголовки форм. ' Событие Activate для UserForml Private Sub UserForm_Activate() UserForml.Caption = "Щелкните на мне" End Sub ' Событие Click для UserForml Private Sub UserForm_Click() Load UserForm2 UserForm2.Startupposition = 3 UserForm2.Show End Sub ' Событие Deactivate для UserForml > . ( J Private Sub UserForm_Deactivate() UserForml.Caption = "Я потеряла фокус1" UserForm2.Caption = "Фокус перешел от UserForml ко мне " End Sub Для всех примеров достаточно создать форму(ы), поместить на нее указанные эле менты управления и скопировать приведенный код в модуль формы Initialize Инициируется всякий раз, когда форма впервые загружается в память оператором Load или методом Show. Синтаксис Private Sub object lnitialize() Пример Следующий пример предполагает наличие двух UserForm в программе. В событии Initialize формы UserForml загружается и отображается форма UserForm2. Когда пользователь щелкает мышью на UserForm2, она скрывается и отображается UserForml. При щелчке на UserForml форма UserForm2 отображается снова. 846 Приложение Е ' Это процедура события Initialize для UserForml Private Sub UserForm_Initialize() Load UserForm2 UserForm2.Show End Sub ' Это событие Click формы UserForm2 Private Sub UserForm_Click() UserForm2.Hide End Sub ' Это событие click для UserForml Private Sub UserForm_Click() UserForm2.Show ' End Sub QueryClose Инициируется перед тем, как UserForm закрывается. Синтаксис Private Sub UserForm_QueryClose(cancel As Integer, closemode As Integer) Параметры cancel Целое. Задание этому аргументу любого значения, отличного от 0, устанавливает событие QueryClose во всех загружаемых пользовательских формах и предотвращает закрытие UserForm и приложения. closemode Значение или константа, обозначающая причину события QueryClose. Возвращаемые значения Аргумент closemode возвращает следующие значения: Константа Значение Описание vbFormControlMenu 0 Пользователь выбрал команду Close из меню Control в UserForm. VbFormCode 1 Оператор Unload вызывается из кода. vbApp Windows 2 Текущая сессия рабочей среды Windows заканчивается. vbAppTaskManager 3 Windows Task Manager закрывает приложение. Пример Следующий код вынуждает пользователя щелнуть мышью на клиентской области UserForm для ее закрытия. Если пользователь пытается использовать кнопку закрытия окна в строке заголовка, параметр Cancel устанавливается в ненулевое значение, предотвращая завершение программы. Однако если пользователь щелкнул мышью на форме, closemode имеет значение 1 и оператор Unload Me завершает работу приложения. Private Sub UserForm__Activate () UserForml.Caption - "Вы должны щелкнуть на мне, чтобы закрыть меня!" End Sub События объектов UserForm 847 Private Sub UserForm_Click() Unload Me End Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) ' Предотвратить закрытие с помощью Close box в строке заголовка. If CloseMode 1 Then_Cancel = 1 UserForml.Caption = " Close box не работает! Щелкните на мне!" End Sub Resize Инициируется при изменении размеров формы. Синтаксис Private Sub UserForm_Resize() Пример Следующий пример использует события Activate и Click для иллюстрации запуска события Resize формы (UserForm). Когда пользователь щелкает мышью на клиентской области формы, она расширяется или сжимается и в строке заголовка сообщается о новой высоте. Заметьте, что переменная Tag используется для сохранения первоначальной высоты UserForm. ' Событие Activate для UserForml Private Sub UserForm_Activate() UserForml.Caption = "Щелкните на мне для увеличения моей высоты!" Tag = Height ' Сохранить первоначальную высоту. End Sub ' Событие Click для UserForml Private Sub UserForm_Click() Dim NewHeight As Single NewHeight = Height ' Если форма маленькая, увеличить высоту. If NewHeight = Vai(Tag) Then , Height = Vai(Tag) * 2 Else ' Если форма большая, уменьшить ее. Height = Vai(Tag) End If End Sub ' Событие Resize для UserForml Private Sub UserFormResize() UserForml.Caption - "Новая высота: " & Высота & " " & _ "Щелкните, чтобы изменить мой размер!" End Sub Terminate Инициируется всякий раз, когда форма выгружается из памяти. Синтаксис Private Sub object_Terminate( ) Пример Следующие событийные процедуры приводят к тому, что код модуля формы издает звуковой сигнал в течение нескольких секунд после того, как пользователь щелкает на клиентской области, чтобы отменить форму. 848 Приложение Е Private Sub UserForm_Activate() UserForml.Caption = "Щелкните на мне для окончания работы!" End Sub Private Sub UserForm_Click() Unload Me End Sub • , Private Sub UserForm_Terminate() Dim Count As Integer For Count = 1 To 100 Beep Next End Sub События объектов управления AddControl Инициируется всякий раз, когда к форме или элементам Frame, MultiPage (Page) добавляется какой-либо элемент управления. Синтаксис Для элемента Frame: Private Sub obgect_AddControl() Для элемента MultiPage: Private Sub objectAddControl(index As Lpng, Ctrl As Control) Параметры (обязательные): index Индекс страницы (Page), которая будет содержать новый элемент управления. Ctrl Элемент управления, который необходимо добавить. ] Пример Следующий пример использует метод Add для добавления элемента управления в форму во время выполнения приложения и использует событие AddControl в качестве подтверждения того, что элемент управления был добавлен. Для того чтобы использовать этот пример кода, скопируйте код в часть Declarations (объявлений) формы. Поместите на форму CommandButton с именем CommandButtonl. Dim Mycmd as Control Private Sub CommandButtonl Click () ' Set Mycmd = Controls.Av ("MSForms.CommandButton.1", _ CommandButcon2, Visible) Mycmd.Left = 18 Mycmd.Top =150 Mycmd.Width - 175 Mycmd Height = 20 Mycmd.Caption = "Это забавно. " & Mycmd.Name End Sub Private Sub UserForm_AddControl(ByVai Control As MSForms.Control) UserForml.Caption = "Элемент управления был добавлен." End Sub События объектов UserForm 849 AfterUpdate Инициируется после обновления значения элемента управления. Синтаксис Private Sub object_AfterUpdate() Пример В этом примере форма пользователя должна содержать элемент Checkbox с именем CheckBoxl. Тогда следующая событийная процедура после каждого изменения установки флажка будет выдавать звуковое и текстовое сообщение об этом. Private Sub CheckBoxlAfterUpdate() Beep MsgBox ("Установка флажка изменилась") End Sub BeforeDragOver Инициируется при выполнении операции drag-and-drop. Синтаксис Для элементов Frame: Private Sub оЪject_BeforeDragOver( ByVai Cancel As MSForms.ReturnBoolean, Ctrl As Control, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai DragState As fmDragState, ByVai Effect As MSForms.ReturnEffect, ByVai Shift As fmShiftState) Для элементов MultiPage: Private Sub object_BeforeDragOver( index As Long, ByVai Cancel As MSForms.ReturnBoolean, Ctrl As Control, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai DragState As fmDragState, ByVai Effect As MSForms.ReturnEffect, ByVai Shift As fmShiftState) Для элементов TabStrip: Private Sub object_BeforeDragOver( index As Long, ByVai Cancel As MSForms.ReturnBoolean, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai DragState As fmDragState, ByVai Effect As MSForms.ReturnEffect, ByVai Shift As fmShiftState) Для других элементов управления: Private Sub object_BeforeDragOver( ByVai Cancel As MSForms.ReturnBoolean, ByVai Data As DataObject, ByVai X As Single, ByVai У As Single, ByVai DragState As fmDragState, ByVai Effect As MSForms.ReturnEffect, ByVai Shift As fmShiftState) Параметры (все обязательные): index Индекс страницы (Page) (в MultiPage), для которой имеет место операция drag-and-drop. Cancel Статус (status) события. False указывает, что элемент управления должен обрабатывать событие (по умолчанию). True указывает, что событие обрабатывается приложением. Ctrl Элемент-приемник. Data Данные, перетаскиваемые в операции drag-and-drop. Данные упаковываются в DataObject. X, Y Горизонтальная и вертикальная координаты (в пойнтах) положения левого (координата X) верхнего (координата Y) угла элемента управления. 2ft Ппогоаммиоование на VBA 2002 850 Приложение Е DragState Состояние перемещения данных. Effect Операции, поддерживаемые перемещаемым объектом. Shift Определяет состояние клавиш SHIFT, CTRL и ALT. Установки для DragState'. Константа Значение Описание fmDragStateEnter 0 Указатель мыши находится внутри области приемника. fmD rag St at eLeave 1 Указатель мыши находится вне области приемника. fmDragStateOver 2 Указатель мыши находится в новой позиции, но остается внутри области того же приемника. Установки для Effect'. Константа Значение Описание fmDropEffectNone 0 He копирует или передвигает перемещаемый объект на объект-приемник. fmDropE ffec tCopy 1 Копирует перемещаемый объект на объект-приемник. fmDropEffectMove 2 Перемещает объект на объект-приемник. fmDropEffectCopyOrMove 3 Копирует или перемещает объект на объект-приемник. Установки для Shift'. Константа Значение Описание fmShiftMask 1 SHIFT была нажата. fmCtrlMask 2 CTRL была нажата. fmAltMask 4 ALT была нажата. Используйте это событие для контроля за тем, когда указатель (курсор) мыши входит, покидает или остается на доступном элементе-приемнике. При выполнении операции drag-and-drop система инициализирует это событие, кода пользователь перемещает мышь, нажимает или отпускает кнопку(и) мыши. Положение указателя мыши определяет объект-приемник, который принимает это событие. Состояние указателя мыши можно определить посредством аргумента DragState. Если элемент управления обрабатывает это событие, вы можете использовать аргумент Effect, чтобы указать drag-and-drop-действие для выполнения. Если Effect установлен в fmDropEffectCopyOrMove, перемещаемый объект (drop source) поддерживает операцию копирования (fmDropEffectCopy), перемещения (fmDrop-EffectMove) или отмены (fmDropEffectNone). Если Effect установлен в fmDropEffectCopy, перемещаемый объект поддерживает операцию копирования или отмены (fmDropEffectNone). Если Effect установлен в fmDropEffectMove, перемещаемый объект поддерживает операцию перемещения или отмены (fmDropEffectNone). Если Effect установлен в fmDropEffectNone, перемещаемый объект поддерживает операцию отмены. События объектов UserForm 851 BeforeDropOrPaste Инициируется, когда пользователь «бросает» или вставляет данные в объект. Синтаксис Для элементов Frame: Private Sub object_BeforeDropOrPaste( ByVai Cancel As MSForms.ReturnBoolean, Ctrl As Control, ByVai Action As fmAction, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai Effect As MSForms.ReturnEffeet, ByVai Shift As fmShiftState) Для элементов MultiPage: Private Sub object_BeforeDropOrPaste( index As Long, ByVai Cancel As MSForms.ReturnBoolean, Ctrl As Control, ByVai Action As fmAction, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai Effect As MSForms.ReturnEffeet, ByVai Shift As fmShiftState) Для элементов TabStrip: Private Sub object_BeforeDropOrPaste( index As Long, ByVai Cancel As MSForms.ReturnBoolean, ByVai Action As fmAction, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai Effect As MSForms.ReturnEffeet, ByVai Shift As fmShiftState) Для других элементов управления: Private Sub object_BeforeDropOrPaste( ByVai Cancel As MSForms.ReturnBoolean, ByVai Action As fmAction, ByVai Data As DataObject, ByVai X As Single, ByVai Y As Single, ByVai Effect As MSForms.ReturnEffeet, ByVai Shift As fmShiftState) Параметры (все обязательные): index Индекс страницы (Page) (в MultiPage), для которой имеет место операция drag-and-drop. Cancel Статус (status) события. False указывает, что элемент управления должен обрабатывать событие (по умолчанию). True указывает, что событие обрабатывается приложением. Ctrl Элемент-приемник Action Указывает результат, основанный на текущих настройках клавиатуры во время операции drag-and-drop. Data Данные, перетаскиваемые в операции drag-and-drop. Данные упаковываются в DataObject. X, Y Горизонтальная и вертикальная координаты (в пойнтах) положения левого (координата X) верхнего (координата Y) угла указателя мыши при «бросании». Effect Воздействие операции drag-and-drop на элемент-приемник. Shift Определяет состояние клавиш SHIFT, CTRL и ALT. Установки для Action: Константа Значение Описание fmActionPaste 2 Вставляет выделенный элемент в элемент-приемник. I fmActionDrag-Drop 3 Указывает, что пользователь перетащил объект из источника и «бросил» его на объект-приемник. 852 Приложение Е Установки для Effect-. Константа Значение Описание fmDropEffectNone 0 He копирует или передвигает перемещаемый объект на объект-приемник fmD ropE ff ectCopy 1 Копирует перемещаемый объект на объект-приемник. fmDropEffectMove 2 Перемещает объект на объект-приемник. fmDropEffectCopy- OrMove 3 Копирует или перемещает объект на объект-приемник. Установки для Shift: Константа Значение Описание fmShiftMask 1 SHIFT была нажата. fmCtrlMask 2 CTRL была нажата. fmAltMask 4 ALT была нажата. Для элементов MultiPage или TabStrip Visual Basic for Applications инициирует это событие при переносе объекта на элемент управления. Для других элементов управления система инициирует это событие непосредственно перед операцией «бросания» или вставки. Если элемент обрабатывает это событие, вы можете изменить аргумент Action, чтобы указать drag-and-drop-действие для выполнения. Если Effect установлен в fmDropEffectCopyOrMove, аргументу Action можно присвоить fmDropEffectNone, fmDropEffectCopy или fmDropEffectMove. Если Effect установлен в fmDropEffectCopy или fmDropEffectMove, аргументу Action можно присвоить fmDropEffectNone. Нельзя переприсваивать аргумент Action, если Effect установлен в fmDropEffectNone. BeforeUpdate Private Sub object_BeforeUpdate(ByVai Cancel As MSForms.ReturnBoolean) Параметр: । Cancel Обязательный. Статус события. False обозначает, что этот элемент управления должен обрабатывать событие (по умолчанию). True отменяет обновление и обозначает, что приложение должно обрабатывать событие. Change Событие Change возникает, когда изменяется настройка свойства Value, независимо от того, вызвано ли это изменение из выполняемого кода или действиями пользователя (посредством интерфейса). Синтаксис Private Sub object_Change() Вот некоторые примеры действий, которые изменяют свойство Value: События объектов UserForm 853 Щелчок на CheckBox, OptionButton или ToggleButton. Ввод или выбор нового текстового значения для ComboBox, ListBox или TextBox. Выбор другой вкладки в TabStrip. Перемещение ползунка линейки прокрутки в ScrollBar. Щелчок на стрелке вверх или на стрелке вниз на SpinButton. Выбор другой страницы в MultiPage. В качестве примера можно использовать код примера для события AfterUpdate, немного его модифицировав. Click Инициируется всякий раз, когда по элементу управления щелкают мышью. Чаще всего используется для элементов управления типа CommandButton. Для элемента MultiPage и TabStrip Синтаксис Private Sub oi>ject_Click ( index As Long) Для других элементов управления: Private Sub object_Click( ) Параметр: index т====я=====с Обязательный. Индекс страницы или вкладки в MultiPage TabStrip, ассоциированной с этим событием. Пример Этот пример изменяет Caption-свойство элемента CommandButton каждый раз, когда пользователь щелкает на кнопке, используя мышь. Событие Click содержит код для изменения свойства Caption. Чтобы выполнить этот пример, скопируйте код в область Declarations формы, содержащей CommandButton с именем Кнопка. Private Sub Кнопка _Click () If Кнопка.Caption = "OK" Then ' Изменить заголовок Кнопка.Caption = "Щекните еще" Else Кнопка.Caption = "OK" End If End Sub ’ DbICIick Инициируется, когда по элементу управления дважды щелкают мышью. Синтаксис Для элементов MultiPage и TabStrip: Private Sub object_DblClick( index As Long, ByVai Cancel As MSForms.ReturnBoolean) Для других элементов управления: Private Sub object_DblClick( ByVai Cancel As MSForms.ReturnBoolean) Параметры (обязательные): index Позиция объекта Page или Tab в коллекции Pages или Tabs. 854 Приложение Е Cancel Статус события. False обозначает, что элемент управления должен обрабатывать это событие (по умолчанию). True обозначает, что приложение обрабатывает событие. Следующий пример использует форму и код предыдущего примера, но здесь добавлена событийная процедура, которая предупреждает пользователя о том, что нет нужды щелкать по кнопке дважды. (В справочной системе для этого события приведен более интересный, но и более сложный пример.) Private Sub Кнопка _Click() If Кнопка.Caption = "OK" Then ' Изменить заголовок . Кнопка.Caption = "Щекните еще" Else Кнопка.Caption = "OK" End If End Sub Private Sub Кнопка_РЫС11ск(ByVai Cansel As MSForms.ReturnBoolean) Beep MsgBox ("He нужно щелкать дважды, одного щелчка достаточно!") End Sub Enter Инициируется при выделении элемента управления. Синтаксис Private Sub obgect_Enter( ) Параметр: Cancel Обязательный. Статус события. False обозначает, что элемент управления должен обрабатывать событие (по умолчанию). True обозначает, что приложение обрабатывает событие и фокус должен оставаться у текущего элемента управления. Пример । Следующий пример использует свойство ActiveControl в подпрограмме, которая отслеживает элементы управления, выбираемые пользователем. Событие Enter для каждого элемента управления вызывает подпрограмму TraceFocus для идентификации элемента управления, который имеет фокус. Для того чтобы использовать этот пример, скопируйте код в область Declarations формы. Поместите на форму следующие элементы управления: ScrollBar с именем ScrollBarl. ListBox с именем ListBoxl. Два элемента управления OptionButton с именами OptionButton 1 и Option-Button2. Frame с именем Framel. (Элементы OptionButton не помещайте внутрь Frame.) Dim MyControl As Control Private Sub TraceFocus!) ListBoxl.Additem ActiveControl.Name ListBoxl.List(ListBoxl.ListCount - 1, 1) = _ ActiveControl.Tabindex End Sub Private Sub UserForm_Initialize() ' События объектов UserForm 855 ListBoxl.ColumnCount = 2 ListBoxl.Additem "Использованные элементы " ListBoxl.List(0, 1) = "Индекс элемента" End Sub Private Sub Framel_Ent^r() TraceFocus End Sub Private Sub ListBoxl_Enter() TraceFocus End Sub Private Sub OptionButtonl_Enter() TraceFocus End Sub Private Sub 0ptionButton2_Enter() TraceFocus End Sub Private Sub ScrollBarl_Enter() TraceFocus End Sub Если вы запустите этот код на выполнение, то сможете, выделяя в любой последовательности элементы управления на форме, наблюдать в окне элемента ListBox имя активного элемента и его индекс. Error Инициируется, когда элемент управления обнаруживает какую-либо ошибку и не может возвратить информацию об ошибке в вызывющую программу. Синтаксис Для элементов MultiPage: Private Sub object_Error( index As Long, ByVai Number As Integer, ByVai Description As MSForms.Returnstring, ByVai SCode As SCode, ByVai Source As String, ByVai HelpFile As String, ByVai HelpContext As Long, ByVai CancelDisplay As MSForms.ReturnBoolean) Для других элементов управления: Private Sub object_Error( ByVai Number As Integer, ByVai Description As MSForms.Returnstring, ByVai SCode As SCode, ByVai Source As String, ByVai HelpFile As String, ByVai HelpContext As Long, ByVai CancelDisplay As MSForms .ReturnBoolean) Параметры (все обязательные): index Индекс страницы в MultiPage, связанной с этим событием. Number Определяет уникальное значение, используемое элементом управления для идентификации ошибки. Description Текстовое сообщение об ошибке. SCode Определяет код OLE-состояние для ошибки. Младшие 16 битов указывают значение, которое идентично аргументу Number. Source Строка, определяющая элемент управления, который инициализировал это событие. HelpFile Определяет полное имя для Help-файла с описанием ошибки. 856 Приложение Е HelpContext Определяет контекстный ID в Help-файле для указания раздела с описанием ошибки. CancelDisplay Определяет, отображать ли error-строку в окне функции MsgBox. Код для события Error определяет, как элемент управлёния должен реагировать на ошибочную ситуацию. Exit Инициируется, когда с элемента управления снимается выделение. Синтаксис Private Sub object_Exit( ByVai Cancel As MSForms.ReturnBoolean) Параметр (обязательный): Cancel Статус события. False обозначает, что элемент управления должен обрабатывать событие (по умолчанию). True обозначает, что приложение обрабатывает событие и фокус должен оставаться у текущего элемента управления. Key Dow, Key Up Инициируется при нажатии (отпускании) какой-либо клавиши в тот момент, когда форма имеет фокус. Синтаксис Private Sub object_KeyDown( ByVai KeyCode As MSForms.Retumlnteger, ByVai Shift As fmShiftState) Private Sub ob/ect_KeyUp( ByVai KeyCode As MSForms.Retumlnteger, ByVai Shift As fmShiftState) Параметры: KeyCode Обязательный. Целое, представляющее код клавиши, которая была нажата или освобождена. Shift Обязательный. Состояние SHIFT, CTRL и ALT. Установки для Shift: Константа Значение Описание fmShiftMask 1 Была нажата SHIFT. fmCtrlMask 2 Была нажата CTRL. fmAltMask 4 Была нажата ALT. Пример Следующий пример отслеживает установки свойств CurLine и CurX в многострочном элементе TextBox. Эти настройки изменяются в событии KeyUp, когда пользователь выполняет ввод в свойство Text, перемещает место вставки и расширяет выбор, используя клавиатуру. Для того чтобы использовать этот пример, выполните следующее: Скопируйте этот код в область Declarations формы. Добавьте в форму одно большое текстовое окно (TextBox) с именем TextBoxl. События объектов UserForm 857 Добавьте три элемента управления TextBox с именами TextBox2, TextBox3 (в одном столбце). Private Sub TextBoxl.KeyUp(ByVai KeyCode As _ MSForms.Returninteger, ByVai Shift As Integer) TextBox2.Text = TextBoxl.CurLine ' текущая строка (начиная с 0) в окне TextBoxl TextBox3.Text = TextBoxl.CurX ' текущая позиция курсора вставки по горизонтали End Sub Private Sub UserForm_Initialize() TextBoxl.MultiLine = True TextBoxl.Text = "Вводите текст сюда. Используйте CTRL + " _ "ENTER для начала новой строки." End Sub KeyPress Инициируется, когда пользователь нажимает алфавитно-цифровую клавишу. Синтаксис Private Sub object_KeyPress( ByVai KeyANSI As MSForms.Returninteger) Параметр (обязательный): KeyANSI Целое значение, которое представляет стандартный цифровой ANSI-код. Пример Следующий пример использует событие KeyPress для копирования нажатий-клавиш из одного элемента TextBox в другой. Пользователь выполняет ввод в соответствующим образом отмеченное текстовое окно. Для того чтобы использовать этот пример, скопируйте код в часть Declarations формы. Поместите на форму два элемента управления TextBox с именами TextBoxl и TextBox2. Private Sub TextBoxl_KeyPress(ByVai KeyAscii As _ MSForms.Returninteger) TextBox2.Text = TextBox2.Text & Chr(KeyAscii) 1 Чтобы обрабатывать комбинации клавиш клавиатуры (используя 1 SHIFT, CONTROL, OPTION, COMMAND и какую-либо другую клавишу), ' или TAB или ENTER, используйте событие KeyDown или KeyUp. End Sub Private Sub UserForm_Initialize() Move 0, 0, 570, 380 TextBoxl.Move 30, 40, 220, 160 TextBoxl.MultiLine = True TextBoxl.Wordwrap = True TextBoxl.Text = "Ввести текст сюда." TextBoxl.EnterKeyBehavior = True TextBox2.Move 298, 40, 220, 160 TextBox2.MultiLine = True TextBox2.Wordwrap = True TextBox2.Text = "Введенный текст копируется сюда." TextBox2.Locked = True End Sub 858 Приложение Е Layout Инициируется при изменении размера элемента Frame (или MultiPage). Синтаксис Для элемента MultiPage: Private Sub object_Layout( index As Long) Для других элементов управления: Private Sub object_Layout( ) Параметр: Index Обязательный. Индекс страницы в MultiPage, которая изменила размер. MouseDown, MouseUp Инициируются при щелчке мышью. MouseDown — пользователь нажимает на клавишу мыши, MouseUp — отпускает клавишу. Синтаксис: Для элементов MultiPage и TabStrip: Private Sub object_MouseDown( index As Long, ByVai Button As fmButton, ByVai Shift As fmShiftState, ByVai X As Single, ByVai Y As Single) Private Sub object_MouseUp( index As Long, ByVai Button As fmButton, ByVai Shift As fmShiftState, ByVai X As Single, ByVai У As Single) Для других элементов управления: Private Sub object_MouseDown( ByVai Button As fmButton, ByVai Shift As fmShiftState, ByVai X As Single, ByVai Y As Single) Private Sub object_MouseUp( ByVai Button As fmButton, ByVai Shift As fmShiftState, ByVai X As Single, ByVai Y As Single) Параметры (все обязательные): index Индекс страницы или вкладки в MultiPage или TabStrip с определенным событием. Button Целое значение, которое определяет, какая кнопка мыши вызвала событие. Shift Состояние SHIFT, CTRL и ALT. X, Y Горизонтальное или вертикальное положение (в точках) от левого или верхнего края формы, Frame или Page. Установки для Button: Константа Значение Описание FmButtonLeft 1 Была нажата левая кнопка. FmButtonRight 2 Была нажата правая кнопка. FmButtonMiddle 4 Была нажата средняя кнопка. События объектов UserForm 859 Установки для Shift: Значение Описание 1 Была нажата SHIFT. 2 Была нажата CTRL. 3 Были нажаты SHIFT и CTRL. 4 Была нажата ALT. 5 Были нажаты ALT и SHIFT. 6 Были нажаты ALT и CTRL. 7 Были нажаты ALT, SHIFT и CTRL. Вы можете идентифицировать индивидуальные модификаторы клавиатуры, используя следующие константы: Константа Значение Описание fmShiftMask 1 Маска для обнаружения SHIFT. fmCtrlMask 2 Маска для обнаружения CTRL. fmAltMask 4 Маска для обнаружения ALT. MouseMove Инициируется при перемещении мыши. Синтаксис Для элементов MultiPage и TabStrip: Private Sub object_MouseMove(index As Long, By Vai Button As fmButton ByVai Shift As fmShiftState, ByVai X As Single, ByVai Y As Single) Для других элементов управления: Private Sub ot>y'ect_MouseMove(ByVal Button As fmButton, ByVai Shift A fmShiftState, ByVai X As Single, ByVai Y As Single) Параметры (все обязательные): index Индекс страницы или вкладки в MultiPage или TabStrip, ассоцииро ванной с этим событием. Button Целое значение, которое определяет состояние кнопок мыши. Shift Определяет состояние SHIFT, CTRL и ALT. X, Y Горизонтальное или вертикальное положение (в точках) от левого или верхнего края элемента управления. Настройки Аргумент index определяет, на какой странице или вкладке щелкнули khoi кой мыши. Значение -1 обозначает, что пользователь не щелкнул ни на како странице или вкладке. Настройки для Button: Значение Описание 0 Никакая кнопка не нажата 1 Нажата левая кнопка 860 Приложение Е Значение Описание 2 Нажата правая кнопка 3 Нажаты правая и левая кнопки 4 Нажата средняя кнопка 5 Нажаты средняя и левая кнопки 6 Нажаты средняя и правая кнопки 7 Нажаты все три кнопки Настройки для Shift: Значение Описание 1 Была нажата клавиша SHIFT 2 Была нажата клавиша CTRL 3 Были нажаты клавиши SHIFT и CTRL 4 Была нажата клавиша ALT 5 Были нажаты клавиши ALT и SHIFT 6 Были нажаты клавиши ALT и CTRL 7 Были нажаты клавиши ALT, SHIFT и CTRL Вы можете идентифицировать индивидуальные модификаторы клавиатуры, используя следующие константы: Константа Значение Описание fmShiftMask 1 Маска для обнаружения SHIFT. fmCtrlMask 2 Маска для обнаружения CTRL. fmAltMask 4 Маска для обнаружения ALT. Следующий пример демонстрирует операцию перетаскивания элементов списка из одного окна списка (ListBox) в другое (элементы из окна-источника не удаляются), используя объект DataObject для содержимого перетаскиваемого текста. Этот пример кода использует методы SetText и StartDrag в событии MouseMove для реализации операции перетаскивания. Для того чтобы использовать этот пример, скопируйте код в область Declarations формы. Поместите на форму два элемента управления типа ListBox с именами ListBoxl и ListBox2. Также необходимо добавить элементы выбора во второе окно списка (ListBox). Private Sub ListBox2_BeforeDragOver(ByVai Cancel As _ MSForms.ReturnBoolean, ByVai Data As _ MSForms.DataObject, ByVai X As Single, _ ByVai Y As Single, ByVai DragState As Long, _ ByVai Effect As MSForms.ReturnEffect, _ ByVai Shift As Integer) Cancel = True Effect = 1 End Sub Private Sub ListBox2_BeforeDropOrPaste(ByVai _ Cancel As MSForms.ReturnBoolean, _ 1 f События объектов UserForm 861 ByVai Action As Long, ByVai Data As _ , MSForms.DataObject, ByVai X As Single, _ ByVai Y As Single, ByVai Effect As _ MSForms.ReturnEffeet, ByVai Shift As Integer) Cancel = True Effect = 1 ListBox2.Additem Data.GetText End Sub Private Sub ListBoxl_MouseMove(ByVai Button As _ Integer, ByVai Shift As Integer, ByVai X As _ Single, ByVai Y As Single) Dim MyDataObject As DataObject If Button = 1 Then Set MyDataObject = New DataObject Dim Effect As Integer MyDataObject.SetText ListBoxl.Value Effect = MyDataObject.StartDrag End If End Sub Private Sub UserForm_lnitialize() For i = 1 To 10 ListBoxl.Additem "Элемент выбора " & (ListBoxl.ListCount + 1) Next i End Sub Removecontrol Инициируется при удалении элемента управления из контейнера. Синтаксис Для элемента MultiPage: Private Sub object_RemoveControl( index As Long, Ctrl As Control) Для других элементов управления: Private Sub object_RemoveControl( Ctrl As Control) Параметры (все обязательные): index Индекс страницы в MultiPage, которая содержала удаленный элемент управления. Ctrl Удаленный элемент управления. Scroll Инициируется при изменении положения ползунка линейки прокрутки. Синтаксис Для элемента ScrollBar: Private Sub object_Scroll() Для элемента MultiPage: Private Sub object Scroll( index As Long, ActionX As fmScrollAction, ActionY As fmScrollAction, ByVai ReguestDx As Single, ByVai RequestDy As Single, ByVai ActualDx As MSForms.Returnsingle, ByVai ActualDy As MSForms.Returnsingle) Для элемента Frame: Private Sub object_Scroll( ActionX As fmScrollAction, ActionY As fmScrollAction, ByVai RequestDx As Single, ByVai RequestDy As Single, ByVai ActualDx As MSForms.Returnsingle, ByVai ActualDy As MSForms.Returnsingle) 862 Приложение Е Параметры (все обязательные): index Индекс страницы в MultiPage, ассоциированной с этим событием. | ActionX Действие, которое произошло в горизонтальном направлении. 1 ActionY Действие, которое произошло в вертикальном направлении. RequestDx Расстояние (в точках), на которое необходимо переместить линейку прокрутки в горизонтальном направлении. RequestDy Расстояние (в точках), на которое необходимо переместить линейку прокрутки в вертикальном направлении. ActualDx Расстояние (в точках), на которое линейка прокрутки переместилась в горизонтальном направлении. \ActualDy Расстояние (в точках), на которое линейка прокрутки переместилась в вертикальном направлении. Настройки для ActionX и ActionY-. Константа Значение Описание FmScrollActionNoChange 0 Никакого изменения не произошло. fmScrollActionLineUp 1 Небольшое расстояние по направлению вверх на вертикальной линейке прокрутки; небольшое расстояние влево на горизонтальной линейке прокрутки. Перемещение эквивалентно нажатию клавиш со стрелками вверх или влево на клавиатуре для перемещения линейки прокрутки. fmScrollActionLineDown 2 Небольшое расстояние вниз на вертикальной линейке прокрутки; небольшое расстояние вправо на горизонтальной линейке прокрутки. Перемещение эквивалентно нажатию клавиш со стрелками вниз или вправо на клавиатуре для перемещения линейки прокрутки. fmScrollActionPageUp 3 Перемещение на одну страницу вверх на вертикальной линейке прокрутки; перемещение на одну страницу влево на горизонтальной линейке прокрутки. Перемещение эквивалентно нажатию Page Up на клавиатуре для перемещения линейки прокрутки. fmScrollActionPageDown t t 4 Перемещение на одну страницу вниз на вертикальной линейке прокрутки; перемещение на одну страницу вправо на горизонтальной линейке прокрутки. Перемещение эквивалентно нажатию Page Down на клавиатуре для перемещения линейки прокрутки. fmScrollActionBegin 5 Верх вертикальной линейки прокрутки; левый край горизонтальной линейки прокрутки. События объектов UserForm 863 Константа Значение Описание fmScrollActionEnd 6 Низ вертикальной линейки прокрутки; правый край горизонтальной линейки прокрутки. fmScrollActionProperty-Change 8, Значение свойства ScrollTop или ScrollLeft изменилось. Направление и величина перемещения зависят от того, какое свойство было изменено, и от нового значения свойства. fmScrollActionControl- Request 9 Элемент управления указал своему контейнеру выполнить прокрутку. Величина перемещения зависит от конкретного элемента управления и контейнера. fmScrollActionFocus- Request 10 Пользователь перешел к другому элементу управления. Величина перемещения зависит от размещения выбранного элемента управления и обычно в результате выбранный элемент управления перемещается так, чтобы он был полностью видимым для пользователя. Пример Следующий пример демонстрирует автономную линейку прокрутки (ScrollBar) и представляет изменение в ее значении, когда пользователь перемещает ползунок линейки прокрутки. Пользователь может перемещать ползунок линейки, щелкая на любой стрелке на концах элемента управления, щелкая в зоне между ползунком и любой стрелкой или перетаскивая ползунок. Когда пользователь перетаскивает ползунок линейки прокрутки, событие Scroll отображает сообщение, указывающее, что пользователь выполнил прокрутку для получения нового значения. Для того чтобы использовать этот пример, скопируйте код в область Declarations формы. Поместите на форму ScrollBar с именем ScrollBarl и элемент управления типа Label с именем Labell. Private Sub UserForm_Initialize() ' минимальное значение для ScrollBarl.Value: ScrollBarl.Min = -200 ’ ( 1 максимальное значение для ScrollBarl.Value: ScrollBarl.Max = 200 ' текущее значение для ScrollBarl.Value: ScrollBarl.Value = 200 End Sub Private Sub ScrollBarl_Scroll() Labell.Caption = "Текущее значение ScrollBar : " & ScrollBar1.Value End Sub SpinDown, SpinUp Событие SpinDown инициируется при щелчке на стрелке «вниз» (или «влево») кнопки счетчика. Событие SpinUp инициируется при щелчке на стрелке «вверх» (или «вправо») кнопки счетчика. 864 Приложение Е Синтаксис Private Sub objесt_SpinDown( ) Private Sub object_SpinUp( ) Пример Следующий пример демонстрирует временной интервал между последовательными событиями Change, SpinUp и SpinDown, которые возникают, когда пользователь удерживает нажатой кнопку мыши для изменения значения SpinButton или ScrollBar. В этом примере пользователь выбирает настройку задержки, затем щелкает и удерживает нажатой любую часть SpinButton. События SpinUp и SpinDown при инициализации записываются в ListBox. Для того чтобы использовать этот пример, скопируйте код в область Declarations формы. Создайте на форме: 1. SpinButton с именем SpinButtonl. 2. Два элемента управления OptionButton с именами OptionButtonl и OptionBut-ton2. 3. ListBox с именем ListBoxl. Dim Eventcount As Long 'счетчик событий Private Sub Resetcontrol() ListBoxl.Clear Eventcount = 0 SpinButtonl.Value = 5000 End Sub Private Sub UserForm_Initialize() ' инициализация формы 1 установка минимального и максимального значений 1 свойства Value элемента SpinButtonl SpinButtonl.Min = 0 SpinButtonl.Max = 10000 SpinButtonl.Delay = 50 ' заголовки для переключателей: OptionButtonl.Caption = "задержка 50 миллисекунд " OptionButton?.Caption = "задержка 250 миллисекунд " ' инициализация переключателя OptionButtonl.Value = True End Sub •-> Private Sub OptionButtonl_Click() SpinButtonl.Delay = 50 ResetControl End Sub Private Sub OptionButton2__Click() SpinButtonl.Delay = 250 ResetControl , End Sub Private Sub SpinButtonl_SpinDown() Eventcount = Eventcount + 1 ListBoxl.Additem Eventcount End Sub Private Sub SpinButtonl_SpinUp() ' Eventcount = Eventcount +1 , . События объектов UserForm 865 ListBoxl.Additem Eventcount End Sub Zoom Инициируется при изменении свойства Zoom. Для элемента Frame: v Private Sub object_Zoom( Percent As Integer) Для элемента MultiPage: Private Sub object_Zoom( index As Long, Percent As Integer) Параметры (все обязательные): index Индекс страницы в MultiPage, ассоциированной с этим событием. Percent Процентное выражение изменения масштаба формы. Диапазон допустимых значений от 10% до 400%. Пример Следующий пример использует событие Zoom для оценки нового значения свойства Zoom и добавляет линейки прокрутки в форму в соответствующих случаях. Этот пример использует Label для отображения текущего значения. Пользователь задает размер для формы, используя SpinButton, и затем щелкает Command-Button для установки значения в свойстве Zoom. Для того чтобы использовать этот пример, скопируйте код в область Declarations формы. Поместите на форму: Label с именем Label 1. SpinButton с именем SpinButtonl. CommandButton с именем CommandButtonl. Другие элементы управления, помещенные рядом с краями формы. Private Sub UserForm_Initialize() ' инициализация формы ' минимальное/максимальное значение ' свойства элемента SpinButtonl: SpinButtonl.Min = 10 SpinButtonl.Max = 400 ' начальное значение свойства элемента SpinButtonl: SpinButtonl.Value = 100 ' заголовок метки: Labell.Caption = "SpinButton-значение: " & SpinButtonl.Value CommandButtonl.Caption = "Масштабировать форму" End Sub ' Private Sub UserForm_Zoom(Percent As Integer) ' обработка события изменения размеров формы Dim MyResult As Double If Percent > 99 Then ScrollBars = fmScrollBarsBoth ScrollLeft = 0 ScrollTop = 0 MyResult = Width * Percent / 100 866 Приложение Е Scrollwidth = MyResult MyResult = Height * Percent / 100 ScrollHeight = MyResult Else ScrollBars = fmScrollBarsNone ScrollLeft =0 1 e ScrollTop = 0 End If End Sub Private Sub CommandButtonl_Click() ' масштабирование формы Zoom = SpinButtonl.Value End Sub , Private Sub SpinButtonl_SpinDown() Labell.Caption = "SpinButton-значение: " 5 SpinButtonl.Value End Sub Private Sub SpinButtonl_SpinUp() Labell.Caption = "SpinButton-значение: " 5 SpinButtonl.Value End Sub Предметный указатель А Abs(N) * 152 Accelerator 346 Activate 232, 234, 338, 513 ActiveCell 227 ActiveChart 227 ActiveControl 336 ActiveDocument 229 ActivePrinter 229 ActiveSheet 227 ActiveWindow 229 Add 398 AddCallout 251, 253-254 AddCanvas 251 AddComment 254 AddConnector 253-254 AddControl 348 AddCurve 252-253, 255 AddDiagram 252-253, 255 AddForm 253 Addins 245-246, 429 AddLabel 252-253, 255 AddLine 252, 254-255 AddMediaObject 255 AddOLECon tr ol 252 AddOLEObject 252, 254-255 AddPicture 252, 254-255 AddPlaceholder 255 AddPolyline 252, 254-255 Address 227 AddShape 256 AddTable 256 AddTextbox 253-254, 256 AddTextEffect 253-254, 256 AddTitle 256 After Update 348 Anchor 462 AND в SQL-инструкции SELECT 580 Application 224-225 ASC в SQL-инструкции SELECT 584 Asc(S) 153 Atn(N) 152 AutoUpdate 463 AVG в SQL-HHCTpyKiiHHSELECT 585-586 В BackColor BeforeClose BeforeDoubleClick 336, 343, 346 512 514 BeforePrint 519 BeforeUpdate 348 BETWEEN в SQL-инструкции SELECT 580 Bookmark 225, 246 Boolean 96 BottomRightCell 463 Break 375 ByRef 216 Byte 94-95 c Calculate 232, 518 Call Stack 375 Cancel 346, 618 Caption 336, 346 CBool(N) 154 CByte(E) 154 CCur(E) 154 CDate(E) 154 CDbl(E) 154 Cells 227 Change 348, 356, 515 Characters 246, 431 Chart 224 Chartobjects 246 Charts 227, 245 ChDir 302 ChDrive 302 CheckBox 344 CheckSpelling 234 Chr(N) 153 Cint(E) 154 Clear 233, 420 ClearContents 420 ClearFormats 420 ClearNotes 420 Click 338, 348 CLng(E) 154 Close 233-234 Code Window 55 ComboBox 344 CommandButton 345 Comments 246 Const 110 Controls 336 ControlTipText 346 Copy 337, 409, 420 Cos(N) 152 Count 227, 229 COUNT в SQL-инструкции SELECT 585 868 Программирование на VBA 2002 CreateRelation 599 CreateTableDef 599 Create Workspace 597 Critical 149 CSng(E) 154 CStr(E) 154 CurDir 303 Currency z 94, 96, 168 Cut 337, 420 CVar(E) 154 Cycle 336 D Date 155 DateAdd 155 DateDiff 156 DatePart 156 DateSerial 156 DateValue 156 Day 155 dbDriverComplete 614 dbDriverCompleteRequired 614 dbDriver N oPr ompt 614 dbDriverPrompt 614 DBEngine.DefaultPassword 596 DBEngine.DefaultType 595 DBEngine.DefaultUser 596 DBEngine.IniPath 596 DBEngine.LoginTimeout 596 DBEngine. V ersion 596 DblClick 338, 343. 348 dbOpenDynamic 600 dbOpenDynaset 600 dbOpenForwardOnly 600 dbOpenSnapshot 600 dbOpenTable 600 dbRun Async 614 dbUseJet 597 dbUseODBC 597 DDEExecute 487 Deactivate 338, 513 Debugging 61 Default 346 Delete 234 DESC в SQL-инструкции SELECT 584 Dialogs 246 Dim 100 dimension (измерение) 287 Dir 303 Do While 273 Do...Loop While 277 Document 225, 246 Documentchange 529 Double 94 Dynamic data exchange (DDE) 482 E Empty 118 Enabled 336, 346 End 209 End Function * 178 End Sub 178 EndKey 437 Enter 348 Error 349 Exclamation 149 Exit 348 Exp(N) 152 F FileCopy • 303 FileDateTime 303 FileLen 303 FindFirst 610 FindLast 610 FindNext 610 FindPrevious 610 Fix(N) 152 Fixed 168 Font 225, 336 For Each...Next 261 For...Next 261 ForeColor 336, 346 Format 319 FORMAT в SQL-инструкции SELECT 582 Format(E, S) 153 FormatCurrency 171 FormatDateTime 171 FormatNumber 171 FormatPercent 171 Formula 227, 418 Frame 345 Function 178 G General Date 167 General Number 168 GetAttr 303 GetOpenFilename 313 GetOpenFileName 303 GetSaveAsFilename 303, 313 GoTo 234 GROUP BY в SQL-инструкции SELECT 587 H HAVING в SQL-инструкции SELECT 587 Height 463 Hex(N) 153 Предметный указатель 869 Hide HomeKey host-приложение Hour l-J If...Then...ElseIf 195 Image 345 Immediate Window 375 IN в SQL-инструкции SELECT 580 Index 227 Information 149 Initialize 339 InputBox 116, 150 InsertAfter 440 InsertBefore 440 InsertParagraphAfter 440 InsertParagraphBefore 440-441 InStr 157 InStrRev 157 Int 153 Int(N) 152 Integer 94 IS NOT NULL в SQL-инструкции SELECT 581 IS NULL в SQL-инструкции SELECT 580 Justify 233 К KeyDown 349 KeyPress 349 KeyUp 349 Kill 303, 329 337 437 55-56, 59, 64-65 155 LTrim 157 M Max 347 MAX в SQL-инструкции SELECT 585-586 Medium Date 167 Medium Time 167 Microsoft DAO 598 Microsoft Jet 593 Microsoft Jet workspace 594 Mid 157 Min 347 MIN в SQL-инструкции SELECT 585-586 Minute 155 MkDir 303 Modules (Модули) 52 Month 155 MouseDown, MouseUp 349 MouseMove 349 Move 409 MultiPage 345 L Label 344 Layout 349 LCase 157 Left 157, 463 Len 157 LenTrim 179 LIKE в SQL-инструкции SELECT 580 Line 463 LinkFormat 463 List 347 ListBox 1 344 Load 339 Locals Window 375 Log(N) 152 Long 94-95 Long Date 1 167 Long Time 167 N Name 225, 227, 229, 303, 319, 347, 409, 463 Names > 419 New 529 NewW orkbook 520 Next 262 NOT BETWEEN в SQL-инструкции SELECT 581 NOT IN в SQL-инструкции SELECT 581 NOT LIKE в SQL-инструкции SELECT 581 NOT в SQL-инструкции SELECT 580 Now 155 Null 118 NumberFormat 419 0 Object 463 Oct(N) 153 ODBCDirect 593 ODBCDirect workspace 594 Offset -415 OLEFormat 463 On/Off 163 OnAction 463 OnKey 520,522 OnTime 525, 534 On Window 521 Open 397, 510, 527 870 Программирование на VBA 2002 Option Base 287 Option Explicit 108 OptionButton 344 OR в SQL-инструкции SELECT 580 ORDER BY в SQL-инструкции SELECT 584 RmDir 308 Rnd(N) 152 RowSource 347 RTrim 157 Run 233, 235 runtime-ошибки 88 s Paragraph 225, 246, 432 Paste 337 Path 227, 229 Percent 1 168 PopulatePartial 599 PrintForm 337 Printout 234 Private 287, 291 Progid 463 project (проект) 52 Project Explorer (Окно проекта) 55 Properties Window (Ok но свойств) 55 Public 291 Q Question Quick Watch 149 375 Quit R Range Recordset. AddN ew Recordset.BOF Recordset.CancelUpdate Recordset.Close Recordset.Delete Recordset.Edit Recordset.EOF Recordset.FindFirst R ecordset. FindLast Recordset.FindN ext Recordset.FindPrevious R ecordset. MoveFirst Recordset. Mo veLast Recordset. MoveNext Recordset.MovePrevious Recordset.NoMatch Recordset.RecordCount Recordset. Seek Recordset.Update Repaint Reset Resize RGB(N, N, N) Right 225, 229, 437 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 602 337 375 339, 343, 416 154 157 Save 233, 235 SaveAs 233, 235 SaveCopyAs 400 Saved 228-229 Scientific 168 ScrollBar 345 Second 155 Sections 246 Select 233, 235 Selected 347 Selection 228-229, 437 SelectionChange 517, 520 SendKeys 233 Sentences 432 SetAttr 303 Sgn(N) 152 Shadow 463 Sheets > 228, 407 Shell 483 Short Date 167 Short Time 167 Show 337 Sin(N) 152 Single 94 Space 157 SpinButton 345 SpinDown, SpinUp 349 SQL (Structured Query Language) 547 SQL-инструкция SELECT 574 Sqr(N) 152 Standard 168 Static 287 Static 291 StatusBar 228-229 Step 262 Step Into (шаг с заходом) 375, 380 Step Out 375 Step Over 375 Stop 378 Str(N) 154 StrComp 157 StrConv 157 String 96, 157 Style 225 Styles 246 Sub 178 Предметный указатель 871 SUM в SQL-инструкции SELECT Synchronize 585-586 599 т Tabindex 347 Table 225 TableOfContents 225 TabStop 347 TabStrip 345 Tan(N) 152 Template 225, 429 Templates 246, 429 Terminate 339, 340 TextBox 344 ThisWorkBook 228 Time 155 Timer 156 TimeSerial 156 TimeValue 156 Toggle Breakpoint 375 Toggle Folders (Папки) 55 ToggleButton 345 Top 463 TopLeftCell 464 Trim 158 True/False 168 Type 228, 464 TypeParagraph 440 u UBound 296 UCase 158 Underline 412 Unload 339 V Val(S) 154 Value 228, 348, 418 Variant 97 vbAbort 150 vbAbortRetrylgnore 149 vbAlias 305 vbApplicationModal 149 vbArchive 305 vbBinaryCompare 161 vbCancel 150 vbCr 165 vbCritical 149 vbCrLf 165 vbDatabaseCompare 161 vbDefaultBu tton 1 149 vbDefaultButton2 149 vbDefaultButton3 149 vbDefaultButton4 149 vbDirectory 305 vbExclamation 149 vbGeneralDate 172 vbHidden 1 305 vblgnore 150 vblnformation 149 vbLf 165 vbLongDate 173 vbLongTime 173 vbMsgBoxHelpButton 149 vbNewLine 165 vbNo 150 vbNormal 305 vbOK 150 vbOKCancel 150 vbOKOnly 150 vbQuestion 150 vbReadOnly 305 vbRetry i 150 vbRetryCancel 150 vbShortDate 173 vbShortTime 173 vbSystem 305 vbSystemModal 150 vbTab 166 vbTextCompare 161 vbVolume 305 vbYes 150 vbYesNo 150 vbYesNoCancel 150 View Code (Программа) 55 View Object (Объект) 1 55 Visible 228-229, 348, 464 Volatile 233 w Watch Window 375 wdCell 435 wdCharacter 435 wdCollapseDirection 439 wdCollapseEnd 439 wdCollapseStart 439 wdColumn 437 wdColumn 435 wdDialogFileOpen 319 wdDialogFileSaveAs 319 wdExtend 437 wdFormatDocument 427 wdFormatDOSText 427 wdFormatDOSTextLineBreaks 427 wdFormatEncodedText 427 wdFormatFiltere dHTML 427 872 Программирование на VBA 2002 wdFormatHTML 427 Worksheets ' 228, 246 wdFormatRTF 427 Workspace 597 wdFormatTemplate 427 Workspaces 612 wdFormatText 427 wdFormatTextLineBreaks 427 X wdFormatUnicodeText 427 xlExclusive 403 wdFormatWebArchive 427 xlLocalSessionChanges 403 wdGoTo Absol ute 438 xlNoChange 403 wdGoToBookmark 438 xlOtherSessionChanges 403 wdGoToComment 438 xlShared 403 wdGoToDirection 438 xlUnderlineStyle 412 wdGoToField 438 xlUnderlineStyleDouble 412 wdGoToFirst 438 xlUnderlineStyleNone 412 wdGoToHeading 438 xlUnderlineStyleSingle 412 wdGoToItem 438 xlUnderlineStyleDoubleAccounting 412 wdGoToLast 438 xlUnderlineStyleSingleAccounting 412 wdGoToLine 439 xlUserResolution 403 wdGoToNext 438 xlWBATChart 398 wdGoToObject 438 xlWBATExcel4IntlMacroSheet 398 wdGoToPage 439 xlWBATWorksheet 398 wdGoToPercent 439 wdGoToPrevious 438 Y-Z wdGoToRelative 438 Year 155 wdLine 435, 437 Yes/No 168 wdMainTextStory 431 Zoom 349 wdMove 437 wdMovementType 437 A wdParagraph 435 wdPrimary Footer S tory 431 автоматический отступ 84 wdPrimaryHeaderStory 431 (auto indenting) wdRow 435, 437 агрегирующая функция 585 wdS a veFormat 427 апплет (applet) 450 wdSection 435 аргумент (argument) 83, 85 wdSentence 435 аргумент InitialFilename 331 wdStory 435, 437 аргумент обязательный (required) 194 wdStoryType wdTable 431 436 атрибут - Archive 541 304 wdTypeDocument wdTypeTemplate 319 319 - Directory - Hidden 304 304 wdUnits 437 - Read-Only 304, 308 wdWord 436 - System 304 Weekday 155 - Volume Label 305 WeekdayName WHERE в SQL-инструкции 155 - файла Normal r" 304 SELECT 579-580 Б Width 464 бесконечный цикл (infinite loop) 261 Window 225 библиотеки динамической компоновки Windows 246 (Dynamic link libraries, DLL) 496 Words 431 блок кода обработки прерывания 388 Workbook 225, 396 блок (block) оператора 193 WorkbookBeforePrint 519 булевы (Boolean) значения 96 WorkbookBeforeSave 519 Workbooks 228, 246 В Worksheet 225, 396 ветвь (branch) кода 190 Предметный указатель 873 вложение (nesting) циклов 279 вложение операторов (nesting) 197 вложенный запрос в инструкции SELECT 588 внешний ключ 549 внутренних констант * (intrinsic constants) ' 114 входные данные (input) 116 вызов (calling) 145 выражение (expression) 118 вычисляемая информация 542 вязное отношение 548 Д-З действительные (real) числа 95 динамический (dynamic) массив 286 директива Option Compare 132 директивы компилятора (compiler directives) 109 запрос к базе данных 547 знак & 141 И идентификатор (identifier) 98 идентификационный номер задачи (task identification number) 483 извлечение информации 573 именованные аргументы (named arguments) функций 148 именованные константы (named constants) 110 именованный формат (named format) 167 индекс (subscript или index) элемента 284 информационное сообщение (information message) 207 исключающим “ИЛИ” (exclusive or) 138 исходный код (source code) 42, 52 итерация (iteration) цикла 260 К каталоги (directories) г 302 клиентская часть программного обеспечения 639 ключевое слово Binary 132 - - By Vai 216 Dim 287 - - Is 203 Loop 273 — Optional 194 Preserve y 291 — Public 287 - - Until 271 - - While 271 ключ отношения 548 коллекция Connections 612 коллекция Workspaces 597 коллекция (collection) объектов 241 комментарий (comment) 73 компилятор Option Base 286 компиляция (compiling) 87 конкатенация (concatenate) конкатенация (concatenation) 96 строк 139 константа (constant) 110 константа wdDialogFileopen , 319 контейнер (container) 242 кортеж критическое предупредительное 541 сообщение (Critical Warning message) 207 л-м литеральные константы (literal constants) 110 логическое выражение (logical expression) 119, 136 макрокоманды (macro-commands) 24 макрос (macro) маркеры изменения размеров 24, 81 (sizing handles) 350 массив (array) 284 - статический (static) 286 метка строки (line label) 204 метод (method) 187, 222 - Activate 399, 408, 425 - Add 408, 424 - Cells 412 - Close 404, 428 - Collapse 439 - Copy 442 - CreateProperty 599 - CreateQueryDef 599 - CreateWorkspace 597 - Cut 441 - DDEInitiate 485 - DDETerminate 485 - Delete 410, 442 - Display 319 - Execute 599 - Expand 436 - GetOpenFilename 314, 329 - GetSaveAsFilename 317 - GoTo 438 874 Программирование на VBA 2002 - InsertParagraphAfter 441 - MakeReplica 599 - Open 423 - OpenConnection 613 - OpenRecordset 599-600 - Paste 442 - Range 411 - Save 400, 426 - SaveAs 401 - SetRange 434 - TypeText 439 - Volatile 187 многомерные (multi-dimensional) массивы 285 модальными (modal) приложениями 337 модель данных 541 модификация данных 573 f н надстройка (add-in) 423 надстрочные (superscript) символы 93 неопределенные циклы (indefinite loops) 260 нечеткий поиск (fuzzy search) 132 неявное объявление переменной (implicit variable declaration) 100 номер строки (line number) 204 нормализованное отношение 550 обеспечение целостности данных 573 область действия (scope) процедурного уровня 99, 104 (procedure-level scope) обработчик событий 105 (event handler) 503 объект Connection 612 - Err 388 - Database 597 - DBEngine 594 - Recordset 599 - Selection 436 - UserForm 334 - Workspace 612 объектная модель (object model) объектное выражение 243 (object expression) 237 объектное отношение объектно-ориентированное 548 программирование (obj ect-oriented programming, OOP) обязательный аргумент 221 (required argument) 116 ограниченные ключевые слова (restricted keywords) 99 одномерный (single-dimensional) массив 284 оператор (statement) 74 - And 136 - AppActivate 484 - ChDir 324 - ChDrive 325 - Declare 497 - Dim 291 - Do 270 - Do Until 275 - Eqv 138 - Erase 296 - Exit Sub 210 - Exit 209 - FileCopy 327 - If...Then 191 - If...Then...Else 195 - Imp 139 - Like 132 - MkDir 326 - Name 330 - Not 137 - On Error 387 - Or 137 - ReDim 286, 291 - Resume Next 390 - Resume 389 - RmDir 327 - Select Case 201 - SendKeys 494 - SetAttr 308 - To 203 - Xor 138 - безусловного перехода 190 - управления программой (program control) 190 - условного и безусловного перехода (conditional и unconditional branching) 190 - условного перехода 190 - присваивания (=) 122 операция выбора 546 - вычитания 543 - декартова произведения 544 - деления 544 - объединения 542 - пересечения 543 - проекции 545 - соединения 546 - сравнения (comparison operation) 97 - отношения (relational operation) 130 Предметный указатель 875 определенные пользователем функции (user-defined functions) 177 организация данных 573 отмечающие запятые (place holding commas) 231 отношение (relation) 541 ошибка времени исполнения (runtime error) 88 - несоответствия типа (type mismatch) 89, 120 - синтаксиса (syntax error) 87 п папка (folder) f 302 переменная (variable) 87, 97 персистенция (persistence) 107 плавающие (floating) 55 по значению (by value) 215 по ссылке (by reference) 215 побочный результат (side effect) 216 подзапрос в инструкции SELECT 588 подпроцедурами (subprocedures) 81 пользовательские данные (user data) 222 последовательность перехода (tab order) 360 последовательные даты (serial Dates) 93 предмет DDE-обмена (conversation topic) 482 предопределенными константами (predefined constants) 114 предупредительного сообщения (warning message) 207 привязка к сетке (snap to grid) 351 прикрепленный (docked) 54 программный идентификатор (programmatic identifier) 475 процедуры (procedures) 81 процедуры обработки событий (event procedures) 338, 503 процессор баз данных (database engine) 539 Р Рабочий стол (desktop) 221 режим исполнения (run time) 376 - прерывания (break mode) 376 - разработки (design time) 376 результат функции (function result) 119 рекурсивная (recursive) функция 217 реляционная база данных 541 С свойства (properties) ., 222 - Dialogs 319 -, доступные на чтение/запись (read-write) 225 -, доступные только на чтение (read-only) ? 225 свойство AttachedTemplate 431 - CollatingOrder 599 - Connection 599 - Control Source 361 - DefaultType 596 - Enable 356 - Format 319 - Name 319 - QueryTimeout 599 - Repl ace Selection 439 - RowSource 361 - ThisDocument 429 - формы Width 343 символы-заполнители (placeholders) ' 16? символ определения типа (type-definition character) 103 - продолжения строки (line-continuation character) 76 синтаксис (syntax) 87 синтаксические ошибки (syntax errors) 372 синтаксический анализ (parsing) 87 сложное (составное) выражение (complex expression) 142 сложный SELECT-запрос 588 событие (event) 338, 503 - Click 339 - Deactivate 340 - Initialize 342 событийные процедуры (event procedures) 338 совместное использование данных 573 сообщение запроса (Query message) 207 составные документы (compound documents) 444 списки аргументов (argument lists) 86 ссылочная целостность 550 стек (stack) 217 строка (string) 96 - заголовка (title bar) 55 - объявления (declaration) макроса 73 - подключений (connection string) 614 строковое выражение (string expression) 119 т таблица истинности (truth table) 136 текущая папка (current folder) 323 876 Программирование на VBA 2002 текущий диск (current drive) тело (body) - (body) цикла тип Date - Object - данных (data type) - даты (date expression) типизированные переменные трехмерная ссылка (three-dimensional reference) У , унарный минус (unary minus) управление доступом - потоком (flow control) - файлами (file management) Ф форма элемента Label функция (function) 116, - CStr - CurDir - Dir - FileDateTime - FileLen - Fix - GetAttr - IsMissing - LBound - MsgBox - RGB - Sleep - Time функция-процедура (или функция) 323 73 261 93 135 91 119 101 408 126 573 190 302 352 144 145 323 309 331 332 153 305 194 296 148 343 501 145 177 Х-Ч хранимая информация 542 цикл For Each...Next числа с плавающей точкой 267 (floating point numbers) 95 - двойной точности (double-precision numbers) 95 - одинарной точности (single-precision numbers) - с фиксированной точкой 95 (fixed-point numbers) 96 численное выражение (numeric expression) 119 член класса (class member) 223 э-я экспоненциальное представление (scientific notation) 93 элемент массива 284 - коллекции 241 элементы управления (controls) 343 язык запросов данных (data query language — DQL) 573 - обработки данных (data manipulation language — DML) 573 --транзакций (transaction processing language — TPL) 573 - определения данных (data definition language — DDL) 573 - реляционной алгебры 547 - управления данными (data control language — DCL) 573 --курсором (cursor control language — CCL) 574