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

Условные обозначения:
a|b — вводится одно из нескольких возможных значений, [x] — необязательные параметры,
<информация, которая должна быть введена пользователем или программой>.

Содержание
Главная страница VBA.
Настройке параметров безопасности.
Запись макросов (макрорекордер)
Редактор VBA
Непосредственно программирование
Программирование в целом (не VBA)
Операторы
Переменные и типы данных
   Именование
   Создание переменных
   Область видимости переменных
   Типы данных
   Действия над данными
   Действия над массивами
Функции
   Символьные
   Даты и времени
   Числовые и математические
   Задаваемые пользователем (UDF)
   Преобразование типов
Низкоуровневые функции для работы с файлами
Построение диалогов и экранных форм
Диалоги
InputBox
InputBox в Excel VBA
MsgBox
Экранные формы (Forms)
Объектные модели приложений MS Office
Word авторская (2003), от Microsoft
Excel от Microsoft
PowerPoint от Microsoft
Ветвление программ
Циклы

Операторы

Microsoft делит операторы в VBA на арифметические, объединения, сравнения и логические, что, в общем, сразу и нарушает. Поэтому мы пойдем немного своим путем, что сути не изменит, но упростит понимание.

Первичная суть заключается в том, что с помощью операторов можно оценить данные или произвести их простейшие изменения.
ОператорНазвание оператораПример операцииРезультат
=Присваиваниес = с + 1Увеличение
значения x на 1
+Сложениеx = 2 + 5x = 7
-Вычитаниеx = 2 - 5x = -3
*Умножениеx = 2 * 5x = 10
^Возведение в степеньx = 2^3x = 8
/Делениеx = 2/5x = 0,4
\Целая часть от деленияx = 12\5x = 2
ModОстаток от деления (modulo of division)x = 2 Mod 5
x = 10 Mod 4
x = 2 (5*0+2)
x = 2 (4*2+2)
&/+Конкатенация (слияние) выражений с преобразованием их к типу String.
Может использоваться для соединения данных разного типа в символьный
x = "2" & "5",
либо x = "2" & 5,
либо(!) x = "2" + "5"
x = "25"

В отличие от других операторов, присваивание может быть использовано в строке только один раз, в связи с чем во многих случаях для него используется предварительное двоеточие: Unit:=wdCharacter.

В Visual Basic двоеточие служит для оформления нескольких строк в одну. Зачастую это не только делает текст более компактным, но и помогает быстрее его понять:

x(1,1) = "Иванов" : x(1,2) = "Иван" : x(1,3) = "Иванович" : x(1,4) = "01.01.1990"

Операторы сравнения

Возвращают значение True, False или NULL.
ОператорНазвание оператора
=Тот же, что и присвоение
<Меньше
>Больше
<=Меньше или равно
>=Больше или равно
<>Не равно
IsСравнение двух объектов
LikeСравнение двух строк с возможностью использования шаблона
EqvСравнение двух выражений

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

Логические операторы

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

Логические операторы располагаются между двумя логическими выражениями, каждое из которых так или иначе либо истинно, либо ложно.
ОператорНазвание оператора
AndИ. Означает, что оба соединяемых выражения должны быть истинны
ImpИмпликация двух выражений
NotНЕ. Ставится перед логическим выражением, значение которого меняется на противоположное. Может использоваться с группировочными скобками
OrИЛИ. Хоть одно из выражений истинно
XorИсключающее ИЛИ. Только одно из выражений должно быть истинно

Переменные и типы данных

Именование переменных

См. в материале по основам программирования.

Создание переменных

Если не задана обязательность объявления переменной (Option Explicit), то любая переменная может быть создана самим фактом ее использования. То есть строка x = 1 создаст переменную x с типом Variant и присвоит ей числовое значение единицы.

При этом ничто не препятствует использовать команду создания с указанием типа (необязательным), например,

Dim x As Integer

Несколько переменных в одной строке указываются через запятую.

