The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Формулы в Microsoft Excel 2010 ( PDFDrive )

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by sergiu.sulima, 2022-05-22 12:49:43

Формулы в Microsoft Excel 2010 ( PDFDrive )

Формулы в Microsoft Excel 2010 ( PDFDrive )

566 Часть VI. Разработка пользовательских функций

Рис. 23.2. Используйте диалоговое окно Refe­
rences для создания ссылки на проект, в котором
содержится нужная пользовательская функция VBA

Совет

По умолчанию все проекты получают имя VBAProject — такое имя появля­
ется в списке доступных ссылок в диалоговом окне References. Чтобы убе­
диться, что выбран правильный проект в диалоговом окне ссылок, просле­
дите за диалоговым окном, в котором показано имя рабочей книги для вы­
бранного элемента. Еще лучше изменить имя проекта на описательное. Для
этого выберите проект, нажмите <F4> для отображения окна свойств и по­
том укажите имя проекта, отличающ ееся от V BA Project. Не забывайте, что
имя должно быть уникальным.

Аргументы функций

Пользовательские функции, подобно встроенным в Excel функциям, могут изменять
свою работу в зависимости от используемых в них аргументов. Придерживайтесь сле­
дующих советов при определении аргументов в функциях VBА:

• функция может не иметь аргументов;
• функция может иметь фиксированное количество обязательных аргументов (от

1 до 60);
• функция может содержать комбинацию обязательных и необязательных аргументов;
• функция может иметь специальный необязательный аргумент с именем Р а г а -

m a rra y , позволяющий задавать неопределенное число аргументов.
Перекрестная ссылка

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

Все ячейки и диапазоны, используемые функцией, должны быть переданы ей через
аргументы. В коде F u n c t i o n не может быть непосредственных ссылок на ячейки
и диапазоны.

Глава 23. Разработка функций 567

Диалоговое окно вставки функции

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

Примечание

Пользовательская функция, определенная с помощью ключевого слова
P r iv a t e , не отображается в диалоговом окне вставки функции. Эту особен­
ность вы найдете очень удобной при создании функций, которые использу­
ются другими функциями, а не формулами.

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

Добавление описания функции

При выборе встроенной функции Excel с помощью команды Формулы«^Библиотека
функций^Вставить функцию в диалоговом окне вставки отображается ее краткое опи­
сание (рис. 23.3). Таким же описанием можно сопроводить и создаваемые пользователь­
ские функции.

Рис. 23.3. Краткое описание выбранной
встроенной функции в диалоговом окне
вставки функции

Примечание

Если не добавить описание функции, в диалоговом окне вставки будет ото­
бражаться текст Справка недоступна.

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

1. Создайте функцию в редакторе Visual Basic.
2. Перейдите в Excel и выберите команду Разработчика Код1«=>Макросы (или на­

жмите <Alt+F8>). Диалоговое окно Макрос представит в виде списка доступные
процедуры, но не функции.

568 Часть VI. Разработка пользовательских функций

3. Введите имя функции в поле имени макроса и убедитесь, что не допустили опечаток.
4. Щелкните на кнопке Параметры для отображения диалогового окна параметров

макроса. Если кнопка Параметры неактивна, вероятно, введено неправильное
имя функции.
5. Введите описание функции в поле описания (рис. 23.4). Следует отметить, что
горячие клавиши для вызова функций не используются.
6. Щелкните на кнопке ОК, а затем — на Отмена.

Рис. 23.4. В диалоговом окне парамет­
ров макроса введите описание функции

Примечание

При использовании диалогового окна вставки функции (см. рис. 23.3) ди а­
логовое окно аргументов функции появится после щелчка на кнопке ОК. Во
встроенных функциях в окне аргументов функции отображается описание
каждого аргумента.

Определение категории функции

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

Предположим, что вы создали функцию и назвали ее REMOVESPACES. Вам необхо­
димо, чтобы данная функция появилась в категории Текстовые (в Excel она фигурирует
под номером 7). Для этого выполните следующую команду VBA:

A p p l ication.MacroOptions M a c r o :="R EMOVESPACES", Category:=7

Одним из способов выполнения этой инструкции является использование окна отлад­
ки редактора Visual Basic. На рис 23.5 показан пример. Откройте окно Immediate, вве­
дите инструкцию и нажмите <Enter>. Потом сохраните рабочую книгу; в результате в
ней будет сохранено определение функции в указанной категории. Данную инструкцию
необходимо выполнить только один раз. Другими словами, нет необходимости назначать
категорию функции каждый раз, когда открывается книга.

Глава 23. Разработка функций 569

Рис. 23.5. Выполнение инструкции VBA, назначающей функции категорию

Можно также создать соответствующую процедуру и затем выполнить ее.

Sub A s s i g n T o F u n c t i o n C a t e g o r y () M a c r o : = "REMOVESPACES", _
Appliacation.M acroOptions
C a t e g o r y : =7

End Sub

После выполнения процедуры ее можно удалить. Естественно, в этой процедуре
можно заменить существующее имя функции и определить функцию в другую катего­
рию. Процедура определения категории функции ( A s s i g n T o F u n c t i o n C a t e g o r y )
может состоять из любого количества инструкций, каждая из которых соответствует от­
дельной функции.

В табл. 23.1 представлен перечень категорий функций, которые можно использовать.
Замечу, что некоторые из них (10-13), как правило, не отображаются в диалоговом окне
вставки функции. Однако если отнести функцию к одной из этих категорий, она появится
в диалоговом окне.

Таблица 23.1. Категории функций

Номер категории Название категории
0
1 Все (категория не определена)
2 Финансовая
Дата и время
3 Математические
4 Статистические
5 Ссылки и массивы
Работа с базой данных
6 Текстовые
Логические
7 Проверка свойств и значений

8

9

570 Часть VI. Р азработка пользовательских ф ункций

Окончание табл. 23.1

Номер категории Название категории

10 Команды
11 Настройки
12 Управления макросами
13 DDE/в н е ш н и е
14 Пользовательские
15 Инженерные
16 Кубические
17 Совместимости

Можете также создать пользовательскую категорию. Приведенная ниже инструкция
создает пользовательскую категорию Мои ф ун к ци и , после чего присваивает ее функ­
ции REMOVESPACES.

A p p l i c a t i o n . M a c r o O p t i o n s M a c r o : = "REMOVESPACES", _
C a t e g o r y : = "Мои функции"

Добавление описания аргумента

При вставке встроенной функции Excel в окне подсказки и во втором окне вставки
функции отображается описание аргументов. Это же можно сделать и для пользователь­
ской функции. Описание аргументов поможет вам вспомнить, что нужно ввести, если вы
давно не работали с созданной вами же функцией.

Ф Новинка

В Excel 2010 введен метод M acroO ptions, позволяющий добавлять описа­
ние аргументов пользовательской функции.

В главе 25 будет рассмотрена функция EXTRACTELEMENT.

F u n c t i o n EXTRACTELEMENT(T x t , n , S e p a r a t o r ) As S t r i n g
' Возвращает n -й элемент текстовой строки, в которой
' элементы разделены заданным символом

Dim A l l E l e m e n t s As V a r i a n t
AllElem ents = S p lit(T x t, Separator)
EXTRACTELEMENT = A l l E l e m e n t s ( n - 1)
End F u n c t i o n

Эта функция принимает три аргумента и возвращает элемент текстовой строки. На­
пример, следующая формула вернет строку f g h i — третий элемент полученной строки:

=EXTRACTELEMENT( " a b - c d e - f g h i - j k l ", 3 , "-")

Ниже приведена процедура VBA, добавляющая описание аргументов функции

EXTRACTELEMENT.

Sub D e s c r i b e F u n c t i o n ()
Dim d e s c ( l To 3) As S t r i n g
d e s c (l) = "Разделенная текстовая строка"
d esc(2 ) = "Количество элементов строки"
d e s c ( 3 ) = "Символ р аздел и теля"
A p p l i c a t i o n . M a c r o O p t i o n s M a c r o :="EXTRACTELEMENT",
Argum entDescriptions:=desc

End Sub

Глава 23. Разработка функций 571

Описание аргументов сохраняется в массиве d e s c , используемом в методе M a c r o -
O p t i o n s в качестве аргумента A r g u m e n t D e s c r i p t i o n s . Запустить эту процедуру можно
только один раз. После этого описание аргументов будет сохранено в рабочей книге.

Тестирование и отладка функций

Естественно, тестирование и отладка функций — это важный этап; следует внима­
тельно проверить правильность вычислений. В этом разделе рассматриваются некоторые
методы отладки, которые могут оказаться весьма полезными.

Примечание

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

Код VBA может содержать три основных типа ошибок.

• Синтаксические ошибки. Синтаксической ошибкой, например, является непра­
вильное написание ключевого слова, его отсутствие или несогласованные скобки.
Редактор Visual Basic предоставляет возможность ознакомиться с синтаксически­
ми ошибками, отображая на экране специальное окно. Функцию невозможно ис­
пользовать до тех пор, пока синтаксические ошибки не будут исправлены.

• Ошибки выполнения. Ошибки, появляющиеся во время выполнения функции.
Например, попытка выполнить математическую операцию над строковой пере­
менной приведет к такой ошибке. Если вы не знаете о ее существовании заранее,
то не будете знать о ее источнике, пока ошибка не проявится.

• Логические ошибки. Функция запускается, но возвращает неверный результат,
не сообщая об ошибке.

Совет

Для проверки кода в модуле VBA на наличие синтаксических ошибок выбе­
рите команду Debug«=>Compile (О тл а д ка ^К о м п и л я ц и я ). В результате на э к ­
ране появятся сведения о первой встреченной синтаксической ошибке, ес­
ли она существует. Исправьте эту ошибку и запустите операцию еще раз для
поиска других ошибок.

