Национальный исследовательский университет "Высшая Школа Экономики"
Опубликован: 01.04.2010 | Доступ: свободный | Студентов: 4348 / 894 | Оценка: 4.45 / 4.06 | Длительность: 08:48:00
ISBN: 978-5-9556-0119-9
Специальности: Программист
Лекция 7:

Процедуры, подпрограммы и функции

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >

Параметры и аргументы

Через список параметров осуществляется связь между вызывающей и вызываемой процедурами. Параметр:

  • описывается при объявлении процедуры;
  • представляет собой переменную.

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

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

Пример

Для первых пяти натуральных чисел рассчитать квадрат и куб числа ( рис. 7.2).

Основная процедура Proc_param организует цикл на пять чисел и вызывает процедуру Proc_print для распечатки в окне Immediate самого числа, его квадрата и куба.

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

Рис. 7.2. Пример основной и вызываемой процедуры для расчета куба и квадрата числа

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

Call Proc_print (i) - альтернативная запись вызова процедуры.

Замечания

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

Синтаксис описания каждого параметра процедуры имеет следующий вид:

[[Optional][ByVal|ByRef][ParamArray] varname[( )] As type][= defaultvalue]
  • Optional - ключевое слово. Указывает, что параметр может быть опущен.

Важно

  • Необязательные параметры всегда размещаются в конце списка.
  • Тип необязательного параметра - Variant.
  • При наличии необязательного параметра в процедуре необходимо предусмотреть использование значения по умолчанию, если значение аргумента не задано.
  • В процедуре можно проверить, передается необязательный параметр или нет, используя функию IsMissing(argname). Она возвращает значение True, если значение параметра опущено, и False - в противном случае.
  • ByVal 1Указывается одно из двух ByVal или ByRef. - передача параметра по значению. Предполагается, что при вызове процедуры передается только значение переменной и, следовательно, в процессе выполнения процедуры оно не может быть изменено. Используйте этот способ передачи аргументов, чтобы избежать случайной модификации передаваемых данных.
  • ByRef 2Указывается одно из двух ByVal или ByRef. - передача параметров по ссылке. Предполагается, что процедуре передается адрес переменной. В этом случае вызывающая процедура может не только использовать переданное значение переменной, но и изменить его в процессе выполнения. Используется по умолчанию.
  • ParamArray означает передачу необязательного аргумента - массива типа Variant с неопределенным количеством элементов.

Важно

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

  • используется только для последнего параметра процедуры;
  • позволяет задавать произвольное количество передаваемых аргументов;
  • не допускает использование ключевых слов ByVal, ByRef и Optional для описываемого параметра.
  • Varname - идентификатор переменной.
  • type - тип передаваемого аргумента. Если тип данных не указан, то VBA трактует аргумент как Variant.

Важно

  • Разрешены все элементарные типы данных и типы, определенные пользователем.
  • Aргумент типа String должен иметь переменную длину.
  • Если для параметра процедуры описан тип данных, то передаваемый аргумент должен иметь тот же тип данных.
  • Если параметром процедуры является массив, то передаваемый массив должен иметь ту же размерность.

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

  • Value on default - для необязательных аргументов устанавливает значение по умолчанию.

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

Пример

Для сотрудников фирмы (максимально 2000 сотрудников) рассчитать выплаты в соответствии с количеством отработанных часов и ставкой оплаты за час работы. Налог составляет 13%. Если зарплата превышает 300$, то страховой взнос составляет 5%.

Процедура salary_employee (основная) запрашивает ввод количества отработанных часов и размер почасовой оплаты максимально для 2000 сотрудников и передает по значению эти данные в процедуру salary_em_proc.

Вызываемая процедура salary_em_proc рассчитывает и распечатывает денежную выплату. В вызываемой процедуре salary_em_proc определены три параметра. Это io - код сотрудника, ho - количество часов, ra - ставка почасовой оплаты.

Передача аргументов по значению

Рис. 7.3. Передача аргументов по значению

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