Dim x As Integer, y As String

Создание массивов см. в разделе Действия над массивами.

Область видимости переменных

Краткий смысл темы заключается в том, откуда можно обратиться к переменной, чтобы считать значение и/или изменить его: только из программы, любой программы модуля, из любого модуля.

По умолчанию действует следующая схема.

  1. Переменные, объявляемые на уровне процедуры переменные доступны только внутри соответствующей процедуры.
  2. Переменные, объявляемые на уровне модуля (в области общих задач), доступны всем процедурам внутри этого модуля, но имеют статус Private.
  3. Переменные, объявляемые на уровне модуля как глобальные (общие, Public), доступны для всех процедур в проекте.
  4. Константы являются частными (Private) по умолчанию. Внутри процедур константы всегда являются частными, их видимость изменить нельзя. В стандартных модулях по умолчанию видимость констант уровня модуля(!) можно изменить с помощью ключевого слова Public.

Основные типы данных

Хотя типов данных (точнее программных переменных, в которых данные хранятся) довольно много, можно выделить и сгруппировать наиболее важные, имеющие общие правила обработки.

В квадратных скобках указан размер в байтах. Кроме указания на место, занимаемое в памяти, для многих типов это определяет возможный диапазон значений. Так, 2 байта для целых чисел дают 22*8 (65536) значений. Но один бит используется для указания знака, что ограничивает диапазон значений 215 (до ±32768).

Действия над данными

Если для числовых данных и, соответственно, переменных арифметические действия являются само собой разумеющимися, то для других типов обычно возникают некоторое непонимание. Разрешить его вполне можно с помощью логических рассуждений.

Символьные данные обычно используются в операции сложения (объединения/конкатенации), когда нужно собрать из кусочков выражение. Все участвующие фрагменты должны быть только символьного типа, либо преобразовываться в него. Сложение символов обычно вызывает только одну трудность: учет стыковочных пробелов. С одной стороны, пробелы не появляются сами по себе (и два слова могут склеиться). С другой, наличие множества пробелов в конце первого фрагмента также должно быть учтено (иначе возникнет большой пробел между фрагментами).

Кроме этого, в строке можно найти фрагмент (номер символа, с которого он начинается) или выделить (скопировать в переменнуюю) фрагмент слева, справа или из произвольного места.

Логические данные полностью подчиняются законам алгебры логики. Хотя бояться этого точно не стоит: подобные дебри бесконечно редко возникают в программировании, все остается на уровне максимального примитива. Три оператора (Or, And, Not) покрывают более 99% случаев и относятся к области одновременной оценки нескольких объектов или разных характеристик одного объекта.

Дата на самом деле хранится как число и может вычитаться из даты (разница в днях), либо к ней можно прибавить целое число (будущая дата), или вычесть целое число (дата в прошлом).

В связи с вышеизложенным, для того чтобы выполнить над данными определенные действия, во многих случаях необходимо произвести изменение (преобразование) их типа.

Действия над массивами

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

Соответственно, можно условно выделить три варианта:

  1. Одномерный массив, то есть состоящий из одной колонки.
  2. Двумерный массив представляет собой истинную простую таблицу (n колонок на m строк).
  3. Многомерный массив в VBA может содержать до 60 измерений. Реально можно представить трехмерный массив, в виде набора простых двумерных таблиц, расположенных друг за другом.

Нумерация элементов массива в VBA по умолчанию начинается с нуля. Это определяется директивой Option Base.

Функция Array позволяет создать одномерный массив путем перечисления его значений:

A_Arr = Array(1, 5, 15)

В норме же, массив объявляется командой Dim. В первом варианте указываются его размеры. Следующая команда создает одномерный массив из 21 элемента с индексами от 0 до 20, для размещения символьной информации.

Dim MyArray(20) As String

Следующая команда создает двумерный массив (с типом данных Variant, который используется по умолчанию).

Dim MyArray(2, 3)