Процесс поиска и устранения ошибок называется отладкой.
При тестировании функции с использованием формулы рабочего листа сложно локали­
зировать ошибки выполнения, поскольку (в отличие от синтаксических ошибок) они не по­
являются во всплывающем окне ошибок. В случае появления ошибок выполнения форму­
ла, использующая функцию, просто будет возвращать ошибочное значение (#ЗНАЧ1).
В этом разделе описано несколько методов отладки пользовательских функций.

Совет

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

572 Часть VI. Разработка пользовательских функций

Использование окна сообщений VBA

Инструкция MsgBox, используемая в коде VBA, открывает на экране специальное окно

сообщений. Для контроля значения переменных можно использовать инструкции M sgB ox

в ключевых местах кода. Следующий пример демонстрирует функцию, которая обращает

текстовую строку, выступающую в роли ее аргумента. Например, переданное функции сло­

во П р и в ет должно возвращаться как тевирП . Однако если использовать эту функцию в

формуле, то можно убедиться, что она не работает из-за логической ошибки.

F un ction REVERSETEXT(text) As S tr in g & REVERSETEXT
1 Возвращает обращенный аргумент

TextLen = L en(text)
For i = T ex tL en To 1 S t e p -1

REVERSETEXT = M i d ( t e x t , i , 1)
Next i
End F u n c tio n

Можно вставить в код временную инструкцию M sgBox, который поможет идентифи­

цировать источник проблемы. Ниже приведена функция с инструкцией M sgBox, встав­

ленной внутрь цикла.

F un ction REVERSETEXT(text) As S tr in g & REVERSETEXT
' Возвращает обращенный аргумент

TextLen = L en(text)
For i = T extL en To 1 S te p -1

REVERSETEXT = M i d ( t e x t , i , 1)
MsgBox REVERSETEXT
Next i
End F u n c t io n

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

Рис. 23.6. Использование инструкции MsgBox
для тестирования значений переменной во вре­
мя выполнении функции

Щелкая на кнопке ОК, нетрудно заметить, что символы добавляются в начало, а не
в конец строки, в результате чего создается не обращенная, а исходная строка. Следова­
тельно, чтобы исправить ошибку, нужно поменять местами операнды конкатенации. За­
пишите оператор конкатенации наоборот, как показано ниже, и убедитесь в том, что те­
перь функция работает правильно.
REVERSETEXT = REVERSETEXT & M i d ( t e x t , i , 1)

Глава 23. Разработка функций 573

При передаче готовой функции в эксплуатацию следует убедиться, что все инструк­
ции MsgBox удалены, так как они очень раздражают конечного пользователя.

Совет

Если вас замучили окна сообщ ений, можете прервать выполнение процеду­
ры, нажав <Ctrl+Break>. После этого закройте всплывающее диалоговое ок­
но. Щ елкнув на кнопке End (Закончить), можно завершить выполнение кода.
Щелкнув на кнопке Debug (Отладка), можно выполнить код по шагам.

Для отображения в окне сообщений более чем одной переменной следует объединить
их и вставить пробел между каждой их парой. Ниже представлена инструкция, отобра­
жающая значения трех переменных (х, у и z) в окне сообщений:
MsgBox х & " " & у & " " & z

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

В качестве альтернативы можно разделить переменные константой vbN ew L ine,
вставляющей символ разрыва строки. К примеру, при выполнении следующей инструк­
ции каждая из переменных будет отображена в отдельной строке окна сообщений:
MsgBox х & vbNewLine & у & vbNewLine & z

Использование инструкции Debug. Print в коде

Если вам кажется, что инструкции M s g B o x слишком “надоедливы”, то лучший выход
из данной ситуации — вставка временного кода, записывающего переменные непосред­
ственно в окно отладки редактора Visual Basic. Для записи значений выбранных пере­
менных используется инструкция D e b u g . P r i n t .

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

F u n c t i o n VOWELCOUNT (г)
Count = О
For i = 1 То L e n (r)
Ch = U C a s e ( M id ( r , i , 1 ) )
I f Ch L i k e " [AEIOU]" Then
Count = Count + 1
D e b u g .P r in t Ch, i
End I f
Next i
VOWELCOUNT = Count

End F u n c t i o n

В данном примере инструкция D ebug. P r i n t выводит в окно отладки текущие зна­
чения переменных Ch и i . На рис. 23.7 показан результат операции вычисления. Аргу­
ментом функции является слово C a l i f o r n i a .

После отладки функции необходимо удалить все инструкции D ebug . P r i n t .

Вызов функции из процедуры

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

574 Часть VI. Разработка пользовательских функций

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

Рис. 23.7. Использование окна отладки редактора Visual Basic для отображения резуль­
татов во время работы функции
Следующая функция содержит ошибку выполнения. Как отмечалось ранее, ошибки
выполнения не отображаются во время вычисления формулы рабочего листа. Функция
лишь в самом конце возвращает ошибку #ЗНАЧ! , в результате чего тяжело понять, что
произошло.
F u n c tio n REVERSETEXT(text) As S t r i n g
' Возвращает обращенный аргумент

TextLen = L en(text)
For i = T extL en To 1 S te p -1

REVERSETEXT = REVERSETEXT And M i d ( t e x t , i , 1)
Next i
End F u n c t io n
Чтобы установить источник ошибки выполнения, вставьте в модуль следующую про­
цедуру.
Sub T e s t ()
х = REVERSETEXT("Привет")
MsgBox х
End Sub
Эта процедура всего лишь вызывает функцию REVERSETEXT и присваивает резуль­
тат переменной, названной х. Инструкция M sgB ox отображает результат.
Выполните процедуру непосредственно в редакторе Visual Basic. Для этого установи­

те курсор в любом месте процедуры и выберите команду Run^Run Sub/UserForm (Вы-
полнить^Процедуру/Форму) или нажмите <F5>. Когда процедура будет запущена,
в момент выполнения неправильной инструкции на экране отобразится сообщение об
ошибке (рис. 23.8).

Глава 23. Разработка функций 575

Рис. 23.8. Ошибка выполнения, определенная с помощью редактора VBA
Щелкните на кнопке Debug (Отладка), и редактор Visual Basic выделит цветом инструк­
цию, в которой предположительно содержится ошибка (рис. 23.9). Сообщение об ошибке не
объясняет, как ее исправить, но оно позволяет найти место в коде, где произошла ошибка.
После выявления инструкции, содержащей ошибку, ее можно изучить более детально, ис­
пользуя окно Immediate (см. ниже) для более точного нахождения причины ошибки.

Рис. 23.9. Выделена инструкция, вызвавшая ошибку выполнения
В нашем случае проблема заключается в неправильном использовании логического опера­
тора And вместо оператора конкатенации &. Правильная инструкция имеет такой вид.
REVERSETEXT = REVERSETEXT & M i d ( t e x t , i , 1)

576 Часть VI. Разработка пользовательских функций

Примечание

При щелчке на кнопке Debug процедура все еще будет выполняться — она
просто приостанавливается и переводится в режим паузы. После внесения
корректив следует нажать <F5> для продолжения ее выполнения в обычном
режиме или <F8> — в пошаговом. Чтобы завершить выполнение, щелкните
на кнопке Reset (Восстановить).

Использование окна отладки
Окно отладки (Immediate) редактора Visual Basic часто используется для отладки

программного кода (см. рис. 23.7). Для его открытия необходимо нажать <Ctrl+G>.
В окне отладки можно ввести инструкцию VBA и сразу же увидеть результат ее вы­

полнения. Например, введите следующий код в окне отладки и нажмите <Enter>:
Print S qr(1156)

Редактор Visual Basic отобразит результат операции извлечения квадратного корня
(число 34). Чтобы еще больше упростить себе работу, вместо инструкции P r i n t може­
те ввести вопросительный знак.

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

Часто ошибки возникают по причине неправильного задания типа данных. Напри­
мер, следующая инструкция отображает тип переменной C o u n te r (который, вероятнее
всего, должен быть целочисленным):
? TypeName(Counter)

При обнаружении типа данных для переменной C o u n te r, отличного от целочислен­
ного, проблема может быть решена вручную.

В окне отладки можно выполнить несколько инструкций, если разделить их двоето­
чием. В следующей строке содержится три инструкции:
х=12 : у=13 : ? Х+у

Таким методом может быть выполнено подавляющее большинство инструкций.

Задание точек останова в функции

Задание точки останова в коде— это еще один способ отладки. Выполнение кода
приостанавливается, когда VBA доходит до точки останова. Для проверки значений пе­
ременных можно воспользоваться окном отладки, а для пошагового выполнения про­
граммы клавишей <F8>.

Чтобы задать точку останова, необходимо установить курсор в коде инструкции, вы­
полнение которой необходимо приостановить, а затем выбрать команду Debug^Toggle
Breakpoint (Отладка^Точка прерывания). Также можно нажать <F9> или щелкнуть
кнопкой мыши на вертикальной полосе, расположенной в левой части окна кода. Любое
из этих действий приведет к выделению цветом инструкции, напоминая о том, что точка
останова активизирована (эту точку видно в левой части окна кода). В программном коде
можно определить любое количество точек останова. Для удаления точки останова сле­
дует установить курсор в код инструкции, содержащий ее, и нажать <F9>. На рис. 23.10
показана функция, содержащая точку останова.

Глава 23. Разработка функций 577

Рис. 23.10. Выделенная инструкция содержит точку останова

Совет
Для удаления всех точек останова во всех открытых проектах выберите ко­
манду Debug^Clear All Breakpoints (Отладка«=>Очистить все точки прерыва­
ния) или нажмите <Ctrl+Shift+F9>.

Создание надстроек

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

Допустим, у вас есть функция ZAPSPACES, и она находится в файле M yfuncs .x lsm .
Для ее запуска вы должны ввести следующую формулу:
=M yfuncs. x l s m !ZAPSPACES(AI:C l2)

После создания надстройки на основе файла M y fu n c s .x lsm можно пренебречь
ссылкой на файл и ввести формулу следующим образом:
=ZAPS PACES (AI : С12 )

Создание надстроек на основе рабочей книги — достаточно простая задача. Следующие
инструкции описывают процесс создания надстройки из обычного файла рабочей книги.

1. Создайте функции и убедитесь, что они работают надлежащим образом.

2. Активизируйте редактор Visual Basic и выделите рабочую книгу в окне проекта.

Выберите команду Tools*=$имя_проекта Properties (Инструменты■=>имя_проекта
Свойства) и перейдите на вкладку Protection (Защита). Установите флажок Lock
Project for Viewing (Заблокировать проект для просмотра) и дважды введите па­
роль. Щелкните на кнопке ОК.

Эту операцию необходимо выполнить только в том случае, если вы решили за­
щитить свой макрос от вмешательства других пользователей.
3. Активизируйте окно Excel. Выберите команду Файл^Сведения^Свойства1^
Показать область сведений о документе. Над строкой формул будет отображена

578 Часть VI. Разработка пользовательских функций

панель свойств документа. Введите краткий описательный заголовок в поле Назва­
ние и более подробное^описание в поле Примечания.

Этот этап не обязателен, однако данное действие облегчит поиск нужной на­
стройки в диалоговом окне подключения надстроек.

4. Выберите команду Файл^Сохранить как«=>Другие форматы.

5. В диалоговом окне сохранения выберите в списке типов файла пункт Надстрой­
ка Microsoft Excel (*.xlam).

6. Если не хотите использовать папку, предлагаемую по умолчанию, можете указать
другую.

7. Щелкните на кнопке Сохранить. Копия рабочей книги будет сохранена (с рас­
ширением .xlam ) как надстройка, а исходная рабочая книга (с расширением
. xlsm) останется открытой.

Ж йь Предупреждение

n lw При использовании функций, сохраненных в надстройках, Excel создает
ссылку на соответствующий файл надстройки. Таким образом, если вы пе­
редаете такую рабочую книгу кому-либо, ему нужно передать и копию файла
надстройки. Более того, данная надстройка должна быть сохранена на чу­
жом компьютере точно в том же месте, что и оригинал на вашем, поскольку
ссылки хранятся с указанием полного пути к файлу. В результате получате­
лю рабочей книги может потребоваться вручную отредактировать ссылки с
помощью команды Данные<=>Подключения ^Изменить связи.

Созданную надстройку можно установить в Excel, используя стандартную процедуру.

1. Выберите команду Файл^Параметры и в открывшемся окне перейдите во
вкладку Надстройки.

2. В раскрывающемся списке Управление выберите элемент Надстройки Excel.
3. Щелкните на кнопке Перейти, чтобы открыть диалоговое окно Надстройки.
4. Щелкните на кнопке Обзор.
5. Найдите нужный файл надстроек с расширением . xlam и щелкните на кнопке ОК.

Несколько слов о паролях

Компания Microsoft никогда не рекламировала Excel как программу, создающую
приложения с безопасным исходным кодом. Особенности процедур обработки паролей
таковы, что они не обеспечивают достаточный уровень защиты Excel от несанкциониро­
ванного доступа других пользователей к тем приложениям, которые вы хотели бы сде­
лать недоступными. Существует несколько программ по взлому таких паролей. Средст­
ва защиты в Excel 2002 и более поздних версиях более надежны, чем ё предыдущих, но
существует вероятность того, что их тоже можно взломать. Если вам нужна абсолютная
гарантия того, что никто не сможет увидеть код и формулы, то Excel — далеко не луч­
ший выбор в качестве платформы разработки. Впрочем, если информация особенно
ценная, можете после каждого сеанса сохранять рабочую книгу в зашифрованном ар­
хиве . га г; взломать такой архив невозможно. При этом не забывайте удалять неза­
шифрованную копию рабочей книги не только с диска, но также из корзины.

Глава

Концепции
программирования
наУВА

В этой главе...

♦ Пример функции
♦ Использование комментариев в коде
♦ Использование переменных, типов данных и констант
♦ Использование операторов присваивания
♦ Массивы
♦ Встроенные функции VBA
♦ Управление выполнением кода
♦ Работа с диапазонами

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

Компакт-диск
Большую часть примеров этой главы можно найдти на прилагаемом ком­
пакт-диске в файле f u n c t i o n e x a m p l e s . x ls m ( C h a p t e r 2 4 _ R U S . xlsm ).

580 Часть VI. Разработка пользовательских функций

Пример функции

Для начала рассмотрим пример функции. Функция, которая называется RE-
MOVESPACES, принимает текстовый аргумент и возвращает его без пробелов. Например,
в приведенном ниже коде функция REMOVESPACES возвращает значение Э т о т е к с т .
=REMOVESPACES("Это т е к с т ")

Чтобы создать такую функцию, откройте модуль VBA и в окне кода введите следую­
щую процедуру.
F u n c tio n REMOVESPACES(cell) As S t r i n g
' Удаляет из текста ячейки пробелы

Dim C e l l L e n g t h As I n t e g e r
Dim Temp As S t r i n g
Dim i As I n t e g e r
CellLength = L en (cell)
Temp = ""
For i = l To C e ll L e n g t h

Character = M id (c e ll, i ,1)
I f C h a r a c t e r <> C h r (3 2 ) Then Temp = Temp& Character
Next i
REMOVESPACES = Temp
End F u n c t i o n

Рассмотрим подробно каждую строку программного кода.

• Первая строка функции называется строкой объявления. Обратите внимание на то,
что процедура начинается с ключевого слова F u n c t i o n , после которого стоит на­
звание функции (REMOVESPACES). В функции используется один аргумент c e l l ;
имя аргумента заключается в круглые скобки. Выражение As S t r i n g определяет
тип возвращаемого функцией значения. Слово As вводить не обязательно.

• Вторая строка является обычным комментарием (необязательная строка) — на это
указывает апостроф, стоящий в начале строки. Комментарий описывает в произ­
вольной форме, что делает функция.

• В следующих трех строках ключевое слово Dim применяется для объявления трех
переменных, используемых в функции: C e l l L e n g t h (длина ячейки), Temp
(временная переменная) и i (счетчик цикла). Объявлять переменные не обяза­
тельно, но (как будет показано далее) желательно.

• В следующей строке переменной C e ll L e n g t h присваивается значение. Для оп­
ределения длины содержимого аргумента c e l l используется функция Len.

• Далее инициируется переменная Temp, которой присваивается пустая строка.

• В следующих четырех строках находится цикл F o r-N e x t. Операции между F o r
и N e x t выполняются столькочраз, сколько задано значением C e l l L e n g t h . На­
пример, если аргумент c e l l содержит строку Bob S m ith , операции в цикле по­
вторятся девять раз — по одной итерации для каждого символа в строке.

• В теле цикла переменная C h a r a c t e r содержит текущий символ, который извле­
кается функцией Mid. Инструкция I f определяет, является ли символ пробелом
(функция C h r в VBA эквивалентна функции СИМВОЛ в Excel, а аргумент 32 соот­
ветствует пробелу). Если символ не является пробелом, то он ставится в конец
строки, сохраняемой в переменной Temp; в противном случае переменная Temp

Глава 24. Концепции программирования на VBA 581

не изменяется, и процедура переходит к следующему символу. При желании мож­
но заменить эту инструкцию следующей:
I f C h a r a c t e r <> " " Then Temp = Temp& Character

• По завершении цикла в переменной Temp будут содержаться все символы, кото­
рые были переданы в аргументе c e l l , кроме пробелов.

• Строка, содержащаяся в переменной Temp, присваивается имени функции. Эта
строка и будет значением, возвращаемым функцией.

• Процедура F u n c tio n завершается инструкцией End F u n c tio n .

В процедуре REMOVESPACES используются следующие распространенные элементы
языка VBA:

• комментарии (в начале строки стоит апостроф);

• объявления переменных;

• три оператора присваивания;

• три встроенные функции VBA (Len, Mid и Chr);

• циклическая структура F o r -N e x t;

• условная структура I f - Then;

• объединение строк (с помощью оператора &).
Далее будет приведена более подробная информация об этих и других концепциях
программирования.

Примечание
Функция remove spaces, описанная выше, предназначена только для учеб­
ных целей. Того же результата можно достичь при использовании функции
подставить,, что намного рациональнее. Например, следующая формула
удаляет все пробелы в тексте ячейки a i:

=ПОДСТАВИТЬ(А1;" ";"")

Использование комментариев в коде

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

Для комментария можно использовать отдельную строку, также можно написать его
в одной строке с инструкциями, но только после них. Признаком комментария служит
апостроф. VBA игнорирует любой текст до конца строки, который находится после апо­
строфа. Исключениями являются апострофы внутри двойных кавычек. Например, в сле­
дующем выражении отсутствует комментарий, хотя в нем содержится апостроф:
Result = "Can't ca lcu la te"

В следующем примере представлена функция VBA с тремя комментариями.
F u n c t io n MYFUNC()

' Эта функция не де ла е т ничего
х=0 'х не п р е д с та в л я е т реальных данных

' Полезный р е з у л ь т а т не возвращается

582 Часть VI. Разработка пользовательских функций

MYFUNC = х
End F u n c tio n

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

Совет

На панели инструментов Edit (Редактирование) находятся две очень полез­
ные кнопки. Выделите группу инструкций и воспользуйтесь кнопкой Com­
ment Block (Закомментировать блок), чтобы преобразовать их в коммента­
рии. Кнопка Uncomment Block (Раскомментировать блок) преобразует группу
комментариев обратно в команды. Чтобы отобразить эту панель инструмен­
тов на экране, воспользуйтесь в редакторе Visual Basic командой View^Tool-
bars^Edit (Вид^Панели инструментов^Редактирование).

Использование переменных,
типов данных и констант

Переменной называется именованное место хранения данных в памяти компьютера.
Переменные могут иметь различные типы данных — от простых значений логического
типа B o o l e a n (TRUE или FALSE) до больших значений с двойной точностью (см. сле­
дующий раздел). Термины “тип данных” и “тип переменной” — синонимы. Тип пере­
менной влияет на выполняемые над ней операции, например, целочисленные перемен­
ные можно умножать, а строковые — нельзя. Переменная получает значение с помощью
оператора присваивания, которым является знак равенства. Значение, присвоенное пере­
менной, сохраняется в оперативной памяти компьютера.

Далее приведено несколько примеров использования операторов присваивания для
различных типов переменных. Имена переменных находятся слева от знака равенства,
а значения — справа.

X =1

InterestR ate = 0,075
LoanPayoffAmount = 243089
DataEntered = False
x =x + 1
MyNum = YourNum * 1 , 2 5
H a llO fF a m er = "Тревор Гофман"
DateStarted = #3/6/2007#

В VBA существует большое количество зарезервированных слов, которые нельзя ис­
пользовать в качестве имен переменных и процедур. Если попытаться использовать одно
из них, будет выведено сообщение об ошибке. Например, несмотря на то что зарезерви­
рованное слово N e x t могло бы быть описательным именем переменной, следующая ин­
струкция вызовет синтаксическую ошибку:
Next = 132

Глава 24. Концепции программирования на VBA 583

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

VBA существенно помогает программистам, автоматически регулируя характеристи­
ки данных. Тип данных говорит о том, в каком виде данные хранятся в памяти — как це­
лые или действительные числа, как строковые переменные и т.д.

Несмотря на то что VBA автоматически (неявно) заботится о типизации данных, все
не так просто — при этом понижается скорость выполнения формул и эффективность
использования памяти. Чтобы достичь оптимальной производительности выполнения
операций, следует основательно разобраться с типами данных. Как правило, лучше рабо­
тать с данными, которые занимают меньшее количество байт памяти. Когда VBA рабо­
тает с данными, скорость выполнения операций зависит от количества байт, находящих­
ся в распоряжении VBA. Другими словами, чем меньше памяти используется данными,
тем быстрее VBA их получает и оперирует ими. В табл. 24.1 перечислены встроенные
типы данных VBА.

Таблица 24.1. Типы данных VBA

Тип данных Объем занимаемой Диапазон допустимых значений
памяти
От 0 до 255
Byte 1 байт TRUE ИЛИ FALSE
Boolean 2 байта О т-32768 Д032767
Integer 2 байта О т-2147483 648 ДО 21474 83648
Long 4 байта О т- 3 , 402823Е38 ДО - 1 , 4012 98Е-45(ДЛЯ
Single 4 байта отрицательных значений); от l , 401298Е-45
до 3 #402823Е38 (для положительных значе­
Double 8 байт ний)
- 1 , 7976 93134 86231Е3 08 ДО-
Currency 8 байт 4 , 94065645841247Е-324 (ДЛЯ ОТрицатвЛЬ-
Decimal 14 байт НЫХ значений); ОТ4 , 94065645841247Е-324
ДО 1, 79769313486231Е308 (для положитель-
Date 8 байт ных значений)
4 байта О т-9223372 036854 77,5808 ДО
Object 10 байт + длина строки 922337203685477,5808
±7922 8162514264337493543950335 без ЗЭ-
String Длина строки ПЯТОЙ;±7,9228162514264337493543950335
(переменная с 28 символами после запятой
длина) 16 байт С 1 января 0100 года по 31 декабря 9999 года
String 22 байта + длина строки Любая ссылка на объект
(фиксированная От 0 до примерно 2 миллиардов
длина)
Variant От 1до примерно 65400
(с числами)
Любое числовое значение, вплоть до диапа­
Variant зона значений двойной точности
(с символами) От 0 до примерно 2 миллиардов

