Главная страница
Навигация по странице:

  • Синтаксис процедур и функций

  • Функции с побочным эффектом

  • Создание процедуры

  • Создание процедур обработки событий

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

  • информатика. Игнатьева Елена Александровна, Измайлова Елена Ивановна. Информатика. Электронный ресурс методические указания


    Скачать 4.32 Mb.
    НазваниеИгнатьева Елена Александровна, Измайлова Елена Ивановна. Информатика. Электронный ресурс методические указания
    Дата20.06.2022
    Размер4.32 Mb.
    Формат файлаpdf
    Имя файлаинформатика.pdf
    ТипМетодические указания
    #604814
    страница14 из 15
    1   ...   7   8   9   10   11   12   13   14   15
    Классификация процедур
    Процедуры VBA можно классифицировать по нескольким признакам: по способу использования (вызова) в программе, по способу запуска процедуры на выполнение, по способу создания кода процедуры, по месту нахождения кода процедуры в проекте.
    Процедуры VBA подразделяются на подпрограммы и функ- ции. Первые описываются ключевым словом
    Sub
    , вторые –
    Function
    . Различие между этими видами процедур только синтак- сическое, так как преобразовать процедуру одного вида в эквива- лентную процедуру другого вида не сложно.
    По способу создания процедуры делятся на:
     обычные, разрабатываемые "вручную";
     процедуры, код которых создается автоматически генера- тором макросов (MacroRecoder).
    Это разделение можно считать условным, так как многие процедуры создаются генератором макросов, а затем изменяются и дописываются вручную.
    По способу запуска процедур на выполнение можно выде- лить в отдельную группу процедуры, запускаемые автоматически при наступлении того или иного события (процедуры обработки событий).
    По положению в проекте различаются процедуры:
     находящиеся в специальных программных единицах – стандартных модулях, модулях классов и модулях, связанными с объектами;
     реагирующие на события.
    Еще один специальный тип процедур – процедуры-свойства
    Property Let
    ,
    Property Set и
    Property Get
    . Они служат для задания и получения значений закрытых свойств класса.

    182
    Главное назначение процедур во всех языках программиро- вания состоит в том, что при их вызове они изменяют состояние программного проекта, – изменяют значения переменных (свой- ства объектов), описанных в модулях проекта. У процедур VBA сфера действия шире. Их главное назначение состоит в измене- нии состояния системы документов, частью которого является изменение состояния самого программного проекта. Поэтому процедуры VBA оперируют, в основном, с объектами Office.
    Есть два способа, с помощью которых процедура получает и передает информацию, изменяя тем самым состояние системы документов. Первый и основной способ состоит в использовании параметров процедуры. При вызове процедуры ее аргументы, со- ответствующие входным параметрам получают значение, то есть процедура получает информацию от внешней среды, и в резуль- тате работы процедуры формируются значения выходных пара- метров, переданных ей по ссылке. Тем самым изменяется состоя- ние проекта и документов. Второй способ состоит в использова- нии процедурой глобальных переменных и объектов, как для по- лучения, так и для передачи информации.
    Синтаксис процедур и функций
    Описание процедуры
    Sub в VBA имеет следующий вид:
    [Private | Public] [Static] Sub имя([список-аргументов]) тело-процедуры
    End Sub
    Ключевое слово
    Public в заголовке процедуры используется, чтобы объявить процедуру общедоступной, то есть дать возмож- ность вызывать ее из всех других процедур всех модулей любого проекта. Если модуль, в котором описана процедура, содержит закрывающий оператор
    Option Private
    , процедура будет доступна лишь модулям своего проекта. Альтернативный ключ
    Private ис- пользуется, чтобы закрыть процедуру от всех модулей, кроме то- го, в котором она описана. По умолчанию процедура считается общедоступной.
    Ключевое слово
    Static означает, что значения локальных
    (объявленных в теле процедуры) переменных будут сохраняться в промежутках между вызовами процедуры (используемые про-

    183 цедурой глобальные переменные, описанные вне ее тела, при этом не сохраняются).
    Параметр имя
    – это имя процедуры, удовлетворяющее стан- дартным условиям VBA на имена переменных.
    Необязательный параметр список-аргументов
    – это после- довательность разделенных запятыми переменных, задающих пе- редаваемые процедуре при вызове параметры. Аргументы (фор- мальные параметры), задаваемые при описании процедуры, все- гда представляют только имена (идентификаторы). В то же время при вызове процедуры ее аргументы – фактические параметры могут быть не только именами, но и выражениями.
    Последовательность операторов (
    тело процедуры)
    задает программу выполнения процедуры. Тело процедуры может включать как "пассивные" операторы объявления локальных данных процедуры (переменных, массивов, объектов и др.), так и "активные" – они изменяют состояния аргументов, локальных и внешних (глобальных) переменных и объектов. В тело может входить оператор
    Exit Sub
    , приводящий к немедленному завер- шению процедуры и передаче управления в вызывающую про- грамму. Каждая процедура в VBA определяется отдельно от дру- гих, то есть тело одной процедуры не может включать описания других процедур и функций.
    Рассмотрим подробнее структуру одного аргумента из спи- ска-аргументов:
    [Optional] [ByVal | ByRef] [ParamArray] переменная[()] [As тип] [= значение-по-умолчанию]
    Ключевое слово
    Optional означает, что заданный им аргу- мент является возможным, но необязательным, – его необяза- тельно задавать в момент вызова процедуры. Для таких аргумен- тов можно задать значение по умолчанию. Необязательные аргу- менты всегда помещаются в конце списка аргументов.
    Альтернативные ключи
    ByVal и
    ByRef определяют способ передачи аргумента в процедуру.
    ByVal означает, что аргумент передается по значению, то есть при вызове процедуры будет создаваться локальная копия переменной с начальным передаваемым значением и изменения этой локальной переменной во время выполнения процедуры не отразятся на значении переменной, передавшей свое значение в

    184 процедуру при вызове. Передача по значению возможна только для входных параметров, которые передают информацию в про- цедуру, но не являются результатами. Для таких параметров пе- редача по значению удобнее, чем передача по ссылке, так как в момент вызова аргумент может быть задан сколь угодно слож- ным выражением. Входные параметры, являющиеся объектами, массивами или переменными пользовательского типа, передают- ся по ссылке, что позволяет избежать создания копий. Выраже- ния над такими аргументами недопустимы, поэтому передача по значению теряет свой смысл.
    ByRef означает, что аргумент передается по ссылке, то есть все изменения значения передаваемой переменной при выполне- нии процедуры будут непосредственно происходить с перемен- ной-аргументом из вызвавшей данную процедуру программы.
    В VBA по умолчанию аргументы передаются по ссылке (
    ByRef
    ).
    VBA допускает, чтобы фактическое значение аргумента, переда- ваемого по ссылке, было константой или выражением соответст- вующего типа. В таком случае этот аргумент рассматривается как передаваемый по значению, и никаких сообщений об ошибке не выдается, даже если этот аргумент встречается в левой части присвоения.
    Процедура VBA допускает возможность иметь необязатель- ные аргументы, которые можно опускать в момент вызова.
    Обобщением такого подхода является возможность иметь пере- менное, заранее не фиксированное число аргументов. Достигает- ся это за счет того, что один из параметров (последний в списке) может задавать массив аргументов, – в этом случае он задается с описателем
    ParamArray
    . Если список-аргументов включает мас- сив аргументов
    ParamArray
    , ключ
    Optional использовать в списке нельзя. Ключевое слово
    ParamArray
    . может появиться перед по- следним аргументом в списке, чтобы указать, что этот аргумент – массив с произвольным числом элементов типа
    Variant
    . Перед ним нельзя использовать ключи
    ByVal
    ,
    ByRef или
    Optional
    Переменная
    – это имя переменной, представляющей аргу- мент.
    Если после имени переменной заданы круглые скобки, то это означает, что соответствующий параметр является массивом.

    185
    Параметр тип задает тип значения, передаваемого в проце- дуру. Он может быть одним из базисных типов VBA (не допус- каются только строки
    String c фиксированной длиной). Обяза- тельные аргументы могут также иметь тип определенной пользо- вателем записи или класса. Если тип аргумента не указан, то по умолчанию ему приписывается тип
    Variant
    Для необязательных (
    Optional
    ) аргументов можно явно за- дать значение по умолчанию
    . Это константа или константное вы- ражение, значение которого передается в процедуру, если при ее вызове соответствующий аргумент не задан. Для аргументов типа объект (
    Object
    ) в качестве значения по умолчанию можно задать только
    Nothing
    Синтаксис определения процедур-функций похож на опре- деление обычных процедур:
    [Public | Private] [Static] Function имя [(список-аргументов)]
    [As тип-значения] тело-функции
    End Function
    Отличие лишь в том, что вместо ключевого слова
    Sub для объявления функции используется ключевое слово
    Function
    , а по- сле списка аргументов следует указать параметр тип-значения
    , определяющий тип возвращаемого функцией значения. В теле функции должен быть использован оператор присвоения вида: имя = выражение
    Здесь, в левой части оператора стоит имя функции, а в пра- вой – значение выражения, задающего результат вычисления функции. Если при выходе из функции переменной имя значение явно не присвоено, функция возвращает значение соответствую- щего типа, определенное по умолчанию. Для числовых типов это
    0
    , для строк – строка нулевой длины (
    ""
    ), для типа
    Variant функ- ция вернет значение
    Empty
    , для ссылок на объекты –
    Nothing
    Чтобы немедленно завершить вычисления функции и выйти из нее, в теле функции можно использовать оператор
    Exit
    Function.
    Основное отличие процедур от функций состоит в способе их использования в вызывающей программе. Следующая функ- ция возвращает аргумент, возведенный в куб:
    Function cube(ByVal N As Integer) As Long

    186 cube = N*N*N
    End Function
    Вызов этой функции может иметь вид
    Dim x As Integer, y As Integer y = 2 x = cube(y+3)
    При преобразовании функции в процедуру появляется до- полнительный параметр, необходимый для задания результата.
    Поэтому у эквивалентной процедуры
    Cube1
    появляется еще один аргумент:
    Sub cube1(ByVal N As Integer, ByRef C As Long)
    C = N*N*N
    ' получение результата в переменной, заданной по ссылке
    End Sub
    Ее также можно использовать для возведения в куб: cube1(y+3, x)
    Эта взаимозаменяемость не означает, что безразлично, ка- кой вид процедур использовать в программе. Если бы выражение, в котором участвует функция, было сложнее, например, x = cube(y)+sin(cube(x)) то его вычисление с помощью процедуры
    Cube1
    потребовало бы выполнения нескольких операторов и ввода дополнительных пе- ременных: cube1(y,z) cube1(x,u) x = z+sin(u)
    Функции с побочным эффектом
    В классическом варианте все аргументы функции являются входными параметрами, и единственный результат вычисления функции – это ее возвращаемое значение, примером является функция
    Cube
    . Однако чаще всего, используются функции с по- бочным эффектом, то есть такие функции, которые помимо полу- чения значения функции изменяют значения некоторых резуль- тирующих параметров, передаваемых функции по ссылке. На- пример:
    Public Function SideEffect(ByVal X As Integer, ByRef Y As In- teger) As Integer

    187
    SideEffect = X+Y
    Y = Y+1
    End Function
    Public Sub TestSideEffect()
    Dim X As Integer, Y As Integer, Z As Integer
    X = 3: Y = 5
    Z = X+Y+SideEffect(X, Y)
    Debug.Print X, Y, Z
    X = 3: Y = 5
    Z = SideEffect(X, Y)+X+Y
    Debug.Print X, Y, Z
    End Sub
    Вот результаты вычислений:
    3 6
    16 3
    6 17
    В данном примере результат вычисления суммы трех сла- гаемых зависит от порядка их записи. Более того, результат вы- числения будет непредсказуем, поскольку VBA может для увели- чения эффективности изменять порядок действий при вычисле- нии арифметического выражения. Поэтому лучше не использо- вать в выражении вызов функции с побочным эффектом, изме- няющей значения входящих в него переменных.
    Создание процедуры
    Для создания новой процедуры, текст которой пишется вручную, нужно:
    1) открыть в окне проектов "Проект-(VBA)Project" (Project
    Explorer) папку с модулем (формой, документом, рабочим листом и т.п.), к которому требуется добавить процедуру, и, щелкнув этот модуль, открыть окно редактора с кодами процедур модуля;
    2) перейти в редактор, набрать ключевое слово (
    Sub
    ,
    Function или
    Property
    ), имя процедуры и ее аргументы; затем на- жмите клавишу Enter, и VBA поместит ниже строку с соответст- вующим закрывающим оператором (
    End Sub
    ,
    End Function
    ,
    End
    Property
    );
    3) написать текст процедуры между ее заголовком и закры- вающим оператором.

    188
    Можно автоматизировать работу, вызвав диалоговое окно "Вставка процедуры" (Insert Procedure). Последовательность дей- ствий в этом случае следующая:
    1) выбрать в меню "Вставка" (Insert) команду "Процедура"
    (Procedure);
    2) в поле "Имя" (Name) появившегося окна "Вставка проце- дуры" (Insert Procedure) ввести имя процедуры;
    3) указать в группе кнопок-переключателей "Тип" (Type) тип создаваемой процедуры: Подпрограмма (
    Sub
    ), Функция
    (
    Function
    ) или Свойство (
    Property
    );
    4) указать в группе кнопок-переключателей "Область опре- деления" (Scope) вид доступа к процедуре: Общая (Public) или
    Личная (Private);
    5) пометить, если нужно, флажок "Все локальные перемен- ные считать статическими" (All Local Variables as
    Statics
    ), чтобы в заголовок процедуры добавился ключ
    Static
    ;
    6) щелкнуть кнопку "OK" – в окне редактора появится заго- товка процедуры, состоящая из ее заголовка (без параметров) и закрывающего оператора;
    7) добавить параметры в заголовок процедуры и написать текст процедуры между ее заголовком и закрывающим операто- ром.
    Создание процедур обработки событий
    VBA является языком, в котором, как и в большинстве со- временных объектно-ориентированных языков, реализована кон- цепция программирования, управляемого событиями (event driven programming). Здесь нет понятия программы, которая на- чинает выполняться от
    Begin до
    End
    . Пользователи системы до- кументов и операционная система могут инициировать события в мире объектов. В ответ на возникновение события операционная система посылает сообщение соответствующему объекту. Реак- цией объекта на получение сообщения является вызов процедуры
    – обработчика события. Задача программиста сводится к написа- нию обработчиков событий для объектов. Причем, все обычные процедуры и функции VBA, о которых мы говорили выше, вызы- ваются прямо или косвенно из процедур обработки событий, если

    189 только речь не идет о режиме отладки. Именно эти процедуры приводят к последовательности вызовов обычных процедур и функций.
    С каждым из объектов Office связан набор событий, на ко- торые он может реагировать. Процедуры обработки этих событий располагаются в модулях, связанных с объектами, реагирующими на события. Для кнопок меню, у которых есть только один обра- ботчик события, соответствующая процедура может находиться в стандартном модуле или модуле макросов. Office позволяет при описании собственных классов, создаваемых программистом, за- дать определенный набор событий. Обработчики событий таких объектов создаются по определенной технологии. Например, процедура, которая будет пять раз подавать звуковой сигнал при закрытии документа:
    Private Sub Document_Close()
    Dim I As Integer
    For I = 1 To 5
    ' 5 раз подается
    Beep
    ' звуковой сигнал
    Next I
    End Sub
    Эта процедура находится в модуле, связанном с объектом
    ThisDocument
    , и вызывается в момент закрытия документа.
    Вызовы процедур и функций
    Вызовы процедур Sub
    Вызов обычной процедуры
    Sub из другой процедуры можно оформить разными способами.
    Первый способ: имя список фактических параметров, где имя
    – имя вызываемой процедуры; список фактических пара- метров
    – список аргументов, передаваемых процедуре; он должен соответствовать списку аргументов, заданному в описании про- цедуры.
    Задать список параметров можно разными способами.

    190
    В простейшем случае в нем перечисляются через запятую значения передаваемых процедуре аргументов в том же порядке, что и в списке аргументов из заголовка процедуры.
    Может оказаться, что в одном проекте несколько модулей содержат процедуры с одинаковыми именами. Для различия этих процедур нужно при их вызове указывать имя процедуры через точку после имени модуля, в котором она определена. Например, если каждый из двух модулей
    Mod1
    и
    Mod2
    содержит определе- ние процедуры
    ReadData
    , а в процедуре
    MyProc нужно восполь- зоваться процедурой из
    Mod2
    , этот вызов имеет вид:
    Sub Myproc()
    Mod2.ReadData
    End Sub
    Если требуется использовать процедуры с одинаковыми именами из разных проектов, нужно добавить к именам модуля и процедуры имя проекта. Например, если модуль
    Mod2
    входит в проект
    MyBook
    , тот же вызов можно уточнить так:
    MyBooks.Mod2.ReadData
    Второй способ вызова процедур связан с использованием оператора
    Call
    . В этом случае вызов процедуры выглядит так:
    Call имя(список фактических параметров)
    Обратите внимание на то, что в этом случае список факти- ческих параметров заключен в круглые скобки, а в первом случае
    – нет. Если процедура VBA имеет только один параметр, то она может быть вызвана без оператора
    Call и с использованием круг- лых скобок, не сообщая об ошибке вызова, но возвращает не пра- вильный результат. Например:
    Public Sub MyInc(ByRef X As Integer)
    X = X+1
    End Sub
    Public Sub TestInc()
    Dim X As Integer
    X = 1
    'Вызов процедуры с параметром, заключенным в скобки,
    'синтаксически допустим, но работает не корректно!
    MyInc (X)
    Debug.Print X

    191
    'Корректный вызов
    MyInc X
    Debug.Print X
    'Это тоже корректный вызов
    Call MyInc(X)
    Debug.Print X
    End Sub
    Вот результаты ее работы:
    1 2
    3
    Несмотря на то, что при первом вызове процедура вызыва- ется без ошибок и увеличивает значение результата, но по завер- шении ее работы значение аргумента не изменяется. В этой си- туации не действует описатель
    ByRef
    , вызов идет так, как будто параметр описан с описателем
    ByVal
    Если же процедура имеет более одного параметра, то по- пытка вызвать ее, заключив параметры в круглые скобки и не предварив этот вызов ключевым словом
    Call
    , приводит к синтак- сической ошибке. Например:
    Public Sub SumXY(ByVal X As Integer, ByVal Y As Integer,
    ByRef Z As Integer)
    Z = X+Y
    End Sub
    Public Sub TestSumXY()
    Dim a As Integer, b As Integer, c As Integer a = 3: b = 5
    'SumXY (a, b, c)
    'Синтаксическая ошибка
    SumXY a, b, c
    Debug.Print c
    End Sub
    В этом примере некорректный вызов процедуры
    SumXY
    бу- дет обнаружен на этапе проверки синтаксиса.
    Рассмотрим еще одну особенность вызова VBA процедур, связанную с аргументами, передаваемыми по ссылке. Как прави- ло, в языках программирования для таких аргументов возможное значение фактического параметра ограничивается, – он должен

    192 быть именем переменной, ссылка на которую передается проце- дуре. VBA допускает возможность задания для таких аргументов констант и выражений в момент вызова.
    Например, процедура
    CompVal c четырьмя аргументами, которая в зависимости от положительности z возвращает в пере- менной y либо увеличенное, либо уменьшенное на сто значение x
    и сообщает об этом в строковой переменной w
    , определена сле- дующим образом.
    Sub CompVal(ByVal x As Single, ByRef y As Single, _
    ByVal z As Integer, ByRef w As String)
    If z > 0 Then
    ' увеличение y = x+100 w = "increase"
    Else
    ' уменьшение y = x-100 w = "decrease"
    End If
    End Sub
    Рассмотрим процедуру
    TestCompVal
    , в которой несколько раз вызывается процедура
    CompVal
    :
    Sub TestCompVal()
    Dim a As Single
    Dim b As Single
    Dim n As Integer
    Dim S As String n = 5 : a = 7.4
    ' значения параметров
    CompVal a, b, n, S
    ' 1-ый вызов
    Debug.Print b, S
    CompVal 7.4, b, 5, S
    ' 2-ой вызов
    Debug.Print b, S
    CompVal 0, 0, 0, S
    ' 3-ий вызов
    Debug.Print b, S
    CompVal 0, 0, 0, "В чем дело?"
    ' 4-ый вызов
    Debug.Print b, S
    End Sub
    В результате выполнения этой процедуры будут напечатаны следующие результаты:
    107,4 increase

    193 107,4 increase
    107,4 decrease
    107,4 decrease
    Первые два вызова корректны. Следующие два вызова хотя и допустимы в языке VBA, но приводят к тому, что параметры, переданные по ссылке, не меняют своих значений в ходе выпол- нения процедуры и, по существу, вызов
    ByRef по умолчанию за- меняется вызовом
    ByVal
    1   ...   7   8   9   10   11   12   13   14   15


    написать администратору сайта