Во втором варианте определяется набор индексов элементов (от и до) создаваемого массива. Следующая команда создает массив из 10 элементов с индексами от 1 до 10.

Dim MyArray(1 To 10)

Команда может включать несколько диапазонов, например, для трехмерного массива:

Dim MyArray(1 To 5, 4 To 9, 3 To 5)

Наконец, самый примитивный вариант создает массив с именем, требующий последующего задания размерности (командой ReDim).

Dim MyArray()

Обращение к элементу массива производится по имени с указанием координат.

Уже имеющийся массив нельзя объявить снова, например, для изменения размера. Для этого необходимо воспользоваться командой ReDim <имя_массива>(<размер(ы)>):

ReDim A_Arr(5, 8)

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

Использование в команде ключевого слова Preserve не только пересоздаст массив, но и сохранит в нем предыдущие значения. Естественно, с потерей части данных в случае уменьшения размера.

ReDim Preserve A_Arr(20, 8)

Существующий массив может быть исследован на размеры функциями

Из этих функций можно получить потенциальную реализацию цикла

For i = LBound(arr1) To UBound(arr1)

То есть от минимального элемента до максимального. (Приведенный код является нерациональным, и лишь иллюстрирует принцип!)

Функция Split(<строка>, <разделитель>) позволяет разобрать строку и поместить результат в одномерный массив, начинающийся с нуля. Например, список через запятую или слова, разделенные пробелом.

Функции

Функции представляют собой подпрограммы, выполняющие некоторую обработку информации и всегда возвращающие результат этой обработки. Функция — классический пример вспомогательного алгоритма. Именно функции обладают наиболее выраженным свойством массовости, так как многократно используются при решении большого и разнообразного числа задач.

Вызов функций, как правило, одинаковый:

переменная = ИмяФункции([аргументы через запятую]).

Число аргументов может быть различным, что указывается в описании. Некоторые из них являются необязательными, и их приводят в конце списка для удобства использования.

Порядок указания аргументов задается строго. Менять их местами нельзя! Если значение среднего аргумента опускается, то должна быть поставлена пустая запятая:

MsgBox("Сообщение", , "Заголовок").

Но! В описании функции может быть указано, что первый аргумент необязательный, а его значение присваивается по умолчанию (см. InStr()).

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

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

Ниже приведены некоторые наиболее важные функции с их разбивкой по принципу типа обрабатываемой информации (в алфавитном порядке). Как показывает практика, подобное разделение наиболее эффективно.

Символьные (строковые) функции

ФункцияНазначение
Asc(<строка>)Возвращает ASCII-код (0–255) первого символа строки
Chr(<число>)Преобразует ASCII-код (0–255) в символ (строку)
InStr([начало, ]<строка, в которой ищем>, <искомая строка>)Находит позицию первого вхождения одной строки внутри другой. InStr(3, "корова", "о") вернет значение 4. То есть, начиная с третьей буквы, «о» стоит на четвертой позиции в слове. (InstrRev работает также, но с конца строки.)
LCase(<строка>), UCase(<строка>)Возвращает строку, преобразованную в нижний и верхний регистры соответственно
Left(<строка>, <число символов>)Возвращает число первых (слева) символов строки. Если их меньше, чем запрошено, возвращается вся строка
Len(<строка>)Возвращает количество символов в строке (длину строки)
Mid(<строка>, <номер начального символа>[, <число символов>])Выделяет фрагмент из строки. Mid("корова", 2, 3) вернет «оро»: три символа, начиная со второго
Replace(<строка>, <что>, <на что>)Возвращает строку, заменив в ней одни фрагменты на другие
Right(<строка>, <число символов>)Возвращает указанное число последних (справа/концевых) символов строки
Space(<число>)Возвращает строку, состоящую из «числа» пробелов (специализированный String)
StrReverse(<строка>)Возвращает строку со знаками в обратном порядке
String(число, символ)Возвращает строку, состоящую из «числа» повторяющихся символов
Trim(<строка>), LTrim(<строка>) и RTrim(<строка>)Удаляют из строки пробелы слева (LTrim), справа (RTrim), или с обеих сторон (Trim)
Val(<строка>)Преобразует строку в число