584 Часть VI. Разработка пользовательских функций

Объявление переменных

Переменную перед использованием в процедуре рекомендуется объявить. Если пе­
ременная не объявлена явно, она считается объявленной неявно. В явном объявлении пе­
ременной указывается ее имя и тип, при этом очевидны два преимущества.

• Процедуры выполняются быстрее, а память используется рациональнее. Ис­
пользуемый по умолчанию тип V a r i a n t приводит к многократным проверкам, за­
нимающим много времени и памяти. Если в VBA указать специальный тип пере­
менной, то интерпретатору не придется постоянно проверять переменную, и под нее
выделяется ровно столько памяти, сколько необходимо для хранения значений.

• Если в заголовке модуля использовать инструкцию O p tio n E x p l i c i t ,
можно избежать проблем неправильного написания имен переменных. Пред­
положим, что была использована необъявленная переменная C u r r e n t R a t e .
В определенном месте процедуры вводится выражение C u r r e n tR a t e = ,0 7 5 .
Так как объявление переменной пропущено, функция может вернуть неправиль­
ный результат.

Переменные явно объявляются с помощью ключевого слова Dim. Например, в сле­
дующей строке описывается переменная C o u n t типа I n t e g e r :
Dim Count As I n t e g e r

С помощью инструкции Dim можно объявить сразу несколько переменных, например:
Dim х As I n t e g e r , у As I n t e g e r , z As I n t e g e r
Dim F i r s t As Long, L a s t As D o u b le

Предупреждение
В отличие от других языков программирования, VBA не позволяет указать
тип данных для группы переменных, разделяя их запятыми. Например, сле­
дующее выражение (хотя оно и правильное) не описывает все переменные
Стипом I n t e g e r :

Dim i , j , k As I n t e g e r

В этом выражении только переменная к описана как in te g e r. Чтобы для всех
переменных указать тип in te g e r, следует объявить их следующим образом:
Dim i As I n t e g e r , j As I n t e g e r , k As I n t e g e r

Если тип переменной не указан явно, VBA использует стандартный тип данных
V a r i a n t . Данные, описанные как V a r i a n t , ведут себя как хамелеон: они меняют тип в
зависимости от выполняемых действий. В следующей процедуре показано, как одна пе­
ременная принимает различные типы данных.
F u n c t i o n VARIANT_DEMO ()

MyVar = "123"
MyVar = MyVar / 2
MyVar = "Ответ: " & MyVar
VARIANT_DEMO = MyVar
End F u n c t io n

В функции VARI ANT_D EMO переменная MyVar сначала неявно объявляется как
трехсимвольная строка, имеющая вид числа. Затем эта “строка” делится на два, и MyVar
приобретает числовой тип данных. После этого MyVar добавляется к строке, что преоб­
разует ее снова в строку. Функция возвращает строку — О т в е т : 6 1 ,5 .

Глава 24. Концепции программирования на VBA 585

Примечание

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

Как заставить себя объявлять переменные
Чтобы приучить себя объявлять все используемые переменные, вставьте в первую

строку модуля VBA следующее выражение:
Option E x p lic it

Эта инструкция останавливает выполнение процедуры, как только VBA встречает
необъявленную переменную. При этом интерпретатор VBA выводит сообщение об
ошибке C o m p ile e r r o r : V a r i a b l e n o t d e f i n e d и предлагает объявить перемен­
ную, прежде чем выполнение процедуры продолжится.

Чтобы инструкция O p t i o n E x p l i c i t создавалась автоматически в каждом новом
модуле VBA, выберите команду Tools^Options (Инструменты^Параметры) и установите
флажок Require Variable Declaration (Обязательное объявление переменных) во вкладке
Editor (Редактор) диалогового окна Options.

Использование констант

Значение переменной может (причем часто так и происходит) изменяться в процессе
выполнения процедуры (поэтому она и называется переменной). Иногда необходимо со­
слаться на имя переменной или строки, которая никогда не меняется; другими слова­
ми — на константу.

Константа объявляется инструкцией C o n s t. Ниже приведено несколько примеров
объявления констант.
Const NumQuarters as In te g er = 4
C o n st R a te = .0725, P e r i o d = 12
C onst CompanyName a s S t r i n g = "Абракадабра"

Во второй строке две переменные объявляются одной инструкцией, но она не указы­
вает их тип. Следовательно, обе константы имеют тип V a r i a n t . Поскольку константа
никогда не меняет своего значения, для нее необходимо задать значение при объявлении.
Область определения (иногда ее называют областью видимости) константы зависит от
того, в каком месте модуля она объявлена.

• Чтобы константа использовалась только в одной процедуре, ее следует объявить по­
сле ключевых слов Sub и F u n c t i o n ; при этом константа становится локальной.

• Чтобы константа была доступна для всех процедур в модуле, объявите ее перед
первой процедурой модуля.

• Можно сделать константу доступной для всех модулей в рабочей книге. Для этого
примените ключевое слово P u b l i c и объявите константу перед первой процеду­
рой модуля. Следующее выражение создает константу, доступную во всех моду­
лях VBA в рабочей книге:
P u b l i c AppName As S t r i n g = "Расчет бюджета"

586 Часть VI. Разработка пользовательских функций

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

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

В VBA и Excel определено множество встроенных констант, которые можно исполь­
зовать без объявления. В следующем примере использована константа с именем v b I n ­
f o r m a tio n , которая задает вывод значка в окне сообщения:
MsgBox "Привет!", v b ln fo r m a tio n

Константа v b ln f o r m a t io n имеет значение 64, но не важно, знаете ли вы об этом
или нет. Если вы будете создавать макросы путем записи своих действий с помощью ре­
кордера, то обнаружите в сгенерированном коде множество других констант.

Использование строк

Подобно программе Excel, VBA может оперировать как числами, так и текстом
(строками). В VBА поддерживается два типа строк.

• Строки фиксированной длины объявляются с указанием количества символов.
Максимальная длина составляет 65535 символов.

• Строки переменной длины могут содержать до 2 миллиардов символов.

Каждый символ строки занимает 1 байт памяти. Если длина строки известна заранее
(т.е. строка имеет фиксированную длину), то ее можно указать при объявлении с помо­
щью ключевого слова Dim; в противном случае VBA будет определять ее длину динами­
чески во время выполнения кода (строка с переменной длиной). В некоторых случаях
память используется более рационально при работе со строками фиксированной длины.

В следующем примере переменная M y S t r i n g объявлена как строка с фиксирован­
ной длиной в 50 символов. Переменная Y o u r S t r i n g тоже объявлена с типом строки, но
ее длина не указана явно.
Dim M y S tr in g As S t r i n g * 50
Dim Y o u r S t r i n g As S t r i n g

Работа с датами

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

