Использование переменных в VBA

Примеры использования переменных присутствуют во всех программах данного практикума. Здесь же мы познакомимся поближе с объектными переменными и переменными пользовательского типа.

Объектные переменные

Как вы знаете, объектная переменная используется для ссылки на объект. Они объявляются и задаются немного иначе, чем остальные переменные. Ниже представлен фрагменте кода, в котором объектная переменная сначала объявляется, а затем ей присваивается значение: Range1- это первая ячейка первого листа.

Dim Range1 As Object

Set Range1 = Worksheets(1).Range("A1")

Предположим, что в программе Оформление из параграфа 2.3 (стр. 36) нам необходимо указывать «полный» адрес диапазона ячеек A1:A10. Очевидно, что программа окажется перегруженной и трудной для восприятия.

Sub ОформлениеПолнаяСсылка()

Workbooks("Случайные числа.xls"). _

WorkSheets("Случ. числа").Range("A1:A10").Font.Italic = True

With Workbooks("Случайные числа.xls"). _

WorkSheets("Случ. числа")Range("A1:A10"). _

Borders(xlEdgeLeft)

.LineStyle = xlDot

.ColorIndex = 5

End With

. . .

' на досуге можете ввести остальные команды! J

End Sub

Введя объектную переменную, мы существенно сократим программу, сделаем её простой и более наглядной. В следующем коде объектная переменная MyRange – это диапазон ячеек A1:A10, расположенный в книге Случайные числа.xls на листе Случ. числа:

1) Sub ОформлениеОбъектнаяПеременная()
2) Dim MyRange As Object
3) SetMyRange = Workbooks("Случайные числа.xls"). _ WorkSheets("Случ. числа").Range("A1:A10")
4) MyRange.Font.Italic = True
5) With MyRange.Borders(xlEdgeLeft)
6) .LineStyle = xlDot
7) .ColorIndex = 5
8) End With
9) With MyRange.Borders(xlEdgeTop)
10) .LineStyle = xlDot
11) .ColorIndex = 5
12) End With
13) With MyRange.Borders(xlEdgeBottom)
14) .LineStyle = xlDot
15) .ColorIndex = 5
16) End With
17) With MyRange.Borders(xlEdgeRight)
18) .LineStyle = xlDot
19) .ColorIndex = 5
20) End With
21) With MyRange.Borders(xlInsideHorizontal)
22) .LineStyle = xlDot
23) .ColorIndex = 5
24) End With
25) Range("A1").Select
26) End Sub

Задания:

1. В Модуль3 наберите программу ОформлениеОбъектнаяПеременная.

2. На листе Случ. числа очистите форматы, активизируйте другую книгу и запустите программу ОформлениеОбъектнаяПеременная.

Пользовательский тип данных

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

В Модуль3 наберите следующий код и выполните программу:

Type Персона

Имя As String

ДатаРождения As Date

Возраст As Integer

End Type

Sub ПользовательскийТипПеременной()

Dim User1 AsПерсона

User1.Имя = "Иванов”

User1.ДатаРождения = #2/23/75#

User1.Возраст = Year(Date) - Year(User1.ДатаРождения)

MsgBox User1. Имя & ", возраст " & User1.Возраст & _

" дата рождения " & User1.ДатаРождения

End Sub

Обратите внимание на встроенные функции Date, которая возвращает текущую системную дату и Year, которая возвращает год из указанной даты. Первый раз год возвращается из текущей даты, которую определяет функцияDate, второй раз – из даты рождения (третьего элемента пользовательского типа), которая объявлена как Date.

Задание:

1. В Модуль3 напишите программу Данные_Сотрудника, которая, по запросу пользователя, выводит на экран данные о сотруднике (Ф.И.О., Кафедра, Должность, Возраст). Информация хранится в базе данных Excel C:\St\Институт.xls на листе Кадры и имеет следующую структуру:

Использование переменных в VBA - student2.ru

1.1. Диалог программы с пользователем осуществляется с помощью встроенной функции InputBox:

§ сначала запрашивается название кафедры:

Использование переменных в VBA - student2.ru

§ затем Ф.И.О.:

Использование переменных в VBA - student2.ru

1.2. Выходные данные выводятся с помощью MsgBox в следующем виде:

Использование переменных в VBA - student2.ru

1.3. При написании кода создайте пользовательский тип данных Сотрудник, элементами которого являются Имя, Должность, Возраст.

1.4. Предусмотреть обработку событий, связанных с различными состояниями исходной БД: закрыта, открыта, не существует.

Массивы в VBA

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

Действия с массивами очень похожи на действия с переменными. Прежде чем использовать массив, вы должны его описать и указать тип данных. В массивах используются те же типы данных, что и в одиночных переменных, причем массив может содержать только однотипные значения. Обойти это ограничение легко - создайте массив типа Variant, в котором можно хранить данные любого типа.