Коды некоторых важных символов.
СимволASCII-код
Табулятор9
Enter13
Esc27
Пробел32 (первый неслужебный знак)
!33 (первый знак, который выводится на экран и на печать)

Функции даты и времени

ФункцияНазначение
DateAdd(интервал, число, дата)Прибавляет к дате «число» интервалов (лет, месяцев, недель и т.д.). Интервал задается символьным шаблоном
DateSerial(год, месяц, день)Возвращает значение даты. Каждый из числовых аргументов может быть математическим выражением
TimeSerial(час, минута, секунда)Возвращает значение времени. Каждый из числовых аргументов может быть математическим выражением
TimeValue(<строка времени>)Извлекает значение времени (Time) из его строкового представления в любом варианте, основанном на шаблоне разделения двоеточием ("0:00:00")
Hour(<время>)Выделяет из строки времени (тип Time) часы (тип Integer)
Minute(<время>)Выделяет из строки времени (тип Time) минуты (тип Integer)
Second(<время>)Выделяет из строки времени (тип Time) секунды (тип Integer)
TimeВозвращает системное время компьютера. Тип — Time. В VBA используется без скобок (то есть MyTime = Time)
DateВозвращает системную дату компьютера. Тип — Date. В VBA используется без скобок (то есть MyDate = Date)
NowВозвращает системную дату и время компьютера. Today = Now
TimerВозвращает количество секунд (с дробной частью), прошедших после полуночи
Weekday(<дата>, [номер первого дня недели])Возвращает номер дня недели указанной даты. По умолчанию, первый день недели — воскресенье. Чтобы получить в привычном нам порядке, следует задать второй аргумент — двойку: Weekday("01.01.2009", 2)

Числовые и математические функции

ФункцияНазначение
Abs(x)абсолютное значение (модуль) числа x
Atn(x)арктангенс угла x в радианах (от –π/2 до π/2)
Cos(x)косинус угла x в радианах
Exp(x)константа e (основание натурального логарифма ~2.718282) в степени x
Log(x)натуральный логарифм от числа
Rnd([x])генерация случайного числа от 0 до 1. Аргумент x может задавать правила выбора значения
Round(x, [десятичных знаков])округляет числа с заданной точностью
Sgn(x)знак числа, равно -1 для отрицательных чисел; 1 — для положительных и 0 для x = 0
Sin(x)синус угла x в радианах
Sqr(x)квадратный корень из x
Str(x)преобразует число x в строку. Для положительных чисел в начало добавляется пробел
Tan(x)тангенс угла x в радианах
Fix(x)Отбрасывает дробную часть числа и возвращает целое значение. В отличии от Int(), для отрицательных значений дает ближайшее большее целое (Fix(-3,3) = –3)
Int(x)Отбрасывает дробную часть числа и возвращает целое значение. В отличии от Fix(), для отрицательных значений дает ближайшее меньшее целое (Int(-3,3) = –4)

Производные тригонометрические функции (арксинус...) можно посмотреть здесь.

Чтобы преобразовать градусы в радианы, умножьте градусы на π/180 (π ≈ 3,1415926535897932).

Также имеется множество финансовых функций, не входящих в наш курс обучения.

Функции, задаваемые (или определяемые) пользователем (UDF)

Использование UDF (User Defined Function) позволяет многократно расширить возможности языка программирования и, в гораздо большей степени, уменьшить трудозатраты на разработку.

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

Вместе с тем, необходимым является понимание как самой идеи, так и технологии ее реализации. Дальнейшее использование неизбежно связано с методом проб и ошибок.