Под переменную, объявленную с типом D a t e , отводится 8 байт памяти; в ней содер­
жатся данные в диапазоне с 1 января 0100 года по 31 декабря 9999 года. Этого проме­
жутка примерно в десять тысяч лет более чем достаточно даже для самого долгосрочно­
го финансового прогноза. В переменной типа D a t e хранится также время. На экране да­
ты и время в VBA расположены между двумя знаками решетки (#).

Глава 24. Концепции программирования на VBA 587

Примечание

Диапазон дат, поддерживаемых в VBA, намного больше, чем собственный
диапазон дат в Excel, который начинается с 1 января 1900. Поэтому будьте
внимательны и не используйте даты, которые не входят в диапазон дат, при­
емлемых в Excel.

Ниже приведены примеры объявления переменных и констант с типом D a t e .

Dim Today As D ate
Dim S ta r tT im e As D a te
Const F irstD a y As Date = # 1 /1 /2 0 0 2 #
Const Noon = # 1 2 :0 0 :0 0 #

Примечание

Переменные, объявленные с типом D a te , отображают даты в соответствии
с кратким системным форматом даты, а время отображается в соответствии
с системным форматом времени (либо 12-часовым, либо 24-часовым). Сис­
темные параметры отображения дат и времени можно изменить с помощью
окна Язык и региональные стандарты операционной системы Windows.

Использование операторов присваивания

Оператором присваивания называется такой оператор VBA, в котором вычисленный

результат выражения присваивается переменной или объекту. Выражение — это комби­

нация ключевых слов, операторов, переменных и констант, которая возвращает строку,

число и объект. Выражение может выполнять вычисление, оперировать символами или

проверять данные.

Если у вас не возникало трудностей с созданием формул в Excel, то при создании вы­

ражений в VBA они тоже не должны появиться. При введении формулы на рабочем лис­

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

своить переменной или применить его в качестве значения свойства.

В VBA в качестве оператора присваивания используется знак равенства (=). Обратите

внимание на следующие примеры присваивания (выражения расположены справа от

знака равенства).

X=1 / (z * 2)
X=X+ 1 = True
х = (у * 2)

M ultiSheets

В выражениях часто используются функции. Это могут быть встроенные функции
VBA, функции рабочих листов Excel или пользовательские функции, написанные на
VBА. Встроенные функции VBА будут рассмотрены далее.

Главную роль в VBA играют операторы. Математические действия описываются уже
знакомыми вам операторами, а именно: суммирования (+), умножения (*), деления (/),
вычитания (-), возведения в степень (ж) и объединения строк (&). Менее известный опе­
ратор — обратная косая черта ( \ ) — используется для целочисленного деления, а опера­
тор Mod возвращает остаток от деления двух целых чисел. Например, результат следую­
щего выражения равен двум:

17 Mod 3

Возможно, вам уже знакома функция Excel MOD. Обратите внимание, что в VBA вы­
ражение Mod является оператором, а не функцией.

588 Часть VI. Разработка пользовательских функций

VBA также поддерживает операторы сравнения, используемые в формулах Excel:
равно (=), больше (>), меньше (<), больше или равно (>=), меньше или равно (<=) и не
равно (<>). Кроме того, VBA предлагает полный набор логических операторов, перечис­
ленных в табл. 24.2. Обратитесь к справочной системе, чтобы получить дополнительную
информацию и просмотреть примеры, связанные с работой этих операторов.

Таблица 24.2. Логические операторы VBA

Оператор Действие

Not Выполняет логическое отрицание в выражении
And Выполняет логическое умножение двух выражений
Or Выполняет логическое сложение двух выражений
Xor Выполняет логическое исключение двух выражений
Eqv Выполняет логическое приравнивание двух выражений
Imp Выполняет логическое включение двух выражений

Приоритет выполнения операторов в VBA такой же, как и в Excel, но можно изме­
нить его с помощью круглых скобок.

Предупреждение

Оператор отрицания (знак “минус” ) интерпретируется в Excel и VBA по-
разному. Например, в Excel приведенная ниже формула возвращает 25.
=-5"2

Это же выражение в VBA возвращает - 25.
х=-5^2

Это объясняется тем, что в VBA (в отличие от Excel) операция возведения в
степень имеет более высокий приоритет, чем операция отрицания. Изме­
нить последовательность выполнения операторов можно с помощью ско­
бок. Приведенное ниже выражение VBA возвращает 25.
х = ( - 5 ) ж3

Массивы

Массивом называется группа элементов одного типа с одним именем; обратиться
к отдельнному элементу массива можно с помощью имени массива и индекса элемента.
В качестве примера определим массив из 12 строковых переменных, в котором каждая
переменная является названием одного из 12 месяцев. Если массив назвать M onth-
Names, то к первому элементу можно обратиться, как к MonthNames ( 0) , ко второ­
му — MonthNames (1) и т.д. до MonthNames ( 1 1 ) .

Объявление массива

Массив объявляется с помощью ключевого слова Dim или P u b l i c , как и обычная
переменная. В массиве можно объявить сразу несколько элементов. Для этого следует
указать первый индекс, а затем ключевое слово То и последний индекс — все в круглых
скобках. Например, так объявляется массив, состоящий из 100 целых чисел:
Dim M yA rray(l То 100) As I n t e g e r

Глава 24. Концепции программирования на VBA 589

При объявлении массива можно указать только индекс последнего элемента, при
этом в VBA (по умолчанию) предполагается, что 0 — индекс первого элемента. Сле­
дующие два выражения приведут к одинаковому результату:
Dim MyArray(0 t o 100) As I n t e g e r
Dim MyArray(lOO) As I n t e g e r

В обоих случаях массив состоит из 101 элемента.
Чтобы во всех массивах, в которых при объявлении указан только индекс последнего
элемента, индексом первого элемента была единица, введите перед каждой процедурой
в модуле следующее выражение:
Option Base 1

Если такое выражение присутствует в модуле, то следующие два выражения дадут
одинаковый результат (в обоих объявляется массив из 100 элементов):
Dim M yA rray(l t o 100) As I n t e g e r
Dim MyArray(lOO) As I n t e g e r

Объявление многомерных массивов

В предыдущем разделе были приведены примеры одномерных массивов. Массивы
в VBA могут иметь до 60 измерений, хотя редко используется больше трех. В следую­
щем выражении объявлен двухмерный массив, состоящий из 100 целых чисел:
Dim M yA rray(l То 10, 1 То 10) As I n t e g e r

Такой массив похож на матрицу размером 10x10. Чтобы обратиться к элементу двух­
мерного массива, следует указать два индекса. Присвоить значение элементу вышеопи­
санного массива можно следующим образом:
МуАггау(3 ,4 ) = 125

В динамическом массиве нет заранее заданного количества элементов. В динамиче­
ском массиве в круглых скобках ничего не ставится.
Dim М уАггау() As I n t e g e r

Однако перед использованием динамического массива в коде необходимо применить
инструкцию ReDim, чтобы указать VBA, сколько элементов находится в массиве (или
ReDim P r e s e r v e , если в массиве требуется сохранить существующие значения). Ин­
струкцию ReDim можно применять неоднократно, изменяя размерность массива столько
раз, сколько это необходимо.

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

Встроенные функции VBA

В VBA содержится большое количество встроенных функций, упрощающих вычис­
ления и выполнение операций. Многие функции VBA подобны (или идентичны) функ­
циям рабочих листов Excel. Например, функция VBA U C ase, которая изменяет регистр
строкового аргумента с нижнего на верхний, эквивалентна функции ПРОПИСН рабочего
листа Excel.

590 Часть VI. Разработка пользовательских функций

Совет
Чтобы отобразить список функций VBA во время написания кода, введите vba
и поставьте точку. Редактор VBA отобразит в окне подсказки список всех
функций, включая встроенные и пользовательские (рис. 24.1). Если ничего не
произошло и список не появился, убедитесь, что во вкладкё Editor диалогового
окна параметров редактора VBA установлен флажок Auto List Members
(Автоматическое отображение членов). Кроме функций, в отображенный спи­
сок входят встроенные константы. Полезно следующее правило: все, что мож­
но вставить в данном месте кода, есть в окне подсказки. Если вставить что-
либо иное, будет сгенерирована ошибка. Встроенные функции VBA подробно
описаны в справочной системе редактора VBA. Чтобы открыть справку о функ­
ции, наведите указатель на ее имя и нажмите клавишу <F1 >.

Рис. 24.1. Отображение списка функций VBA в окне кода

Ниже приведено выражение, в котором с помощью функции S q r вычисляется квад­
ратный корень переменной M y V a lu e, а результат присваивается переменной х.
х = Sqr(MyValue)

Имея представление о функциях VBA, можно избавить себя от большого объема ра­
боты. Например, рассмотрим процедуру функции REMOVESPACES, которая упоминалась
в начале этой главы. В этой функции для проверки каждого символа строки используется
цикл F o r - N e x t , а затем создается новая строка. Намного проще (и более эффективно)
использовать встроенную функцию R e p l a c e . Ниже представлена новая версия функции
REMOVESPACES.
F u n c tio n REMOVESPACES(cell) As S t r i n g
' Удаляет из строки все пробелы

REMOVESPACES = R e p l a c e ( c e l l , " ", "")
End F u n c t io n

В коде VBA можно использовать многие (но не все) функции рабочего диета Excel.
Чтобы отобразить в окне подсказки и применить в выражении VBA функцию Excel, вве­
дите перед именем функции слово W o r k s h e e t F u n c t i o n и точку.

В следующем примере продемонстрировано использование функции Excel в выраже­
нии VBA. Редко используемая в Excel функция РИМСКОЕ (Roman) преобразует десятич­
ные числа в римские. В коде VBA всегда необходимо использовать английские имена
функций, даже в русифицированной версии Excel.
DecValue = 2010
RValue = W orksheetFunction.Rom an(DecValue)

Глава 24. Концепции программирования на VBA 591

Переменной R V alue будет присвоена строка ММХ. Пользователей часто приводит в

замешательство тот факт, что в Excel нет функции преобразования римских чисел в их

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

затраченных усилий?

Важно помнить, что в коде VBA нельзя использовать функции Excel, для которых

есть эквивалент в VBA. Например, в VBA отсутствует доступ к функции рабочего листа

SQRT (КВКОРЕНЬ), так как в VBA есть собственная версия этой функции — Sqr. Таким

образом, следующее выражение вызовет ошибку:

х = A pplication.SQ R T(123) 'ошибка

Управление выполнением кода

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

В этом разделе рассмотрено несколько способов управления выполнением процедур VBА:

• конструкция I f - Then;

• конструкция S e l e c t Case;

• цикл F o r -N e x t;

• цикл Do W h ile;

• цикл Do U n t i l ;

• выражение On E rro r.

Конструкция I f - Then

Вероятно, наиболее часто используемой управляющей конструкцией в VBA является
I f-T h e n . Это единственный случай, в котором выражению предоставляется возмож­
ность выбора. В конструкции I f - T h e n используется следующий синтаксис.
I f условие Then код, выполняемый в случае и с т и н н о с т и условия

[ E l s e код, выполняемый в случае ложности условия]

Конструкция I f-T h e n выполняет одну или несколько команд в зависимости от истин­
ности условия. Ключевое слово E ls e вводить не обязательно, однако если он добавлен, это
позволяет выполнить одну или несколько команд в случае, когда условие не выполнено.

В примере следующей функции структура I f-T h e n представлена без ключевого
слова E ls e . Это пример со временем суток. Время суток выражено дробным значением
(например, полдень записывается как 0 , 5). Функция Time в VBA возвращает значение,
которое показывает время суток в системных часах компьютера. В следующем примере
функция начинается с присвоения переменной GreetM e пустой строки. Выражение I f -
Then проверяет время суток. Если это время до полудня, то ветвь Then выполняется,
и функция возвращает строку Д оброе утро.
F u n c t io n G r ee tM e()

GreetMe = ""

592 Часть VI. Разработка пользовательских функций

I f Time < 0 .5 Then GreetMe = "Доброе утро"
End F u n c t io n

В следующей функции используются две конструкции I f - T h e n . Эта функция воз­
вращает либо Д о б р о е у т р о , либо Добрый д е н ь :

F u n c t io n G r ee tM e()
I f Time < 0 .5 Then GreetMe = "Доброе утро"
I f Time >= 0 . 5 Then GreetM e = "Добрый день"
End F u n c t io n

Обратите внимание, что во второй раз в конструкции I f - T h e n применен оператор
>= (больше или равно). В этом случае при выполнении функции учитывается точное
время 12 : 00. Конечно, смысла в этом немного (вряд ли вы когда-либо запустите функ­
цию точно в полдень, не промахнувшись даже на микросекунду), тем не менее, так при­
нято писать, чтобы не возникали вопросы вроде: “А что произойдет, если запустить ее
точно в полдень?”. В общем случае придерживайтесь правила, согласно которому долж­
на быть заполнена вся ось значений.

В следующем примере продемонстрировано использование в конструкции I f - T h e n
ключевого слова E ls e .

F u n c t io n G r ee tM e()
I f Time < 0 .5 Then GreetMe = "Доброе утро" E lse _
GreetMe = "Добрый день"

End F u n c t io n

Заметьте, что в данном примере применяется символ продолжения строки (пробел
и подчеркивание). Выражение I f - T h e n - E l s e является одной инструкцией.

Далее приведен еще один пример использования конструкции I f - T h e n . Функция
вычисляет скидку в зависимости от количества (предполагается целое число) товара.
Функция принимает один аргумент (количество) и с учетом этого значения возвращает
соответствующую скидку (D is c o u n t).

Function D iscount(quantity)
I f q u a n t i t y <= 5 Then D i s c o u n t = 0
I f q u a n t i t y >= 6 Then D i s c o u n t = 0 . 1
I f q u a n t i t y >= 25 Then D i s c o u n t = 0 . 1 5
I f q u a n t i t y >= 50 Then D i s c o u n t = 0 . 2
I f q u a n t i t y >= 75 Then D i s c o u n t = 0 . 2 5

End F u n c tio n

Обратите внимание, что в этой функции выражение I f - T h e n всегда выполняется,
а значение D i s c o u n t изменяется по мере выполнения функции. Возвращаемое значе­
ние является конечным.

Во всех приведенных выше примерах конструкции I f - T h e n в выражении T hen ис­
пользуется один оператор. Однако часто требуется выполнить несколько действий, если
условие является верным. Воспользоваться конструкцией I f - T h e n можно и в этом слу­
чае, но для обозначения последней операции в блоке T h en придется применить выраже­
ние End I f . Ниже приведен пример выполнения двух инструкций, когда условие спра­
ведливо.

I f х > 0 Then
у =2
z =3

End I f

Глава 24. Концепции программирования на VBA 593

В конструкции I f - T h e n - E l s e также можно использовать несколько инструкций.
Следующий пример демонстрирует выполнение двух инструкций при истинном условии
и двух других инструкций — при ложном.

I f х > 0 Then
у =2
z =3

Else
у = -2
z = -3

End I f

Конструкция Select Case

Конструкция S e l e c t C ase используется для выбора одного из нескольких вариан­

тов действий. Она является альтернативой конструкции I f - T h e n - E l s e . В ней исполь­
зуется следующий синтаксис.

S e l e c t C ase выражение
[Case список_выражений
[инструкции] ]
[Case E lse
[инструкции_по_умолчанию] ]

End S e l e c t

В следующем примере конструкции S e l e c t C ase показан другой способ решения
задачи из примера G re etM e, приведенного в предыдущем разделе:

F u n c t i o n G r e e tM e ()
S e le c t Case Time
Case Is < 0.5
GreetMe = "Доброе утро"
Case 0 . 5 To 0 .7 5
GreetMe = "Добрый день"
Case E lse
GreetMe = "Добрый вечер"
End S e l e c t

End F u n c t io n

Далее приведем пример функции D is c o u n t, на этот раз с использованием конструк­
ции S e l e c t C ase:

Function D iscount(quantity)
S e le c t Case q u a n tity
C ase I s <= 5
Discount = 0
Case 6 To 24
Discount = 0.1
Case 25 To 49
Discount = 0.15
Case 50 To 74
Discount = 0.2
Case I s >=75
Discount = 0.25
End S e l e c t

End F u n c tio n

В инструкцию C ase можно вводить любое количество операций; все они выполня­
ются, если условие верно.

594 Часть VI. Разработка пользовательских функций

Создание циклов

Цикл — это процесс повторения группы команд VBA в процедуре. Количество по­
вторений (итераций) можно задать самому или определить на основе значений перемен­
ных в программе. VBA предлагает несколько конструкций циклов:

• цикл F o r -N e x t;

• цикл Do W h ile;

• цикл Do U n t i l .

Цикл F o r-N ex t

В цикле F o r -N e x t используется следующий синтаксис:

For счетчик = начало То конец [Step шаг]
[инструкции]
[E xit For]
[инструкции]

N e x t [ счетчик]

В приведенном ниже примере показано использование цикла F o r -N e x t, в котором
нет необязательного ключевого слова S te p и выражения E x i t For. Функция возвра­
щает сумму всех целых чисел в диапазоне, ограниченном двумя аргументами.

Function S u m ln te g er(first, la s t)
total = 0
For num = f i r s t To l a s t
t o t a l = t o t a l + num
N e x t num
Sumlnteger = to ta l

End F u n c t io n

Следующая формула Excel возвращает число 55 — сумму всех целых чисел от 1 до 10.

=Sum Integers(1,10)

В этом примере num (счетчик итераций) начинается со значения, переданного в пер­
вом аргументе, и увеличивается на единицу в каждой итерации. Цикл завершается, когда
num равно значению последнего аргумента. Переменная t o t a l складывает все значения
num, которые она получала во время выполнения цикла.

Предупреждение

При использовании цикла F o r-N ex t следует иметь в виду, что счетчик цикла —
обычная переменная, а не особый ее тип. Поэтому значение счетчика в цикле кода
между выражениями For и N ex t можно изменять. Однако это не очень хорошая
идея— при ее реализации могут возникнуть проблемы. Будьте внимательны
и следите, чтобы счетчик изменялся только сам по себе, а не другими командами.

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

Function S u m ln te g ers2 (fir st, la st)
total = 0
F or num = f i r s t To l a s t S t e p 2
t o t a l = t o t a l + sum
N e x t num
Sumlntegers2 = Total

End F u n c t io n

Глава 24. Концепции программирования на VBA 595

Следующая строка возвращает значение 25, которое является суммой чисел 1, 3, 5, 7 и 9:

= Su m Integers2(1,10)

В цикле F o r -N e x t может содержаться одна или несколько инструкций E x i t For.
Когда встречается эта инструкция, цикл немедленно завершается, как показано в сле­
дующем примере.

Function RowOfLargest(с)
NumRows = R o w s. Count
MaxVal = W ork sh eetF u nction .M ax (C o lu m n s(c ))
For r = 1 To NumRows
I f C e l l s (r, c) = MaxVal Then
RowOfLargest = r
E xit For
End I f
Next r

End F u n c t io n

Функция R o w O fL a rg e st принимает в качестве аргумента номер столбца (от 1 до
16384) и возвращает номер строки с наибольшим значением в этом столбце. Функция
начинается с получения количества строк в таблице (оно зависит от версии Excel). Это
число присваивается переменной NumRows. Максимальное значение в столбце вычисля­
ется функцией MAX Excel, и это значение присваивается переменной MaxVal.

Цикл F o r -N e x t проверяет каждую ячейку в столбце. Когда обнаруживается ячейка,
равная MaxVal, номер строки (переменная г, счетчик цикла) присваивается имени
функции, а выражение E x i t F or завершает цикл. Если не написать инструкцию E x i t
For, цикл продолжит проверять все ячейки столбца, на что может потребоваться до­
вольно много времени!

В предыдущих примерах использовались сравнительно простые циклы. Но бывают
ситуации, когда в цикле применяется несколько сложных выражений, а иногда один цикл
F o r-N e x t вкладывается в другой. Далее показан код VBA, в котором массив размерно­
сти 10x10x10 инициализируется значениями -1 . Для этого используются вложенные
циклы F o r - N e x t. Когда завершится выполнение трех циклов, каждому из тысячи эле­
ментов М уАггау будет присвоено значение -1 .

Dim М уАггау(1 t o 10, l t o 1 0 , 1 t o 10)

For I = 1 To 10

For j = 1 To 10

For k = 1 To 10

M yArray(I, j , k) = -1

Next k

Next j

Next i x

Цикл Do W h ile

Еще одной циклической конструкцией, предлагаемой VBA, является Do W h ile. В от­
личие от цикла F o r -N e x t, конструкция Do W h ile выполняется до тех пор, пока не будет
выполнено заданное условие. В цикле Do W h ile используется следующий синтаксис.

Do [W hile условие]
[инструкции]
[ E x i t Do]
[инструкции]

Loop

596 Часть VI. Разработка пользовательских функций

Или:

Do
[инструкции]
[ E x i t Do]
[инструкции]

Loop [W hile условие]

Как видите, в VBA можно поставить условие W h ile в начале или в конце цикла. Разни­
ца между представленными выше вариантами синтаксиса заключается во времени провер­
ки выполнения условия. Цикл первого варианта синтаксиса может не выполниться ни разу.
Во втором варианте синтаксиса содержимое цикла всегда выполняется хотя бы один раз.

В следующем примере приведена функция R o w O fL a rg e st, написанная с использо­
ванием цикла Do W h ile (первый вариант синтаксиса).

Function RowOfLargest(с)
NumRows = R ow s. Count
MaxVal = A p p lic a tio n .M a x (C o lu m n ( с ) )
r =1
D oW hile C e l l s ( r , c) <> MaxVal
r =r +1
Loop
RowOfLargest = r

End F u n c t i o n

Первым значением переменной г является единица, затем это значение увеличивает­
ся в цикле Do W h ile . Цикл продолжает выполняться, пока не встретится значение
ячейки, равное M axVal. Затем выполнение цикла прекращается, и функции присваива­
ется значение г. Обратите внимание: если максимальное значение расположено в первой
строке, то цикл выполняться не будет.

В приведенной ниже функции использован второй вариант синтаксиса Do W h ile .
Этот цикл всегда выполняется хотя бы один раз.

F un ction R ow O fLargest(с)
NumRows = R o w s. Count
MaxVal = A p p lic a tio n .M a x (C o lu m n s ( с ) )
r =0
Do
r =r +1
Loop W h ile C e l l s ( r , c) <> MaxVal
RowOfLargest = r

End F u n c t io n

В цикле Do W h ile может содержаться один или несколько инструкций E x i t Do.
Когда встречается выражение E x i t Do, цикл сразу прерывается.

Цикл Do U n t il

Структура цикла Do U n t i l напоминает конструкцию Do W h ile . Разница заметна
только при тестировании условия. В цикле Do W h ile инструкции выполняются, пока
условие верно, а в цикле Do U n t i l инструкции выполняются до тех пор, пока усло­
вие не станет верным. В цикле Do U n t i l используется следующий синтаксис.

Do [Unt i 1 условие]
[инструкции]
[ E x i t Do]
[инс трукции]

Loop

Глава 24. Концепции программирования на VBA 597

Или:

Do [инструкции]
Loop [ E x i t Do]
[инструкции]
[ U n t i l условие]

В следующем примере продемонстрировано использование первого варианта синтак­
сиса цикла Do U n t i l . В этом коде проще разобраться, поскольку в нем нет отрицатель­
ного сравнения, используемого в цикле Do W h ile .

Function RowOfLargest(с)
NumRows = R ow s. Count
MaxVal = A p p lic a tio n .M a x ( C o lu m n s (c ) )
r =1
Do U n t i l ( r , c) = MaxVal
r =r +1
Loop
RowOfLargest = r

End F u n c t io n

В следующей функции используется второй вариант синтаксиса цикла Do U n t i l .

Function RowOfLargest(с)
NumRows = R ow s. Count
MaxVal = A p p lic a tio n .M a x (C o lu m n (c ))
r =0
Do
r =r +1
Loop U n t i l C a l l s ( r , c) = MaxVal
RowOfLargest = r

End F u n c t io n

Инструкция On Error

Несомненно, при использовании функций в формулах Excel иногда случается так, что
формула возвращает значение ошибки (например, #ЗНАЧ!). Формула может вернуть
значение ошибки во множестве ситуаций, среди которых встречаются следующие:

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

• использован аргумент неправильного типа (например, текстовый вместо числового);

• аргумент находится за пределами приемлемого числового диапазона (например,
деление на нуль).

Во многих случаях ошибку можно просто проигнорировать. Если не указать правиль­
ное значение аргумента, то функция вернет значение ошибки. Устранением ошибки
пользователь занимается вручную. К сожалению, именно так функции рабочего листа
Excel обрабатывают ошибки.

В других случаях необходимо знать о существовании ошибки, чтобы предпринять
определенные действия. Инструкция On E r r o r позволяет идентифицировать и обрабо­
тать ошибки в Excel.

Чтобы проигнорировать ошибку, воспользуйтесь следующим выражением:
Or E r r o r Resume N e x t

При использовании этого выражения ошибки выявляются в результате проверки
свойства N um ber объекта E r r . Если это свойство равно нулю, ошибка не выводится.
Если E r r . N um ber равно другому значению, то выводится сообщение об ошибке.

598 Часть VI. Разработка пользовательских функций

В следующем примере представлена функция, возвращающая имя ячейки или диапа­
зона. Если ячейка или диапазон не имеет имени, то появляется ошибка, а формула, в ко­
торой используется функция, возвращает ошибку #ЗНАЧ!.
Func t i on RENGENAME(r n g )

RANGENAME = r n g . Name. Name
End F u n c t i o n

В приведенном ниже листинге показана улучшенная версия этой же функции. Инст­
рукция On E r r o r R esu m e N e x t сообщает VBA, что ошибку нужно проигнорировать.
Инструкция I f E r r проверяет наличие ошибок. Если они есть, то функция возвращает
пустую строку.
Func t i on RANGENAME(r n g )

On E r r o r Resume N e x t
RANGENAME = r n g . Name. Name
I f Err.N um ber <> 0 Then RANGENAME =
End F u n c t io n

Представленное ниже выражение предлагает VBA проверить существование ошибок
и, если ошибка найдена, продолжить выполнение с другого места (в данном случае —
с инструкции E r r H a n d l e r ) .
On E r r o r GoTo E r r H a n d le r

В следующей функции продемонстрировано практическое использование этого вы­
ражения. Функция DIVIDETWO принимает два аргумента (nu m l и num2) и возвращает
результат деления n um l на num 2.
F u n c t i o n DIVIDETWO(numl, num2)

on E r r o r GoTo E r r H a n d le r
DIVIDETWO = numl / num2
Exit Function
E rrH and ler:
DIVIDETWO = "ОШИБКА"
End F u n c t io n

В случае возникновения ошибки выражение On E r r o r GoTo предлагает VBA пе­
рейти к операциям, помеченным как E r r H a n d l e r . В результате функция вернет строку
ОШИБКА, если при ее выполнении возникнет ошибка. Обратите внимание на инструкцию
E x i t F u n c t i o n . Без этого выражения выполнение кода продолжалось бы и обработка
ошибки происходила бы постоянно, даже когда ее нет. Другими словами, функция всегда
возвращала бы строку ОШИБКА.

Важно понять, что функция DIVIDETWO нестандартная. При появлении ошибки в ка­
честве результата возвращается строка, чего нельзя сказать об Excel. В Excel обычно
возвращается фактическое значение ошибки.

Перекрестная ссылка

В главе 25 приведены примеры использования выражения On E r r o r , в том
числе пример, иллюстрирующий способ возвращения функцией фактиче­
ского значения ошибки.

Работа с диапазонами

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

Глава 24. Концепции программирования на VBA 599

В этом разделе описываются основные методы обработки диапазонов. Приведенная да­
лее информация рассчитана на практическое применение и не является исчерпывающей.
Если вам интересны подробности, обратитесь к справочной системе VBA.

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

Конструкция For Each-Next

Иногда функции необходимо пройти в цикле по диапазону ячеек. Например, можно
написать функцию, которая в качестве аргумента принимает диапазон. В таком случае
код будет проверять каждую ячейку диапазона и выполнять определенное действие.
Конструкция F o r E a c h -N e x t очень удобна для операций такого рода. Она имеет сле­
дующий синтаксис.
For Each элемент In группа

[инс трукции]
[E xit For]
[инс трукции]
N e x t [элемент]

Следующая функция принимает в качестве аргумента диапазон и возвращает сумму
квадратов значений в ячейках.
F u n c t i o n SUMOFSQUARES(rng a s Range)

Dim t o t a l a s D o u b le
Dim c e l l a s Range
total = 0
For Each c e l l In rng

total = total + ce ll A 2
Next c e ll
SUMOFSQUARES = t o t a l
End F u n c t io n

В следующей формуле Excel используется функция SumOf S q u a re s :
= S u m O fS q u a r e s(A 1 : C100)

В описанном случае аргументом функции является диапазон, состоящий из трехсот ячеек.

Примечание
В предыдущем примере c e l l и m g — это имена переменных. В этих именах нет
ничего необычного; их можно заменить любым допустимым именем переменной.

Ссылка на диапазон

В коде VBA к диапазону можно обратиться с помощью одного из свойств:

• Range;

• C ells;

• O ffset.

Свойство Range
Свойство R ange служит для прямого обращения к диапазону, при этом используется

адрес или имя ячейки. В следующем примере значение ячейки А1 присваивается пере­

600 Часть VI. Разработка пользовательских функций

менной, которая называется I n i t . Таким образом, мы получаем доступ к свойству
V a lu e этого диапазона.
I n it = R ange("AI" ) .Value

Кроме V a lu e , VBA предлагает и другие свойства диапазона. Например, следующее
выражение подсчитывает количество ячеек в диапазоне и присваивает это значение пе­
ременной C nt:
Cnt = R a n g e("А1:СЗ0 0 " ) .Count

Свойство R ange также удобно использовать для обращения к одной ячейке многояче­
ечного диапазона. Например, можно создать функцию, которая принимает в качестве аргу­
мента одну ячейку. Если пользователь задает в качестве аргумента диапазон из нескольких
ячеек, то с помощью свойства R ange можно получить значение левой верхней ячейки диа­
пазона. В следующем примере используется свойство R ange (с аргументом А1) для полу­
чения значения левой верхней ячейки диапазона, представленного аргументом c e l l .
Function S q u a r e (c e ll as Range)

Dim C e ll V a l u e a s D oub le
C ellV alue = c e l l . Range( "AI" ) .Value
Square = C ellV alue A 2
End F u n c tio n

Предположим, что пользователь ввел следующую формулу:
=Square(С5:С12)

Функция S q u a r e обращается к левой верхней ячейке диапазона С 5 :С 1 2 (т.е. С5)
и возвращает квадрат его значения

Примечание
Так работают многие функции Excel. Например, если в качестве первого ар­
гумента функции левсим в задать многоячеечный диапазон, то Excel будет
использовать левую верхнюю ячейку диапазона. Однако в этом отношении
Excel — достаточно противоречивая программа. Если многоячеечный диа­
пазон указать в качестве аргумента функции s q r t , то Excel вернет ошибку.

Свойство C e lls
Еще одним методом обращения к диапазону является свойство C e l l s . Оно принима­

ет два аргумента (номер строки и столбца) и возвращает одну ячейку. В следующем вы­
ражении значение ячейки А1 присваивается переменной F i r s t Се 11:
F ir stC e ll = C e l l s ( 1 ,1 ) .Value

Представленное далее выражение возвращает левую верхнюю ячейку диапазона
С5 : С12.
UpperLeft = R ange( "С5:С12" ) . C e l l s (1 ,1 )

Совет
Если свойство Cells используется без аргумента, то оно возвращает диапа­
зон, содержащий все ячейки рабочего листа. В приведенном ниже примере
переменная T o t a l C e l l s содержит общее количество ячеек рабочего листа.

T otalC ells = C ells.C ount

В следующем выражении используется функция Excel, вычисляющая количество за­
полненных ячеек листа:
NonEmpty = W o rk sh ee tF u n c tio n . COUNTA(Cells)

Глава 24. Концепции программирования на VBA 601

Свойство O ffse t

Свойство O f f s e t (как и свойства R a n g e и C e l l s ) также возвращает объект R a n g e .
Свойство O f f s e t применяется к диапазону. Оно принимает два аргумента, соответст­
вующих относительному расположению левой верхней ячейки объекта R a n g e . Аргумен­
ты могут быть положительными, отрицательными или равными нулю. В следующем
примере извлекается значение ячейки, которая расположена на одну строку ниже ячейки
А1 (т.е. А2). Значение ячейки присваивается переменной N e x t C e l l .

N extC ell = Range( "Al") .O f f s e t ( 1 ,0 ) .Value

Следующая функция принимает в качестве аргумента одну ячейку и возвращает сум­

му восьми ячеек, распложенных вокруг нее.

Function Sum SurroundingCells(cell)

Dim T o t a l As D ou b le

Dim r As Long, с As Long

Total = 0 ^

For r = - 1 To 1

For с = - 1 To 1 1

Total = Total + c e l l .O ffset(r, c)

Next с

Next r

SumSurroundingCells = T otal - c e l l

End F u n c t io n

В этой функции использованы вложенные циклы F o r - N e x t. По этой причине, когда

счетчик цикла г равен - 1 , счетчик с “пробегает” значения от - 1 до 1. При этом сумми­

руются девять ячеек, включая ячейку, указанную в аргументе (она имеет смещение Of f -

s e t (0 , 0)). Заключительная инструкция функции вычитает значение ячейки аргумента

из общей суммы. Если ячейка, на которую указывает смещение, не существует на листе,

функция O f f s e t возвращает ошибку.

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

выполняющих ту же операцию.

Total = T o ta l+ c e l l .O f f s e t (-.1, -1) 'левая верхняя
Total
Total = T o t a l+ c e l l . O f f s e t ( - 1 , 0) 'сл ев а
Total
Total = T otal + c e l l . O f f s e t ( - 1 , 1) 'верхняя правая
Total 'сверху
Total =Total + c e l l .O f f s e t (0, -1) 'сама ячейка
Total 'справа
Total = T otal + c e l l . O f f s e t (0, 0) 'нижняял е в а я

= T otal + c e l l .O f f s e t (0, 1) 'нижняяправая

= T otal + c e l l .O f f s e t (1, -1)

= T o t a l+ c e l l . O f f s e t (1, 0) 'вн и зу

= T otal + c e l l . O f f s e t (1, 1)

Некоторые полезные свойства диапазонов

В предыдущих разделах приводились примеры использования свойства V a l u e диа­
пазона. VBA предоставляет возможность работать со многими дополнительными свой­
ствами диапазона. Некоторые наиболее полезные свойства кратко описаны в следующих
разделах. Более полную информацию о свойствах можно найти в справочной системе.

Свойство Formula
Свойство F o r m u l a возвращает в виде строки формулу, которая находится в ячейке.

При обращении к свойству F o r m u l a диапазона, содержащего несколько ячеек, возника­
ет ошибка. Если в ячейке формула отсутствует, то свойство вернет значение ячейки в та­

602 Часть VI. Разработка пользовательских функций

ком виде, в котором оно отображается в строке формул. Следующая функция отображает
формулу левой верхней ячейки диапазона.
F u n c t io n CELLFORMULA(cell)

CELLFORMULA = c e l l . R a n g e ( "A I" ) . Form ula
End F u n c tio n

Чтобы выяснить, содержится ли в ячейке формула, используйте свойство Has Form ula.

Свойство Address
Свойство A d d r e s s возвращает адрес диапазона в виде строки. По умолчанию оно

возвращает абсолютную ссылку (например, $А $1:$С $12). Следующая функция, ис­
пользуемая не так уж часто, возвращает адрес диапазона.
F u n c t i o n RANGEADDRESS(rng)

RANGEADDRESS = r n g . A d d r e s s
End F u n c t io n

Следующая формула возвращает строку $А $1: $С$3:
=RANGEADDRESS (А 1 : СЗ)

Приведенная ниже формула возвращает адрес именованного диапазона MyRange.
=RANGEADDRES S ( M y R a n g e )

Свойство Count
Свойство Count возвращает количество ячеек в диапазоне. Оно демонстрируется

в следующем примере.
F u n ct i o n CELLCOUNT(r n g )

CELLCOUNT = r n g . C o u n t
End F u n c t io n

Приведенная ниже формула возвращает число 9.
=CELLCOUNT(AI: СЗ)

Предупреждение
Свойство Count объекта Range функционально отличается от функции рабочего
листва счёт. Свойство c o u n t возвращает общее количество ячеек диапазона,
включая пустые и содержащие любые типы данных. Функция рабочего листа
сч ё т возвращает количество ячечек диапазона, содержащих числовые значения.

Новинка
Рабочие листы Excel содержат более 17 миллиардов ячеек, по сравнению с
примерно 17 миллионами в предыдущих версиях. Благодаря такому гигант­
скому увеличению, свойство Count, имеющее тип Long, вернет ошибку при
обработке диапазона, содержащего более 2147483647 ячеек. Во избежание
потенциальных ошибок можно использовать новое свойство C ountLarge, од­
нако учтите, что в предыдущих версиях программы оно не доступно.
В функции c e l l c o u n t (см. выше) следующий оператор способен обработать
диапазон любого размера (в том числе и все ячейки рабочего листа):

CELLCOUNT=rng. C o u n tL a rg e

Свойство Parent

Свойство P a re n t возвращает объект контейнера текущего объекта. Для объекта Range
свойство P a re n t возвращает объект W orksheet (рабочий лист, содержащий диапазон).

Глава 24. Концепции программирования на VBA 603

В приведенной ниже функции используется свойство P a r e n t; она возвращает имя
рабочего листа диапазона, полученного в качестве аргумента.
F u n ct i o n SHEETNAME(r n g )

SHEETNAME = r n g . P a r e n t . Name
End F u n c t io n

Следующая формула вернет строку Л ист1:

=SHEETNAME( Л и с т 1 !А 1 6 )

Свойство Name

Свойство Name возвращает объект Name ячейки диапазона. Чтобы получить реальное
имя ячейки или диапазона, следует обратиться к свойству Name объекта Name. Если
ячейка или диапазон не имеет имени, то свойство Name вернет ошибку.

Следующая функция извлекает имя ячейки или диапазона, переданного в качестве ар­
гумента. Если диапазон или ячейка не имеют имени, функция возвращает пустую строку.
Обратите внимание на использование инструкции On E r r o r R esu m e N e x t . Благода­
ря ей обрабатывается ошибка, возникающая, когда у диапазона отсутствует имя.
F u n c t i o n RANGENAME (rn g)

On E r r o r Resume N e x t
RANGENAME = r n g . Name. Name
I f Err.N um ber <> 0 Then RANGENAME = ""
End F u n c tio n

Свойство NumberFormat

Свойство NumberFormat возвращает числовой формат ячейки (в виде строки), ко­
торый присваивоен ячейке или диапазону. Следующая функция возвращает числовой
формат левой верхней ячейки диапазона.
F u n c t i o n NUMBERFORMAT(cell)

NUMBERFORMAT = c e l l . R a n g e ("A l " ) . NumberFormat
End F u n c t io n

Свойство Font

Свойство Font возвращает объект F on t диапазона или ячейки. Чтобы сделать что-либо с
помощью объекта Font, необходимо обратиться к его свойствам. Например, объект Font
имеет такие свойства, как B old, I t a l i c , Name, C o lo r и т.д. Следующая функция возвра­
щает значение TRUE, если к левой верхней ячейке применено полужирное начертание.
Function ISBOLD(cell)
ISBOLD = c e l 1 . R a n g e ( " A l " ) . F o n t . B o l d
End F u n c t io n

Совет

Цвет фона ячейки не является частью объекта F o nt, он хранится в объекте
i n t e r i o r . Следующая функция вернет значение t r u e, если верхняя левая
ячейка диапазона окрашена в красный цвет (константа vbRed является
встроенной).
F u n ction ISREDBKGRD(cell)
ISREDBKGRD = c e l l . R a n g e ( " A l" ) . I n t e r i o r . C o l o r = vbRed
End F u n c tio n

604 Часть VI. Разработка пользовательских функций

Свойства Columns и Rows

Свойства C olum ns и Rows используются для управления строками и столбцами диа­
пазона. Например, следующая функция при обращении к свойству C o u n t возвращает
количество столбцов в диапазоне.
F u n c t i o n COLUMNCOUNT(r n g )

COLUMNCOUNT = r n g . C o lu m n s . Count
End F u n c t io n

Свойства E ntirerow и E ntirecolum n

Свойства E n t ir e r o w и E n t ir e c o lu m n позволяют работать со всей строкой или
столбцом, в котором расположена текущая ячейка. Приведенная ниже функция принима­
ет в качестве аргумента одну ячейку и с помощью свойства E n tireC o lu m n получает
диапазон, содержащий целый столбец с заданной ячейкой. Далее используется функция
Excel CountA (аналог СЧЁТЗ), вычисляющая количество заполненных ячеек в столбце.
F u n ctio n NONEMPTY(cell)

NONEMPTY = W o r k s h e e t F u n c t i o n . C o u n t A ( c e l l . E n t ir e C o lu m n )
End F u n c tio n

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

Свойство Hidden

Свойство H id d e n используется для управления строками и столбцами. Оно возвра­
щает значение TRUE, если строка или столбец скрыты. Если применить это свойство
к диапазону, в который не входит целая строка или столбец, возникает ошибка. Приве­
денная ниже функция принимает аргумент в виде одной ячейки и возвращает TRUE, если
либо строка, либо столбец с указанной ячейкой скрыты.
F un ction CELLISHIDDEN(cell)

I f c e l l . E n t i r e R o w . H i d d e n Or c e l l . E n t i r e C o l u m n . H id d en
Then

CELLISHIDDEN = True
Else

CELLISHIDDEN = F a l s e
End I f
End F u n c t i o n

Эту функцию можно переписать без использования конструкции I f - T h e n - E l s e .
В следующей функции выражение справа от знака равенства возвращает либо TRUE, ли­
бо FALSE. Это значение присваивается переменной, возвращаемой функцией.
F un ction CELLISHIDDEN(cell)

CELLISHIDDEN = c e l l . E n t i r e R o w . H id d en Or _
c e l l . EntireColum n.Hidden

End F u n c tio n

Ключевое слово Set

Важной особенностью VBA является возможность создавать новый объект Range
и присваивать его переменной (т.е. создавать объектную переменную). Эта задача реша­
ется с помощью ключевого слова S e t. Следующее выражение создает объектную пере­
менную MyRange:
S e t MyRange = R a n g e ( " A l :А 1 0 ")

Глава 24. Концепции программирования на VBA 605

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

Примечание
Объект Range существенно отличается от именованного диапазона тем, что
его нельзя использовать в формулах.

Функция Intersect

Функция I n t e r s e c t возвращает диапазон, созданный в результате пересечения
двух диапазонов. Например, диапазоны D3 : D10 и В5 : F5 (рис. 24.2) имеют одну общую
ячейку (D5). Таким образом, D5 является пересечением диапазонов D3 : D10 и В5 : F5.

Рис. 24.2. Пересечение диапазонов

Следующая функция принимает в качестве аргументов два диапазона и подсчитывает
количество их общих ячеек.
F u n c t i o n CELLSINCOMMON(rngl, rn g 2 )

Dim CommonCells As Range
On E r r o r Resume N e x t
S et CommonCells = I n t e r s e c t ( r n g l , rng2)
I f Err.Number = 0 Then

CELLINCOMMON = C o m m o n C e lls. Count
Else

CELLINCOMMON = 0
End I f
End F u n c t io n

Функция CELLINCOMMON использует функцию I n t e r s e c t для создания объекта диа­
пазона C o m m o n C e lls . Обратите внимание на использование инструкции On E r r o r R e ­
sume N e x t . Она необходима, поскольку в случае отсутствия у диапазонов общих ячеек
функция I n t e r s e c t возвращает ошибку. Если ошибка встречается, когда задано выраже­
ние On E r r o r R esu m e N e x t , она игнорируется. Последнее выражение проверяет свой­
ство Num ber объекта E r r. Если оно равно нулю, то ошибка не возникает, и функция воз­
вращает значение свойства C o u n t объекта C o m m o n C e lls . Если же возникает ошибка, то
E r r . Num ber принимает значение, отличное от нуля, и функция возвращает нуль.

Функция Union

Функция U n i o n объединяет несколько диапазонов в один. В следующем выражении
функция U n i o n используется для создания объекта диапазона, содержащего первый
и третий столбцы рабочего листа:

606 Часть VI. Разработка пользовательских функций

S et TwoCols = U nion(R an ge( "А:А") , R ange("C:C"))

Функция U n ion может содержать от двух до тридцати аргументов.

Свойство UsedRange

Свойство U sedR ange возвращает объект Range, ссылающийся на используемый
диапазон рабочего листа. При нажатии клавиш <Ctrl+End> активизируется правая ниж­
няя ячейка используемого диапазона. Свойство U sed R an ge применяется для повыше­
ния эффективности выполнения функций.

Рассмотрим следующую функцию, принимающую аргумент диапазона и возвращаю­
щую количество ячеек с формулами в диапазоне.

F u n c t i o n FORMULACOUNT(r n g )
Dim c n t As Long
Dim c e l l As Range
cnt = 0
For Each c e l l In rng
I f c e l l .HasFormula Then cn t = cn t + 1
Next c e ll
FORMULACOUNT = c n t

End F u n c t io n

В большинстве случаев эта функция прекрасно работает. Но пользователь может вве­
сти следующую формулу:

=FORMULACOUNT (А: С)

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

F u n c t i o n FORMULACOUNT (rn g)
Dim c n t As Long
Dim c e l l As Range
cnt = 0
s e t WorkRange = I n t e r s e c t ( r n g , rn g .P a ren t.U sed R a n g e)
I f WorkRange I s N o th in g Then
FORMULACOUNT = 0
Exit Function
End I f
For Each c e l l In WorkRange
I f cell.H asF orm u la Then cn t = cnt + 1
Next c e l l
FORMULACOUNT = c n t

End F u n c t io n

Эта функция создает объект Range с именем WorkRange, в котором сохраняется
пересечение диапазона, принимаемого в качестве аргумента, а также диапазона рабочего
листа. Другими словами, WorkRange состоит из подмножества аргументов диапазона,
в которое входят ячейки используемого диапазона рабочего листа. Обратите внимание
на инструкцию I f , которая проверяет, не пуст ли диапазон. Это происходит, если аргу­
мент функции указывает за пределй используемого диапазона. В этом случае функция
возвращает нуль, и ее выполнение завершается.

Глава

Примеры
пол ьзовател ьских
функций VBA

В этой главе...

♦ Простые функции
♦ Выяснение типа данных в ячейке
♦ Мноцелевая функция
♦ Генерация случайных чисел
♦ Вычисление комиссионных от продаж
♦ Функции управления текстом
♦ Функции подсчета
♦ Функции управления датами
♦ Возвращение последней заполненной ячейки столбца или строки
♦ Функции для работы с несколькими листами
♦ Дополнительные пользовательские функции

В этой главе приведен ряд примеров полезных (вернее, потенциально полезных)
пользовательских функций VBA. Большинство функций можно использовать в том виде,
в котором они представлены. Некоторые функции следует немного изменить, чтобы они
соответствовали поставленным задачам. Для повышения производительности и эффек­
тивности выполнения таких функций в них объявляются все используемые переменные.

Простые функции

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

608 Часть VI. Разработка пользовательских функций

VBA может обратиться к свойству ячейки H a sF o rm u la , чтобы определить, содержится ли
в ячейке формула. Как ни странно, но в Excel не встроена подобная функция.

Компакт-диск fu n ction s .xlsm

Примеры этого раздела содержатся в файле s i m p l e
(ch a p ter2 5 _ R U S .x ls m ) на прилагаемом компакт-диске.

Проверка, содержит ли ячейка формулу

Приведенная ниже функция CELLHAS FORMULA принимает аргумент в виде одной
ячейки и возвращает значение TRUE, если в ячейке содержится формула.

F u n c t i o n CELLHASFORMULA(cell) As B o o l e a n
' Возвращ ает TRUE, е с л и в яч ей к е е с т ь формула

CELLHASFORMULA = c e l l . R a n g e ( " A l" ) . H asF orm u la
End F u n c t io n

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

Возвращение формулы ячейки

Следующая функция CELLFORMULA возвращает формулу, содержащуюся в ячейке, в
виде строки. Если в ячейке нет формулы, функция возвращает пустую строку.

F u n c t io n CELLFORMULA(cell) As S t r i n g
' Возвращает формулу ячейки или
' пустую с т р о к у , есл и в ячейке нет формулы

Dim U p p er L e ft As Range
S e t U p p e r L e f t = c e l l . R a n g e ( " A l")
I f U p p er L e ft. HasFormula Then

CELLFORMULA = U p p e r L e f t . Form ula
E lse

CELLFORMULA = ""
End I f
End F u n c t io n

Эта функция создает объектную переменную R a n g e , которая называется U p p e r -

L e f t . Эта переменная представляет левую верхнюю ячейку аргумента функции.

Использование функций этой главы
Если в этой главе вам встретится функция, полезная для решения конкретных задач,

то используйте ее в своем рабочем листе. Все процедуры этой главы приведены на при­
лагаемом компакт-диске. Откройте рабочую книгу с примером, активизируйте редактор
Visual Basic и вставьте текст функции в модуль VBA вашей рабочей книги. При необходи­
мости воспользуйтесь несколькими функциями или создайте надстройку (см. главу 23).

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

Проверка, скрыта ли ячейка

Следующая функция CELLISHIDDEN принимает аргумент в виде одной ячейки
и возвращает значение TRUE, если ячейка скрыта. Ячейка считается скрытой, если скры­
та ее строка или столбец.

Глава 25. Примеры пользовательских функций VBA 609

F unction CELLISHIDDEN(cell) As B oolean
Возвращает TRUE, е с л и ячейка скрыта
Dim U p p e r L e ft As Range
S e t U p p e r L e f t = c e l l . R a n g e ( "A I")
CELLISHIDDEN = U p p e r L e f t . E n t i r e R o w . H id d en Or _
U pperL eft. EntireColum n. Hidden

End F u n c t i o n

Возвращение имени рабочего листа

Приведенная ниже функция SHEETNAME принимает один аргумент (диапазон) и воз­
вращает имя рабочего листа, на котором он находится. В функции используется свойство
P a r e n t объекта Range. Свойство P a r e n t возвращает объект, в котором содержится
объект Range.

F u n c t i o n SHEETNAME( г ng) As S t r i n g
' Возвращает имя р а б о ч е г о л и с т а для д и а п а зо н а rn g

SHEETNAME = r n g . P a r e n t . Name
End F u n c t io n

Представим еще один вариант этой же функции. В ней не используется аргумент;
действие данной функции основано на возможности определить ячейку, из которой она
вызвана с помощью свойства A p p l i c a t i o n . C a lle r .

F u n c t i o n SHEETNAME2() As S t r i n g
' Возвращает имя р о д и т е л ь с к о г о л и с т а
1 для ячейки, содержащей формулу

SHEETNAME2 = A p p l i c a t i o n . C a l l e r . P a r e n t . Name
End F u n c t io n

В этой функции свойство A p p l i c a t i o n . C a l l e r возвращает объект Range, который
соответствует ячейке с функцией. Предположим, в ячейке А1 содержится такая формула:

=SHEETNAME2()

Когда выполняется функция SHEETNAME2, свойство A p p l i c a t i o n . C a l l e r возвра­
щает объект Range, который соответствует ячейке, содержащей функцию. Свойство P a r ­
e n t возвращает объект W ork sh eet, а свойство Name возвращает имя рабочего листа.

Возвращение имени рабочей книги

Приведенная ниже функция WORKBOOKNAME возвращает имя рабочей книги. Обрати­
те внимание, что в этой функции свойство P a r e n t используется дважды. Первый раз
оно возвращает объект W o rk sh eet, а во второй р а з— объект Workbook; свойство
Name возвращает имя рабочей книги.

F u n c t i o n WORKBOOKNAME() As S t r i n g
' Возвращает имя р абочей книги
' для ячейки, содержащей формулу

WORKBOOKNAME = A p p l i c a t i o n . C a l l e r . P a r e n t . P a r e n t . Name
End F u n c t io n

Возвращение имени приложения

Следующая функция (используемая довольно редко) переносит операции с родитель­
скими объектами на следующий логический уровень, обращаясь к свойству P a r e n t
трижды. Эта функция возвращает имя объекта A p p l i c a t i o n , которое всегда представ­
лено строкой M i c r o s o f t E x c e l.

610 Часть VI. Разработка пользовательских функций

F u n c t i o n APPNAME() As S t r i n g
1 Возвращает название приложения
' для ячейки, содержащей формулу

APPNAME = A p p l i c a t i o n . C a l l e r . P a r e n t . P a r e n t . P a r e n t .N a m e
End F u n c t io n

Понятие родительского объекта
Объекты в Excel выстроены в иерархическом порядке. На верхнем уровне иерархии

расположен объект A p p l i c a t i o n (сама программа Excel). В Excel есть и другие объек­
ты; они, в свою очередь, состоят из иных объектов и т.д. Ниже показано, на каком месте
в этой иерархии находится объект Range.
Объект A p p l i c a t i o n (Excel)

=>Объект Workbook

«=><=>Объект W o rk sh ee t
с>с>с=>Объект Range

В объектно-ориентированном программировании родительским для объекта Range
является объект W o rk sh ee t, в котором находится объект Range. Родительским для
объекта W o rk sh ee t является Workbook. И наконец, родителем объекта Workbook вы­
ступает объект A p p l i c a t i o n . Разобравшись в этой структуре, используйте свойство
P a r e n t для создания полезных функций.

Возвращение версии Excel

Следующая функция возвращает номер версии Excel. Например, если используется
Excel 2010, то она вернет текстовую строку 1 4 .0 .
F u n c t i o n EXCELVERSION() As S t r i n g
1 Возвращает номер версии E xcel

EXCELVERSION = A p p l i c a t i o n . V e r s i o n
End F u n c t io n

Обратите внимание, что функция EXCELVERSION возвращает строку, а не значение.
Приведенная ниже функция возвращает значение TRUE, если используемым приложением
является Excel версии 97 или более поздней (Excel 2007 соответствует версии 12). В этой
функции используется функция V al для преобразования текстовой строки в значение.
F u n c t i o n EXCEL20 0 7 ORLATER() As B o o l e a n

EXCEL2 0 0 70RLATER = V a l ( A p p l i c a t i o n . V e r s i o n ) >= 12
End F u n c t io n

Возвращение информации о форматировании ячейки

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

Следующая функция возвращает значение TRUE, если к ячейке-аргументу применен
полужирный шрифт.
F un ction ISBOLD(cell As Range) As B oolean
1 Возвращ ает TRUE, е с л и т е к с т ячейки в в е д е н полужирным
' шрифтом

Глава 25. Примеры пользовательских функций VBA 611

ISBOLD = c e l l . R a n g e ( "AI") . F o n t . B o l d
End F u n c t io n

Предупреждение

В функциях этого раздела используется следующее выражение:

A p p lic a tio n .V o la tile True

Такое выражение заставляет функцию проводить перерасчет формул в ра­
бочей книге, однако эти функции не всегда возвращают правильные значе­
ния. Причина в том, что изменение формата ячеек не приводит к автомати­
ческому пересчету рабочего листа. Чтобы все же выполнить общий пере­
расчет (и обновить все пользовательские функции), нажмите <Ctr+Alt+F9>.

А эта функция возвращает значение TRUE, если к аргументу ячейки применен кур­
сивный шрифт.

Function ISITA LIC (cell As Range) As B oolean
1 Возвращает TRUE, е с л и т е к с т ячейки в в е д е н курсивом

ISITALIC = c e ll.R a n g e C 'A l" ) .F o n t. I t a l i c
End F u n c t io n

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

Следующая функция вернет значение TRUE только в том случае, если все символы
в ячейке имеют полужирный шрифт. Если свойство B o ld объекта F o n t содержит пус­
тое значение (N u ll), что указывает на смешанное форматирование, инструкция I f гене­
рирует ошибку; тогда имени функции не может быть присвоено значение T ru e . Если
имя функции ранее было установлено в F a l s e , именно это значение и вернет функция.

F un ction ALLBOLD(cell As Range) As B oolean
' Возвращает TRUE, е с л и т е к с т ячейки полностью в в е д е н
' полужирным шрифтом

Dim U p p e r L e ft As Range
Set UpperLeft = cell.R angeC 'A l")
ALLBOLD = F a l s e
I f U p p e r L e f t . F o n t . B o l d Then ALLBOLD = True
End F u n c t io n

Следующая функция FILLCOLOR возвращает целочисленное значение, которое соот­
ветствует индексу цвета заливки ячейки. Если в ячейке нет заливки, функция возвращает
значение -4 1 4 2 . Свойство C o l o r l n d e x принимает значения в диапазоне от нуля до 56.

F un ction FILLCOLOR(cell As Range) As I n te g e r
1 Возвращает целое число, соответствующее
' цвету заливки ячейки

FILLCOLOR = c e l l . R a n g e ( "AI") . I n t e r i o r . C o l o r l n d e x
End F u n c tio n

Примечание

Если ячейка является частью таблицы, использующей какой-либо стиль,
функция f i l l c o l o r вернет неправильный цвет. Аналогично, функция не
вернет цвет заливки, заданный условным форматированием.

612 Часть VI. Разработка пользовательских функций

Приведенная далее функция возвращает в виде строки числовой формат ячейки.

F u n c t i o n NUMBERFORMAT(cell As Range) As S t r i n g
' Возвращает с т р о к у , описывающую
1 числовой формат ячейки

A p p lic a tio n .V o la t ile True
NUMBERFORMAT = c e l l . R a n g e ("A l " ) . NUMBERFORMAT
End F u n c tio n

Если в ячейке используется числовой формат, заданный по умолчанию, то функция
вернет строку G e n e ra l.

Выяснение типа данных в ячейке

Excel предлагает несколько встроенных функций, возвращающих тип данных в ячейке.
Эти функции называются ЕТЕКСТ, ЕЛОГИЧ и ЕОШИБКА. Кроме них, в VBA предусмотре­
ны такие функции, как IS EMPTY (ЕПУСТО), ISDATE (ЕДАТА) и ISNUMERIC (ЕЧИСЛО).

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

F un ction CELLTYPE(cell As Range) As S tr in g
' Возвращает тип данных в левой верхней ячейке диапазона

Dim U p p erL eft As Range
A pplication.V olatile
S e t U p p e r L e f t = c e l l . R a n g e ( " A l")
S e le c t Case True

Case UpperLeft .NumberFormat =
CELLTYPE = "Текст"

Case IsEmpty(UpperLeft)
CELLTYPE = "Пусто"

Case W orksheetFunction.IsText(U pperLeft)
CELLTYPE = "Текст"

Case W orksheetF unction.IsL ogical(U pperL eft)
CELLTYPE = "Л оги ч еск ое зн ач ен и е"

Case W orksheetFunction. IsE rr(U pperL eft)
CELLTYPE = "Ошибка"

Case IsD ate(U pperLeft)
CELLTYPE = "Дата"

C ase I n S t r ( l , U p p e r L e f t . T e x t , ":") <> 0
CELLTYPE = "Время"

Case IsNumeric(UpperLeft)
CELLTYPE = "Значение"

End S e l e c t
End F u n c tio n

На рис. 25.1 показана функция CELLTYPE в действии. В столбце В содержатся фор­
мулы, в которых используется функция CELLTYPE с аргументами из столбца А. Напри­
мер, в ячейке В1 находится такая формула:

=CELLTYPE(A l )

Компакт-диск

Эта функция содержится на прилагаемом компакт-диске в файле c e l l t y p e
fu n ctio n .x lsm (Chapter25_RUS .xlsm).

Глава 25. Примеры пользовательских функций VBA 613

Рис. 25.1. Функция c e l l t y p e возвращает строку с описанием
типа содержимого ячейки

Многоцелевая функция

В данном разделе показана пользовательская функция, которая работает как несколь­
ко функций. Эта функция VBA, называемая STATFUNCTION, работает с двумя аргумен­
тами — диапазоном (rn g ) и оператором (ор). В зависимости от значения ор, функция
возвращает значение, вычисленное с помощью одной из функций рабочего листа:
СРЗНАЧ, СЧЁТ, МАКС, МЕДИАНА, МИН, МОДА и т.д. Эту функцию можно использовать на
рабочем листе.

=STATFUNCTION ( C l : С12 ; В14 )

Результат формулы зависит от ячейки В14, которая содержит строку (например,
A v e ra g e , C o u n t, Мах и т.д.). Таким же образом можно работать и с другими типами
функций.

F u n c t io n STATFUNCTION(rng As V a r i a n t , op As S t r i n g ) As V arian t

S e le c t Case UCase(op)

C ase "SUM"

STATFUNCTION = A p p l i c a t i o n . Sum (rng)

C a se "AVERAGE"

STATFUNCTION = A p p l i c a t i o n . A v e r a g e ( r n g )

C ase "MEDIAN"

STATFUNCTION = A p p l i c a t i o n . M e d ia n ( r n g )

C ase "MODE"

STATFUNCTION = A p p l i c a t i o n . M od e(rng)

C ase "COUNT"

STATFUNCTION = A p p l i c a t i o n . C o u n t ( r n g )

C ase "MAX"

STATFUNCTION = A p p l i c a t i o n . Max(rn g)

C ase "MIN"

STATFUNCTION = A p p l i c a t i o n . M in (r n g )

C a se "VAR"

STATFUNCTION = A p p l i c a t i o n . V a r ( r n g )

C a se "STDEV" /

STATFUNCTION = A p p l i c a t i o n . S t D e v ( r n g )

Case E lse

STATFUNCTION = CVErr(xlErrNA)

End S e l e c t

End F u n c t io n

614 Часть VI. Разработка пользовательских функций

На рис. 25.2 представлена функция STATFUNCTION, которая используется вместе
с раскрывающимся списком, созданным с помощью команды Excel Данные1^Работа
с данными^Проверка данных^Проверка данных. Следующая формула находится
в ячейке С14:
=STATFUNCTION(C l : С 1 2 ; В 1 4 )

Рис. 25.2. Результат выбранной в списке операции отображается в ячейке С14

Компакт-диск

Эта функция содержится на прилагаемом компакт-диске в файле s t a t -
fun ction function.xlsm (Chapter25_RUS.xlsm ).

Следующая функция STATFUNCTI ON2 имеет более простой вид, но работает так же,
как и функция STATFUNCTION. Для вычисления выражения в ней используется опера­
тор E v a lu a te .

F u n c t io n STATFUNCTION2(rng a s Range, op As S t r i n g ) As Double
STATFUNCTI0N2 = E v a l u a t e ( o p & "(" & _
r n g .A d d r e ss (e x te r n a l:=True) & ")")

End F u n c t io n

Предположим, что аргумент r n g соответствует диапазону С1:С12, а аргумент ор
является строковым значением Sum. Тогда выражение, используемое в качестве аргу­
мента оператора E v a l u a t e , имеет следующий вид.

=Sum(Cl:С12)

Метод E v a l u a te вычисляет аргументы и возвращает результат. Кроме того, что
данное выражение довольно короткое, преимущество этой версии функции STATFUNC­
TION заключается еще и в том, что необязательно перечислять все возможные функции
в конструкции S e l e c t - C a s e .

Типы данных функций рабочего листа

Вы, наверное, уже заметили некоторые отличия в типах данных, используемых для
функций и аргументов. Например, в функции s ta tfu nction переменная rn g была объяв­
лена с типом V a r i a n t , а в функции s t a t f u n c t io n 2 она уже имела тип Range. Результат
первой функции был определен как V a r i a n t , а второй — как D o u b le .

Глава 25. Примеры пользовательских функций VBA 615

Использование типов данных имеет как преимущества, так и недостатки. Они могут
применяться для ограничения типа данных, передаваемых в функцию и возвращаемых
из нее. В то же время четкое определение типа данных уменьшает гибкость функций.
Использование типа данных v a r i a n t максимизирует гибкость, но в то же время снижа­
ет скорость вычислений.

Одним из возможных значений, возвращаемых функцией s t a t f u n c t i o n , является
значение ошибки (раздел C ase E l s e конструкции S e l e c t Case). Это значит, что функ­
ция может вернуть как число с двойной точностью, так и ошибку. Единственным вари­
антом типа данных, который приемлет числа с двойной точностью и ошибки, является
v a r i a n t , поэтому этот тип имеет и функция. С другой стороны, в функции STATFUNC-
TION2 не обеспечен возврат значения ошибки, поэтому ей достаточно более жесткого
типа данных D o u b le. Числовые данные в ячейках трактуются как числа с двойной точно­
стью (Double), даже если внешне выглядят как целые числа ( i n t e g e r ) .

Аргументы rn g также вводятся по-разному. Во второй функции используется свой­
ство A d d r e s s объекта Range, поэтому в функцию должен передаваться этот же тип
данных; в противном случае будет сгенерирована ошибка. В то же время в первой
функции нет ничего, что требовало бы от аргумента rn g иметь тип Range. Объявляя пе­
ременную rn g как v a r i a n t , мы предоставляем пользователю возможность ввода зна­
чений в другом виде, отличном от диапазона. Excel попытается преобразовать вводи­
мые данные в нечто, что сможет обработать. Если же программе не удастся преобразо­
вать передаваемые данные, естественно, будет сгенерирована ошибка. К примеру,
пользователь может ввести следующую формулу и получить правильный результат:

=STATFUNCTION( { 1 2 3 , 4 5 ; 6 4 3 / 8 9 3 , 2 2 } ; "Min")

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

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

Генерация случайных чисел

В этом разделе представлены две функции, работающие со случайными числами. Од­
на из них генерирует случайные числа, которые не изменяются. Другая выбирает из диа­
пазона случайную ячейку.

Компакт-диск
Представленные функции содержатся в файле random fu n c tio n s .x ls m
(ch a p ter2 5 _ R U S .x ls m ) на прилагаемом компакт-диске.

Генерация неизменяемых случайных чисел

Чтобы быстро создать диапазон ячеек, состоящих из случайных чисел, можно вос­
пользоваться встроенной функцией Excel СЛЧИС. Однако на практике оказывается, что
функция СЛЧИС генерирует новое случайное число каждый раз при пересчете рабочего
листа. Если требуется создать диапазон случайных чисел, которые не изменяются при
каждом пересчете, используйте процедуру STATICRAND.


Click to View FlipBook Version