
2 семестр / vba_2002
.pdf•Функция Excel СУММ считает, что текстовая строка имеет значение 0, если только она не является символьным аргументом (т.е. фактическим значением, а не переменной). Следовательно, функция MySum прибавляет значение ячейки лишь в том случае, если его можно оценить как число (для этого применяется функция VBA IsNumeric}.
•Для аргументов-диапазонов функция использует: метод I n t e r s e c t с целью создания временного диапазона, который состоит из пересечения заданного диапазона и используемого диапазона листа. В результате обрабатываются те случаи, когда аргумент состоит из полной строки или столбца, а его просмотр будет длиться вечность.
Возможно, вас интересует относительная скорость выполнения функций СУММ и MySum. Конечно, функция MySum значительно медленнее, ее скорость зависит от быстродействия вашей системы и самих формул. Если в системе рабочий лист с 1000-ей формул СУММ вычисляется за долю секунды, то после замены функций. СУММ на функции MySum. пересчет занимает 12 секунд. Функция MySum несколько улучшена, но ее производительность все же намного меньше, чем у функции СУММ.
Надеемся, вы понимаете, что цель этого примера— не создать новую функцию СУММ. Скорее, этот пример показывает, как создавать пользовательские функции рабочих листав, которые выглядят и работают так же, как встроенные функции Excel.
Отладка функций
При использовании формулы на рабочем листе идя тестирования процедуры функции происходящие в процессе выполнения ошибки не отображаются в знакомом диалоговом окне сообщений. Формула просто возвратит значение ошибки (#ЗНАЧ !). К счастью, это не представляет большой проблемы при отладке функций, так как всегда существует несколько ''обходных путей11.
•Поместить в стратегически важных местах функции MsgBox, чтобы контролировать значение отдельных переменных. Удобно, если в процессе выполненкя функций окна сообщений все-таки появляются, в отличие от окон ошибок. Убедитесь, что ваша функция используется только в одной формуле на рабочем листе, иначе окна сообщений будут появлятьсядля каждой такой формулы (подобное поведение быстро надоедает).
•Протестировать функцию, вызвав ее из процедуры, а не в формуле рабочего листа.
Ошибки в процессе выполнения отображаются обычным образом, поэтому можно либо сразу решить проблему (если она вам известна), либо перейти к отладке.
•Определить точку остановки в функции и просмотреть функцию пошагово. При этом можно воспользоваться всеми стандартными инструментами отладки. Чтобы добавить точку остановки, поместите курсор в операторе, в котором вы решили приостановить выполнение, и выберите команду Debug^Toggle Breakpoint (иди нажмите <F9>).
•Использовать в программе один или несколько временных операторов Debug. P r i n t , чтобы отобразить значения в окне VBE Immediate. Например, если необходимо контролировать циклически изменяемое значение, используйте следующий метод.
F u n c t i o n VowelCount(r) Count = 0
For i = 1 То Len(r)
Ch - UCase(Mid(r, i, 1)) If Ch Like " [AEIOU]n Then Count = Count + 1 Debug.Print Ch, i
End If
Часть111.VisualBasicforApplications

Next i
VowelCount = Count
End Function
В данном случае значения двух переменных, Ch и i, выводятся в окне Immediate всякий раз, когда в программе встречается оператор Debug. P r i n t . На рис. 10.6 показан результат, если функция получает аргумент M i s s i s s i p p i .
Рис.10.6.ИспользованиеокнаImmediateдляотображения результатовво времяработы фунщии
Работа с диалоговым окном Мастер функции
Диалоговое окно Excel Мастер функции — очень удобный инструмент. При создании формулы рабочего листа он позволяет выбрать необходимую функцию из списка (рис. 10.7). Функции в списке группируются в разные категории, таким образом облегчая их поиск. Кроме того, в диалоговом окне Мастер функции отображаются пользовательские функции, и предоставляется справка по аргументам функций.
По умолчанию пользовательские функции помещены в категорию Определенные пользов;этелем, но при желании можно перенести их в другую категорию. Кроме того, вы можете добавить текст, описывающий функцию (рекомендуем это сделать).
Рис.10.7.Вставкапользовательскойфункциивформулу
Пользовательские процедуры функций, определенные с помощью ключевого слова Private, не отображаются в диалоговом окне Мастер функции (хотя их можно вводить в формулы вручную). Если вы разрабатываете функцию исключительно для использования в других процедурах VBA, то необходимо объявить ее, применив ключевое слово Private.
В версиях Excel, более ранних, чем Excel 2002 диалоговое окно Мастер функций называлось Вставка функции. Это диалоговое окно в Excel 2002 усовершенствовано, оно выглядит по-другому и имеет команду поиска функции по ключевому слову. К сожалению, команду пэиска нельзя применять для поиска пользовательских функций, созданных на VBA.
Определение категории функции
Как ни странно, но Excel не позволяет напрямую определить пользовательскую функцию в одну из категорий. Если вы хотите, чтобы пользовательская функция находилась в категории, отличной от Определенные пользователем, то вам придется прибегнуть к программированию на VBA.
260 |
Глава 10. Создание функций |

Следующий оператор добавляет функцию с названием Commission в категорию Финансовые — первую категорию списка.
Appliсв.tion.MacroOptions Macro: = "Commission" , Category: =1
Указанный оператор необходимо выполнить только один раз (а не каждый раз, когда открывается рабочая книга). С этого момента при каждом открытии рабочей книги функция будет помещаться в определенной вами категории.
В табл. 10.1 перечислены номера категорий, которые можно использовать в коде VBA. Обратите внимание, что некоторые из этих категорий (с 10 по 13) обычно не отображаются в диалоговом окне Мастер функции. Если вы добавите пользовательскую функцию в одну из них. то она будет отображена в диалоговом окне.
-Таблица10.1.Категориифункций
Номер категории |
Название категории |
0Полный алфавитный перечень
1Финансовые
2Дата и время
3Математические
4Статистические
5Ссылки и массивы
6Работа с базой данных
7Текстовые
8Логические
9Информационные
10Команды
11Настройка
12Управление макросами
13Динамический обмен данными/Внешние
14Определенные пользователем
15Инженерные
Добавление описания функции
При выборе функции в диалоговом окне Мастер функции появляется краткое описание этой функции (рис. 10.8), Вы можете задать описание для иользовательской функции двумя способами: использовать диалоговое окно Макрос или написать программу VBA.
Рис. 10.8. В диалоговом окне Excel Мастер функции отображаетсякраткоеописаниефункций
ЧастьШ. VisualBasicforApplications |
261 |

Если вы не задали описание пользовательской функции, то в диалоговом окне Мастер функции отображается текст Справка недоступна. Конечно, в большинстве случаев это разочаровует.
Описание функции в диалоговом окне Макрос
Выполните следующие действия, чтобы добавить описание пользовательской функции.
1.Создайте функцию в VBE.
2.Активизируйте Excel, выберите Сервис^Макрос^Макросы.
В диалоговом окне Макрос перечислены доступные процедуры, но функции не будут отображаться в списке.
3- Введите название функции в поле Имя макроса.
4.Щелкните на кнопке Параметры, чтобы отобразить диалоговое окно Параметры макроса.
5.Введите описание функции в специальное поле, как показано на рис. 10.9. Поле Сочетание клавиш к описанию функции не относится.
6.Щелкните на кнопке ОК, затем — на кнопке Отмена.
Рис.10.9.Введениеописания
После выполнения указанных действий в диалоговом окне фуНКции в диалоговом окне Мастер функции при выделении данной функции будет ото- Параметры макроса бражаться описание, которое вы ввели в шаге 5.
Информацию о создании специального раздела справочной системы, доступного в окне Мастер функций, вы найдете в главе 24.
Если для ввода функции используется диалоговое окно Мастер функций, то диалоговое окно Аргументы функции отображается поело щелчка на кнопке ОК. Для встроенных функций диалоговое окно Аргументы функции предоставляет описание каждого аргумента. К сожалению, отобразить такое описание для аргументов пользовательских функций невозможно.
Описание функции с помощью VBA
Второй способ добавить описание специальной функции— написать программу VBA. Представленный далее оператор назначает описание функции с названием Commission:
Арр1icat ion.MacroOptions _ Macro:= "Commission", _
Description:= "Вычисляет комиссионные с продаж"
Этот оператор необходимо выполнить только один раз (а не каждый раз, когда открывается рабочая книга).
Использование надстроек для хранения пользовательских функций
Вы можете по желанию сохранить часто используемые пользовательские функции в файле надстройки. Основное преимущество такого подхода заключается в следующем: функции могут быть применены в формулах без спецификатора имени файла.
262 |
Глава 10. Созданиефункций |

Предположим у вас есть пользовательская функция с названием ZapSpaces, она хранится в файле Myfuncs .xls. Чтобы применить эту функцию в формуле другой рабочей книги (отличной от Myfuncs . xls), необходимо ввести формулу =Myfuncs.xls!ZapSpaces(Al:C12)
Если вы создадите надстройку на основе файла Mytunes, xls и эта надстройка будет загружена в текущем сеансе работы Excel, то ссылку на файл можно пропустить, введя формулу, как показано ниже:
=ZapSpaces(Al:C12)
О надстройкахречь идет в главе 21.
Использование Windows API
VBA может заимствовать методы из других файлов, которые не имеют ничего общего с Excel или VBA— например, файлы DLL (Dynamic Link Library— динамически присоединяемая библиотека), используемые Windows и другими программами. В результате в VBA появляется возможность выполнять операции, которые без заимствованных методов находятся за пределами возможностей языка.
Windows API (Application Programming Interface— прикладной программный интерфейс) представляет собой набор функций, доступных программистам в среде Windows. При вызове функции Windows из VBA вы обращаетесь к Windows API. Многие ресурсы Windows, используемые программистами Windows, можно получить из файлов DLL, в которых хранятся программы и функции, подсоединяемые в процессе выполнения программы, а не во время компиляции.
В Excel, например, тоже есть несколько DLL. Код многих из них можно было скомпилировать непосредственно в исполняемый файл программы— e x c e l . e x e , но разработчики решили сохранить его в формате DLL, чтобы зафужать только при необходимости. Такой подход делает главный исполняемый файл Excel меньше. Кроме того, более эффективно используется память, так как библиотека загружается только при необходимости.
Файлы DLL также применяются для совместного использования кода. Например, во многих программах Windows имеются диалоговые окна для открытия и сохранения файлов. В Windows есть DLL, в которой хранится код создания нескольких стандартных диалоговых окон. Программисты, таким образом, могут вызвать необходимую DLL, а не писать собственные процедуры.
Если вы программируете на языке С, то умеете создавать собственные DLL и использовать их в VBA. В языке Visual Basic от Microsoft тоже есть возможность создавать файлы DLL, которые можно вызывать из Excel.
Примеры использования Windows API
Прежде чем использовать функцию Window's API, ее необходимо объявить вверху программного модуля. Если программный модуль— это не стандартный модуль VBA то есть модуль для UserForm, Лист или ЭгаКнига), то функцию API необходимо объявить как P r i v a t e .
Объявление функции API имеет некоторую сложность; она должна объявляться максимально точно. Оператор объявления указывает VBA следующее.
ЧастьIII. VisualBasicforApplications |
263 |
•Какую функцию API вы используете.
•В какой библиотеке расположена функция API.
•Аргументы функции API.
После объявления функции API ее можно использовать в программе VB А.
Определение папки Windows
Ниже показан пример объявленияфункцииAPI.
Declare Function GetWindowsDirectoryA Lib "kernel32" _ (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Эта функция, имеющая два аргумента, возвращает название папки, в котором установлена операционная система Windows (с помощью только VBA такое действие выполнить невозможно). После вызова функции расположение папки Windows хранится в переменной lpBuffer, а длина строки пути— enSize.
После вставки оператора Declare вверху модуля вы можете обратиться к функции GetWindowsDirectoryA. Ниже следует пример вызова функции и отображения результата в
окне сообщений: |
|
|
|
Sub ShowWindowsDir() |
|
||
Dim WinPath |
As |
String |
|
Dim WinDir |
As |
String |
|
WinPath = Space(255) |
' |
||
WinDir = Left(WinPath, GetWindowsDirectoryA _ |
|||
(WinPath, |
Len(WinPath))) |
|
|
MsgBox WinDir, |
vblnformation, |
"Папка Windows" |
|
End Sub |
|
|
|
Впроцессе выполнения процедуры ShowWindowsDir отображается окно сообщения
суказанием расположения папки Windows. Обычно Windows устанавливается в папке
С: \Windows, но это не обязательно. Windows NT часто, но не всегда, устанавливается в папке С: WINNT.
Иногда требуется создать оболочку (wrapper) для функций API. Другими словами, вы создадите собственную функцию, использующую функцию API. Такой подход существенно упрощает использование функции API. Ниже приведен пример такой функции VBA:
Function WindowsDir{) |
As String |
|||
1 Возвращает |
путь к |
папке Windows |
||
Dim |
WinPath |
As String |
||
WinPath = |
Space<255) |
|||
WindowsDir |
= |
Left(WinPath, GetWindowsDirectoryA _ |
||
(WinPath, |
Len(WinPath))) |
|||
End Function |
|
|
|
|
После объявления эту функцию можно вызывать из другой процедуры. |
||||
MsgBox |
WindowsDir |
|
Данную функцию можно также использовать в формуле рабочего листа: =WindowsDir{)
Элементы API выполняют действия, которые другим способом выполнить невозможно (или, как минимум, очень сложно). Если приложение должно найти путь к папке Windows, вы можете целый день искать и не найти is Excel или VBA функцию, которая выполняет эту задачу, Но, зная, как получить доступ к Windows API, вы без особого труда решите свою проблему.
264 Глава 10. Создание функций

Определение состояния клавиши <Shift>
Приведем еще один пример. Предположим, вы написали макрос VBA, который будет выполняться с помощью кнопки на панели инструментов. Необходимо, чтобы этот макрос выполнялся по-другому, если пользователь при щелчке на кнопке удерживает клавишу <Shifi>. Чтобы узнать о нажатии клавиши <Shift>, можно использовать функцию API G e t K e y S t a t e . Функция G e t K e y S t a t e сообщает о том, нажата ли конкретная клавиша. Функция имеет один аргумент, nVirtKey, который представляет код интересующей вас клавиши.
Далее отображена программа, демонстрирующая, как выявить, что при выполнении процедуры обработки события B u t t o n _ C l i c k нажата клавиша <Shift>. Обратите внимание, ч го для клавиши <Shift> определена константа (с использованием шестнадцатеричного значения), которая затем используется как аргумент функции G e t K e y S t a t e . Если G e t K e y S t a t e возвращает значение меньше 0, это означает, что клавиша <Shift> нажата; в противном случае клавиша <Shift> не нажата.
Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Sub Button_Click{)
Const V K _ S H I F T As Integer = &H10
If GetKeyState(VK_SHIFT) < 0 Then
MsgBox "Shi ft нажата"
Else
MsgBox "Shift не нажата"
End If
End Sub
Рабочая книга на Web-узле демонстрирует, как определить следующие клавиши (и любые их комбинации): <Ctrl>, <Shift>, <Alt>.
Дополнительная информация о функциях API
Работа с функциями Windows API может быть довольно сложной. Во многих книгах но программированию перечислены операторы объявления функций API с примерами. Как правило, можно просто скопировать выражения объявления и использовать функции, детально не вникая в их суть. Большинство программистов Excel рассматривают функции API как аналог поваренной книги. В Internet вы найдете сотни вполне надежных примеров, которые можно скопировать и вставить в собственную программу.
В главе 11 приведено несколько примеров использования функций Windows API
На Web-узле издательства содержится текстовый файл с названием win32api. txt, в котором описаны операторы объявления и константы Windows API. Этот файл можно открыть в текстовом редакторе и оттуда скопировать соответствующие объявления в модуль VBA.
При работе с функциями API довольно часто встречаются системные ошибки so время тестирования, поэтому почаще сохраняйте проекты.
Часть III. VisualBasic forApplications |
2S5 |

Если вы разрабатываете приложения, которые должны работать во всех версиях Excel, помните о некоторых потенциально "болезненных" вопросах совместимости, возникающих при вызове функций API. Например, при разработке приложения для Excel 97 или более поздней версии, которое использует функции API, оно не сможет быть запущено в Excel 5 —даже если вы сохраните рабочую книгу в формате Excel 5 {так как Excel 5 является 16-битовым приложением). Версии Excel 97 и выше — 32-битовые приложения. Подробнее об этой проблеме и способах ее предотвращения рассказано в главе 26.
Резюме
В настоящей главе рассмотрены методы создания и использования специальных функций VBAЭти функции могут применяться в формулах рабочего листа и в других процедурах VBA. Кроме того, в данной главе рассмотрено, как вызываются функции Windows API.
Следующая глава содержит ряд примеров, иллюстрирующих приемы, которые описывались в этой и предыдущих главах.
Глава10.Созданиефункций

Примеры и методы программирования Ha VBA
Изучениелюбогопредмета,втомчислеипрограммирования, можно сделать более эффективным, приведя
ряд примеров. Практический подход используется и программистами на VBA. Хорошо продуманный пример, как правило, передает определенную идею лучше, чем описание теории, которая лежит в его основе. Поэтому я не ставил своей целью создать справочник, в котором скрупулезно описаны все нюансы работы с VBA. Вместо этого я подготовил ряд примеров, демонстрирующих полезные приемы программирования в Excel.
В предыдущих главах этой части предоставлен вводный теоретический материал, кроме того, в электронной справочной системе можно найти все детальные сведения, которые в книге опущены. В этой главе представлены примеры решения практических задач, благодаря которым вы сможете углубить свои познания в области VBA.
Примеры, приведенные в данной главе, можно разделить на шесть категорий.
•Работа с диапазонами.
•Управление рабочими книгами и листами.
•Методы программирования на VBA.
•Функции, используемые в процедурах VBA.
•Функции, применяемые в формулах рабочего листа.
•Вызов функций Windows API.
Впоследующих главах этой книги представлены частные примеры управления диаграммами, сводными таблицами, событиями, формами и т.п.

Использование примеров данной главы
Не все примеры а настоящей главе представляют независимые программы. Однако они являются исполняемыми процедурами, которые вы можете приспособить в собственных приложениях, Настоятельно рекомендуем в процессе чтения данной главы работать за компьютером. Вы сможете изменять примеры и наблюдать, что же происходит. Этот практический опыт гарантированно даст вам больше, чем чтение справочников.
Работа с диапазонами
Примеры данного раздела демонстрируют VBA принципы управления диапазонами на рабочих листах Excel.
Примеры из этого раздела можно найти на Web-узле издательства.
Копирование диапазона
Функция записи макросов Excel используется не столько для создания хорошего кода, сколько для поиска названий необходимых объектов, методов и свойств. Программа, которая получена в результате записи макросов, не всегда наиболее эффективна, но обычно она предоставляет немало полезных сведений.
Например, при записи простой операции копирования и вставки мною получено пять строк VBA-кода.
Sub Macrol(J
Range("Al")-Select Selection.Copy Range("Bl").Select ActiveSheet.Paste Application.CutCopyMode = False
End Sub
Обратите внимание, что данная программа выделяет ячейки. Однако в VBA для работы с объектом не обязательно его выделять. Вы бы никогда не узнали об этом важном моменте, если бы копировали показанный выше код макроса, где в двух строках содержится метод S e l e c t . Данную процедуру можно заменить значительно более простой— применить метод Сору, который использует аргумент, представляющий адрес места вставки копируемого диапазона.
Sub CopyRange()
Range("Al").Copy Range{"Bl") End Sub
В обоих макросах предполагается, что рабочий лист является активным, и операция происходит на активном рабочем листе. Чтобы скопировать диапазон на другой рабочий лист или в другую книгу, необходимо задать ссылку. В следующем примере диапазон из листа Лист1 книги File . xl s копируется на лист Лист2 книги File2.xls. Так как ссылки заданы правильно, пример работает независимо от того, какая рабочая книга активна.
Sub CopyRange2 <)
Workbooks("Filel.xls").Sheets{"ЛистIй ).Range("Al").Copy _ Workbooks("File2.xls").Sheets("Лист2").Range{"Al"}
End Sub |
|
268 |
Глава 11, Примеры и методы программирования на VBA |