Основания для написания UDF:

  1. Очевидные. Необходимость одинаковых действий, осуществляемых из разных процедур и, особенно, для разных проектов. Начинающему программисту это очевидным не кажется, пока не нарастет критическая масса знаний и опыта.
  2. Неочевидные. Необходимость одинаковых действий из одной процедуры. Часто это может быть решено программно (всегда сложнее) и без создания функции.
  3. Скрытые. Уменьшение кода основной программы, очень сходное с рассуждениями на первых этапах устного описания бытовых алгоритмов: создается своего рода «черный ящик», обращение к которому и результат такового очевиден, но скрыт. Более сложным будет видение возможной перспективы выделения функции, когда, с большой вероятностью, ее удастся применить позже. Может быть с существенной переработкой, но первый шаг простимулирует обдумывание решения.

При определении функции вместо Sub используется Function, а для завершения — End Function.

Область видимости. Данный вопрос не обсуждается в литературе. Сразу отметим, что ни одна функция не видна в списке макросов, так как ее запуск пользователем не подразумевается. Вызвать функцию можно только обращением из программы. При обычном определении, функция доступна из любого модуля проекта. При определении Private Function, к ней можно обратиться только из текущего модуля. Наоборот, Public Function доступна из любого модуля любого открытого проекта.

Нормой следует считать ситуацию, когда функции передается какая-то информация, подвергающаяся анализу или обработке. В первом случае возвращается результат анализа, чаще всего логического типа (True или False). Во втором — обработанные данные.

Чтобы использовать возвращаемое значение функции, следует назначить ее переменной, а аргументы заключить в скобки. То есть также, как для встроенной функции. Например, для вызова функции без аргументов с ожиданием возврата целого числа в диапазоне 0–255:

	Dim Var As Byte
	Var = MyFunc()

Значение, которое возвращается функцией, должно быть присвоено в процессе обработке переменной с именем функции.

	Function MyFunc()
		Код функции...
		MyFunc = 1 'Возвращаемое значение равно единице 
	End Function

Преобразование типов данных

Во всех языках программирования существует большое число функций, предназначенных для преобразования одного типа данных в другой. Необходимость этого связана с тем, что многие действия можно производить только над данными одного типа. Например, нельзя сложить число 10 и строку из двух цифр: "20" (в VBA — можно). Если первое превратить в строку, то результат будет представлять собой четырехсимвольную строку "1020". Наоборот, преобразовав "20" в число и опять сложив их, получим число 30.

В других ситуациях просто предполагаются разнообразные математические операции над числами, а результат нужно вывести в виде строки, снабженными поясняющими словами. Например, обработали число 5 и получили число 120. Чтобы собрать строку: "Из числа 5 получен результат 120!", нужно провести преобразование чисел и их сложение с текстом:

"Из числа" + Str(5) + "получен результат" + Str(120) + "!"

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

Для проверки типа данных (точнее, их анализа) можно воспользоваться одной из функций в формате Функция(<переменная>): IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNull, IsNumeric, IsObject.

Также можно применить общую функцию TypeName(имя_переменной), возвращающую название типа данных словом из списка: Byte, Integer, Long, Single, Double, Currency, Decimal, Date, String, Boolean, Error, Empty, Null, Object.

Весьма небесполезна в этом плане также VarType(имя_переменной), возвращающая идентичную информацию, но числом.

Преобразования числа в строку: Str(<число>)

В большинстве языков программирования для положительных чисел мы получим строку, в начале которой стоит пробел, а для отрицательных — дефис.

Для того, чтобы избавиться от этого пробела, можно использовать одну из двух функций Trim(<строка>) или Ltrim(<строка>).

Важно! В качестве десятичного разделителя распознается исключительно точка!

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

Format(Expression, [ Format ], [ FirstDayOfWeek ], [ FirstWeekOfYear ])

Ее побочным эффектом будет строка из числа без ведущего пробела. Синтаксис довольно сложный, так что приведем простейший пример:

Format(x, "General Number")

Следующий вариант выведет число с отделением разрядов (классов) пробелами:

Format(x, "Standard")

