Пакеты прикладных программ / Учебно-методический комплекс / Конспект лекций / Лабораторные работы / Дополнительные материалы / Список литературы
2.5.2. VBA. Организация циклов |
- Циклы с фиксированным числом повторений ( циклы со счетчиком).
- Циклы с неопределенными числом повторений ( циклы с условием).
Фиксированные циклы
VBA предоставляет две управляющие структуры для организации фиксированного цикла: For … Next (цикл со счетчиком) и For Each … Next (цикл с перечислением). Оператор For … Next это типовой цикл со счетчиком, выполняющий заданное число итераций. Синтаксис оператора For … Next:For <счетчик> = <начЗначение> То <конЗначение> [Step <приращение>] <блок операторов> Next [<счетчик>]
Пример использования оператора For ... Next.
Листинг 9. Оператор For … Next
' ЗАДАЧА: Составить программу, которая получает два числа от пользователя. ' Складывает все числа в диапазоне, заданном этими двумя числами, а затем ' отображает результирующую сумму. Sub sample7() Dim i As Integer ‘счетчик цикла Dim sStart ‘начальное значение счетчика Dim sEnd ‘конечное значение счетчика Dim sSum As Long ‘результирующая сумма sStart = InputBox("Введите первое число:") sEnd = InputBox("Введите второе число:") sSum = 0 For i = CInt(sStart) To CInt(sEnd) sSum = sSum + i Next i MsgBox "Сумма чисел от " & sStart & " до " & sEnd & " равна: " & sSum End Sub
Оператор цикла For Each … Next относится к категории операторов объектного типа, т.е. применяется в первую очередь к коллекциям объектов, а также к массивам. Тело цикла выполняется фиксированное число раз, соответствующее числу элементов массиве или коллекции. Формат оператора For Each … Next:
For Each <элемент> In <группа> <блок операторов> Next [<элемент>]Циклы с условием используются в тех случаях, когда повторяющиеся действия нужно выполнять только при определенных условиях. Количество итераций не определено и в общем случае может быть равно нулю (в частности, для циклов с предусловием). VBA предлагает разработчикам несколько управляющих структур для организации циклов с условием:
- Четыре вида циклов Do..Loop, которые различаются типом проверяемого условия и временем выполнения этой проверки.
- Непрерываемый цикл While … Wend.
Do While <условие> <блок операторов> Loop
Листинг 10. Цикл Do While … Loop
' ЗАДАЧА: Составить программу, которая предусматривает ввод пользователем ' произвольной последовательности чисел. Ввод должен быть прекращен ' только после того, как сумма введенных нечетных чисел превысит 100. Sub sample8() Dim OddSum As Integer ‘сумма нечетных чисел Dim OddStr As String ‘строка с нечетными числами Dim Num ‘для приема вводимых чисел OddStr = "" ‘инициализация выходной строки OddSum = 0 ‘инициализация суммы OddSum Do While OddSum < 100 ‘начало цикла Num = InputBox("Введите число: ") If (Num Mod 2) <> 0 Then ‘проверка на четность OddSum = OddSum + Num ‘изменение суммы OddSum OddStr = OddStr & Num & " " End If Loop 'вывод строки с нечетными числами: MsgBox prompt:="Нечетные числа: " & OddStr End Sub
Оператор Do … Loop While предназначен для организации цикла с постусловием. Условие проверяется после того, как тело цикла, будет выполнено хотя бы один раз. Цикл продолжает свою работу, пока <условие> остается истинным. Формат цикла Do … Loop While:
Do <блок операторов> Loop While<условие>
Листинг 11. Цикл с постусловием
' ЗАДАЧА: Составить программу игры "Угадай число". Программа должна случайным ' образом генерировать число в диапазоне от 1 до 1000, пользователь должен ' угадать это число. Программа на каждое вводимое число выводит подсказку ' "больше" или "меньше". Sub sample8() Randomize Timer ' инициализация генератора случайных чисел Dim msg As String ' строка сообщения Dim SecretNumber As Long, UserNumber As Variant Begin: SecretNumber = Round(Rnd * 1000) ' число, сгенерированное компьютером UserNumber = Empty ' число, вводимое пользователем Do ' игровой процесс Select Case True Case IsEmpty(UserNumber): msg = "Введите число" Case UserNumber > SecretNumber: msg = "Слишком много!" Case UserNumber < SecretNumber: msg = "Слишком мало!" End Select UserNumber = InputBox(prompt:=msg, Title:="Угадай число") Loop While UserNumber <> SecretNumber ' проверка If MsgBox("Играть еще? ", vbYesNo + vbQuestion, "Вы угадали!") = vbYes Then GoTo Begin End If End Sub
Циклы Do Until … Loop и Do … Loop Until являются инверсиями ранее рассмотренных циклов с условием. В общем случае они работают аналогично, за исключением того, что тело цикла выполняется при ложном условии (т.е. <условие>=False). Формат цикла Do Until … Loop:
Do Until <условие> <блок операторов> Loop
Формат цикла Do … Loop Until:
Do <блок операторов> Loop Until<условие>
Практическое задание: Перепишите программы из листингов 10 и 11 с использованием инвертированных операторов цикла.
Цикл While … Wend также относится к циклам с условием. Данный оператор полностью соответствует структуре Do While … Loop. Формат цикла While … Wend:
While <условие> <блок операторов> Wend
Отличительной особенностью этого оператора является невозможность принудительного завершения (прерывания) тела цикла (оператор Exit Do не работает в цикле While … Wend).
Для досрочного завершения итерации и выхода из цикла применяется оператор Exit. Этот оператор применим в любой циклической структуре, кроме While ... Wend. Общий синтаксис использования Exit для прерывания цикла таков:<начало_цикла> [<блок операторов1>] Exit (For | Do) [<блок операторов2>] [Exit (For | Do)] ... <конец_цикла>
При выполнении оператора Exit цикл прерывается, и управление передается оператору, следующему за оператором <конец_цикла>. В теле цикла может присутствовать несколько операторов Exit.
Листинг 12. Принудительный выход из цикла
Sub sample9() For i = 1 To 10000000 If i = 10 Then Exit For ' выход из цикла, когда счетчик достигнет 10 Next End SubVBA поддерживает два типа подпрограмм: процедуры и функции.
- Функция — это подпрограмма, которая возвращает результат. Вызов функции является выражением, и может использоваться в других выражениях или в правой части оператора присваивания.
- Процедура — это любая подпрограмма, которая не является функцией. Любой макрос VBA является подпрограммой типа "процедура".
Sub <имяПроцедуры> [(<списокПараметров>)] <операторы> End Sub
- где:
- <имяПроцедуры> – любой допустимый идентификатор VBA;
- <списокПараметров> – список формальных параметров процедуры, если он пуст, то такая процедура является макросом;
-
<операторы> - любая последовательность операторов VBA.
Листинг №.13 Пример объявления процедуры
' Процедура выводит в отладчик максимальное из трех чисел Sub sMax3(A As Long, B As Long, C As Long) If (A > B) And (A > C) Then Debug.Print "Max is "; A ElseIf (B > A) And (B > C) Then Debug.Print "Max is "; B Else Debug.Print "Max is "; C End If End Sub
Синтаксис объявления функции несколько сложнее, чем синтаксис процедуры:
Function <имяФункции> [(<списокПараметров>)] [As <типФункции>] <операторы> . . . <имяФункции> = <возвращаемое_значение> [<операторы>] End Function
- где:
- <имяФункции> - любой допустимый идентификатор;
- <списокПараметров> – список формальных параметров процедуры;
- <типФункции> - имя любого поддерживаемого VBA типа данных;
- <операторы> - любая последовательность операторов VBA.
-
<возвращаемое_значение> - результат, передаваемый в вызывающую программу.
Листинг №14. Пример объявления функции
' Функция возвращает максимальное из трех чисел Function fMax3(A As Long, B As Long, C As Long) As Long If (A > B) And (A > C) Then fMax3 = A ElseIf (B > A) And (B > C) Then fMax3 = B Else fMax3 = C End If End Function
Подпрограммы VBA могут принимать для обработки формальные параметры, указываемые при объявлении. При вызове они заменяются фактическими параметрами, т.е. реально используемыми в вызывающей программе. В VBA список формальных параметров подпрограммы представляет имена переменных, разделенных запятой. При этом желательно указать тип каждой переменной:
Function | Sub <имяПроцедуры> (<параметр1> As <тип>, _ <параметр2> As <тип>, ..., <параметрN> As <тип>)
Если тип данных параметра не указан, то автоматически будет использован тип Variant. Список параметров может быть пустым как для процедуры, так и для функции. В этом случае после имени процедуры ставятся пустые круглые скобки. При передаче фактических параметров в подпрограмму может использоваться один из двух различных способов:
- передача по значению;
- передача по ссылке.
Способ передачи указывается при описании параметров в строке объявления подпрограммы. Имени параметра может предшествовать один из явных описателей способа передачи:
- ByRef – задает передачу по ссылке;
- ByVal – задает передачу по значению.
Листниг 15. Передача параметров в подпрограмму
' sample10 - вызывающая программа (макрос) ' ByValByRefDemo - вызываемая процедура Sub sample10() Dim a As Long, b As Long, c As Long ' фактические параметры a = 10 b = 10 c = 10 ByValByRefDemo a, b, c ' передача фактических параметров Debug.Print "2: " & "a = " & a & "; b = " & b & "; c = " & c End Sub Sub ByValByRefDemo(x As Long, ByVal y As Long, ByRef z As Long) ' выполнение действий над формальными параметрами x = x * 2 y = y * 3 z = z * 4 Debug.Print "1: " & "x = " & x & "; y = " & y & "; z = " & z End Sub
Здесь объявлены две процедуры: sample10 и ByValByRefDemo. Процедура sample10 вызывает процедуру ByValByRefDemo и передает ей предварительно инициализированные переменные a, b и c. Процедура ByValByRefDemo получает значения переменных a, b и c в виде формальных параметров x, y и z соответственно, выполняет над ними указанные действия, выводит результат и завершается. После возврата из подпрограммы процедура sample10 выводит значения переменных a, b, c в окно отладчика (рис. 4).
Рис. 4. Передача параметров в подпрограмму
Именованные параметры
При вызове подпрограмм в VBA параметры необходимо передавать в определенном порядке. Отсутствующие необязательные параметры отмечаются запятыми. Нарушение этого правила часто приводит к ошибкам – легко пропустить или поменять местами параметры. Чтобы избежать этих проблем, в VBA можно использовать именованные параметры функций. Для этого в вызове подпрограммы явно указываются имена параметров (как это было задано при объявлении подпрограммы), каждому из которых присваивается требуемое значение с помощью оператора ":=" ("двоеточие_равно"). При использовании именованных параметров можно не обозначать отсутствующие параметры и, кроме того, порядок перечисления параметров может быть произвольным.Следующий пример показывает два обращения к функции MsgBox, которые имеют один и тот же результат:
' обычный вызов MsgBox "Здравствуй, мир!", , "Окно приветствия" ' вызов, с использованием именованных параметров MsgBox Prompt:= "Здравствуй, мир!", Title:= "Окно приветствия"
Вызов подпрограмм
Подпрограммы могут быть вызваны различными способами:-
Процедуру (Sub)с непустым списком параметров можно вызвать только из другой процедуры или функции так:
<имяПроцедуры> <списокПараметров>
Или так:
Call <имяПроцедуры> (<списокПараметров>) ’использована инструкция Call.
-
Процедура с пустым списком параметров рассматривается VBA как командный макрос. Ее также можно вызвать двумя способами:
- из другой процедуры или функции;
- с помощью комбинации клавиш быстрого вызова, команд меню или кнопок панелей инструментов.
- Функцию (Function) можно вызывать точно так же, как и процедуру, в виде отдельного оператора. В этом случае возвращаемое функцией значение игнорируется.
Листинг №16. Вызов процедуры
Sub sample11() ' вызывающий макрос Dim usr As String usr = InputBox("Login") Hello usr ' вызов процедуры Hello
без Call Call Hello(usr) ' использование инструкции Call End Sub ' процедура принимает один параметр, формирует строку сообщения, ' выводит сообщение в окно отладчика Sub Hello(usrname As String) Debug.Print "Hello, " & usrname & "!" End Sub
Если в проекте используется несколько подпрограмм с одинаковыми названиями (это возможно, если они в разных модулях), то при их вызове перед именем подпрограммы надо указывать (через точку) имя модуля, в котором процедура расположена:
<имяМодуля>.<имяПроцедуры> <списокФактическихПараметров>
Например
MyModule.MySub fArg, sArg ' вызов процедуры из модуля MyModule
<имяПроекта>.<имяМодуля>.<имяПроцедуры> <списокФактическихПараметров>
Например
someVal = MyProject.MyModule.MyFunc(fArg, sArg) ' вызов функции из проекта MyProject
Прерывание подпрограммы
В случае необходимости, выполнение процедуры или функции может быть прервано досрочно. Для этого нужно использовать инструкцию прерывания Exit Sub. В этом случае синтаксис объявления примет следующий вид (на примере объявления процедуры):Sub <имяПроцедуры> [(<списокпараметров>)] <операторы> Exit Sub <операторы> End SubЛюбая программа на VBA представлена в виде проекта. Проект - это совокупность программных модулей различных типов. В свою очередь модуль - это основная программная единица уровня проекта, в которой размещаются описания и реализация переменных, констант, типов, подпрограмм и т.д. Имеется три типа модулей:
- Стандартные модули - это модули, в которых можно описать доступные во всем проекте процедуры.
- Модули класса содержат описание свойств, методов и событий пользовательского класса.
- Модули форм содержат процедуры обработки событий, генерируемых элементами управления в форме.
Структура модуля VBA включает два неявных (т.е. не требующих специального описания) раздела: общий (General) и объявлений (Declarations). В общем разделе задаются параметры среды (Option Base, Option Explicit), приводятся описания глобальных переменных, констант и типов. Раздел объявлений предназначен для описания процедур и функций.
VBA поддерживает две области видимости для переменных и подпрограмм: локальную и глобальную.Локальные переменные определены на уровне подпрограммы с помощью ключевых слов Dim или Static. Они доступны только внутри этой подпрограммы и по выходу из нее уничтожаются. Глобальные переменные объявляются на уровне модуля. Такие переменные доступны:
- для всех подпрограмм модуля, в котором они объявлены (при объявлении с ключевым словом Private, либо Dim);
- для всего приложения – при объявлении с ключевым словом Public;
Public Sub Query(price, count) ' видимость на уровне проекта Private Sub Sub Query(price, count) ' видимость на уровне модуля
По умолчанию используется уровень проекта.
При описании локальных переменных можно использовать ключевое слово Static. Такие переменные являются статическими и сохраняют значения между вызовами.
Встроенные функции VBA
В языке программирования VBA предусмотрено несколько десятков встроенных функций. Они доступны в любой программе на языке VBA, при этом безразлично, в среде какого программного продукта мы находимся — Excel, Word, Access или, к примеру, AutoCAD. Используются они очень активно, и во многих ситуациях без них не обойтись. Встроенные функции обычно группируют по назначению: математические, строковые, преобразования типов, логические и т.п. В справке по VBA имеется подробная информация о всех встроенных функциях. Здесь же приведем краткое описание только некоторых.Функции приведения типов
Используются для конвертации типов данных. Вот перечень этих функций: CBool(), CByte(), CCur(), CDate(), CDbl(), CDec(), CInt(), CLng(), CSng(), CStr(), CVar(), CVDate(), CVErr() . Просмотреть, что в итоге получилось, можно при помощи функции TypeName() , например: nVar1 = CInt(InputBox("Введите значение"))
MsgBox TypeName(nVar1)
Кроме того, еще несколько полезных для конвертации функций:
- Str() — позволяет перевести числовое значение в строковое, при этом вставляет пробел впереди для положительных чисел.
- Val() — извлекает из строки числовое значение (до первого нечислового символа, кроме точки). Очень удобно, когда вперемежку с числовыми данными прописываются единицы измерения или валюта.
Строковые функции
- Left(), Right(), Mid() — получить фрагмент строки слева, справа или из середины исходной строки соответственно.
- Len() — получить число символов в строке.
- LCase() и UCase() — перевести строку в нижний и верхний регистры соответственно.
- LSet() и RSet() — заполнить строку символами без изменения длины (соответственно слева и справа). Лишние символы обрезаются, на место недостающих подставляются пробелы.
- LTrim(), RTrim(), Trim() — убрать пробелы соответственно слева, справа или и слева, и справа.
- Replace() — заменить в строке одну последовательность символов на другую.
- StrComp() — сравнить две строки.
- StrReverse() — "перевернуть" строку, разместив ее символы в обратном порядке.
Математические функции
Функций для работы с числовыми значениями в VBA очень много. Приведем только некоторые из них.- ABS() — эта функция возвращает абсолютное значение переданного ей числа.
- Int(), Fix() и Round() позволяют по разному округлять числа: Int возвращает ближайшее меньшее целое, Fix() отбрасывает дробную часть, Round() округляет до указанного количества знаков после запятой.
-
Rnd() и команда
Randomize используются для получения случайных значений. Обычный синтаксис при применении Rnd выглядит так:
-
случайное_число = Int(минимум + (Rnd()* максимум)) MsgBox(Int(1 + (Rnd() * 100)))
-
Перед вызовом функции Rnd() следует выполнить команду Randomize для инициализации генератора случайных чисел.
-
- Sgn() — позволяет вернуть информацию о знаке числа. Возвращает 1, если число положительное, -1, если отрицательное и 0, если проверяемое число равно 0.
Функции для работы с датой и временем
Основные функции VBA для работы с датой/временем:- Date() — возвращает текущую системную дату.
- Time() возвращает текущее системное время, а Now() — дату и время вместе.
- DateAdd() — возможность добавить к дате указанное количество лет, кварталов, месяцев и так далее — вплоть до секунд.
- DateDiff() — возможность получить разницу между датами.
- DatePart() — возвращает указанную часть даты (например, только год, только месяц или только день недели).
- DateSerial() — формирует значение даты на основе передаваемых символьных значений. То же самое делает DateValue(), отличия — в формате принимаемых значений. Аналогичным образом (для времени) работают TimeSerial() и TimeValue().
- Day() (а также Year(), Month(), Weekday(), Hour(), Minute(), Second()) — специализированные заменители функции DatePart(), которые возвращают нужную часть даты.
- MonthName() — возвращает имя месяца словами по его номеру. Возвращаемое значение зависит от региональных настроек. Если они русские, то вернется русское название месяца.
- Timer() — возвращает количество секунд, прошедших с полуночи.
Функции взаимодействия с пользователем
Для организации диалога с пользователем VBA представляет две встроенные функции - MsgBox и InputBox. Окно сообщений MsgBox выводит сообщения для пользователя, а окно ввода InputBox обеспечивает возможность получения информации от пользователя.Функция MsgBox() выводит на экран диалоговое окно, содержащее сообщение, устанавливает режим ожидания нажатия кнопки пользователем, а затем возвращает значение типа Integer, указывающее, какая кнопка была нажата.
Формат функции MsgBox:
MsgBox (Prompt [, Buttons] [, Title] [, HelpFile, Context])
Назначение параметров:
- Prompt – строковое выражение, отображаемое как сообщение в диалоговом окне;
- Title – строковое выражение, отображаемое в строке заголовка диалогового окна. Если этот параметр опущен, в строку заголовка помещается имя приложения, из которого запускается программа VBA;
- HelpFile – строковое выражение, определяющее имя файла справки, содержащего справочные сведения о данном диалоговом окне; обычно это файл, который вы уже должны были создать с помощью Windows Help Compiler. Если этот параметр указан, необходимо также указать параметр Context;
- Context – числовое выражение, определяющее номер соответствующего раздела справочной системы. Если этот параметр указан, необходимо указать также параметр HelpFile;
- Buttons – числовое выражение, которое задает количество и тип кнопок в диалоговом окне MsgBox. Buttons указывает также кнопку по умолчанию в диалоговом окне и содержит ли это диалоговое окно стандартные значки Windows для предупредительных сообщений и запросов пользователя. Значения Buttons можно получить из справочной системы.
Sub sample3() MsgBox "Видите ли вы две кнопки?", vbYesNo + vbInformation, "Сообщение" End Sub
В данном примере MsgBox применяется не в виде функции, а в виде процедуры (т.е. не возвращает никакого значения). Следовательно, код выбранной кнопки нигде не сохраняется и не может быть использован. Чтобы определить, какая кнопка была нажата, MsgBox необходимо вызвать как функцию, т.е. сохранить возвращаемое значение в переменную (Листинг 17.
Листинг 17. Использование MsgBox
Sub sample4() Dim res ' объявляем переменную ' вызываем MsgBox и сохраняем значение в переменной res = MsgBox("Видите ли вы две кнопки?", vbYesNo + vbInformation, "Сообщение") Debug.Print res ' печатаем полученное значение End Sub
При выполнении этого макроса, когда пользователь выбирает кнопку Yes или No в переменной res сохраняется число, соответствующее выбранной кнопке.
Вместо возвращаемых функцией MsgBox целочисленных значений удобнее пользоваться предопределенными константами VBA. В таб. 11 приведены возвращаемые значения констант функции MsgBox.
Таблица 11. Возвращаемые значения функции MsgBox
| Константа | Означает, что пользователь нажал кнопку |
| vbAbort | Стоп (Abort) |
| vbCancel | Отмена (Cancel) |
| vbIgnore | Пропустить (Ignore) |
| vbNo | Нет (No) |
| vbOk | Ок |
| vbRetry | Повтор (Retry) |
| vbYes | Да (Yes) |
Листинг 18. Проверка возращаемого значения MsgBox
Sub sample5() ' вызываем MsgBox и сохраняем значение в переменной res = MsgBox("Видите ли вы две кнопки?", vbYesNo + vbInformation, "Сообщение") ' проверяем, какая кнопка нажата If res = vbYes Then : MsgBox "Вы нажали Yes", , "Результат выбора" Else : MsgBox "Вы нажали No", , "Результат выбора" End If End Sub
Функция InputBox() выводит на экран диалоговое окно, содержащее сообщение и поле ввода, устанавливает режим ожидания ввода текста, а затем возвращает значение типа String, содержащее текст, введенный в поле. Формат функции InputBox:
InputBox (Prompt [, Title] [, Default] [, XPos] [, Ypos] [, HelpFile, Context])
Назначение параметров:
- Prompt – строковое выражение, отображаемое как сообщение в диалоговом окне;
- Title – строковое выражение, отображаемое в строке заголовка диалогового окна. Если этот параметр опущен, в строку заголовка помещается имя приложения;
- Default – строковое выражение, отображаемое в поле ввода и используемое по умолчанию, если пользователь не введет другую строку. Если этот параметр опущен, поле ввода изображается пустым;
- Xpos и Ypos – числовые выражения, которые указывают местоположение окна ввода и являются координатами верхнего левого угла диалогового окна; Xpos – горизонтальное расстояние от левого края окна; Ypos – вертикальное расстояние от верхнего края окна. Если эти параметры опущены, диалоговое окно выравнивается по центру экрана;
- HelpFile – строковое выражение, определяющее имя существующего файла справки, содержащего справочные сведения о данном диалоговом окне. Если этот параметр указан, необходимо также указать параметр Context;
- Context – числовое выражение, определяющее номер соответствующего раздела справочной системы. Если этот параметр указан, необходимо указать также параметр HelpFile.
Sub sample6() Dim username As String username = InputBox("Введите ваше имя ", "Пример 6") MsgBox ("Здравствуйте, "+username) End Sub
В результате выполнения этого макроса на экран последовательно выводятся диалоговые окна ввода и вывода (рис. 5).
Рис. 5 Интерактивные функции VBA
Структурные типы данных
Кроме простых типов VBA предоставляет возможность создавать и использовать структурные типы данных. Структурный тип данных – это тип данных, который позволяет в одной величине хранить одновременно несколько значений. К структурным типам данных VBA относятся массивы и пользовательские типы данных. Массив – это упорядоченная совокупность данных одного типа. Порядок элементов массива задается индексами его элементов. Количество элементов определяет размер массива, а количество индексов (в VBA - до 60) - его размерность. VBA поддерживает статические и динамические массивы.Статический массив имеет фиксированный размер и размерность, заданные при объявлении и неизменяемые в ходе выполнения программы. Синтаксис объявления статического массива:
(Public | Private | Dim) <имяМассива> (<размер1>, <размер2>, ..., <размер N>) As <типДанных>
Указанные в скобках величины <размер1>, <размер2>, …, <размер N> задают количество индексов и максимально допустимое значение для каждого конкретного индекса (его верхняя граница). Таким образом, определяются размерность массива (количество индексов) и размер массива – количество элементов данного массива. При этом индексирование элементов массива по умолчанию начинается с нуля. Так, объявление
Dim Array1 (9) As Integer,
определяет одномерный массив из 10 целых чисел, а объявление
Dim Array3 (4, 9) As Variant,
определяет двумерный массив из пятидесяти (5х10) элементов типа Variant.
В VBA имеется возможность изменить индекс нижней границы с помощью оператора Option Base (указание Option Base 1 или Option Base 0 в общем разделе модуля). Более того, при объявлении массива можно явно указать и верхнюю, и нижнюю границы. Синтаксис оператора объявления массива с указанием границ для индексов:
Dim <имяМассива> (<мин1> To <макс1>[, ..., <минN> To <максN>]) As <типДанных>
Примеры:
Dim A (1 To 3, 1 To 3) As Single Dim B (1 To 12) As Integer
Правила инициализации элементов массива такие же, как и для переменных того типа, который использован при объявлении массива. Доступ к элементам массива выполняется по индексу. Листинг 19 иллюстрирует работу с одномерным массивом.
Листинг 19. Обращение к элементам массива
' ЗАДАЧА: Сгенерировать 10 случайных целых чисел от 0 до 100, ' записать их в массив и вывести в окно отладчика Sub sample14() Randomize Timer ' запуск генератора случайных чисел Dim myarr(1 To 10) As Long ' объявление массива ' запись чисел в массив For i = 1 To 10 myarr(i) = Round(Rnd * 100) Next ' чтение элементов массива и вывод значений в отладчик For i = 1 To 10 Debug.Print myarr(i) Next End Sub
Удобным способом определения одномерных массивов является функция Array, преобразующая список элементов, разделенных запятыми, в массив из этих значений:
Dim A As Variant A = Array (10, 20, 30) B = A(2)
В данном примере переменная А создается как одномерный массив, состоящий из трех элементов (10, 20, 30), а переменная В принимает значение второго элемента массива А (20).
VBA поддерживает использование динамических массивов, размер и размерность которых может изменяться во время выполнения программы. Объявление динамического массива аналогично объявлению статического, но при этом не задаются ни размер, ни размерность:
Dim <имяМассива> () As <типДанных>
Для указания и изменения размеров такого массива используется специальный оператор - ReDim:
ReDim <имяМассива> (<размер1>, <размер2>, ..., <размер N>)
Размерность и размер определяется динамически в той процедуре и в тот момент, когда они становится фактически известной. Обратите внимание, в этом операторе границы изменения индексов можно задать не только как константы, но и как выражения, зависимые от переменных.
Для повторных изменений массива можно снова использовать оператор переопределения ReDim. При каждом переопределении динамического массива все его значения теряются. Чтобы сохранить все ранее полученные элементы необходимо использовать ключевое слово Preserve при переопределении.
Листинг 20 демонстрирует работу с динамическим массивом (нумерация строк приведена только для удобства пояснений).
Листинг20. Работа с динамическим массивом
1: Public Vector() As Integer 2: Public Sub DMassiv() 3: Dim N As Byte, I As Byte 4: 5: N = InputBox("Введите фактическую размерность вектора") 6: ReDim Vector(N) 7: For I = 1 To N 8: Vector(I) = 2 * I + 1 9: Next I 10: 11: 'Массив расширяется с сохранением ранее вычисленных элементов 12: ReDim Preserve Vector(2 * N + 1) 13: For I = N + 1 To 2 * N + 1 14: Vector(I) = 2 * I 15: Next I 16: Debug.Print "Элементы массива Vector:" & Chr(13) 17: For I = 1 To 2 * N + 1 18: Debug.Print Vector(I) 19: Next I 20: End Sub
Поясним приведенный код. Сначала на уровне модуля объявляется глобальный динамический массив Vector (строка 1). В момент объявления размерность динамического массива не указывается, соответственно не выделяется память. Все это произойдет позже, в процессе выполнения программы. Далее приводится одна из возможных процедур, работающая с этим массивом Vector. В строке 12 массив переопределяется (увеличивается его размер) с сохранением предыдущих значений. Затем массив расширяется (цикл в строках 13-15). В последнем цикле (строки 17-19) значения элементов сформированного массива выводятся в окно отладки (Immediate).
В рассмотренном примере изменялся размер динамического массива, но не его размерность (массив оставался одномерным). Приведем фрагмент кода программы, в котором изменяются и размер, и размерность динамического массива:
1: Sub sample22 () 2: Dim dArray ( ) As Variant 3: ReDim dArray(1,2) 4: dArray(0,0) = 2 5: dArray(0,1) = 3 6: k = dArray(0,0) + dArray (0,1) 7: ReDim dArray(k) 8: dArray(0) = "Строка1" 9: End Sub
В этом примере массив dArray сначала определяется как двумерный массив из шести элементов (2x3) (строка 3), а затем переопределяется как одномерный массив, причем верхняя граница индекса задается значением k (строка 7).
Динамические массивы с успехом можно применять там, где необходимы динамические структуры данных, например списки, стеки, очереди.
VBA поддерживает возможность создавать пользовательские типы данных на основе ранее определенных типов. Такой тип в VBA называется User-defined type (UDT) - тип, определенный пользователем. Это соответствует понятиям типа данных record (запись) в языке Pascal или struct (структура) в языке С/С++. Для создания пользовательского типа предназначен оператор Type. Он позволяет на уровне модуля определить структуру данных, включающую другие разнородные, но логически связанные переменные различных типов. После описания типа на его основе можно создавать и использовать переменные.Синтаксис оператора Type:
Type <имяТипа> <имяЭлемента1> As <тип> <имяЭлемента2> As <тип> End Type
- где:
- <имяТипа> – имя пользовательского типа данных;
-
<имяЭлемента> – имя структуры, составляющей новый тип данных.
С помощью ключевых слов Private и Public можно задать область видимости создаваемого типа. Опции Private и Public указываются в строке объявления типа перед ключевым словом Type.
Листинг 21. Пример использования пользовательского типа
' Тип TStudent хранит информацию о студенте. Public Type TStudent ID As Long 'идентификатор LastName As String 'фамилия FirstName As String 'имя MiddleName As String 'отчество BirthDay As Date 'дата рождения End Type ' Учебная группа Public Type TGroup Num As String * 10 'номер группы Students() As TStudent 'список (массив) студентов End Type ' Объявления переменных Private stud As TStudent ' студент Public group As TGroup 'группа
Для обращения к элементам пользовательского типа (полям структуры) используется точечная нотация:
<имяПеременнойUDT>.<имяЭлемента>
Листинг22. Работа с переменными пользовательского типа
Sub sample20() ReDim group.Students(10) group.Num = "АС-1234" group.Students(0).LastName = "Петров" group.Students(0).FirstName = "Иван" Debug.Print group.Num & group.Students(0).LastName & " " & group.Students(0).FirstName End Sub
Широкие возможности, представляемые программисту пользовательским типом имеют ограничение: все операции должны выполняться на уровне полей. Единственная разрешенная операция — присваивание (листинг 23).
Листинг 23. Операции над пользовательским типом
Sub sample21() Dim group1 As TGroup, group2 As TGroup ReDim group1.Students(25) ReDim group2.Students(28) group1.Num = "AS-1234" group2.Num = "AS-5678" Debug.Print "1: "; group1.Num, group2.Num ' If group2 > group1 Then ... - Это вызовет ошибку If UBound(group2.Students) > UBound(group1.Students) Then ' Так можно group1 = group2 ' Так тоже можно End If Debug.Print "2: "; group1.Num, group2.Num End Sub
← 2.5.1 VBA. Ветвления ↑ 2.5.2. VBA. Организация циклов Тема 2.6 Объектно-ориентированное программирование в VBA →