Нумерация массивов VBA может начинаться с 0 или 1. Конкретный способ указан в инструкции Option Base в начале модуля. Так, Option Base 0 задает нумерацию всех массивов по умолчанию с 0, a Option Base 1 — с 1. В отсутствие инструкции Option Base нумерация массивов по умолчанию начинается с 0. Но в следующих примерах мы для простоты считаем, что она начинается с 1.

В Модуль4 наберите и протестируйте работу следующих программ:

1. Пример одномерного трехэлементного целочисленного массива (при отсутствии инструкции Option Base 1 этот массив стал бы четырехэлементным):

Option Base 1

Sub ЦелочисленныйМассив()

Dim Vals(3) As Integer

Vals(1) = Int(100 * Rnd())

Vals(2) = Int(100 * Rnd())

Vals(3) = Int(100 * Rnd())

MsgBox "Выиграли лотерейные номера: " & Vals(1) & ", " & _

Vals(2) & ", " & Vals(3)

End Sub

2. Пример одномерного, трехэлементного массива Variant, в котором можно хранить «разношерстные» данные:

Sub МассивVariant()

Dim Data(3) As Variant

Data(1) = "Иванов"

Data(2) = #3/21/1947#

Data(3) = Year(Date) - Year(Data(2))

MsgBox Data(1) & " , возраст " & Data(3) & ", родился " _

& Data(2)

End Sub

3. Пример одномерного двухэлементного массива, в котором определены нижняя и верхняя границы:

Sub НомерПервогоЭлемента()

Dim Data4(4 To 5) As Integer

Data4(4) = lnt(100 * Rnd())

Data4(5) = Int(100 * Rnd())

MsgBox "Выиграли лотерейные номера: " & Data4(4) & ", " _

& Data4(5)

End Sub

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

Sub ДинамическийМассив()

Dim Data5() As Variant

DimКолЗаписейAs Integer

'Первое объявление массива Data5 как одномерного _

двухэлементного массива:

ReDim Data5(2)

Data5(1) = Int(100 * Rnd())

Data5(2) = Int(100 * Rnd())

MsgBox " Выиграли лотерейные номера: " & Data5(1) & ", " _ & Data5(2)

КолЗаписей = Int(InputBox("Введите количество записей:", _

"Кадры"))

'Второе объявление массива Data5 как двухмерного массива:

ReDim Data5(КолЗаписей,3)

Data5(1,1) = "Иванов"

Data5(1,2) = #3/21/1947#

Data5(1,3) = Year(Date)-Year(Data5(1,2))

MsgBox "Определено " & КолЗаписей & " записей!"

MsgBox "1-я запись: " & Data5(1,1) & ", возраст: " & _

Data5(1,3) & ", родился: " & Data5(1,2)

End Sub

5. Пример динамического массива с сохранением данных.

Пусть имеется база данных (БД) Excel с полным именем C:\St\Институт.xls, в которой на листе Кадры хранятся сведения о сотрудниках института (Рис. 4‑1). Книга имеет один лист. Количество записей в БД может меняться.

Использование переменных в VBA - student2.ru

Рис. 4‑1. Фрагмент БД

Требуется: вывести в новую книгу данные о доцентах (Кафедра, Ф.И.О., Разряд), работающих в институте.

1) Sub МассивДоценты_СохранениеДанных()[СЮМ1]
2) Dim Сотрудники() As String
3) DimКолДоцентовAs Integer
4) DimНомерСтрокиAs Integer
5) КолДоцентов = 0
6) НомерСтроки = 3
7) ' Данные о доцентах считываем в массив:
8) While Cells(НомерСтроки,2).Value <> “”
9) If Cells(НомерСтроки,3).Value = “Доцент” Then
10) КолДоцентов = КолДоцентов + 1
11) ReDim Preserve Сотрудники(3,КолДоцентов)
12) Сотрудники(1,КолДоцентов) = Cells(НомерСтроки,1).Value
13) Сотрудники(2,КолДоцентов) = Cells(НомерСтроки,2).Value
14) Сотрудники(3,КолДоцентов) = Cells(НомерСтроки,3).Value
15) End If
16) НомерСтроки = НомерСтроки + 1
17) Wend
18) 'Добавляем новую книгу и переписываем в неё данные 'из массива:
19) WorkBooks.Add
20) For I = 1 To КолДоцентов
21) Cells(I + 2,1).Value = Сотрудники(1, I)
22) Cells(I + 2,2).Value = Сотрудники(2, I)
23) Cells(I + 2,3).Value = Сотрудники(3, I)
24) Next I
25) Range("A1").Select
26) MsgBox "Операция завершена!",vbInformation
27) End Sub

В 10-й строке этого кода, при выполнении критерия отбора, счетчик увеличивается на 1 и в оперативной памяти выделяется место для следующей записи (строка 11). При этом предыдущие записи сохраняются. При отсутствии ключевого слова Preserve при повторном определении динамического массива память выделяется заново, при этом все данные уничтожаются.

ОБРАТИТЕ ВНИМАНИЕ: при использовании ключевого слова Preserve, изменяемая размерность должна быть последней. Это значит, что команда:

ReDim Preserve Сотрудники(КолДоцентов, 3)

недопустима!

Замечание: данный код корректен, если находится в книге Институт.xls. Для того чтобы отделить программу от данных, модернизируйте код, как показано ниже, и протестируйте его (код поместите в Модуль4).

1) Sub МассивДоценты_СохранениеДанных_Мод()[СЮМ2]
2) Dim Сотрудники() As String
3) DimКолДоцентовAs Integer
4) DimНомерСтрокиAs Integer
5) Dimflag As Integer
6) ' Проверяем существование книги C:\St\Институт.xls
7) If Dir("C:\St\Институт.xls") = "" Then
8) MsgBox "Файл C:\St\Институт.xls не найден!", _
9) vbInformation
10) Exit Sub
11) End If
12) ' Проверяем, открыта ли книга Институт.xls:
13) For I = 1 To Workbooks.Count
14) If Workbooks(I).Name = "Институт.xls" Then
15) Workbooks(I).Activate
16) flag = 1
17) Exit For
18) End If
19) NextI
20) If flag = 0 ThenWorkbooks.Open Filename:= _
21) "C:\St\Институт.xls"
22) ' Проверяем, существует ли лист Кадры:
23) flag = 0
24) For I = 1 To Worksheets.Count
25) If Worksheets(I).Name = "Кадры" Then
26) flag = 1
27) Exit For
28) End If
29) Next I
30) If flag = 1 Then
31) Sheets("Кадры").Select
32) Else
33) MsgBox "Лист Кадры не найден!", vbInformation
34) Exit Sub
35) End If
36) Sheets("Кадры").Select
37) КолДоцентов = 0
38) НомерСтроки = 3
39) ' Данные о доцентах считываем в массив:
40) While Cells(НомерСтроки,2).Value <> “”
41) If Cells(НомерСтроки,3).Value = “Доцент” Then
42) КолДоцентов = КолДоцентов + 1
43) ReDim Preserve Сотрудники(3,КолДоцентов)
44) Сотрудники(1,КолДоцентов) = _
45) Cells(НомерСтроки,1).Value
46) Сотрудники(2,КолДоцентов) = _
47) Cells(НомерСтроки,2).Value
48) Сотрудники(3,КолДоцентов) = _
49) Cells(НомерСтроки,3).Value
50) End If
51) НомерСтроки = НомерСтроки + 1
52) Wend
53) 'Добавляем новую книгу и переписываем в неё данные из _ массива:
54) WorkBooks.Add
55) For I = 1 To КолДоцентов
56) Cells(I + 2,1).Value = Сотрудники(1, I)
57) Cells(I + 2,2).Value = Сотрудники(2, I)
58) Cells(I + 2,3).Value = Сотрудники(3, I)
59) Next I
60) ' Вызываем программу оформления таблицы, передавая в неё _
61) количество форматируемых строк и столбцов:
62) ' Call ОформлениеТаблицы(КолДоцентов, 3)
63) Range(“A1”).Select
64) MsgBox "Операция завершена!",vbInformation
65) End Sub

Замечания:

1. Обратите внимание на строки с 24 по 29 – здесь происходит проверка существования листа Кадры. В строка 30 – 35 происходит обработка событий «лист существует/не существует».

2. Строка 62 – вызов подпрограммы оформления таблицы – пока занесена в комментарий (см. задание на стр. 61).

Функция Erase

Она используется для удаления данных, хранимых в элементах массива. Если это массив фиксированного размера, функция Erase лишь очищает его, а память, выделенная массиву, остается за ним. Динамический массив уничтожается функцией Erase полностью. Программа ФункцияErase демонстрирует удаление всех значений, записанных в массив фиксированного размера.

SubФункцияErase()

DimData7(2) As Integer

Data7(1) = Int(100 * Rnd())

Data7(2) = Int(100 * Rnd())

MsgBox "Лотерейные номера: " & Data7(1) & ", " & Data7(2)

EraseData7

MsgBox "Лотерейные номера: " & Data7(1) & ", " & Data7(2)

End Sub

Здесь элементам массива присваиваются значения и выводятся в информационном окне. Затем для удаления содержимого массива вызывается функция Erase. Второй вызов функции MsgBox свидетельствует, что во всех элементах Data7 содержатся нули. В следующем примере показан вызов функции Erase для динамического массива.

Sub EraseДинамичМассив()

Dim Data8() As Integer

ReDim Data8(2)

Data8(1) = Int(100 * Rnd())

Data8(2) = Int(100 * Rnd())

MsgBox "Лотерейные номера: " & Data8(1) & ", " & Data8(2)

EraseData8

MsgBox "Лотерейные номера: " & Data8(1) & ", " & Data8(2)

End Sub

Выполнение программы EraseДинамичМассив приводит к ошибке в строке 8, потому что функция Erase в предыдущей строке освободила всю память, занятую динамическим массивом. После этого VBA уже не может работать с индексами Data8, и обращение к этому массиву вызывает ошибку.

Наши рекомендации