Преобразования строки в число: Val(<строка>)

Следует четко понимать, что любой текст, взятый из документа, изначально будет набором символов, даже если они представляют собой числа. Для того, чтобы произвести с ним математические операции и, зачастую, корректное сравнение, требуется превратить их в число.

  1. Функция обработает любую строку и, если она содержит в качестве первого знака цифру, производится преобразование для последующих цифр.
  2. При этом игнорируются пробелы, а первая(!) точка воспринимается как десятичный разделитель. Вторая точка прервет процесс.
  3. Анализ продолжается, пока выполняются пп.1 и 2.
  4. Если цифра в начале не обнаружено, будет возвращен ноль.

Важно! В качестве десятичного разделителя распознается исключительно точка! Если вам нужно обработать десятичную запятую, воспользуйтесь функцией

Replace(x, ",", ".")

где x — строковая переменная, содержащая число с десятичной запятой.

Ветвление программ (условные операторы)

Для осуществления ветвления программ используются два основных оператора: If... Else... End If и Case...

Оператор If... Else... End If

По существу, оператор следует переводить как Если... Иначе... Конец Если.

1. Первичным следует считать использование так называемого неполного If. В этом случае не используется часть Else.

	If <условие> Then
	    ...[блок команд]
	End If

Таким образом, блок команд будет выполнен только когда будет истинным условие, заданное на входе оператора.

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

	If x > 10 Then
	    x = x/10
	End If

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

	If <условие> Then
	    ...[блок команд 1]
	Else
	    ...[блок команд 2]
	End If

Пример, в котором переменная памяти x возводится в квадрат, если она отрицательна, а иначе — в куб (ноль также будет возводиться в куб):

	If x < 0 Then
	    x = x^2
	Else
	    x = x^3
	End If

3. Наконец, ряд языков (как и VBA) позволяет составлять многоуровневую конструкцию без использования вложения If.

	If a = 1 Then
	    ...[блок команд 1]
	ElseIf a = 2 Then
	    ...[блок команд 2]
	ElseIf b > 0 Then
	    ...[блок команд 3]
	Else
	    ...[блок команд 4]
	End If

Функция IIf()

Так как чрезвычайно часто встречается ситуация, когда единственное назначение условного оператора — изменение переменной памяти по условию, все развитые языки содержат функцию IIf(). Она решает названную задачу в гораздо более компактном виде.

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

x = IIf(x < 0, 0, 1)

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

Оператор Case

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

	Select Case <проверяемое выражение>
	Case значение1
	    [действия1]
	[Case значение2
	    [действия2]]
	...
	[Case Else
	    [действия для любых других случаев]]
	End Select

Циклы

Организация циклов в программах встречается довольно часто и применяется для двух основных случаев: когда нужно повторить фрагмент программы определенное количество раз и когда это повторение осуществляется до тех пор, пока выполняется некое условие.

Цикл For...

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

Общий синтаксис:

	For счетчик = start To end [Step шаг]
	    [программа]
	    [Exit For]
	    [программа]
	Next [счетчик]

В приводимом далее примере находится произведение четных чисел (шаг = 2) от 2 до введенного пользователем значения y. Если произведение превысит 1 трлн, то произойдет выход из цикла. Нетрудно убедиться, что i достигнет только 24, а y будет равен 1,961,990,553,600.

	Dim i As Byte, x As Double, y As Integer
	x = 1
	y = InputBox()
	For i = 2 To y Step 2
	    x = x * i
	    If x > 1000000000000 Then
	        Exit For
	    End If
	Next i

Программа не содержит никаких проверок и вывода результата, но, если пользователь введет не то, цикл просто не будет выполняться. Далее — важный для начинаюших момент. Строка "x = x * i" означает, что переменной x будет присвоен результат ее текущего значения, умноженный на четное i. После этого производится сравнение. Запись триллиона в явном виде, а не как 10^9 экономит ресурсы, так как иначе производилось бы возведение в степень на каждом повторении цикла. For Each In...Next

