Опубликован: 25.03.2009 | Уровень: для всех | Доступ: свободно
Лекция 6:

Основы VBA: встроенные и пользовательские функции

< Лекция 5 || Лекция 6: 123 || Лекция 7 >

6.3. Пользовательские процедуры и функции

06-03-Пользовательские процедуры и функции.docm - пример к п. 6.3. - 6.5.

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

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

Например, очевидно, что при обработке такой последовательности команд: num_A = num_B + val(str_C) вместо выражения val(str_C) подставляется числовое значение переменной str_C, найденное благодаря функции Val. Или, скажем, такое выражение: num_A = InputBox("Введите число"). Здесь функция InputBox возвращает введенное пользователем число в переменную num_A.

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

Разобравшись в отличиях процедур и функций, поговорим о том, зачем они нам нужны. Во-первых, процедуры удобно использовать для сокращения объема программы, выделяя в них часто используемые блоки операторов. Если вам придется создавать реальные программы, вы очень скоро убедитесь в том, что некоторые операции (например - запись каких-либо значений на лист MS Excel, создание и сохранение документов и т.д.) могут быть нужными в различных местах программы и занимать порой несколько десятков строчек кода. Нерационально каждый раз копировать эти участки кода в нужное место. Во-первых - увеличивается размер текста программы, во-вторых - если вам понадобится изменить что-нибудь в часто используемом наборе операторов - придется искать все такие участки и редактировать каждый из них. Гораздо удобнее будет выделить часто используемый участок в виде самостоятельной процедуры и каждый раз, когда он будет нужен, вызывать его с помощью одной лишь строчки кода.

6.4. Пользовательская процедура

Рассмотрим пример создания и использования пользовательской процедуры. Предположим, нам нужно опросить пятерых пользователей, обработав и записав их ответы в файл. Самое главное в этом примере не то, куда мы будем записывать ответы, и как их будем обрабатывать, а то, что блок кода будет повторяться для каждого пользователя. Сначала напишем этот блок в расчете на одного пользователя. Для этого добавим в документ Microsoft Word кнопку cmd_User_Data и создадим для нее такой обработчик события (листинг 6.6.):

Private Sub cmd_User_Data_Click()
    Dim str_Name As String
    Dim byte_Age As Byte
    MsgBox ("Здравствуйте, вы пользователь № 1")
    str_Name = InputBox("Введите ваше имя")
    byte_Age = InputBox("Введите ваш возраст")
    'Здесь находится блок обработки и
    'записи введенных данных
End Sub
Листинг 6.6. Опрос пользователя - заготовка для процедуры

Для наглядности мы оставили операторы начала и конца процедуры.

Давайте подумаем, что нужно сделать с кодом при переходе ко второму пользователю. Очевидно, что мы сможем работать с теми же переменными, что и в первом случае, будем использовать те же операторы. Единственным, что изменится, будет надпись в первом окне сообщения. Вместо "Здравствуйте, вы пользователь №1" будет выведено "Здравствуйте, вы пользователь №2".

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

Чтобы создать процедуру, добавим в проект новый модуль, например, командой Insert o Module (Вставить o Модуль).

В модуле создадим для начала "скелет" процедуры. Он будет выглядеть так (листинг 6.7.):

Public Sub UserInput(UserNumber As Integer)
    'пользовательская процедура
    'для ввода и обработки данных
End Sub
Листинг 6.7. Начало и конец текста пользовательской процедуры

Внутри процедуры - там, где будет располагаться ее тело, мы разместили комментарии. Вы уже знаете, что End Sub означает конец процедуры. А вот первая строка объявления выглядит гораздо интереснее. Давайте разберем ее составные части.

UserInput - это имя процедуры. Мы выбираем его самостоятельно. В скобках после имени находится объявление переменной, которую можно передать процедуре в качестве параметра. В нашем случае это переменная, имеющая имя UserNumber и тип Integer. Вспомните, как мы работаем с функцией MsgBox - вызывая ее мы пишем такой код: MsgBox ("Привет"). В данном случае мы передаем функции MsgBox текстовый параметр "Привет", который она выведет на экран. Точно так же, мы сможем передать нашей процедуре числовой параметр типа Integer, который будет "виден" ей под именем UserNumber. Вызов нашей процедуры для первого пользователя из обработчика события Click будет выглядеть так:

UserInput (1)

Тот номер, который мы указали в скобках, будет присвоен переменной UserNumber и мы сможем пользоваться ей внутри процедуры. Давайте проиллюстрируем это. Как вы помните, выше мы определили, что в общем коде будет изменяться лишь номер пользователя. Поэтому перепишем строку приглашения таким образом, чтобы для каждого номера пользователя она выводила бы собственный текст. После этого текст процедуры будет выглядеть так (листинг 6.8.):

Public Sub UserInput(UserNumber As Integer)
     MsgBox _
     ("Здравствуйте, вы пользователь № " + _
     Str(UserNumber))
End Sub
Листинг 6.8. Модификация пользовательской процедуры

Теперь рассмотрим остальные части первой строки процедуры. Ключевое слово Sub означает, что перед нами процедура. А модификатор доступа Public означает, что эту процедуру можно вызвать из любого модуля проекта. Существуют и другие модификаторы доступа, в частности, Private. Он дает доступ к процедуре только из того модуля, где она объявлена.

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

Private Sub cmd_User_Data_Click()
    UserInput (1)
    UserInput (2)
    UserInput (3)
    UserInput (4)
    UserInput (5)
End Sub
Листинг 6.9. Код события Click для cmd_User_Data
Public Sub UserInput(UserNumber As Integer)
    Dim str_Name As String
    Dim byte_Age As Byte
    MsgBox _
     ("Здравствуйте, вы пользователь № " + _
     Str(UserNumber))
    str_Name = InputBox("Введите ваше имя")
    byte_Age = InputBox("Введите ваш возраст")
End Sub
Листинг 6.10. Окончательный вариант пользовательской процедуры

Теперь поговорим о функциях.

6.5. Пользовательская функция

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

Функция, реализующая эту задачу, выглядит так (листинг 6.11.):

Public Function Square(num_One As Double) As Double
    Square = num_One ^ 2
End Function
Листинг 6.11. Пользовательская функция

Объявление функции очень похоже на объявление процедуры. Здесь мы используем модификатор доступности Public, дающий доступ к функции из всех модулей. Ключевое слово Function означает, что мы объявляем функцию. Следом за ним, в скобках, идет объявление параметров, которые мы можем передать функции. В нашем случае это - одна переменная num_One типа Double. После объявления имени и параметров функции следует объявление типа самой функции, или, точнее - типа возвращаемого функцией значения. В нашем случае с помощью конструкции As Double мы задали тип функции Double. При объявлении функции можно не указывать тип - тогда он автоматически будет установлен в Variant.

Последняя строка объявления функции - End Function, означает конец функции. Как и в случае с процедурой, внутри тела функции можно разместить операторы, необходимые для выполнения задачи. Однако, здесь есть одна очень важная особенность. После того, как найдено значение, которое функция должна возвратить, в тексте кода функции нужно присвоить это значение переменной, которая имеет то же имя, что и функция. В нашем случае, при имени функции Square это присвоение выглядит как Square = num_One ^ 2.

Для испытания функции добавим в документ еще одну кнопку - cmd_UserCalc, подписанную как Функция с таким кодом (листинг 6.12.):

Private Sub cmd_UserCalc_Click()
    Dim num_Res As Double
    Dim num_Input As Double
    num_Input = CDbl(InputBox("Введите число"))
    num_Res = Square(num_Input)
    MsgBox (Str(num_Input) + " во 2-й степени = " + _
    Str(num_Res))
End Sub
Листинг 6.12. Работа с пользовательской функцией

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

< Лекция 5 || Лекция 6: 123 || Лекция 7 >
Евгений Ушаков
Евгений Ушаков
О стоимости курса
Александр Новиков
Александр Новиков
Справочник по объектам VBA
Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989
Михаил Алексеев
Михаил Алексеев
Россия, Уфа, УГАТУ, 2002