В основной процедуре salary_employee объявите переменную AC (Dim AC as Double), в которой будет накапливаться суммарная выплата. В вызываемой процедуре введите четвертый параметр SI - накапливаемая сумма. Этот параметр передается по ссылке, т.к. его значение изменяется в вызываемой процедуре. Оператор вызова процедуры будет выглядеть так: salary_em_sum id, h, r, AC.

Передача аргумента по ссылке (параметр SI)

Рис. 7.4. Передача аргумента по ссылке (параметр SI)

Возврат значения функции

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

function name=expression

Если значение явно не присваивается, то оно устанавливается по умолчанию в соответствии с типом возвращаемого значения: 0 - для числовых типов, строку нулевой длины - для строковых переменных, Empty - для типа Variant и Nothing - для ссылок на объекты.

Замечание

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

Пример

Функция возвращает количество выделенных ячеек, если тип выделения - объект Range (подробно об объекте Range см. "Объекты MS Excel" ). Если выделен объект другого типа, например, встроенная диаграмма или рисунок, то возвращаемое значение - символьная строка с сообщением о некорректности выделения.

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

В вызывающей процедуре вычисленное функцией значение сохраняется на активном листе в ячейках D1 (количество ячеек в интервале A1:C5 ) и D2 (сообщение о некорректности выделения).

Пример сохранения вычисленного функцией значения на активном листе

увеличить изображение
Рис. 7.5. Пример сохранения вычисленного функцией значения на активном листе

Использование процедур-функций на рабочем листе

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

При построении формулы с помощью мастера функций пользовательские функции можно найти в категории Определенные пользователем (User Defined).

Пример

Создать функцию расчета выплат, учитывая, что налог составляет 13% и, если зарплата превышает 300 $, то в страховой фонд дополнительно взимается 5%.

В отличие от процедуры salary_em_proc функция salary_em_ возвращает рассчитанное значение. Возврат значения происходит при помощи операторов присваивания, в которых слева используется имя функции. В вызывающей процедуре salary_employee вместо оператора вызова процедуры salary_em_proc io, h, r записан оператор, распечатывающий рассчитанную выплату как MsgBox io & " salary " & salary_em(h, r).

Пример высвечивания в диалоге значения, вычисленного функцией

Рис. 7.6. Пример высвечивания в диалоге значения, вычисленного функцией

Функцию salary_em_ можно использовать как в процедурах VBA, так и на рабочем листе, как пользовательскую функцию.

На рис. 7.7 в ячейку E3 введены отработанные часы, а в ячейку F3 - ставка оплаты за час. В ячейке G3 рассчитана выплата по формуле =salary_em_(E3;F3).

Использование функции salary_em_ как пользовательской функции на рабочем листе

Рис. 7.7. Использование функции salary_em_ как пользовательской функции на рабочем листе

Замечания

  • Разделитель между аргументами при записи функций в ячейках рабочего листа русифицированной версии MS Excel - точка с запятой ( ; ), тогда как в процедурах VBA это всегда запятая ( ,).
  • Не рекомендуется включать в пользовательские функции операторы, выполняющие какие-либо действия с объектами таблиц, так как при использовании подобной функции на рабочем листе может возникнуть ошибка. Для действий с объектами таблиц применяйте вызываемые процедуры.
< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Дмитрий Денисов
Дмитрий Денисов

Еще раз повторяю вопрос  - отправил договор и сканы документов по почте - в начале августа, до  5 го, внес предоплату - летом действовала скидка - чтобы пройти курс в августе, но я уезжал в Москву. По возвращению - и  в течение месяца - никакого ответа, никаких зачислений, ничего. Как проверить, пришли ли мои документы в Интуит, предоплата, почему нет зачисления.

Дмитрий Денисов
Дмитрий Денисов

Как записаться на курс, оплатить, не ориентируюсь в программе.

Ранее у Вас учился.

Работаю преподавателем, есть справка. Как получить скидку, т.е. оплата 2000