Объектно-ориентированное программирование предполагает наличие объектов, состоящих из «кучи» элементов. Результатом стал специализированный цикл For без счетчика, но с перебором каждого (Each) элемента, спрятанноего внутри какого-то объекта (In).

	For Each элемент In имя_объекта(массива)
	    [программа]
	    [Exit For]
	    [программа]
	Next [элемент]

Цикл While...Wend

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

Общий синтаксис:

	While <условие>
	    [тело цикла]
	Wend

Условие является обязательным и может представлять собой символьное или числовое выражение, анализ которого возвращает истинное или ложное значение (то есть логическое). Если результатом вычисления будет значение Null, то оно расценивается как ложное.

Тело цикла выполняется при истинном значении условия, вплоть до оператора Wend, а затем вновь возвращается на строку While для повторной оценки условия. Если оно истинно, то происходит повтор тела цикла. Иначе происходит завершение цикла и исполнение программы продолжается со строки, идущей после Wend.

Цикл While может быть вложенным.

Обратите внимание, что принудительного выхода из цикла нет: только анализ исходного условия! Для того, чтобы его реализовать, следует воспользоваться циклом Do...Loop. Эта реализация цикла лучше всего подходит для так называемого «зацикливания» программы, когда он повторяется бесконечно.

Ремарка: прервать ситуацию можно клавишами Esc (если разработчик ее не заблокировал) и Ctrl+C.

Цикл Do (While...|Until...)... Loop

Данный цикл в том или ином виде используется в большинстве языков программирования и исполняется, пока (While) истинно условие или пока условие не будет достигнуто (Until)

Общий синтаксис:

	Do {While|Until} <условие>
	    [тело цикла]
	    [Exit Do]
	    [продолжение тела цикла]
	Loop

или

	Do
	    [тело цикла]
	    [Exit Do]
	    [продолжение тела цикла]
	Loop {While|Until} <условие>

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

Число команд Exit Do внутри тела не ограничено и обычно реализуется через ветвление с использованием If...Then. При таком завершении, исполнение программы продолжается со строки, идущей после Loop.

Конструкция With...End With

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

Она предназначена для случаев, когда объектные выражения с одинаковым началом (нередко довольно длинным) повторяются много раз. Макрорекордер использует эту конструкцию слишком часто, что приводит к необходимости обратного действия — сборке конструкции в одну строку.

Понятно, что в следующем примере речь идет о поиске — всё, что внутри конструкции — строки которого не нужно выискивать в программе. Фраза «Selection.Find» записана только один раз. Все строки, которые должны получить её в начало, следует начинать с точки.

	With Selection.Find
	    .ClearFormatting
	    .Replacement.ClearFormatting
	    .Text = "?"
	    .Replacement.Text = "!"
	    ...
	End With

Без With это выглядело бы так:


	Selection.Find.ClearFormatting
	Selection.Find.Replacement.ClearFormatting
	Selection.Find.Text = "?"
	Selection.Find.Replacement.Text = "!"
	...

Некоторые мысли по оптимизации программного кода

«Идеальное» написание программы всегда было «идолом». Недостижимым даже теоретически.

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

К сожалению, как не существует решения для многих противоречий, невозможно


Доступ к размещенным в этом месте материалам ограничен и предоставляется следующим категориям:

  1. Студент I курса ВХК РАН
  2. Бывший студент ВХК РАН
  3. Подготовка к ОГЭ
  4. Подготовка к ЕГЭ

Перенос текста программ из модулей

Примитивная задача, ведь все умеют копировать! Попробуйте. Желаю успеха. Я вижу два примитивных способа, основанные на одинаковом исходном действии.

Рассказ — на занятии.


Copyright © 1993–2020 Мацкявичюс Д.А. Все права защищены.
Никакая часть сайта не может быть воспроизведена никаким способом без письменного разрешения правообладателя и явной ссылки на данный ресурс.