Основы офисного программирования и язык VBA

Операторы

Разбить на страницы
Показывать лекцию целиком

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

Операторы

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

VBA - операторный язык. Это значит, что его программы (модули) представляют последовательности операторов. Набор операторов VBA весьма обширен и не уступает в этом "большим" языкам вроде Паскаля и С. Группу декларативных операторов VBA, служащих для описания объектов, с которыми работает программа (типов, переменных, констант, объектов приложений и др.), мы уже рассмотрели. Операторы другой группы обеспечивают присвоение и изменение значений этих объектов, операторы третьей группы управляют ходом вычислений, четвертой - работой с каталогами и файлами и т.д. Часть операторов досталась VBA в наследство от предыдущих версий Бейсика и без них вполне можно обойтись при написании новых программ.

Операторы и строки

При записи текста программ для упрощения чтения, отладки и модификации программы удобней каждый оператор располагать в отдельной строке текста. Следуйте правилу: "Один оператор - одна строка". Но, разрешается размещать на строке и несколько операторов, в отличие от общепринятого символа разделения операторов "точки с запятой", в VBA символом разделения двух операторов в одной строке служит двоеточие. Заметьте, некоторые операторы, например оператор If, могут стоять лишь на первом месте в строке. И по этой причине каждый оператор, как правило, следует начинать с новой строки, лишь иногда, разумно, группу операторов присваивания размещать в одной строке. Чаще возникает другая ситуация, - оператор слишком длинный и его текст не виден полностью на экране дисплея, что затрудняет чтение и понимание программы. В этом случае оператор следует продолжить в одной или нескольких строках. Чтобы продолжить (перенести) оператор на следующую строку, используется пара символов пробел-подчеркивание " _ ". Например,

MyAddress = "дом: "  Number  "улица: "  Street _
		 "город: "  City

Перед оператором в строке может стоять метка - последовательность символов, начинающаяся с буквы и кончающаяся двоеточием " :". Метки можно размещать и в отдельных строках перед теми операторами, которые они должны помечать. Они нужны для операторов перехода типа GoTo, использование которых считается "дурным тоном" в структурном программировании. Но иногда без меток и переходов на них обойтись трудно - в частности, для указания входов в обработчики ошибок в некоторых процедурах.

Оператор комментария

