Лекция 12. ПРОГРАММИРОВАНИЕ ДЛЯ ОФИСНЫХ ПРИЛОЖЕНИЙ
В результате освоения материалов данной главы студенты должны:
знать
– основные конструкции языка Visual Basic for Application (VBA);
– основные объекты приложений Microsoft Excel и Microsoft Word;
– стандартные элементы управления;
уметь
– использовать возможности, предоставляемые средой VBA для решения аналитических и исследовательских задач;
– создавать макросы, функции пользователя и диалоговые окна на VBA;
– использовать объекты одного приложения в другом;
владеть
– навыками создания программ на VBA
Основные сведения о Visual Basic for Application
Инструменты, рассмотренные в предыдущих главах, позволяют решить большинство задач, возникающих у пользователей Microsoft Office. Однако опыт показывает, что всегда находятся такие задачи, которые либо неудобно, либо вообще невозможно решить с помощью стандартных средств пакета. В этом случае поможет только программирование.
Встроенным языком программирования в продуктах Microsoft Office является Visual Basic for Application (VBA). Он используется прежде всего для автоматизации часто решаемых задач (создания макросов). Эти макросы могут быть гораздо более "умными", чем те, которые получены с помощью команды Записать макрос. Для удобства пользователя можно также изменить интерфейс приложения: настроить ленту и контекстные меню, создать диалоговые окна, использовать элементы управления. В приложениях, где пользователь работает со встроенными функциями (Excel, Access), можно разрабатывать собственные функции. Все эти задачи решаются с помощью программирования на VBA.
Как следует из названия, VBA является упрощенной версией языка Visual Basic. У них много общего, особенно в синтаксисе, но тем не менее это разные языки. Впервые VBA появился в Excel 5.0. С тех пор он входит в состав всех приложений Microsoft Office и не только. Используя встроенные объекты, с помощью VBA мы можем управлять приложением, но следует учитывать, что набор объектов в каждом программном продукте (Word, Excel, Access, PowerPoint и т.д.) свой. Поэтому, чтобы программировать на УВД обычно мало знать синтаксис языка, нужно еще изучить объектную модель необходимого приложения. Далее мы рассмотрим основные объекты Excel и Word. Для более полного изучения объектов следует обращаться к специальной литературе и справочной системе соответствующего приложения.
Программа на VBA состоит из инструкций. Каждая инструкция должна быть написана на отдельной строке. Если нужно написать несколько инструкций на одной строке, то они разделяются двоеточием. Если же, наоборот, длинную инструкцию нужно разместить на нескольких строках, то в конце каждой строки, кроме последней, ставится так называемый символ продолжения: пробел с подчеркиванием.
Инструкции, предназначенные для решения определенной задачи, объединяются в процедуры. Все исполняемые инструкции обязательно должны находиться внутри какой-нибудь процедуры. Процедуры сохраняются в модулях. Модули могут быть различных типов: программный модуль, модуль формы, модуль класса.
Как и другие языки, VBA имеет много зарезервированных слов, которые нельзя использовать в качестве имен переменных и процедур вашей программы. Регистры VBA не различает, поэтому, например, слова For, for и FOR для него одинаковы.
Комментарий в программе задается с помощью апострофа. VBA игнорирует любой текст, начинающийся с апострофа и до конца строки. Таким образом, комментарий можно разместить как на отдельной строке, так и после инструкции в той же строке.
Основные типы данных VBA Byte (байт), Boolean (логическое), Integer (целое), Long (длинное целое), Single (с плавающей точкой обычной точности), Double (с плавающей точкой двойной точности), Date (дата), Object (ссылка на объект), String (строка), Variant (может содержать данные различных типов, используется как тип по умолчанию).
Переменные в программах представляют собой именованное место хранения данных в памяти компьютера. Их имена должны удовлетворять следующим условиям:
• начинаться с буквы;
• не содержать пробел, точку, восклицательный знак и символы @, &, $, #;
• не совпадать с другими именами или с зарезервированными словами VBA;
• содержать не более 255 символов.
Переменные объявляются с помощью следующей инструкции:
Dim ИмяПеременной [As ИмяТипа] [, ИмяПеременной [As ИмяТипа]]
При описании синтаксиса языков программирования квадратные скобки используют для того, чтобы показать, что какая-то часть синтаксической конструкции может отсутствовать. В приведенной выше инструкции они имеют именно этот смысл: тип переменной можно нс указывать, в одной инструкции можно объявить более одной переменной через запятую. Если не указать тип переменной, то по умолчанию он будет Variant. Обратите внимание, что хотя имена переменных можно перечислять через запятую, тип нужно указывать для каждой переменной. После выполнения инструкции
Dim х, у, z As Integer
только z будет иметь тип Integer, а х и у – Variant.
Ключевое слово Dim в объявлении переменной означает, что эта переменная – локальная. Если переменная объявлена внутри процедуры, то она существует только в этой процедуре. Если переменная объявлена в разделе глобальных объявлений модуля (перед первой процедурой), то она будет доступна для всех процедур этого модуля, но для других модулей такая переменная все равно будет "невидимой".
Вместо Dim можно использовать слова Private или Public. Private отличается от Dim тем, что не может объявлять переменные внутри процедуры, при объявлении же в разделе глобальных объявлений модуля Dim и Private равнозначны.
Переменная, объявленная как Public, является глобальной на уровне приложения и доступна из всех модулей. Такую переменную следует объявлять в разделе глобальных объявлений модуля. Если переменная объявлена в программном модуле, то в других модулях достаточно указать ее имя. Если переменная объявлена в форме, то из других форм и модулей доступ к ней возможен через конструкцию Имя- Формы. ИмяПеременной.
Переменные в программах на VBA можно не объявлять. В этом случае они по умолчанию имеют тин Variant. Необходимые преобразования типов при работе программы выполняются автоматически. Однако программы с такими переменными работают медленнее и менее надежны. Например, очень трудно заметить ошибку, вызванную элементарной опечаткой, когда в имени А1 вы в одном месте использовали русскую букву, а в другом – английскую. В результате у вас получились две переменные, имена которых на экране выглядят одинаково. Чтобы обезопасить себя от подобных ошибок, рекомендуется добавить в качестве первой строки каждого модуля инструкцию Option Explicit. В этом случае при обнаружении необъявленной переменной будет выводиться сообщение об ошибке.
Константы в VBA объявляются с помощью слова Const. Ниже приведено несколько примеров:
Const n = 10, eps = 0.0001
Const BDDate = #9/30/1993# 'формат даты месяц/день/год
Const Beg_time = #12:00:00# 'задано время
Const S = "Пример строки"
Public Const Version As Integer = 1001
VBA автоматически определяет тип константы по ее значению, но тип можно указать и явно, как это сделано в последнем примере. Если вы хотите объявить глобальную константу, то в добавление к слову Const следует использовать слово Public.
Для работы с текстом VBA использует тип String. В языке существуют два типа строк: фиксированной и переменной длины. Максимальная длина строки фиксированной длины равна 65 535 символов. Длина строки фиксированной длины указывается при объявлении переменной после символа "звездочка". Если при присваивании фактическое значение строки будет меньше, то строка дополняется пробелами справа, если больше – то сохраняются первые символы строки, лишние символы в конце строки теряются. Строки переменной длины теоретически могут содержать до 2 млрд символов. В следующем примере объявлены две переменные: Name и Text (Name имеет длину 20 символов, Text – переменную длину):
Dim Name As String * 20
Dim Text As String
В языке имеется большое количество встроенных функций для работы с различными типами данных.
Основные математические функции приведены в табл. 12.1.
Прежде чем описывать функции для работы с датами и временем (табл. 12.3), приведем возможные значения некото-
Таблица 12.1
Основные математические функции
Функция |
Описание |
Abs (число) |
Возвращает абсолютное значение числа |
Atn (число) |
Возвращает арктангенс числа |
Cos (число) |
Возвращает косинус угла, заданного в радианах |
Ехр (число) |
Возвращает результат возведения числа е в указанную степень |
Fix (число) |
Отбрасывает дробную часть числа и возвращает целое значение. Для отрицательного значения Fix возвращает ближайшее отрицательное целое число, большее либо равное указанному |
Int (число) |
Отбрасывает дробную часть числа и возвращает целое значение. Для отрицательного значения Int возвращает ближайшее отрицательное целое число, меньшее либо равное указанному |
Sgn (число) |
Возвращает натуральный логарифм числа |
Rnd [(число)] |
Возвращает случайное число, меньшее единицы и большее или равное нулю. Аргумент число определяет способ генерации случайного числа. Перед вызовом функции Rnd используйте инструкцию Randomize без аргумента для инициализации генератора случайных чисел значением, возвращаемым системным таймером |
Sgn (число) |
Возвращает 1, если число > 0; -1, если число < 0: 0, если число = 0 |
Sin (4Hcno) |
Возвращает синус угла, заданного в радианах |
Sqr (4HOio) |
Возвращает квадратный корень числа |
Таn (число) |
Возвращает тангенс угла, заданного в радианах |
рых параметров, которые используются в качестве аргументов этих функций (табл. 12.2).
Таблица 12.2
Параметры функций для работы с датами и временем
Параметр |
Описание |
|
Интервал |
Определяет нужный компонент даты. Возможные значения параметра: |
|
Год |
||
Квартал |
||
Месяц |
||
День года |
||
День месяца |
||
День недели |
||
Неделя |
||
Часы |
||
Минуты |
||
Секунды |
||
Первый_день |
Определяет, какой день недели считать первым. Если он опущен, первым днем недели считается воскресенье. Возможные значения параметра: |
|
0 |
Используется значение национальных системных установок |
|
1 |
Воскресенье (по умолчанию) |
|
2 |
Понедельник |
|
3 |
Вторник |
|
4 |
Среда |
|
5 |
Четверг |
|
6 |
Пятница |
|
7 |
Суббота |
|
Первая_неделя |
Определяет, какая неделя считается первой неделей года. Возможные значения параметра: |
|
0 |
Используется значение национальных системных установок |
|
1 |
Неделя, которая содержит 1 января (по умолчанию) |
|
2 |
Первая неделя, которая содержит, по крайней мере, четыре дня нового года |
|
3 |
Первая полная неделя года |
Таблица 12.3
Функции для работы с датами и временем
Функция |
Описание |
Date |
Возвращает значение, содержащее текущую системную дату |
Time |
Возвращает значение, содержащее текущее системное время |
Now |
Возвращает значение, содержащее текущую дату и время по системному календарю и часам компьютера |
Hour(время) |
Возвращает целое число (от 0 до 23 включительно), которое представляет часы в значении времени |
Minute(время) |
Возвращает целое число (от 0 до 59 включительно), которое представляет минуты в значении времени |
Second(время) |
Возвращает целое число (от 0 до 59 включительно), которое представляет секунды в значении времени |
Day (дата) |
Возвращает целое число (от 1 до 31 включительно), которое представляет день месяца в значении даты |
Моnth(дата) |
Возвращает целое число (от 1 до 12 включительно), которое представляет месяц в значении даты |
Year(дата) |
Возвращает целое число, представляющее год в значении даты |
Weekday(дата, [первый_день]) |
Возвращает целое число (от 1 до 7), представляющее номер дня недели в значении даты |
DateDiff (интервал, дата1, дата2 [, первый_день [. первая_неделя]]) |
Возвращает разность между двумя датами (дата2 – - дата1) в заданных интервалах (годах, днях, неделях, кварталах и т.д.). Если значение нецелое, то оно округляется с избытком. Поэтому, например, при сравнении дат 31 декабря и 1 января следующего года функция для интервала типа год ("уууу") возвращает значение 1, хотя разница между датами составляет всего один день |
DatePart(интервал, дата [, первый_день [, первая_неделя]]) |
Возвращает значение, содержащее компонент даты, указанный в параметре "интервал". Например, номер месяца, номер недели, номер дня в году и т.п. |
DateAdd(интервал, количество, дата) |
Возвращает новую дату, которая получена путем добавления к указанной дате заданного количества интервалов. Например, DateAdd("m", 1, "31-янв-04") возвратит дату "29-фев-04" |
DateSerial(под, месяц, день) |
Возвращает дату во внутреннем представлении системы, полученную из отдельных компонентов (года, месяца и дня). При указании аргументов функции можно использовать выражения |
TimeSerial (часы, минуты, секунды) |
Возвращает время во внутреннем представлении системы, полученное из отдельных компонентов (часов, минут и секунд). Аргументы могут быть выражениями |
Для преобразования значений различных типов в строку можно использовать функции, приведенные в табл. 12.4.
Таблица 12.4
Функции преобразования числовых значений в строку
Функция |
Значение |
Str(число) |
Возвращает значение, являющееся строковым представлением числа |
Format (выражение 1, формат]) |
Возвращает значение, отформатированное согласно инструкциям, заданным в описании формата. Можно представить числовые значения как дату, время, денежное значение или в специальном формате |
СStr(выражение) |
Возвращаемое значение зависит от выражения. Если выражение имеет тип Boolean, то возвращается строка "True" или "False", если тип Date, то строка в кратком системном формате даты. Для других числовых типов возвращается строка, содержащая число |
Обратное преобразование из строкового представления в другой тип можно выполнить с помощью функций CBool, CByte, CCur, CDate, CDbl, CDec, CInt, CLng, CSng, Cvar. Они преобразуют выражение, заданное в качестве аргумента, в значение соответствующего типа. Выражение может быть строковым или числовым. Можно также использовать функцию Vа1(строка), которая возвращает для заданного аргумента числовое значение с подходящим типом данных.
При преобразовании числовых данных в строку и обратно следует учитывать, что не все функции воспринимают национальные настройки. Подробнее об этом можно прочитать в справочной системе. Кроме того, во многих случаях преобразования значений из одного типа в другой выполняются автоматически, и можно вообще не использовать функции явного преобразования типов.
Функции для работы со строками, имеющиеся в УВД приведены в табл. 12.5.
Из переменных, констант, функций с помощью знаков операций и скобок можно конструировать выражения. Операции, имеющиеся в УВД для различных типов данных: • арифметические операции: сложение (+), вычитание или изменение знака (-), умножение (*), деление (/), целочисленное деление (), получение остатка от деления (mod), возведение в степень (^);
Таблица 12.5
Функции для работы со строками
Функция |
Описание |
Asc(crpoKa) |
Возвращает код первого символа строки |
Сhr(кодСимвола) |
Возвращает символ, соответствующий указанному колу |
LCase(cTpoKa) |
Возвращает строку, преобразованную к нижнему регистру |
UCase(cTpoKa) |
Возвращает строку, преобразованную к верхнему регистру |
Left(cтpoкa, длина) |
Возвращает строку, содержащую указанное число первых символов исходной строки |
Right(cTpoKa, длина) |
Возвращает строку, содержащую указанное число последних символов исходной строки |
Mid(CTpOKa, позиция [, длина]) |
Возвращает подстроку, начинающуюся в указанной позиции исходной строки и содержащую указанное число символов. Если длина подстроки не задана, то возвращаются все символы с указанной позиции до конца строки |
LTrim(cтpoкa) |
Возвращает копию строки, из которой удалены пробелы, находившиеся в начале строки |
RTrim(cтpoкa) |
Возвращает копию строки, из которой удалены пробелы, находившиеся в конце строки |
Тrim(строка) |
Возвращает копию строки, из которой удалены пробелы, находившиеся в начале и конце строки |
Len(cTpoKa) |
Возвращает число символов в строке |
InStr([позиция,] строка 1, строка2 [.0/1]) |
Возвращает позицию первого вхождения второй строки внутри первой строки. Поиск начинается с указанной позиции, а если она не задана, то с начала строки. Последний аргумент задает способ сравнения строк: 0 – двоичное сравнение (по умолчанию), 1 – посимвольное сравнение без учета регистра |
StrComp(строка1, строка2 [, 0/1]) |
Возвращает: -1, если строка1 < строка2; 0, если строка1 = строка2; 1, если строка 1 > строка2. Последний аргумент задает способ сравнения строк (см. InStr) |
String(длина, символ) |
Возвращает строку указанной дайны, состоящую из указанного символа. Для задания символа можно использовать код или строковое выражение, первый символ которого используется при создании строки |
Space(число) |
Возвращает строку, содержащую указанное число пробелов |
• операции над строками: конкатенация (&);
• операции сравнения: меньше (<), больше (>), меньше или равно (<=), больше или равно (>=), равно (=), не равно (<>), соответствие строки маске (Like), сравнение объектов (Is);
• логические операции: И (AND), ИЛИ (OR), отрицание (NOT), импликация (IMP), эквивалентность (EQV), исключающее ИЛИ (XOR).
Значение выражения может быть сохранено в переменной соответствующего типа. Для этого используется инструкция присваивания. В VBA присваивание обозначается знаком равно (=). Например:
N = "Иванов Иван Иванович”
S = "Уважаемый" & Mid(N, lnStr(1, N,"") + 1) & "!"
D = #12/25/2011#+ 10
LD = Format(DateSerial(Year(D), Month(D) + 1,0), "Medium Date")
После выполнения этих инструкций значением S будет строка "Уважаемый Иван Иванович!", значением D – дата 01/04/2012, значением LD – строка "31-янв-12".
Массив – это группа элементов одного типа. У всех этих элементов одно имя (имя массива), но разные порядковые номера (индексы). Для доступа к конкретному элементу нужно указать индекс элемента в массиве. Если индексов несколько, то они перечисляются через запятую.
Инструкция объявления массива имеет вид
Dim ИмяМассива([Размер]) [As ИмяТипа]
Кроме Dim можно использовать Public. Если тип не указан, элементы будут иметь тип Variant. Количество индексов и их возможные значения (размер массива) определяются внутри скобок в виде списка:
[НомПерв1 То] НомПосл1, [НомПерв2 То] НомПосл2, ...
Выражение НомПерв То НомПосл устанавливает диапазон изменения значений индекса. Нижняя и верхняя границы диапазона – это любые целые числа, в том числе и отрицательные. Обязательно указывается только верхняя граница индекса, нижняя граница по умолчанию равна нулю. После выполнения инструкции Option Base 1 в качестве значения нижней границы по умолчанию будет использоваться единица. Инструкцию нужно поместить перед первой процедурой модуля.
Если вы хотите объявить динамический массив, т. е. массив, у которого границы индексов зависят от переменных, то в объявлении массива размер не указывается (в скобках пусто). Для таких массивов размер определяется с помощью специальной инструкции Redim позднее, но сделать это нужно до первого обращения к его элементу:
ReDim [Preserve] ИмяМассива(Размер)
Инструкцию ReDim для массива можно выполнять несколько раз, изменяя его размер по мере необходимости. При переопределении содержимое элементов массива будет теряться. Если нужно сохранить эти значения, используйте ключевое слово Preserve.
Во время выполнения программы текущие значения границ индекса массива можно узнать с помощью функций Lbound и Ubound:
Lbound(ИмяМассива, НомерИндекса)
Ubound(ИмяМассива, НомерИндекса)
Параметр НомерИндекса по умолчанию равен единице, поэтому для первого индекса его можно не указывать.
Примеры объявления массивов:
Dim А(20) As Integer
'массив из 21 элемента, индекс изменяется с нуля
Dim В(-10 То 10) As Double 'тоже массив из 21 элемента
Dim С(1 То 10, 1 То 5) 'двумерный массив типа variant
Dim D() As Integer 'динамический массив
ReDim D(1 To n) 'определяем размер динамического массива
ReDim Preserve D(1 To n+10)
'изменяем размер массива, сохраняя данные
В VBA можно создавать составные пользовательские типы (аналоги записей Pascal или структур С), используя инструкцию Туре:
[Private | Public] Туре ИмяТипа
ИмяЭлемента [(Размер)] As Тип
[ИмяЭлемента [(Размер)] As Тип]
…
End Туре
Инструкцию Туре можно использовать только па уровне модуля (перед процедурами). Аргумент "размер" указывается в том случае, если элемент является массивом.
После того как тип определен, на него ссылаются так же, как на стандартный тип. Если объявлена переменная пользовательского типа, то к любой ее составляющей можно обратиться следующим образом:
ИмяПеременной.ИмяЭлементаВОбъявленииТипа
В качестве примера рассмотрим новый тип BirthDayType. В начале модуля нужно поместить следующее описание:
Type BirthDayType
BName As String * 20
BDay As Date
End Type
Каждая переменная этого типа будет содержать имя (BName) и дату рождения (BDay). Объявить переменную пользовательского типа BirthDayType и присвоить ей значение можно так:
Dim X As BirthDayType
X.BName = "Иван Иванович"
X.BDay = #10/20/1965#
Разветвленные алгоритмы предусматривают выполнение различных инструкций в зависимости от выполнения или невыполнения некоторых условий. Для реализации таких алгоритмов в программах на VBA используются инструкции If и Select Case.
Существуют две разновидности инструкции If: линейная и блочная. Линейная форма If предполагает, что вся конструкция размещается на одной строке. Инструкция имеет следующий синтаксис:
If Условие Then Инструкции [Else Инструкции]
Здесь под условием понимается любое логическое выражение, в частном случае – это просто операция сравнения. Если выражение имеет значение True, то выполняются инструкции, указанные после Then, в противном случае – инструкции, указанные после Else. Секция Else может отсутствовать, в этом случае при невыполнении условия ничего не делается. Если после Then или Else нужно написать несколько инструкций (но все в одной строке), то они разделяются двоеточием. Примеры линейной инструкции If:
If X > Y Then Max = X Else Max = Y
If A(i) >= 0 Then k = k + 1: B(k) = A(i)
Линейная форма If используется для программирования простых ветвлений. В более сложных случаях удобнее пользоваться блочной разновидностью инструкции If:
If Условие Then
Инструкции
[Elself Условие Then
Инструкции
[Else
Инструкции
End If
Выполнение инструкции начинается с проверки первого условия. Если оно истинно, то выполняется первая группа инструкций, после чего программа перейдет к выполнению инструкций, следующих за End If. Если первое условие ложно, то проверяется второе условие и т.д. Количество секций ElseIf может быть любым. Инструкции в секции Else выполняются в том случае, если все условия оказались ложными. Секции ElseIf и Else могут отсутствовать. Заканчивается блочный If всегда конструкцией End If в отдельной строке. Такая форма инструкции If позволяет запрограммировать любые ветвления. Среди инструкций, использующихся внутри If, могут быть другие инструкции If или циклы.
Пусть переменные а, Ь, с содержат коэффициенты квадратного уравнения ах2 + bх + с = 0. Напишем программу, которая находит решение этого уравнения.
Ответ помещается в переменную Ans в виде текстовой строки:
If а = 0 Then
If (b = 0) And (с = 0) Then
Ans = "X – любое число"
Elself (b = 0) And (со 0) Then
Ans = “Нет решения"
Else
Ans = "X = "&Format(-c / b, "Fixed")
End If
Else
d = b * b – 4 * a * c
If d >= 0 Then
Ans = "X1 = "&Format((-b + Sqr(d)) / (2 * a), "Fixed") &", "& _
"X2 = "&Format((-b – Sqr(d)) / (2 * a), "Fixed")
Else
Ans = "Нет действительных корней"
End If End If
В данном примере использованы вложенные инструкции If.
Для реализации выбора из нескольких вариантов также применяется инструкция Select Case, которая позволяет выполнять одну из нескольких групп инструкций в зависимости от значения выражения:
Select Case Выражение
[Case Список выражений
Инструкции] ...
[Case Else
Инструкции]
End Select
Анализируемое выражение указывается в первой строке после Select Case, в частном случае это может быть просто переменная. Тип выражения должен быть совместим с типом значений в строках Case. Управление получит та Case-строка, значение которой совпадет со значением анализируемого выражения. Значения в строках Case можно указывать явно (в том числе в виде списка через запятую), можно задать диапазон (используется ключевое слово То), можно использовать операторы сравнения (значение анализируемого выражения в этом случае обозначается словом Is). Секция Case Else используется для всех остальных значений.
Рассмотрим, как с помощью Select Case можно для текущей даты определить время года. Значением выражения в данном случае является номер месяца. В каждой секции Case указываются месяцы, относящиеся к одному времени года. Значения специально заданы по-разному, чтобы продемонстрировать возможности языка:
Select Case Month(Date)
Case Is < 3, 12
S = "Зима"
Case 3 To 5
S = "Весна"
Case 6, 7, 8
S = "Лето"
Case Else
S = "Осень"
End Select
Многократное автоматическое выполнение некоторых действий (инструкций) в программировании называют циклом. Повторяемые инструкции называются телом цикла. VBA как и большинство современных языков программирования, поддерживает несколько видов циклов.
Цикл For... Next применяют в тех случаях, когда заранее известно, сколько раз нужно выполнить инструкции:
For Счетчик цикла = Старт То Стоп [Step Шаг]
Инструкции
Next [Счетчик цикла]
Счетчик цикла – это обычная переменная. В начале выполнения цикла ее значение равно Старт. После выполнения тела цикла Next изменяет счетчик цикла на величину Шаг. Если после изменения счетчик меньше или равен Стоп, то тело цикла выполняется еще раз. Шаг по умолчанию равен единице, но можно сделать его любым, в том числе отрицательным. Если шаг отрицательный, то цикл выполняется до тех пор, пока значение счетчика больше или равно Стоп. В случае вложенных циклов рекомендуется после Next указывать имя переменной цикла. Для досрочного выхода из цикла используется инструкция Exit For.
В качестве примера применения цикла For ... Next рассмотрим вычисление максимального элемента массива А
Мах = А(1)
For i = 2 То n
If A(i) > Max Then Max = A(i)
Next
Циклы с условиями (While и Until) предназначены для ситуаций, когда количество проходов заранее неизвестно, но известно условие завершения цикла. Синтаксис инструкций:
Do While I Until Условие |
Do |
Инструкции |
Инструкции |
Loop |
Loop While I Until Условие |
Особенностью VBA является то, что в обоих случаях вы можете проверить условие и перед выполнением тела цикла, и после, как вам удобно. Разница между циклами While и Until состоит в том, что цикл While выполняется до тех пор, пока условие остается истинным, а цикл Until – до тех пор, пока условие в строке Until ложно. Для досрочного выхода из циклов используется инструкция Exit Do.
Большинство задач можно решить с помощью любой разновидности цикла. Приведем три различные реализации вычисления суммы чисел от 1 до п, в которых использованы разные типы циклов:
s = 0 |
s = 0 |
s = 0 |
For i = 1 To n |
i = 1 |
i = 1 |
s = s + i |
Do While i <= n |
Do |
Next |
s = s + i |
s = s + i |
i = i + 1 |
i = i + 1 |
|
Loop |
Loop Until i > n |
В VBA имеются два типа процедур: процедуры Sub (подпрограммы) и процедуры Function. Для краткости процедуры Sub обычно называют просто процедурами, а процедуры Function – просто функциями. Синтаксис процедуры:
[Private | Public] [Static] Sub Имя [(Параметры)]
[Инструкции]
[Exit Sub]
[Инструкции]
End Sub
Синтаксис функции выглядит несколько иначе:
[Private | Public] [Static] Function Имя [(Параметры)] [As Тип]
[Инструкции]
[Имя = Выражение]
[Exit Function]
[Инструкции]
[Имя = Выражение]
End Function
С помощью слова Public объявляют процедуру или функцию, которая будет доступна во всех модулях. Если требуется, чтобы процедура или функция была доступна только в пределах того модуля, где она объявлена, используют Private. Если при объявлении процедуры или функции использовано Static, то все объявленные внутри нее переменные сохраняются между вызовами этой процедуры.
В теле функции обязательно должна быть хотя бы одна инструкция присваивания значения имени функции. Так определяется возвращаемое функцией значение.
Для досрочного выхода из процедуры используется инструкция Exit Sub, для досрочного выхода из функции – Exit Function.
Процедуры и функции не могут быть вложенными, т.е. нельзя объявить процедуру или функцию внутри процедуры или функции.
Процедуры и функции могут иметь параметры. Параметры, которые указываются при определении функции, называются формальными, а параметры, подставляемые на место формальных при вызове, – фактическими. Параметры перечисляются через запятую. Каждый формальный параметр представляет собой следующую конструкцию:
[Optional] [ByVal | ByRef] Имя [As Тип] [= поУмолчанию]
ByVal указывает, что параметр передается по значению, ByRef – по ссылке. По умолчанию параметры передаются по ссылке. При использовании ByVal в процедуру передается только значение фактической переменной. У процедуры нет доступа к самой переменной, поэтому изменить ее внутри процедуры невозможно. При использовании ByRef в процедуру передается адрес фактической переменной, поэтому процедура может изменить значение этой переменной.
Optional указывает, что параметр не является обязательным. Необязательные параметры должны располагаться в конце списка. Для них можно задать значения по умолчанию.
Вызвать процедуру Sub можно, указав ее имя и фактические значения параметров или применив оператор Call. Если используется оператор Call, список параметров следует заключить в круглые скобки. Если Call опускается, скобки вокруг списка параметров не нужны.
Фактические параметры перечисляются через запятую. Необязательные параметры можно не указывать, но необходимые запятые нужно писать. В списке фактических параметров можно использовать имена параметров. В этом случае именованными должны быть все параметры, причем каждый из них имеет вид
ИмяПараметра:= Значение
Такие параметры можно перечислять в любом порядке. В этом случае запятые для обозначения отсутствующих необязательных параметров не нужны.
Пусть, например, у нас имеется две процедуры Proc1 и Рrос2:
Sub Prod ()
'тело процедуры
End Sub
Sub Proc2(P As Integer, Optional W As Integer = 0)
'тело процедуры
End Sub
Тогда мы можем вызвать их следующим образом:
Prod
Ргос2 12, 25 'параметры без скобок
Ргос2 12 'второй параметр по умолчанию равен нулю
Call Ргос2(12, 25) 'вызов с помощью Call, параметры в скобках
Proc2 W:=25, Р:=12 'использование именованных параметров
Функции обычно используют в выражениях. Чтобы получить возвращаемое функцией значение, надо указать имя функции и значения параметров. Параметры заключаются в скобки. Если возвращаемое значение функции не требуется, можно вызвать функцию так же, как процедуру Sub: опустить скобки и указать список параметров. Параметры функций и процедур задаются одинаково.
Так, например, можно вызвать стандартную функцию MsgBox, у которой второй и третий параметры (Buttons и Title) необязательные. В первых двух случаях возвращаемое значение присваивается переменной Ans, в трех остальных оно не используется, поэтому функция вызывается как процедура:
Ans = MsgBox("Закончить работу?'', 4, "Пример")
Ans = MsgBox(Title:="Пример", Рготр1:="Закончить работу?", _ Buttons:=4)
MsgBox "Работа завершена",, "Пример"
MsgBox ТШе:="Пример", Prompt:= "Работа завершена"
MsgBox "Работа завершена"