Комментарии на исполнение программы не влияют, но необходимы как признак "хорошего стиля". Офисные программы используются многократно и не раз модернизируются в процессе своей жизни. Вы можете сэкономить на комментариях и написать и отладить небольшой модуль без них. Но уже через неделю никто, в том числе и автор, не сможет понять его действие и модифицировать нужным образом. Затраченные на это усилия и время намного превзойдут "экономию". Любая строка текста программы может заканчиваться комментарием. Комментарий в VBA начинается апострофом (') и включает любой текст, расположенный правее в строке. Обычно в комментариях описывают задачи, решаемые модулями, функции, выполняемые процедурами, смысл основных переменных (если он неясен из имен), алгоритмы работы процедур. Полезно также комментировать операторы вызовов внешних для данного модуля процедур, объясняя их действия.

Другое применение комментарии находят при отладке программ. Если требуется исключить из программы некоторые операторы (например, вызовы еще не реализованных или сомнительных процедур), достаточно перед ними поместить апостроф. Например, при выполнении последовательности операторов

x=x+z
'z=fun(z,x)
y=y*x

функция fun для вычисления нового значения z во второй строке не вызывается и не мешает проверить правильность значения y.

В VBA имеется еще один способ выделения комментариев с помощью ключевого слова Rem. Такой комментарий (в отличие от комментария, начинающегося апострофом) должен отделяться от предыдущего оператора в строке двоеточием:

weight= weight+z: 	Rem Увеличение веса
value=weight*price 		'Новая стоимость

При отладке VBA программ часто приходится временно комментировать целые участки текста, иногда страницы текста. В этом случае закомментировать или снять комментарии довольно утомительное дело. В этих случаях следует пользоваться двумя полезными командами меню Edit: "Comment Block" и "UnComment Block". Они позволяют автоматически закомментировать или снять комментарий с выделенного блока. Я всегда использую настройку (Customize) и выношу на панель редактора VBE кнопки, выполняющие эти команды.

Присваивание

Операторы присваивания - основное средство изменения состояния программы (значений переменных и свойств объектов). Мы уже многократно использовали их в примерах из предыдущих лекций. В VBA несколько видов операторов присваивания.

Оператор Let

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

Синтаксис:

[Let] переменная = выражение

Ключевое слово Let, как правило, опускается. Переменная является именем переменной или свойства; выражение задает значение, присваиваемое переменной. Его тип должен соответствовать типу переменной. Нарушение этого условия, например, при попытке присвоить числовой переменной строковое значение, приводит к тому, что при компиляции появится сообщение об ошибке. Переменным типа Variant можно присваивать значения разных типов, например, строковых или числовых выражений. Строковой переменной можно присваивать любое значение типа Variant, кроме Null. Числовой же переменной значение типа Variant можно присвоить, только если оно может быть преобразовано к числу.

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

Примеры:

Public Sub Assign1()
	Dim MyStr As String, MyInt As Integer
		
	Let MyStr = "Здравствуй, зайчик!"	' С ключевым словом Let
	MyInt = 5					' Без него. Обычный вариант.
	Debug.Print MyStr, MyInt

End Sub

Оператор LSet

Этот оператор служит для присвоения строк с одновременным выравниванием слева, а также для копирования записи одного определенного пользователем типа в запись другого типа. Его синтаксис:

Lset СтрПеременная = СтрВыражение
Lset переменная1 = переменная2

Здесь ключевое слово LSet обязательно, СтрПеременная - имя строковой переменной, СтрВыражение - выражение строкового типа. Во втором варианте переменная1 - имя переменной некоторого определенного пользователем типа, в которую выполняется копирование, переменная2 - имя переменной, возможно, другого пользовательского типа, значение которой копируется.

Результатом присвоения строк всегда является строка той же длины, что и у СтрПеременная. Если при этом СтрВыражение короче, добавляются пробелы справа; длиннее - лишние символы справа удаляются.

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

Примеры.

Public Sub Assign2()
	Dim Str1 As String, Str2 As String
		
	Str1 = "0123456789" ' Начальное значение
	Str2 = "abcd"
	Debug.Print Str1, Str2

	LSet Str2 = Str1		' Результат - "0123"
	LSet Str1 = "	Влево"	' Результат -	"	Влево
	Debug.Print Str1, Str2

End Sub"

Вот результаты отладочной печати:

0123456789		abcd
	Влево		0123

В следующем примере происходит корректное копирование одной записи в другую; типы соответствующих элементов в определенных пользователем типах MyType1 и MyType2 совпадают:

Type MyType1
	age As Integer
	cost As Long
End Type

Type MyType2
	year As Integer
	pay As Long
	'pay As Integer
End Type

Public Sub Assign3()
	Dim my1 As MyType1
	Dim my2 As MyType2

	my1.age = 50
	my1.cost = 45666

	my2.year = 1997
	my2.pay = 22000
	Debug.Print my1.age, my1.cost, my2.pay, my2.year
		
	LSet my2 = my1
	' после этого присвоения my2.year=50 и my2.pay=45666
	Debug.Print my1.age, my1.cost, my2.pay, my2.year

End Sub

Вот результаты отладочной печати:

50				45666			22000			1997 
50				45666			45666			50

Если изменить тип элемента pay в MyType2 на Integer, то будет напечатано значение my2.pay, равное 0.

Оператор RSet

Этот оператор присваивает значение строковой переменной с выравниванием справа:

RSet	СтрПеременная =	СтрВыражение

СтрПеременная - имя строковой переменной, СтрВыражение - выражение строкового типа. В отличие от LSet оператор RSet нельзя использовать для копирования переменных записей. Результатом присвоения строк всегда является строка той же длины, что и СтрПеременная. Если при этом СтрВыражение короче, добавляются пробелы слева, длиннее - лишние символы слева удаляются.

Примеры:

Public Sub Assign4()
	Dim Str1, Str2, Str3
		
	Str1 = "0123456789"             ' Начальное значение
	Str2 = "abcd"
	Debug.Print Str1, Str2
		
	RSet Str2 = Str1                ' Результат - "0123"
	RSet Str1 = "Вправо "           ' Результат -	"	Вправо "
	RSet Str3 = Str1                ' Результат - пустая строка ""
	Debug.Print Str1, Str2, Str3
End Sub

Вот результаты отладочной печати:

0123456789		abcd
	Вправо		0123

Оператор Set

Этот оператор применим при работе с объектами, устанавливает ссылку на вновь созданный или существующий объект. Его синтаксис:

Set ОбПеременная = {[New] ОбВыражение| Nothing}

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

Примеры:

Определим класс объектов Child:

'Класс Child
'Свойства
Public Age As Byte
Public Name As String
'Другие свойства и методы пока не определены

А теперь введем объекты этого класса:

Public Sub Assign5()
	Dim Children(1 To 2) As Child
	Dim Boy As Child, Girl As Child
		
	'Создаем объекты
	Set Children(1) = New Child
	Set Children(2) = New Child
	'Инициализируем их
	Children(1).Age = 10
	Children(1).Name = "Александр"
	Children(2).Age = 7
	Children(2).Name = "Мария"
	Debug.Print "Имя: ", Children(1).Name, "Возраст: ", Children(1).Age
	Debug.Print "Имя: ", Children(2).Name, "Возраст: ", Children(2).Age
		
	'Утанавливаем дополнительные ссылки на существующие объекты
	Set Boy = Children(1)
	Set Girl = Children(2)
	Boy.Name = "Саша"
	Girl.Name = "Маша"
	'Изменились сввойства объектов
	Debug.Print "Имя: ", Children(1).Name, "Возраст: ", Children(1).Age
	Debug.Print "Имя: ", Children(2).Name, "Возраст: ", Children(2).Age
		
	'Удаляем одну из ссылок, но объект остается
	Set Children(1) = Nothing
	Set Children(2) = Nothing
	Debug.Print "Имя: ", Boy.Name, "Возраст: ", Boy.Age
	Debug.Print "Имя: ", Girl.Name, "Возраст: ", Girl.Age

End Sub

Вот результаты отладочной печати:

Имя:				Александр		Возраст:			10 
Имя:				Мария			Возраст:			7 
Имя:				Саша			Возраст:			10 
Имя:				Маша			Возраст:			7 
Имя:				Саша			Возраст:			10 
Имя:				Маша			Возраст:			7

Управляющие операторы

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

Условный оператор If Then Else End If

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

Синтаксис.

Имеется два варианта синтаксиса: в одну строку и в форме блока. В первом случае он имеет вид:

If условие Then [операторы1] [Else операторы2 ]

Во втором случае оператор расположен на нескольких строках:

If условие Then
[операторы]
[ElseIf условие-n Then
[операторы-n]...
[Else
[ИначеОператоры]]
End If

Здесь условие обязательно в обоих вариантах. Оно может быть числовым или строковым выражением со значениями True или False ( Null трактуется как False ). В качестве условия можно использовать и выражение вида TypeOf ИмяОбъекта Is ТипОбъекта, где ИмяОбъекта - ссылка на объект, а ТипОбъекта - произвольный корректный тип объекта. Операторы1 и операторы2 - это последовательности из одного или нескольких разделенных двоеточием операторов. По крайней мере, одна из этих последовательностей должна быть непустой. Если условие истинно ( True ), выполняется последовательность операторы1, ложно ( False ) - операторы2. Форма условного оператора определяется по наличию в строке, начинающейся If условие Then, текста после Then, отличного от комментария. Если такой текст есть, считается, что использована форма в одну строку, нет - оператор должен иметь форму блока. В этом случае подблоки вида:

[ElseIf условие-n Then
	[операторы-n]

могут отсутствовать либо повторяться несколько раз; подблок:

[Else
	[ИначеОператоры]]

также необязателен, а закрывающий оператор End If необходим. По крайней мере одна из последовательностей операторы, операторы-n … или ИначеОператоры должна быть непустой. Если условие истинно, выполняются операторы, нет - отыскивается первое истинное условие-n, и выполняются операторы-n. Если все эти условия ложны, выполняются ИначеОператоры. После выполнения одной (возможно, пустой) последовательности операторов управление передается оператору, следующему за End If.

Примеры:

Public Sub MinMax1(ByVal X As Integer, ByVal Y As Integer, _
		Min As Integer, Max As Integer)
		'Оператор If	в одну строку
		If X > Y Then Max = X: Min = Y Else Max = Y: Min = X

End Sub

Public Sub MinMax2(ByVal X As Integer, ByVal Y As Integer, _
		Min As Integer, Max As Integer)
		'Оператор If	в виде блока
		If X > Y Then
			Max = X
			Min = Y
		Else
			Max = Y
			Min = X
		End If
		
End Sub

Public Sub If1()
		Dim Max As Integer, Min As Integer
		
		Call MinMax1(2 + 3, 2 * 3, Min, Max)
		Debug.Print Max, Min
		Call MinMax2(2 + 3, 2 * 3, Min, Max)
		Debug.Print Max, Min
End Sub

По-видимому, можно было бы классифицировать программистов в зависимости от того, какая из форм записи процедуры MinMax кажется им предпочтительнее при записи и при чтении. Приведем еще один пример, где идет работа с объектами. Вначале добавим еще один класс объектов:

'Класс Man
'Свойства
Public Age As Byte
Public Name As String
'Другие свойства и методы пока не определены

А теперь приведем процедуру, в которой будем работать с объектами класса Child и Man. Заметьте, в условии оператора IF проверяется тип объекта:

Public Sub BoyOrMan()
	Dim Boy As New Child
	Dim Person As New Man
	Dim SomeBody As Object
	Dim Answer As Integer
		
	Boy.Age = 10: Boy.Name = "Александр"
	Person.Age = 21: Person.Name = "Александр"
	Answer = InputBox("Введите число от 10 до 20", "Возраст", 15)
	If Answer > 15 Then
		Set SomeBody = Person
		Else: Set SomeBody = Boy
	End If
		
	If TypeOf SomeBody Is Child Then
		Debug.Print "Это мальчик!"
	ElseIf TypeOf SomeBody Is Man Then
		Debug.Print "Это Мужчина"
	Else
		Debug.Print "Не знаю, кто это"
	End If
End Sub

Результат ее работы зависит от того, какой возраст Вы введете в окне ввода.

Оператор выбора Select Case

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

Синтаксис.

Select Case Выражение-тест
[Case СписокВыражений-n
	[операторы-n]]
[Case Else
	[ИначеОператоры]]
End Select

Выражение-тест должно присутствовать обязательно. Оно может быть произвольным выражением с числовым или строковым значением. СписокВыражений-n должен присутствовать в строке, начинающейся ключевым словом Case (Случай). Выражения в этом списке отделяются запятыми и могут иметь одну из форм:

  • выражение,
  • выражение-нижняя-граница To выражение-верхняя-граница,
  • Is оператор-сравнения выражение.
  • Первая форма задает отдельные значения, вторая и третья позволяют задавать сразу целые диапазоны (области) значений. Последовательность операторов операторы-n необязательна. Она будет исполнена, если соответствующий СписокВыражений-n является первым списком, сопоставимым с текущим значением Выражения-теста (т. е. он явно содержит это значение, либо оно попадает в один из заданных в списке диапазонов). После исполнения операторов последовательности операторы-n проверка на соответствие другим спискам выражений не производится, и управление передается на оператор, следующий за End Select. Необязательная последовательность ЕслиОператоры выполняется, если ни один из списков выражений несопоставим со значением Выражения-теста.

    Пример:

    Public Sub Case1()
    	Dim Before As Integer
    	Dim CurrentYear As Integer, Str As String
    
    	' Инициализация переменных:
    	CurrentYear = 1999
    	Before = InputBox("Сколько лет тому назад?", "Когда", 10)
    	
    	Select Case CurrentYear - Before
    		Case 1954 To 1969, 1971 To 1974, 1982, Is < 1970
    			Str = " Годы учебы"
    		Case 1972 To 1989
    			Str = "Годы воспитания"
    		Case Else
    			Str = "Прочие годы"
    	End Select
    	Debug.Print Str
    
    End Sub

    Здесь, если перед выполнением выбора Before = 20, значением тестового выражения будет 1979, и будет работать второй вариант (" Годы воспитания "). При Before = 25 значение 1974 сопоставимо с двумя списками, но для исполнения будет выбран лишь первый вариант (" Годы учебы ").

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

    Case "everything", "nuts" To "soup"

    Задаваемое им множество строк включает строку " everything " и все строки от " nuts " до " soup " (например, " onion ").

    Цикл For Next

    Позволяет повторять группу операторов заданное число раз.

    Синтаксис:

    For счетчик_цикла = начало To конец [Step шаг]
    тело цикла
    Next [счетчик_цикла]

    Здесь счетчик_цикла - это числовая переменная. В начале выполнения цикла она принимает значение, задаваемое числовым выражением начало. (Переменная счетчик_цикла не может иметь тип Boolean или быть элементом массива.) Числовое выражение конец задает заключительное значение счетчика цикла. Оно вычисляется до начала исполнения тела цикла и не меняется, даже если входящие в него переменные изменяют в теле цикла свои значения. Числовое выражение шаг необязательно. Его значение также вычисляется в начале цикла и прибавляется к счетчику цикла всякий раз, когда завершается выполнение тела цикла и вычисление достигает строки Next [счетчик_цикла]. Если шаг цикла явно не указан, по умолчанию он равен 1. тело цикла - это последовательность операторов, которая будет выполнена заданное число раз. При каком значении переменной счетчик_цикла происходит завершение цикла, зависит от знака параметра шаг. Если шаг положителен, цикл завершится, когда впервые выполнится условие:

    счетчик_цикла > конец

    Если шаг цикла отрицателен, условие его завершения:

    счетчик_цикла < конец

    Это условие проверяется перед началом выполнения цикла, а затем - после каждого прибавления шага к счетчику цикла в операторе Next. Если оно выполнено, управление передается на оператор, следующий за Next, нет - выполняются операторы из тела цикла. Завершить цикл For … Next можно и с помощью оператора Exit For. Такие операторы могут быть расположены в тех местах тела цикла, где требуется из него выйти, не дожидаясь выполнения условия завершения.

    Примеры.

    В нашем примере три вложенных цикла For … Next использованы для вычисления произведения двух целочисленных матриц, инициализированных случайными числами. Затем результирующая матрица проверяется на наличие в ней нулевого значения:

    Public Sub For1()
    	Dim A(1 To 5, 1 To 5) As Integer
    	Dim B(1 To 5, 1 To 5) As Integer
    	Dim C(1 To 5, 1 To 5) As Integer
    	Dim I As Integer, J As Integer, K As Integer
    	Dim Res As String
    	' Инициализация матриц	A и B случайными числами в интервале [-10, +10]
    	VBA.Randomize
    	For I = 1 To 5
    		For J = 1 To 5
    			'Получение случайного числа Rnd и преобразование в целое
    			A(I, J) = Int(21 * Rnd) - 10
    		Next J
    	Next I
    	For I = 1 To 5
    		For J = 1 To 5
    			B(I, J) = Int(21 * Rnd) - 10
    		Next J
    	Next I
    		
    	'Вычисление произведения матриц
    	For I = 1 To 5
    		For J = 1 To 5
    			C(I, J) = 0
    			For K = 1 To 5
    					C(I, J) = C(I, J) + A(I, K) * B(K, J)
    			Next K
    		Next J
    	Next I
    		
    	Res = "No"
    	C(2, 2) = 0
    	'Проверка на нулевое значение
    	For I = 1 To 5
    		For J = 1 To 5
    			If C(I, J) = 0 Then
    					Debug.Print "Индексы: ", I, J
    					Res = "Yes"
    					Exit For
    			End If
    		Next J
    	Next I
    	Debug.Print Res
    End Sub

    Обратите внимание, оператор выхода Exit For прекращает выполнение только внутреннего цикла, так что проверка на ноль будет осуществляться в каждой строке матрицы, независимо от существования нулей в предыдущих строках. Сделаем еще несколько замечаний по поводу оператора For Next:

  • По окончании цикла счетчик цикла сохраняет свое значение в момент выхода и его можно использовать, например, для анализа преждевременного выхода из цикла. Заметим, что в большинстве языков программирования значение счетчика цикла считается неопределенным по завершении цикла.
  • В операторе Next можно не указывать имя переменной, задающей счетчик, это имя подразумевается по умолчанию, как завершающее последний открытый оператор For. Однако и эту возможность не следует использовать. Рекомендуем всегда явно указывать имя счетчика в операторе Next.
  • Допускается менять значение счетчика в теле цикла. Этого не следует делать никогда. К сожалению, система не следит за этим и допускает подобные безобразия. Этот цикл никогда не завершится:
  • Public Sub For2()
    	Dim A(1 To 5) As Integer
    	Dim i As Integer
    	For i = 5 To 1 Step -1
    		A(i) = i
    		i = i + 1
    	Next i
    		
    End Sub

    Обычно попытка изменить значение счетчика цикла в его теле означает, что вместо цикла For…Next следовало бы применить цикл другого вида, например Do…Loop.

    Цикл Do...Loop

    Повторяет блок операторов, пока заданное условие является истинным или пока оно не станет истинным.

    Синтаксис:

    Имеется четыре варианта синтаксиса этого цикла. В двух первых вариантах условие проверяется в начале цикла:

    Do [{While | Until} условие]
    тело цикла
    Loop

    В других двух вариантах условие проверяется в конце цикла:

    Do
    тело цикла
    Loop [{While | Until} условие]

    Здесь условие является числовым или строковым выражением со значениями True или False. Вообще оно необязательно. Значение Null условия трактуется как False. Тело цикла - это последовательность операторов, которая будет выполняться, пока условие остается истинным, если перед ним стоит ключевое слово While или пока оно остается ложным - в вариантах цикла с ключевым словом Until. Таким образом, циклы вида While условие эквивалентны циклам вида Until Not условие. Кроме того, в тело цикла может входить оператор Exit Do, выполнение которого сразу прекращает цикл и передает управление оператору, непосредственно следующему за Loop. В случае нескольких вложенных циклов Do … Loop оператор Exit Do завершает лишь самый внутренний цикл, в теле которого он расположен.

    Примеры.

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

    Public Sub Loop1()
    	Const Size = 5
    	Dim X() As Integer
    	Dim i As Integer
    	Dim Found As Boolean
    	Const pat = 7
    	'Инициализация случайными числами в интервале [1 - 10]
    	ReDim X(1 To Size)
    	Randomize
    	For i = 1 To Size
    		X(i) = Int(11 * Rnd)
    	Next i
    		
    	'Поиск по образцу с проверкой в начале цикла
    	i = 1: Found = False
    	Do While (i <= Size) And (Not Found)
    		If X(i) = pat Then
    			Found = True
    		Else: i = i + 1
    		End If
    	Loop
    	If Found Then
    		Debug.Print "Найден образец!"
    	Else: Debug.Print "Образец не найден!"
    	End If
    		
    	'Поиск по образцу с проверкой в конце цикла
    	i = 1: Found = False
    	Do
    		If X(i) = pat Then
    			Found = True
    		Else: i = i + 1
    		End If
    	Loop Until Found Or (i = Size + 1)
    	If Found Then
    		Debug.Print "Найден образец!"
    	Else: Debug.Print "Образец не найден!"
    	End If
    		
    	'Поиск с барьером
    	ReDim Preserve X(1 To Size + 1)
    	X(Size + 1) = pat
    	i = 1
    	Do
    		If X(i) = pat Then Exit Do
    		i = i + 1
    	Loop
    	If i = Size + 1 Then
    		Debug.Print "Образец не найден!"
    	Else: Debug.Print "Образец найден!"
    	End If
    End Sub

    Цикл While...Wend

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

    Синтаксис:

    While	условие
    тело цикла
    Wend

    Здесь условие и тело цикла такие же, как и для цикла Do…Loop. Только для этого вида цикла не предусмотрен оператор выхода Exit. Фактически цикл While…Wend - частный случай цикла Do…Loop - оставлен в языке для совместимости с предыдущими версиями.

    Цикл For Each...Next

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

    Синтаксис:

    For Each элемент In группа
    тело цикла
    Next [элемент]

    Здесь элемент - переменная, которая пробегает в качестве значений элементы коллекций или массива. Для коллекций элемент может быть переменной типа Variant, переменной типа Object или переменной (объектом) некоторого класса. В случае цикла по массиву элемент обязан быть переменной типа Variant. Группа - это имя набора объектов (чаще всего это коллекция объектов) или массива, для элементов которых выполняется цикл. Цикл не применим для массивов, тип элементов которых определен пользователем, так как такие элементы не могут быть значениями переменной типа Variant. В таких массивах можно использовать цикл вида For … Next. Тело цикла - последовательность операторов, выполняемая для каждого элемента набора или массива, - может содержать операторы Exit For, позволяющие прервать выполнение цикла и передать управление оператору, следующему за Next (обычно такой выход происходит при выполнении некоторого условия, проверяемого в операторе If…Then…Else ). Указывать переменную элемент после ключевого слова Next не обязательно, но желательно.

    Примеры.

    В примере создается коллекция, число элементов которой и сами элементы выбираются случайным образом. Затем эта коллекция копируется в динамический массив, размерность которого увеличивается в процессе копирования. На последнем этапе массив распечатывается. Циклы типа For …Each прекрасно работают в подобных ситуациях:

    Public Sub ForEach1()
    	Dim X As New Collection
    	Dim Y() As Integer
    	Dim item As Variant
    	Dim i As Integer, Size As Integer
    		
    	'Инициализация коллекции
    	Randomize
    	Size = Int(21 * Rnd)
    	For i = 1 To Size
    	    X.Add Int(11 * Rnd)
    	Next i
    		
    	'Копирование коллекции в динамический массив
    	Size = 1
    	For Each item In X
    		ReDim Preserve Y(1 To Size)
    		Y(Size) = item
    		Size = Size + 1
    	Next item
    	
    	'Печать элементов динамического массива
    	For Each item In Y
    		Debug.Print item
    	Next item
    End Sub

    Кроме рассмотренных управляющих операторов VBA содержит доставшиеся в наследство от прежних версий операторы перехода по метке GoTo, перехода по метке с возвратом GoSub...Return и условные операторы перехода по меткам On...GoSub и On...GoTo. Мы никогда не пользуемся этими операторами.

    Работа с каталогами, папками и файлами

    Операторы этой группы позволяют перемещать текущий каталог (папку) по дискам системы, создавать новые и удалять каталоги (папки): изменять атрибуты файлов, копировать и удалять файлы. Их набор по существу совпадает с набором соответствующих команд операционной системы.

    Изменение текущего диска: оператор ChDrive

    Синтаксис:

    ChDrive диск

    Обязательный параметр диск - это строка, задающая имя существующего диска, который должен стать текущим, например:

    ChDrive "D"

    сделает диск "D" текущим.

    Изменение текущего каталога (папки): оператор ChDir

    Синтаксис:

    ChDir путь

    Обязательный параметр путь - это строковое выражение, значение которого задает новый текущий каталог (папку). Если путь не содержит имени диска, меняется текущий каталог на текущем диске. Подчеркнем, что оператор ChDir меняет текущий каталог (папку), но не диск. Например, если текущим является диск С, команда:

    ChDir "D:\TMP"

    изменит текущий каталог на диске D, но диск C останется текущим.

    Создание каталога (папки): оператор MkDir

    Синтаксис:

    MkDir путь

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

    Public Sub Dirs()
    	'Сделать текущим диск F
    	ChDrive "F"
    	'Создать 3 каталога на F
    	MkDir "Temp1"
    	MkDir "F:\Temp2"
    	MkDir "F:Temp3"
    End Sub

    Переименование каталогов (папок) и файлов: оператор Name

    Позволяет переименовывать каталоги (папки) и файлы и перемещать файлы.

    Синтаксис:

    Name СтароеИмя As НовоеИмя

    СтароеИмя и НовоеИмя - обязательные параметры, задающие старое и новое имя файла (каталога, папки). Они могут включать имя диска и путь. СтароеИмя должно быть именем существующего файла (каталога, папки), а НовоеИмя не должно быть именем уже существующего объекта. Оба имени должны использовать один и тот же диск. Если указанный новый путь существует и отличается от старого, оператор перемещает файл в новый каталог (папку) и, если требуется, переименовывает его. Каталоги и папки с помощью оператора Name перемещать нельзя, - лишь переименовывать. Перед переименованием файл должен быть закрыт.

    В этом примере файл переименовывается, а затем и перемещается в другой каталог:

    Public Sub DirsAndFiles()
    	'Сделать текущим диск F
    		ChDrive "F"
    		'Переименование файла
    		Name "Exam1E.xls" As "Example1.xls"
    		'Перемещение файла
    		Name "Example1.xls" As "Temp1\Example1.xls"
    End Sub

    Удаление каталога (папки): оператор RmDir

    Синтаксис:

    RmDir путь

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

    RmDir "Temp3"

    удалит папку Temp3 с текущего диска.

    Установка атрибутов файла: оператор SetAttr

    Синтаксис:

    SetAttr имяфайла, атрибуты

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

    Атрибуты файла
    Имя константы Значение Описание
    VbNormal 0 Нормальный (по умолчанию)
    vbReadOnly 1 Только для чтения
    VbHidden 2 Скрытый
    VbSystem 4 Системный файл
    VbArchive 32 Файл изменен со времени последнего создания резервной копии

    Нельзя менять атрибуты открытого файла (иначе будет выдано сообщение об ошибке).

    Копирование файлов: оператор FileCopy

    Синтаксис:

    FileCopy файл-источник, файл-результат

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

    Пример:

    'Копирование файла
    		FileCopy "Temp1\Example1.xls", "Temp2\Example1.xls"

    Удаление файлов: оператор Kill

    Синтаксис:

    Kill файл

    Параметр файл - строковое вырыжение, задающее имя удаляемого файла. Он может включать имя диска и путь по каталогам или папкам. Для удаления нескольких файлов можно использовать в образце имени файла символ '*' для обозначения произвольной последовательности букв и '?' - для обозначения одного символа. Нельзя удалять открытый в данный момент файл.

    Пример.

    Допустим, в текущем каталоге находятся файлы PROG.DOC, PROG.CPP и PROG.OBJ. Тогда оператор:

    Kill "PROG.*"

    удалит эти файлы с диска.

    Прочие операторы

    И еще несколько полезных операторов VBA, не попавших ни в одну из предыдущих групп.

    Операции с одним объектом. Оператор With

    Если в одном блоке программы предстоит выполнить несколько операций с одним объектом, то, чтобы не повторять многократно имя этого объекта, можно ввести оператор With.

    Синтаксис:

    With объект
    [операторы]
    End
    With

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

    Допустим, пользовательский тип Person и переменная MyFriend определены так.

    Type Person
    	Name As String
    	Age As Integer
    	Height As Single
    End Type
    
    Dim MyFriend As Person

    Тогда присвоение значений свойствам переменной MyFriend можно произвести с помощью оператора With:

    With MyFriend
    	Name = "Сергей"
    	Age= 35
    	.Height = 178.5
    End With

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

    With объект1
    	операторы1
    	With объект2
    		операторы2
    	End With
    
    End With

    в блоке операторы2 имя объекта1 нужно указывать полностью. Если же объект2 - элемент (подобъект) объекта1, то, использовав оператор With объект2, можно получить во внутреннем блоке сокращенный доступ к свойствам объекта " объект1. объект2 ".

    Например, если к типу Person добавить данные о встрече:

    Type Meeting
    	Place As String
    	Date As Date
    End Type
    
    Type Person
    	Name As String
    	Age As Integer
    	Height As Single
    	LastMeeting As Meeting
    End Type
    
    Dim NewAcquaintance As Person

    то задавать данные о новом знакомом NewAcquaintance можно, используя вложенные операторы With.

    With NewAcquaintance
    	.Name = "Елена"
    	.Age= 40
    	.Height = 168
    	With.LastMeeting
    		.Place= "библиотека"	
    		'этот оператор эквивалентен:
    		'NewAcquaintance. LastMeeting.Place="библиотека"
    		.Date= #08/03/99#
    	End With
    End With

    Звуковой сигнал: оператор Beep

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

    Синтаксис:

    Beep

    Частота и сила звука зависят от оборудования и могут меняться от компьютера к компьютеру. Обычно звуковой сигнал используется как реакция на какие-либо ошибки или исключительные ситуации, возникающие при выполнении программы.

    Установка системной даты: оператор Date

    Синтаксис:

    Date = дата

    Пример:

    Date = #April 29, 1999#	' Изменение системной даты.

    Установка системного времени: оператор Time

    Синтаксис оператора Time:

    Time = время

    Пример:

    Time = #8:15:47 PM#	' Установка системного времени

    Моделирование ввода с клавиатуры: оператор SendKeys

    Посылает один или несколько кодов символов в текущее активное окно, как если бы соответствующие клавиши были нажаты.

    Синтаксис:

    SendKeys строка[, режим-ожидания]

    Параметр строка - строковое выражение, задающее последовательность посылаемых символов. Необязательный параметр режим-ожидания - выражение с булевым значением. Если оно False (по умолчанию), управление возвращается в процедуру сразу же после посылки кодов; True - посланная последовательность кодов должна быть обработана, прежде чем управление возвратится в процедуру.

    Большинство символов, набираемых на клавиатуре, входят в строку непосредственно. Например, чтобы послать последовательность из трех символов Y, E и S, возьмите в качестве строки " YES ". Символы: +, ^, %, ~, скобки и некоторые другие следует помещать в фигурные скобки. Например, чтобы послать +, в параметр строка нужно поместить {+}. Для посылки кодов клавиш, не отображаемых на экране, имеются специальные коды. Некоторые представлены в таблице, остальные можно найти с помощью подсказки:

    Коды клавиш, не отображаемых на экране
    Клавиша Код
    BACKSPACE {BS}
    BREAK {BREAK}
    CAPS LOCK {CAPSLOCK}
    DEL {DEL}
    DOWN ARROW {DOWN}
    END {END}
    ENTER {ENTER} или ~
    ESC {ESC}
    HOME {HOME}
    INS {INS}
    LEFT ARROW {LEFT}
    PAGE DOWN {PGDN}
    PAGE UP {PGUP}
    RIGHT ARROW {RIGHT}
    TAB {TAB}
    UP ARROW {UP}
    Fn {Fn} (n=1,…, 12)

    Чтобы послать комбинацию клавиш, для Shift, Ctrl и Alt используются следующие коды (В примере используется документ DocTwo7:

    Shift - +
    Ctrl 	 ^
    Alt 	 %

    Пример:

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

    Public Sub OpenDocWithPassword()
    	'Открытие документа с паролем
    	SendKeys "+^"	'Переключение раскладки клавиатуры
    	SendKeys "don"  "{'}"  "t know", False		'пароль "don't know"
    	Documents.Open "e:\O2000\CD2000\Ch7\DocTwo7.doc"
    	Documents("DocTwo7.doc").Activate
    	
    End Sub

    Обратите внимание на два момента:

  • Прежде, чем послать сам пароль, происходит переключение клавиатуры на другую раскладку, для чего используется комбинация символов "Shift + Ctrl".
  • Символы клавиатуры посылаются в буфер ввода еще до того, как они потребуются. Если бы оператор Open предшествовал оператору SendKeys, то окно ввода пароля появилось бы до выполнения этого оператора. В данном же случае при открытии документа пароль автоматически появится в окне ввода, так что останется только щелкнуть по кнопке OK.
  • Страницы:

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

    Операторы

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

    VBA - операторный язык. Это значит, что его программы (модули) представляют последовательности операторов. Набор операторов VBA весьма обширен и не уступает в этом "большим" языкам вроде Паскаля и С. Группу декларативных операторов VBA, служащих для описания объектов, с которыми работает программа (типов, переменных, констант, объектов приложений и др.), мы уже рассмотрели. Операторы другой группы обеспечивают присвоение и изменение значений этих объектов, операторы третьей группы управляют ходом вычислений, четвертой - работой с каталогами и файлами и т.д. Часть операторов досталась VBA в наследство от предыдущих версий Бейсика и без них вполне можно обойтись при написании новых программ.

    Операторы и строки

    При записи текста программ для упрощения чтения, отладки и модификации программы удобней каждый оператор располагать в отдельной строке текста. Следуйте правилу: "Один оператор - одна строка". Но, разрешается размещать на строке и несколько операторов, в отличие от общепринятого символа разделения операторов "точки с запятой", в VBA символом разделения двух операторов в одной строке служит двоеточие. Заметьте, некоторые операторы, например оператор If, могут стоять лишь на первом месте в строке. И по этой причине каждый оператор, как правило, следует начинать с новой строки, лишь иногда, разумно, группу операторов присваивания размещать в одной строке. Чаще возникает другая ситуация, - оператор слишком длинный и его текст не виден полностью на экране дисплея, что затрудняет чтение и понимание программы. В этом случае оператор следует продолжить в одной или нескольких строках. Чтобы продолжить (перенести) оператор на следующую строку, используется пара символов пробел-подчеркивание " _ ". Например,

    MyAddress = "дом: "  Number  "улица: "  Street _
    		 "город: "  City

    Перед оператором в строке может стоять метка - последовательность символов, начинающаяся с буквы и кончающаяся двоеточием " :". Метки можно размещать и в отдельных строках перед теми операторами, которые они должны помечать. Они нужны для операторов перехода типа GoTo, использование которых считается "дурным тоном" в структурном программировании. Но иногда без меток и переходов на них обойтись трудно - в частности, для указания входов в обработчики ошибок в некоторых процедурах.

    Оператор комментария

    Комментарии на исполнение программы не влияют, но необходимы как признак "хорошего стиля". Офисные программы используются многократно и не раз модернизируются в процессе своей жизни. Вы можете сэкономить на комментариях и написать и отладить небольшой модуль без них. Но уже через неделю никто, в том числе и автор, не сможет понять его действие и модифицировать нужным образом. Затраченные на это усилия и время намного превзойдут "экономию". Любая строка текста программы может заканчиваться комментарием. Комментарий в VBA начинается апострофом (') и включает любой текст, расположенный правее в строке. Обычно в комментариях описывают задачи, решаемые модулями, функции, выполняемые процедурами, смысл основных переменных (если он неясен из имен), алгоритмы работы процедур. Полезно также комментировать операторы вызовов внешних для данного модуля процедур, объясняя их действия.

    Другое применение комментарии находят при отладке программ. Если требуется исключить из программы некоторые операторы (например, вызовы еще не реализованных или сомнительных процедур), достаточно перед ними поместить апостроф. Например, при выполнении последовательности операторов

    x=x+z
    'z=fun(z,x)
    y=y*x

    функция fun для вычисления нового значения z во второй строке не вызывается и не мешает проверить правильность значения y.

    В VBA имеется еще один способ выделения комментариев с помощью ключевого слова Rem. Такой комментарий (в отличие от комментария, начинающегося апострофом) должен отделяться от предыдущего оператора в строке двоеточием:

    weight= weight+z: 	Rem Увеличение веса
    value=weight*price 		'Новая стоимость

    При отладке VBA программ часто приходится временно комментировать целые участки текста, иногда страницы текста. В этом случае закомментировать или снять комментарии довольно утомительное дело. В этих случаях следует пользоваться двумя полезными командами меню Edit: "Comment Block" и "UnComment Block". Они позволяют автоматически закомментировать или снять комментарий с выделенного блока. Я всегда использую настройку (Customize) и выношу на панель редактора VBE кнопки, выполняющие эти команды.

    Присваивание

    Операторы присваивания - основное средство изменения состояния программы (значений переменных и свойств объектов). Мы уже многократно использовали их в примерах из предыдущих лекций. В VBA несколько видов операторов присваивания.

    Оператор Let

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

    Синтаксис:

    [Let] переменная = выражение

    Ключевое слово Let, как правило, опускается. Переменная является именем переменной или свойства; выражение задает значение, присваиваемое переменной. Его тип должен соответствовать типу переменной. Нарушение этого условия, например, при попытке присвоить числовой переменной строковое значение, приводит к тому, что при компиляции появится сообщение об ошибке. Переменным типа Variant можно присваивать значения разных типов, например, строковых или числовых выражений. Строковой переменной можно присваивать любое значение типа Variant, кроме Null. Числовой же переменной значение типа Variant можно присвоить, только если оно может быть преобразовано к числу.

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

    Примеры:

    Public Sub Assign1()
    	Dim MyStr As String, MyInt As Integer
    		
    	Let MyStr = "Здравствуй, зайчик!"	' С ключевым словом Let
    	MyInt = 5					' Без него. Обычный вариант.
    	Debug.Print MyStr, MyInt
    
    End Sub

    Оператор LSet

    Этот оператор служит для присвоения строк с одновременным выравниванием слева, а также для копирования записи одного определенного пользователем типа в запись другого типа. Его синтаксис:

    Lset СтрПеременная = СтрВыражение
    Lset переменная1 = переменная2

    Здесь ключевое слово LSet обязательно, СтрПеременная - имя строковой переменной, СтрВыражение - выражение строкового типа. Во втором варианте переменная1 - имя переменной некоторого определенного пользователем типа, в которую выполняется копирование, переменная2 - имя переменной, возможно, другого пользовательского типа, значение которой копируется.

    Результатом присвоения строк всегда является строка той же длины, что и у СтрПеременная. Если при этом СтрВыражение короче, добавляются пробелы справа; длиннее - лишние символы справа удаляются.

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

    Примеры.

    Public Sub Assign2()
    	Dim Str1 As String, Str2 As String
    		
    	Str1 = "0123456789" ' Начальное значение
    	Str2 = "abcd"
    	Debug.Print Str1, Str2
    
    	LSet Str2 = Str1		' Результат - "0123"
    	LSet Str1 = "	Влево"	' Результат -	"	Влево
    	Debug.Print Str1, Str2
    
    End Sub"

    Вот результаты отладочной печати:

    0123456789		abcd
    	Влево		0123

    В следующем примере происходит корректное копирование одной записи в другую; типы соответствующих элементов в определенных пользователем типах MyType1 и MyType2 совпадают:

    Type MyType1
    	age As Integer
    	cost As Long
    End Type
    
    Type MyType2
    	year As Integer
    	pay As Long
    	'pay As Integer
    End Type
    
    Public Sub Assign3()
    	Dim my1 As MyType1
    	Dim my2 As MyType2
    
    	my1.age = 50
    	my1.cost = 45666
    
    	my2.year = 1997
    	my2.pay = 22000
    	Debug.Print my1.age, my1.cost, my2.pay, my2.year
    		
    	LSet my2 = my1
    	' после этого присвоения my2.year=50 и my2.pay=45666
    	Debug.Print my1.age, my1.cost, my2.pay, my2.year
    
    End Sub

    Вот результаты отладочной печати:

    50				45666			22000			1997 
    50				45666			45666			50

    Если изменить тип элемента pay в MyType2 на Integer, то будет напечатано значение my2.pay, равное 0.

    Оператор RSet

    Этот оператор присваивает значение строковой переменной с выравниванием справа:

    RSet	СтрПеременная =	СтрВыражение

    СтрПеременная - имя строковой переменной, СтрВыражение - выражение строкового типа. В отличие от LSet оператор RSet нельзя использовать для копирования переменных записей. Результатом присвоения строк всегда является строка той же длины, что и СтрПеременная. Если при этом СтрВыражение короче, добавляются пробелы слева, длиннее - лишние символы слева удаляются.

    Примеры:

    Public Sub Assign4()
    	Dim Str1, Str2, Str3
    		
    	Str1 = "0123456789"             ' Начальное значение
    	Str2 = "abcd"
    	Debug.Print Str1, Str2
    		
    	RSet Str2 = Str1                ' Результат - "0123"
    	RSet Str1 = "Вправо "           ' Результат -	"	Вправо "
    	RSet Str3 = Str1                ' Результат - пустая строка ""
    	Debug.Print Str1, Str2, Str3
    End Sub

    Вот результаты отладочной печати:

    0123456789		abcd
    	Вправо		0123

    Оператор Set

    Этот оператор применим при работе с объектами, устанавливает ссылку на вновь созданный или существующий объект. Его синтаксис:

    Set ОбПеременная = {[New] ОбВыражение| Nothing}

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

    Примеры:

    Определим класс объектов Child:

    'Класс Child
    'Свойства
    Public Age As Byte
    Public Name As String
    'Другие свойства и методы пока не определены

    А теперь введем объекты этого класса:

    Public Sub Assign5()
    	Dim Children(1 To 2) As Child
    	Dim Boy As Child, Girl As Child
    		
    	'Создаем объекты
    	Set Children(1) = New Child
    	Set Children(2) = New Child
    	'Инициализируем их
    	Children(1).Age = 10
    	Children(1).Name = "Александр"
    	Children(2).Age = 7
    	Children(2).Name = "Мария"
    	Debug.Print "Имя: ", Children(1).Name, "Возраст: ", Children(1).Age
    	Debug.Print "Имя: ", Children(2).Name, "Возраст: ", Children(2).Age
    		
    	'Утанавливаем дополнительные ссылки на существующие объекты
    	Set Boy = Children(1)
    	Set Girl = Children(2)
    	Boy.Name = "Саша"
    	Girl.Name = "Маша"
    	'Изменились сввойства объектов
    	Debug.Print "Имя: ", Children(1).Name, "Возраст: ", Children(1).Age
    	Debug.Print "Имя: ", Children(2).Name, "Возраст: ", Children(2).Age
    		
    	'Удаляем одну из ссылок, но объект остается
    	Set Children(1) = Nothing
    	Set Children(2) = Nothing
    	Debug.Print "Имя: ", Boy.Name, "Возраст: ", Boy.Age
    	Debug.Print "Имя: ", Girl.Name, "Возраст: ", Girl.Age
    
    End Sub

    Вот результаты отладочной печати:

    Имя:				Александр		Возраст:			10 
    Имя:				Мария			Возраст:			7 
    Имя:				Саша			Возраст:			10 
    Имя:				Маша			Возраст:			7 
    Имя:				Саша			Возраст:			10 
    Имя:				Маша			Возраст:			7

    Управляющие операторы

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

    Условный оператор If Then Else End If

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

    Синтаксис.

    Имеется два варианта синтаксиса: в одну строку и в форме блока. В первом случае он имеет вид:

    If условие Then [операторы1] [Else операторы2 ]

    Во втором случае оператор расположен на нескольких строках:

    If условие Then
    [операторы]
    [ElseIf условие-n Then
    [операторы-n]...
    [Else
    [ИначеОператоры]]
    End If

    Здесь условие обязательно в обоих вариантах. Оно может быть числовым или строковым выражением со значениями True или False ( Null трактуется как False ). В качестве условия можно использовать и выражение вида TypeOf ИмяОбъекта Is ТипОбъекта, где ИмяОбъекта - ссылка на объект, а ТипОбъекта - произвольный корректный тип объекта. Операторы1 и операторы2 - это последовательности из одного или нескольких разделенных двоеточием операторов. По крайней мере, одна из этих последовательностей должна быть непустой. Если условие истинно ( True ), выполняется последовательность операторы1, ложно ( False ) - операторы2. Форма условного оператора определяется по наличию в строке, начинающейся If условие Then, текста после Then, отличного от комментария. Если такой текст есть, считается, что использована форма в одну строку, нет - оператор должен иметь форму блока. В этом случае подблоки вида:

    [ElseIf условие-n Then
    	[операторы-n]

    могут отсутствовать либо повторяться несколько раз; подблок:

    [Else
    	[ИначеОператоры]]

    также необязателен, а закрывающий оператор End If необходим. По крайней мере одна из последовательностей операторы, операторы-n … или ИначеОператоры должна быть непустой. Если условие истинно, выполняются операторы, нет - отыскивается первое истинное условие-n, и выполняются операторы-n. Если все эти условия ложны, выполняются ИначеОператоры. После выполнения одной (возможно, пустой) последовательности операторов управление передается оператору, следующему за End If.

    Примеры:

    Public Sub MinMax1(ByVal X As Integer, ByVal Y As Integer, _
    		Min As Integer, Max As Integer)
    		'Оператор If	в одну строку
    		If X > Y Then Max = X: Min = Y Else Max = Y: Min = X
    
    End Sub
    
    Public Sub MinMax2(ByVal X As Integer, ByVal Y As Integer, _
    		Min As Integer, Max As Integer)
    		'Оператор If	в виде блока
    		If X > Y Then
    			Max = X
    			Min = Y
    		Else
    			Max = Y
    			Min = X
    		End If
    		
    End Sub
    
    Public Sub If1()
    		Dim Max As Integer, Min As Integer
    		
    		Call MinMax1(2 + 3, 2 * 3, Min, Max)
    		Debug.Print Max, Min
    		Call MinMax2(2 + 3, 2 * 3, Min, Max)
    		Debug.Print Max, Min
    End Sub

    По-видимому, можно было бы классифицировать программистов в зависимости от того, какая из форм записи процедуры MinMax кажется им предпочтительнее при записи и при чтении. Приведем еще один пример, где идет работа с объектами. Вначале добавим еще один класс объектов:

    'Класс Man
    'Свойства
    Public Age As Byte
    Public Name As String
    'Другие свойства и методы пока не определены

    А теперь приведем процедуру, в которой будем работать с объектами класса Child и Man. Заметьте, в условии оператора IF проверяется тип объекта:

    Public Sub BoyOrMan()
    	Dim Boy As New Child
    	Dim Person As New Man
    	Dim SomeBody As Object
    	Dim Answer As Integer
    		
    	Boy.Age = 10: Boy.Name = "Александр"
    	Person.Age = 21: Person.Name = "Александр"
    	Answer = InputBox("Введите число от 10 до 20", "Возраст", 15)
    	If Answer > 15 Then
    		Set SomeBody = Person
    		Else: Set SomeBody = Boy
    	End If
    		
    	If TypeOf SomeBody Is Child Then
    		Debug.Print "Это мальчик!"
    	ElseIf TypeOf SomeBody Is Man Then
    		Debug.Print "Это Мужчина"
    	Else
    		Debug.Print "Не знаю, кто это"
    	End If
    End Sub

    Результат ее работы зависит от того, какой возраст Вы введете в окне ввода.

    Оператор выбора Select Case

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

    Синтаксис.

    Select Case Выражение-тест
    [Case СписокВыражений-n
    	[операторы-n]]
    [Case Else
    	[ИначеОператоры]]
    End Select

    Выражение-тест должно присутствовать обязательно. Оно может быть произвольным выражением с числовым или строковым значением. СписокВыражений-n должен присутствовать в строке, начинающейся ключевым словом Case (Случай). Выражения в этом списке отделяются запятыми и могут иметь одну из форм:

  • выражение,
  • выражение-нижняя-граница To выражение-верхняя-граница,
  • Is оператор-сравнения выражение.
  • Первая форма задает отдельные значения, вторая и третья позволяют задавать сразу целые диапазоны (области) значений. Последовательность операторов операторы-n необязательна. Она будет исполнена, если соответствующий СписокВыражений-n является первым списком, сопоставимым с текущим значением Выражения-теста (т. е. он явно содержит это значение, либо оно попадает в один из заданных в списке диапазонов). После исполнения операторов последовательности операторы-n проверка на соответствие другим спискам выражений не производится, и управление передается на оператор, следующий за End Select. Необязательная последовательность ЕслиОператоры выполняется, если ни один из списков выражений несопоставим со значением Выражения-теста.

    Пример:

    Public Sub Case1()
    	Dim Before As Integer
    	Dim CurrentYear As Integer, Str As String
    
    	' Инициализация переменных:
    	CurrentYear = 1999
    	Before = InputBox("Сколько лет тому назад?", "Когда", 10)
    	
    	Select Case CurrentYear - Before
    		Case 1954 To 1969, 1971 To 1974, 1982, Is < 1970
    			Str = " Годы учебы"
    		Case 1972 To 1989
    			Str = "Годы воспитания"
    		Case Else
    			Str = "Прочие годы"
    	End Select
    	Debug.Print Str
    
    End Sub

    Здесь, если перед выполнением выбора Before = 20, значением тестового выражения будет 1979, и будет работать второй вариант (" Годы воспитания "). При Before = 25 значение 1974 сопоставимо с двумя списками, но для исполнения будет выбран лишь первый вариант (" Годы учебы ").

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

    Case "everything", "nuts" To "soup"

    Задаваемое им множество строк включает строку " everything " и все строки от " nuts " до " soup " (например, " onion ").

    Цикл For Next

    Позволяет повторять группу операторов заданное число раз.

    Синтаксис:

    For счетчик_цикла = начало To конец [Step шаг]
    тело цикла
    Next [счетчик_цикла]

    Здесь счетчик_цикла - это числовая переменная. В начале выполнения цикла она принимает значение, задаваемое числовым выражением начало. (Переменная счетчик_цикла не может иметь тип Boolean или быть элементом массива.) Числовое выражение конец задает заключительное значение счетчика цикла. Оно вычисляется до начала исполнения тела цикла и не меняется, даже если входящие в него переменные изменяют в теле цикла свои значения. Числовое выражение шаг необязательно. Его значение также вычисляется в начале цикла и прибавляется к счетчику цикла всякий раз, когда завершается выполнение тела цикла и вычисление достигает строки Next [счетчик_цикла]. Если шаг цикла явно не указан, по умолчанию он равен 1. тело цикла - это последовательность операторов, которая будет выполнена заданное число раз. При каком значении переменной счетчик_цикла происходит завершение цикла, зависит от знака параметра шаг. Если шаг положителен, цикл завершится, когда впервые выполнится условие:

    счетчик_цикла > конец

    Если шаг цикла отрицателен, условие его завершения:

    счетчик_цикла < конец

    Это условие проверяется перед началом выполнения цикла, а затем - после каждого прибавления шага к счетчику цикла в операторе Next. Если оно выполнено, управление передается на оператор, следующий за Next, нет - выполняются операторы из тела цикла. Завершить цикл For … Next можно и с помощью оператора Exit For. Такие операторы могут быть расположены в тех местах тела цикла, где требуется из него выйти, не дожидаясь выполнения условия завершения.

    Примеры.

    В нашем примере три вложенных цикла For … Next использованы для вычисления произведения двух целочисленных матриц, инициализированных случайными числами. Затем результирующая матрица проверяется на наличие в ней нулевого значения:

    Public Sub For1()
    	Dim A(1 To 5, 1 To 5) As Integer
    	Dim B(1 To 5, 1 To 5) As Integer
    	Dim C(1 To 5, 1 To 5) As Integer
    	Dim I As Integer, J As Integer, K As Integer
    	Dim Res As String
    	' Инициализация матриц	A и B случайными числами в интервале [-10, +10]
    	VBA.Randomize
    	For I = 1 To 5
    		For J = 1 To 5
    			'Получение случайного числа Rnd и преобразование в целое
    			A(I, J) = Int(21 * Rnd) - 10
    		Next J
    	Next I
    	For I = 1 To 5
    		For J = 1 To 5
    			B(I, J) = Int(21 * Rnd) - 10
    		Next J
    	Next I
    		
    	'Вычисление произведения матриц
    	For I = 1 To 5
    		For J = 1 To 5
    			C(I, J) = 0
    			For K = 1 To 5
    					C(I, J) = C(I, J) + A(I, K) * B(K, J)
    			Next K
    		Next J
    	Next I
    		
    	Res = "No"
    	C(2, 2) = 0
    	'Проверка на нулевое значение
    	For I = 1 To 5
    		For J = 1 To 5
    			If C(I, J) = 0 Then
    					Debug.Print "Индексы: ", I, J
    					Res = "Yes"
    					Exit For
    			End If
    		Next J
    	Next I
    	Debug.Print Res
    End Sub

    Обратите внимание, оператор выхода Exit For прекращает выполнение только внутреннего цикла, так что проверка на ноль будет осуществляться в каждой строке матрицы, независимо от существования нулей в предыдущих строках. Сделаем еще несколько замечаний по поводу оператора For Next:

  • По окончании цикла счетчик цикла сохраняет свое значение в момент выхода и его можно использовать, например, для анализа преждевременного выхода из цикла. Заметим, что в большинстве языков программирования значение счетчика цикла считается неопределенным по завершении цикла.
  • В операторе Next можно не указывать имя переменной, задающей счетчик, это имя подразумевается по умолчанию, как завершающее последний открытый оператор For. Однако и эту возможность не следует использовать. Рекомендуем всегда явно указывать имя счетчика в операторе Next.
  • Допускается менять значение счетчика в теле цикла. Этого не следует делать никогда. К сожалению, система не следит за этим и допускает подобные безобразия. Этот цикл никогда не завершится:
  • Public Sub For2()
    	Dim A(1 To 5) As Integer
    	Dim i As Integer
    	For i = 5 To 1 Step -1
    		A(i) = i
    		i = i + 1
    	Next i
    		
    End Sub

    Обычно попытка изменить значение счетчика цикла в его теле означает, что вместо цикла For…Next следовало бы применить цикл другого вида, например Do…Loop.

    Цикл Do...Loop

    Повторяет блок операторов, пока заданное условие является истинным или пока оно не станет истинным.

    Синтаксис:

    Имеется четыре варианта синтаксиса этого цикла. В двух первых вариантах условие проверяется в начале цикла:

    Do [{While | Until} условие]
    тело цикла
    Loop

    В других двух вариантах условие проверяется в конце цикла:

    Do
    тело цикла
    Loop [{While | Until} условие]

    Здесь условие является числовым или строковым выражением со значениями True или False. Вообще оно необязательно. Значение Null условия трактуется как False. Тело цикла - это последовательность операторов, которая будет выполняться, пока условие остается истинным, если перед ним стоит ключевое слово While или пока оно остается ложным - в вариантах цикла с ключевым словом Until. Таким образом, циклы вида While условие эквивалентны циклам вида Until Not условие. Кроме того, в тело цикла может входить оператор Exit Do, выполнение которого сразу прекращает цикл и передает управление оператору, непосредственно следующему за Loop. В случае нескольких вложенных циклов Do … Loop оператор Exit Do завершает лишь самый внутренний цикл, в теле которого он расположен.

    Примеры.

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

    Public Sub Loop1()
    	Const Size = 5
    	Dim X() As Integer
    	Dim i As Integer
    	Dim Found As Boolean
    	Const pat = 7
    	'Инициализация случайными числами в интервале [1 - 10]
    	ReDim X(1 To Size)
    	Randomize
    	For i = 1 To Size
    		X(i) = Int(11 * Rnd)
    	Next i
    		
    	'Поиск по образцу с проверкой в начале цикла
    	i = 1: Found = False
    	Do While (i <= Size) And (Not Found)
    		If X(i) = pat Then
    			Found = True
    		Else: i = i + 1
    		End If
    	Loop
    	If Found Then
    		Debug.Print "Найден образец!"
    	Else: Debug.Print "Образец не найден!"
    	End If
    		
    	'Поиск по образцу с проверкой в конце цикла
    	i = 1: Found = False
    	Do
    		If X(i) = pat Then
    			Found = True
    		Else: i = i + 1
    		End If
    	Loop Until Found Or (i = Size + 1)
    	If Found Then
    		Debug.Print "Найден образец!"
    	Else: Debug.Print "Образец не найден!"
    	End If
    		
    	'Поиск с барьером
    	ReDim Preserve X(1 To Size + 1)
    	X(Size + 1) = pat
    	i = 1
    	Do
    		If X(i) = pat Then Exit Do
    		i = i + 1
    	Loop
    	If i = Size + 1 Then
    		Debug.Print "Образец не найден!"
    	Else: Debug.Print "Образец найден!"
    	End If
    End Sub

    Цикл While...Wend

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

    Синтаксис:

    While	условие
    тело цикла
    Wend

    Здесь условие и тело цикла такие же, как и для цикла Do…Loop. Только для этого вида цикла не предусмотрен оператор выхода Exit. Фактически цикл While…Wend - частный случай цикла Do…Loop - оставлен в языке для совместимости с предыдущими версиями.

    Цикл For Each...Next

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

    Синтаксис:

    For Each элемент In группа
    тело цикла
    Next [элемент]

    Здесь элемент - переменная, которая пробегает в качестве значений элементы коллекций или массива. Для коллекций элемент может быть переменной типа Variant, переменной типа Object или переменной (объектом) некоторого класса. В случае цикла по массиву элемент обязан быть переменной типа Variant. Группа - это имя набора объектов (чаще всего это коллекция объектов) или массива, для элементов которых выполняется цикл. Цикл не применим для массивов, тип элементов которых определен пользователем, так как такие элементы не могут быть значениями переменной типа Variant. В таких массивах можно использовать цикл вида For … Next. Тело цикла - последовательность операторов, выполняемая для каждого элемента набора или массива, - может содержать операторы Exit For, позволяющие прервать выполнение цикла и передать управление оператору, следующему за Next (обычно такой выход происходит при выполнении некоторого условия, проверяемого в операторе If…Then…Else ). Указывать переменную элемент после ключевого слова Next не обязательно, но желательно.

    Примеры.

    В примере создается коллекция, число элементов которой и сами элементы выбираются случайным образом. Затем эта коллекция копируется в динамический массив, размерность которого увеличивается в процессе копирования. На последнем этапе массив распечатывается. Циклы типа For …Each прекрасно работают в подобных ситуациях:

    Public Sub ForEach1()
    	Dim X As New Collection
    	Dim Y() As Integer
    	Dim item As Variant
    	Dim i As Integer, Size As Integer
    		
    	'Инициализация коллекции
    	Randomize
    	Size = Int(21 * Rnd)
    	For i = 1 To Size
    	    X.Add Int(11 * Rnd)
    	Next i
    		
    	'Копирование коллекции в динамический массив
    	Size = 1
    	For Each item In X
    		ReDim Preserve Y(1 To Size)
    		Y(Size) = item
    		Size = Size + 1
    	Next item
    	
    	'Печать элементов динамического массива
    	For Each item In Y
    		Debug.Print item
    	Next item
    End Sub

    Кроме рассмотренных управляющих операторов VBA содержит доставшиеся в наследство от прежних версий операторы перехода по метке GoTo, перехода по метке с возвратом GoSub...Return и условные операторы перехода по меткам On...GoSub и On...GoTo. Мы никогда не пользуемся этими операторами.

    Работа с каталогами, папками и файлами

    Операторы этой группы позволяют перемещать текущий каталог (папку) по дискам системы, создавать новые и удалять каталоги (папки): изменять атрибуты файлов, копировать и удалять файлы. Их набор по существу совпадает с набором соответствующих команд операционной системы.

    Изменение текущего диска: оператор ChDrive

    Синтаксис:

    ChDrive диск

    Обязательный параметр диск - это строка, задающая имя существующего диска, который должен стать текущим, например:

    ChDrive "D"

    сделает диск "D" текущим.

    Изменение текущего каталога (папки): оператор ChDir

    Синтаксис:

    ChDir путь

    Обязательный параметр путь - это строковое выражение, значение которого задает новый текущий каталог (папку). Если путь не содержит имени диска, меняется текущий каталог на текущем диске. Подчеркнем, что оператор ChDir меняет текущий каталог (папку), но не диск. Например, если текущим является диск С, команда:

    ChDir "D:\TMP"

    изменит текущий каталог на диске D, но диск C останется текущим.

    Создание каталога (папки): оператор MkDir

    Синтаксис:

    MkDir путь

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

    Public Sub Dirs()
    	'Сделать текущим диск F
    	ChDrive "F"
    	'Создать 3 каталога на F
    	MkDir "Temp1"
    	MkDir "F:\Temp2"
    	MkDir "F:Temp3"
    End Sub

    Переименование каталогов (папок) и файлов: оператор Name

    Позволяет переименовывать каталоги (папки) и файлы и перемещать файлы.

    Синтаксис:

    Name СтароеИмя As НовоеИмя

    СтароеИмя и НовоеИмя - обязательные параметры, задающие старое и новое имя файла (каталога, папки). Они могут включать имя диска и путь. СтароеИмя должно быть именем существующего файла (каталога, папки), а НовоеИмя не должно быть именем уже существующего объекта. Оба имени должны использовать один и тот же диск. Если указанный новый путь существует и отличается от старого, оператор перемещает файл в новый каталог (папку) и, если требуется, переименовывает его. Каталоги и папки с помощью оператора Name перемещать нельзя, - лишь переименовывать. Перед переименованием файл должен быть закрыт.

    В этом примере файл переименовывается, а затем и перемещается в другой каталог:

    Public Sub DirsAndFiles()
    	'Сделать текущим диск F
    		ChDrive "F"
    		'Переименование файла
    		Name "Exam1E.xls" As "Example1.xls"
    		'Перемещение файла
    		Name "Example1.xls" As "Temp1\Example1.xls"
    End Sub

    Удаление каталога (папки): оператор RmDir

    Синтаксис:

    RmDir путь

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

    RmDir "Temp3"

    удалит папку Temp3 с текущего диска.

    Установка атрибутов файла: оператор SetAttr

    Синтаксис:

    SetAttr имяфайла, атрибуты

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

    Атрибуты файла
    Имя константы Значение Описание
    VbNormal 0 Нормальный (по умолчанию)
    vbReadOnly 1 Только для чтения
    VbHidden 2 Скрытый
    VbSystem 4 Системный файл
    VbArchive 32 Файл изменен со времени последнего создания резервной копии

    Нельзя менять атрибуты открытого файла (иначе будет выдано сообщение об ошибке).

    Копирование файлов: оператор FileCopy

    Синтаксис:

    FileCopy файл-источник, файл-результат

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

    Пример:

    'Копирование файла
    		FileCopy "Temp1\Example1.xls", "Temp2\Example1.xls"

    Удаление файлов: оператор Kill

    Синтаксис:

    Kill файл

    Параметр файл - строковое вырыжение, задающее имя удаляемого файла. Он может включать имя диска и путь по каталогам или папкам. Для удаления нескольких файлов можно использовать в образце имени файла символ '*' для обозначения произвольной последовательности букв и '?' - для обозначения одного символа. Нельзя удалять открытый в данный момент файл.

    Пример.

    Допустим, в текущем каталоге находятся файлы PROG.DOC, PROG.CPP и PROG.OBJ. Тогда оператор:

    Kill "PROG.*"

    удалит эти файлы с диска.

    Прочие операторы

    И еще несколько полезных операторов VBA, не попавших ни в одну из предыдущих групп.

    Операции с одним объектом. Оператор With

    Если в одном блоке программы предстоит выполнить несколько операций с одним объектом, то, чтобы не повторять многократно имя этого объекта, можно ввести оператор With.

    Синтаксис:

    With объект
    [операторы]
    End
    With

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

    Допустим, пользовательский тип Person и переменная MyFriend определены так.

    Type Person
    	Name As String
    	Age As Integer
    	Height As Single
    End Type
    
    Dim MyFriend As Person

    Тогда присвоение значений свойствам переменной MyFriend можно произвести с помощью оператора With:

    With MyFriend
    	Name = "Сергей"
    	Age= 35
    	.Height = 178.5
    End With

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

    With объект1
    	операторы1
    	With объект2
    		операторы2
    	End With
    
    End With

    в блоке операторы2 имя объекта1 нужно указывать полностью. Если же объект2 - элемент (подобъект) объекта1, то, использовав оператор With объект2, можно получить во внутреннем блоке сокращенный доступ к свойствам объекта " объект1. объект2 ".

    Например, если к типу Person добавить данные о встрече:

    Type Meeting
    	Place As String
    	Date As Date
    End Type
    
    Type Person
    	Name As String
    	Age As Integer
    	Height As Single
    	LastMeeting As Meeting
    End Type
    
    Dim NewAcquaintance As Person

    то задавать данные о новом знакомом NewAcquaintance можно, используя вложенные операторы With.

    With NewAcquaintance
    	.Name = "Елена"
    	.Age= 40
    	.Height = 168
    	With.LastMeeting
    		.Place= "библиотека"	
    		'этот оператор эквивалентен:
    		'NewAcquaintance. LastMeeting.Place="библиотека"
    		.Date= #08/03/99#
    	End With
    End With

    Звуковой сигнал: оператор Beep

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

    Синтаксис:

    Beep

    Частота и сила звука зависят от оборудования и могут меняться от компьютера к компьютеру. Обычно звуковой сигнал используется как реакция на какие-либо ошибки или исключительные ситуации, возникающие при выполнении программы.

    Установка системной даты: оператор Date

    Синтаксис:

    Date = дата

    Пример:

    Date = #April 29, 1999#	' Изменение системной даты.

    Установка системного времени: оператор Time

    Синтаксис оператора Time:

    Time = время

    Пример:

    Time = #8:15:47 PM#	' Установка системного времени

    Моделирование ввода с клавиатуры: оператор SendKeys

    Посылает один или несколько кодов символов в текущее активное окно, как если бы соответствующие клавиши были нажаты.

    Синтаксис:

    SendKeys строка[, режим-ожидания]

    Параметр строка - строковое выражение, задающее последовательность посылаемых символов. Необязательный параметр режим-ожидания - выражение с булевым значением. Если оно False (по умолчанию), управление возвращается в процедуру сразу же после посылки кодов; True - посланная последовательность кодов должна быть обработана, прежде чем управление возвратится в процедуру.

    Большинство символов, набираемых на клавиатуре, входят в строку непосредственно. Например, чтобы послать последовательность из трех символов Y, E и S, возьмите в качестве строки " YES ". Символы: +, ^, %, ~, скобки и некоторые другие следует помещать в фигурные скобки. Например, чтобы послать +, в параметр строка нужно поместить {+}. Для посылки кодов клавиш, не отображаемых на экране, имеются специальные коды. Некоторые представлены в таблице, остальные можно найти с помощью подсказки:

    Коды клавиш, не отображаемых на экране
    Клавиша Код
    BACKSPACE {BS}
    BREAK {BREAK}
    CAPS LOCK {CAPSLOCK}
    DEL {DEL}
    DOWN ARROW {DOWN}
    END {END}
    ENTER {ENTER} или ~
    ESC {ESC}
    HOME {HOME}
    INS {INS}
    LEFT ARROW {LEFT}
    PAGE DOWN {PGDN}
    PAGE UP {PGUP}
    RIGHT ARROW {RIGHT}
    TAB {TAB}
    UP ARROW {UP}
    Fn {Fn} (n=1,…, 12)

    Чтобы послать комбинацию клавиш, для Shift, Ctrl и Alt используются следующие коды (В примере используется документ DocTwo7:

    Shift - +
    Ctrl 	 ^
    Alt 	 %

    Пример:

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

    Public Sub OpenDocWithPassword()
    	'Открытие документа с паролем
    	SendKeys "+^"	'Переключение раскладки клавиатуры
    	SendKeys "don"  "{'}"  "t know", False		'пароль "don't know"
    	Documents.Open "e:\O2000\CD2000\Ch7\DocTwo7.doc"
    	Documents("DocTwo7.doc").Activate
    	
    End Sub

    Обратите внимание на два момента:

  • Прежде, чем послать сам пароль, происходит переключение клавиатуры на другую раскладку, для чего используется комбинация символов "Shift + Ctrl".
  • Символы клавиатуры посылаются в буфер ввода еще до того, как они потребуются. Если бы оператор Open предшествовал оператору SendKeys, то окно ввода пароля появилось бы до выполнения этого оператора. В данном же случае при открытии документа пароль автоматически появится в окне ввода, так что останется только щелкнуть по кнопке OK.
  • Вернуться к учебному плану