Vba excel вызов процедуры
VBA-Урок 9. Процедуры и функции
Public — Private
На данный момент, все процедуры, мы создавали, имеют тип Public , что означает, что они доступны из любого модуля.
Чтобы сделать процедуру доступной только в определенном модуле, используется ключевое слово Private:
Запуск процедуры с середины другой процедуры
Чтобы выполнить процедуру с середины другой процедуры, просто введите ее название.
Здесь есть очень простой пример:
Аргументы
Аргументы делают возможным использование значений из процедуры в под-процедуры (запомните, что по умолчанию, переменные являются доступны только по той процедуры, в которой они были объявлены).
К процедуре «warning» был добавлен аргумент, в данном случае это переменная «var_text» с типом «String» (строка):
Эта процедура требует аргумент, поэтому мы должны поставить значение после «warning», чтобы выполнить ее:
Когда мы хотим прописать несколько аргументов, тогда они должны быть отделены запятыми.
Необязательные аргументы
По умолчанию, если процедура имеет аргументы, то они должны быть обязательно проставлены, и если они не проставлены, тогда процедура не выполнится.
Необязательный аргумент может быть добавлен после обязательного, с помощью ключевого слова Optional . Например:
Теперь эта процедура может быть выполнена с или без опционального аргумента, как здесь:
Аргументы должны быть введены в правильном порядке.
Чтобы протестировать, присутствует ли опциональный аргумент в процедуре, мы используем функцию IsMissing . Эта функция совместима только с некоторыми типами функций (типа Variant) и это является решающим, так как тип необязательно аргументов не был указан в объявлении (необъявленный тип = Variant).
Здесь есть пример, который использует два фрагмента кода, которые рассматривались выше:
См. рисунок ниже (пример 1):
ByRef — ByVal
По умолчанию, аргументы имеют тип ByRef , что означает: если переменная передается как аргумент, ссылка на нее будет также передаваться. Иными словами, если переменная была изменена другой под-процедурой, то она также будет изменена во внешней процедуре, которая вызывает эту под-процедуру.
Чтобы стало понятнее, ниже есть пример того, что произойдет, если макрос будет запущен на выполнение:
Второй метод заключается в использовании ByVal .
В отличие от ByRef , который передает ссылки (ярлык), ByVal передает значение, которое означает, что значение передано как аргумент не было изменено.
Ниже вы можете увидеть как предыдущий код и ByVal работают:
Что вам нужно запомнить: используйте ByVal когда переменная не должна быть изменена .
Функции
Основным отличием между процедурой и функцией является то, что функция возвращает значение.
Вот простой пример:
Функция может быть использована на рабочем листе, подобно любой другой функции в Excel.
Например, чтобы получить квадрат значения, которое введенное в ячейку A1:
Работа с процедурами VBA
Процедура — это последовательность операторов VBA, расположенная в модуле VBA, доступ к которому можно получить с помощью VBE. Модуль может включать любое количество процедур.[1] Некоторые процедуры получают аргументы. Аргумент — это информация, используемая процедурой в процессе выполнения. Аргументы процедуры во многом подобны аргументам, используемым функциями Excel.
При объявлении процедуры с использованием ключевого слова Sub применяется следующий синтаксис.
Рис. 1. Запуск процедуры из Visual Basic Editor
Скачать заметку в формате Word или pdf
Private (необязательное ключевое слово). Указывает на то, что процедура доступна только для других процедур в том же модуле.
Public (необязательное ключевое слово). Указывает на то, что процедура доступна для всех остальных процедур во всех модулях рабочей книги. При использовании в модуле, содержащем оператор Option Private Module, процедура будет недоступна за пределами проекта.
Static (необязательное ключевое слово). Указывает на то, что переменные процедуры сохраняются после окончания процедуры.
Sub (обязательное ключевое слово). Обозначает начало процедуры.
Имя. Любое корректное название процедуры.
Список_аргументов. Представляет заключенный в скобки список переменных, содержащих аргументы, которые передаются в процедуру. Для разделения аргументов используется запятая. Если процедура не использует аргументы, то необходимо включить в объявление процедуры пустые скобки.
Инструкции (необязательные). Корректные инструкции VBA.
Exit Sub (необязательный оператор). Вызывает немедленный выход из процедуры до ее формального завершения.
End Sub (обязательный оператор). Указывает на завершение процедуры.
Выполнение процедуры
Основные способы выполнения, или вызова, процедуры VBA.
1-й способ. С помощью команды Run–>Run Sub/UserForm (Выполнить –> Выполнить процедуру/ пользовательскую форму, рис. 1) в VBE. Альтернатива — нажать либо воспользоваться кнопкой Run Sub/UserForm панели инструментов Standard (Стандартная, рис. 2).
Рис. 2. Кнопка Run Sub/UserForm на панели Standard VBE
2-й способ. Из диалогового окна Макрос в Excel (рис. 3). Чтобы вызвать окно пройдите по меню Разработчик –> Макрос или нажмите Alt+F8.
Рис. 3. Диалоговое окно Макрос в Excel
3-й способ. С помощью комбинации клавиши и присвоенной процедуре клавиши (если процедуре присвоена комбинация клавиш). Если в момент создания процедуры ей не была присвоена клавиша, сделать это никогда не поздно. Откройте окно Макрос, как описано выше, выделите процедуру в окне Имя макроса, кликните Параметры, и введите букву в окне Сочетание клавиш (рис. 4).
Рис. 4. Присвоение процедуре комбинации клавиш
4-й способ. Щелкнув на кнопке или любой фигуре рабочего листа. Для этого кнопке или фигуре должна быть присвоена процедура (рис. 5).
Рис. 5. Назначение макроса фигуре
5-й способ. Из другой процедуры. Процедуры Sub и Function могут вызывать другие процедуры.
6-й способ. С помощью пользовательского элемента управления, находящегося на ленте. Кроме того, встроенные элементы управления ленты могут быть «перенастроены» для вызова макроса на выполнение.
7-й способ. Из пользовательского контекстного меню.
8-й способ. После выполнения определенного события. Такими событиями могут выступать открытие рабочей книги, сохранение рабочей книги, закрытие рабочей книги, изменение ячейки, переход на другой рабочий лист и многие другие.
9-й способ. Из окна отладки (Immediate) в VBE. Просто введите название процедуры, укажите все необходимые аргументы и нажмите клавишу .
Передача аргументов процедурам
Аргументы обеспечивают процедуру данными, использующимися в ее инструкциях. Аргумент может передавать следующие данные: переменная, константа, массив, объект.
Используются два способа передачи аргументов процедуре.
- По ссылке. При передаче аргумента по ссылке (метод, применяемый по умолчанию) процедуре передается адрес ячейки памяти, в которой хранится переменная. Поэтому изменение аргумента в процедуре приводит к изменению исходной переменной.
- По значению. Передача аргумента по значению фактически означает передачу процедуре копии исходной переменной. Следовательно, изменение аргумента при выполнении процедуры не отражается на исходной переменной.
В следующем примере аргумент процедуры Process передается по ссылке (по умолчанию). После того как процедура Main присваивает переменной MyValue значение 10, она вызывает процедуру Process и передает MyValue в качестве аргумента. Процедура Process умножает значение своего аргумента (с названием YourValue) на 10. По окончании процедуры Process возобновляется выполнение процедуры Main, а функция MsgBox отображает строку MyValue: 100.
Sub Main ()
Dim MyValue As Integer
MyValue = 10
Call Process(MyValue)
MsgBox MyValue
End Sub
Sub Process (YourValue)
YourValue = YourValue * 10
End Sub
Если требуется, чтобы вызываемая процедура не изменяла переменные, полученные как аргументы, измените список аргументов вызываемой процедуры так, чтобы аргументы передавались по значению, а не по ссылке. Для этого добавьте перед аргументом ключевое слово ByVal. Тогда вызываемая процедура будет управлять копией переданных данных, а не самими данными. В следующей процедуре, например, изменения, которые происходят с YourValue в процедуре Process, не влияют на значение переменной MyValue в процедуре Main. В результате функция MsgBox отображает 10, а не 100.
Sub Process(ByVal YourValue)
YourValue = YourValue * 10
End Sub
Обработка ошибок
Чтобы указать. программе, что должно произойти при возникновении ошибки, используется оператор On Error. Вы вправе выбрать один из двух вариантов.
- Проигнорировать ошибку и позволить VBA продолжить выполнение программы. После этого можно проанализировать объект Err, чтобы узнать, какая ошибка произошла, и при необходимости принять меры для ее предотвращения.
- Перейти к специальному разделу кода для обработки ошибок, чтобы выполнить необходимые действия. Этот раздел вводится в конце процедуры и обозначается специальной меткой.
Чтобы программа продолжала выполняться после возникновения ошибки, необходимо вставить в начало процедуры оператор On Error Resume Next. При возникновении ошибки можно использовать объект Err для определения ее номера. Например, на рис. 6 представлена процедура, присваивающая Листу2 имя Исходные данные. Однако, в книге может не быть Листа2. В этом случае появится сообщение об ошибке.
Рис. 6. Процедура присвоения имени Листу Excel, обрабатывающая ошибку
Ссылка на Err эквивалентна обращению к свойству Number объекта Err. Следовательно, два приведенных ниже оператора идентичны:
MsgBox Err
MsgBox Err.Number
Оператор On Error также применяется для определения места в процедуре, к которому должна перейти программа в случае ошибки. Чтобы обозначить это место, используется метка.
On Error GoTo ErrorHandler
Следующая процедура выделяет все ячейки в текущем диапазоне, содержащие формулы, возвращающие число. Процедура также использует оператор If для определения результата: произошла ли ошибка. Оператор On Error GoTo 0 восстанавливает нормальную обработку ошибок перед выходом из процедуры.
Sub SelectFormulas2()
On Error Resume Next
Selection.SpecialCells(xlFormulas, xlNumbers).Select
If Err.Number = 1004 Then MsgBox » He найдены ячейки с формулами. »
On Error GoTo 0
‘ …[код]
End Sub
Если свойство Number объекта Err не равно 0, происходит ошибка. С помощью оператора If проверяется, не равно ли свойство Err.Number 1004, и, если это так, отображается окно сообщения. В рассмотренном примере осуществляется проверка кода на предмет обнаружения ошибки с указанным номером.
В следующем примере кода демонстрируется обработка ошибок путем перехода по метке.
Sub ErrorDemo()
On Error GoTo Handler
Selection.Value = 123
Exit Sub
Handler:
MsgBox » Невозможно присвоить значение выделенному диапазону. »
End Sub
В процедуре предпринимается попытка присвоить значение текущему выделенному объекту. Если происходит ошибка (например, не выделен диапазон ячеек или лист защищен), то оператор присваивания выдает ошибку. Оператор On Error задает переход к метке Handler в случае ошибки. Обратите внимание, что перед меткой используется оператор Exit Sub. Программа обработки не выполняется, если ошибок не было.
Урок 7 по VBA — Процедуры
В отличии от языка VBScript, VBA процедуры классифицируются не на два типа (процедура-функция и процедура-подпрограмма), а четырех типов: процедура-функция, процедура-подпрограмма, процедура свойств и обработка событий. Также существуют некоторые дополнения в плане передачи параметров (по значению или по ссылке). Третьим моментом является область видимости – в VBA вызов процедуры может осуществляться как в пределах текущего модуля (макроса), так и за его пределами – во всех проектах. Все это обусловлено тем, что VBA – это не столько язык программирования, сколько программный пакет, с возможностью создания форм и проектов.
Давайте сначала кратко рассмотрим типы VBA процедур:
Подпрограммы – блоки кода заключенные в конструкцию Sub …. End Sub. Сама по себе подпрограмма не возвращает никакого значения, а просто выполняет прописанные в ней команды.
Функции – также блок кода, но прописанный в конструкцию Function … End Function. После выполнения функции возвращается определенное значение, доступ к которому можно получить через имя VBA функции.
Помимо этого, стоит упомянуть про обработку событий (нажатие кнопки клавиатуры или перемещение мыши) и доступ к объектам, но это отдельная тема.
VBA процедуры типа Sub – подпрограммы
После того как вы добавили в проект новый модуль, для объявления процедуры VBA нужно ее заключить в специальную конструкцию:
Sub ИмяПодпрограмм([аргументы])
Операторы
[Exit Sub]
операторы
End Sub
После ключевого слова Sub следует имя подпрограммы, в круглых скобках можно указывать или не указывать аргументы. Аргументы – это переменные (параметры), значение которых может обрабатываться, аргументы разделяются запятыми. Конструкция Exit Sub также не является обязательной, она говорит том, что нужно произвести выход из подпрограммы и продолжить выполнение кода, следующего после выражения End Sub.
Вызов VBA процедуры осуществляется с помощью ключевого слова call, например, Call MySub.
Давайте напишем простой пример: добавьте в проект новую форму и новый модуль. На поверхность формы добавьте два текстовых поля (TextBox), одну метку (Label) и одну кнопку (CommandButton). Создайте связь между формой и модулем, прописав в редакторе кода для модуля:
Я назвал форму SubForm, а модуль – SubModule, за имя отвечает свойство Name.
Теперь в редакторе кода для формы пропишите:
Тут все предельно просто, вначале мы объявили процедуру Hipotenuze, которой будут передаваться два аргумента, далее происходит проверка на нулевые значения. Вызов происходит при нажатии на кнопку, находящуюся на форме, параметрами будут значения, хранящиеся в текстовых полях TextBox1 и TextBox2. Результат отображается в метке Label1.
Вызов процедуры VBA может осуществляться и без использования ключевого слова Call, в таком случае, параметры не надо заключать в круглые скобки. Так же, при определении аргументов можно явно указать тип данных, например:
Sub MySub (a As Integer, b As String) … End Sub
Static – данное ключевое слово, прописанное перед ключевым словом Sub позволяет сохранять в памяти значения всех переменных после выполнения процедуры. Его мы рассматривали в с статье – переменные VBA.
ParamArray – данное ключевое слово позволяет передавать процедуре переменное количество параметров, оно может использоваться только для последнего элемента в списке аргументов.
ParamArray нельзя использовать вместе со словами ByRef, ByVal или Optional, например:
Как видим, мы фактически с помощью ParamArray показываем, что передаем массив, для его обработки мы использовали оператор For …. Each. Тут мы передали при вызове VBA процедуры пять параметров, при этом, первый будет храниться в аргументе a, а остальные в аргументе b, который обрабатывается как массив.
Optional – позволяет указать, что аргумент не является обязательным и одновременно задать значение по умолчанию.
В данном примере на поверхности формы находится всего одна метка и три кнопки. Каждая из кнопок будет производить VBA вызов процедуры MyArguments с различными значениями.
Передача параметров по ссылке и по значению – по умолчанию, при вызове процедуры все параметры ей передаются по ссылке. Передача по ссылке – в простом варианте, это передача адреса по которому хранится значение. При передаче параметра по ссылке, передается не адрес, а копия значения.
Что бы все стало понятно, рассмотрим следующий пример:
MySub1 – тут происходит объявление переменной MyVar и присвоение ей значения 100, далее в теле происходит вызов VBA процедуры MySumm1, ей в качестве параметры мы передаем значение переменной MyVar – 100. Сама процедура MySumm принимает значение по ссылке, на что указывает ключевое слово ByRef, к принятому значению прибавляется число 100. Стоит обратить внимание, что ByRef можно было и не писать. После VBA вызова процедуры MySumm1 происходит запись значения переменной MyVar в свойство Caption объекта Label1, в итоге, отобразится число 200.
MySub2 – аналог предыдущей процедуры, но тут происходит вызов MySumm2, в которой происходит передача параметров по значению, о чем говорит ключевое слово ByVal, в итоге, значение переменной MyVar не изменится.
VBA процедуры типа Function – функции
Пользовательским функциям языка VBA присущи практически те же правила, что и подпрограммам. Общая структура функции:
Function ИмяФункции ([аргументы]) [As ТипДанных]
Операторы
[Exit Function]
Операторы
[ИмяФункции=Выражение]
End Function
Видим, что тут при объявлении функции можно указать ее тип, данный тип будет содержать возвращаемое значение. Что бы функция возвращала значение, в конце нужно его присвоить переменной с именем функции, например:
Спасибо за внимание. Автор блога Владимир Баталий
Канал в Telegram
Вы здесь
Выполнение процедур в VBA
Ранее, с запуском процедур из меню «Макросы» мы уже сталкивались. Так же, мы уже назначали нашим процедурам горячие клавиши. Теперь поговорим о еще нескольких способах запуска процедур в VBA.
Выполнение процедур из пользовательского меню Excel
Этот способ позволяет нам создать свои элементы в пользовательских меню и назначить этим элементам макросы т.е. процедуры. Ниже приводится первый способ создания элемента меню и привязку к нему макроса. Данный способ использовать не предпочтительно т.к. отсутствует гибкость, при переходе на другую рабочую станцию (ПК) элементы придется создавать и настраивать повторно. Со вторым способом, а именно с программным созданием панелей меню и подключением их как надстройки, мы поговорим в следующих статьях, ну а для создания простенького меню из одного- двух элементов смотрим способ ниже.
Итак, допустим, нам необходимо запускать простенькую процедуру, которая возвращает: Имя пользователя и Текущие время и дату ПК в сообщении. Код процедуры:
Sub GetUserDate()
Dim msg As String
msg = «Пользователь: » & Environ(«UserName») & Chr(13) _
& «Текущая дата и время: » & Now
‘Environ(«UserName») возвращает имя текущего пользователя
‘ Now — возвращает дату и время ПК
MsgBox msg
End Sub
Для запуска этой процедуры из пользовательского меню, проделываем следующее:
1. Выберите команду Вид — Панели инструментов — Настройка. В открывшемся окне «Настройка«, перейдите на вкладку «Команды«, и в «Категории» найдите строчку «Макросы«
Обратите внимание. При открытом окне «Настройка», Вы можете изменить любой пункт меню, как панелей, так и выпадающих меню.
2. Перетащите методом Drag & Drop из списка «Команды«, элемент который называется «Настраиваемая команда меню«, в нижнюю часть меню «Данные«, расположив его после элемента «Обновить данные«.
3. Щелкните правой кнопкой мыши на новом пункте меню «Настраиваемая команда меню» и в контекстном меню, в поле Имя введите название пункта меню «&Имя пользователя и дата»
4. Теперь нам остается только связать нашу процедуру (макрос) с этим пунктом. Для этого, в контекстном меню настройки элемента «Настраиваемая команда меню» т.е. уже «Имя пользователя и дата», выбираем пункт «Назначить макрос» и выбираем нашу процедуру из списка:
Все. Жмем ОК и закрываем окно «Настройка». Тестируем, меню Данные — Имя пользователя и дата, получаем сообщение:
Примечание: Приведенные выше действия создают постоянный пункт меню, т.е. данный пункт будет отображаться во всех книгах, даже после закрытия книги содержащей макрос. В последующих статьях будет рассмотрено создание собственных меню только для определенной книги.
Выполнение процедуры из другой процедуры
Самый распространенный способ вызова (выполнения) процедуры это вызов процедуры из другой процедуры. Существует три способа вызова:
- Ввод названия процедуры и ее аргументы через запятую (если есть аргументы). Самый распространенный способ. В прошлых статьях мы уже вызывали таким способом процедуры, например «Создание расширенного списка выбора».
- Ввод ключевого слова Call, после, ввод названия процедуры и аргументов, только в этом случае, аргументы необходимо заключить в скобки.
- Вызов с использованием метода Run объекта Application. Этот способ можно применить и для выполнения других процедур VBA. С помощью метода Run можно выполнить процедуру, имя которой присвоено в переменной. В этом случае в метод Run переменная передается как аргумент.
Рассмотрим каждый способ на примерах. Для этого создадим в модуле с созданной ранее процедурой GetUserDate, вызывающую процедуру CallProc.
Способ 1.
Sub CallProc()
GetUserDate
End Sub
Способ 2.
Sub CallProc()
Call GetUserDate [арг_1, арг_2]
End Sub
Т.к. наша процедура GetUserDate не имеет входных аргументов, то вызываем ее без них. арг_1, арг_2 даны для примера. В правилах хорошего тона, вызов процедур правильнее делать вторым способом т.к. это явно указывает на вызов другой процедуры, но необязательно. Сознаюсь честно, сам ленивый и постоянно использую первый способ :).
Способ 3.
Этот способ требует особого внимания. Создадим процедуру, определяющую сегодняшний день недели и сообщающую нам в MsgBox, выходной сегодня или нет. Для этого создадим две процедуры, содержащие только сообщения:
Sub Работаем()
MsgBox «Пашем! Суббота еще не скоро!»
End Sub
Sub Отдыхаем()
MsgBox «Ура! Выходные!»
End Sub
И теперь добавим процедуру, которая определяет сегодняшний день недели и вызывает соответствующие процедуры с сообщением.
Dim SubToCall As String ‘переменная содержащая имя процедуры
Select Case Weekday(Now, vbMonday)
Case 1 To 5: SubToCall = «Работаем»
Case 6 To 7: SubToCall = «Отдыхаем»
End Select
Обратите внимание, имя вызываемой процедуры присваивается в текстовую переменную SubToCall в виде обычной текстовой строки. Функция Weekday определяет по текущей дате (которая возвращена встроенной функцией Now) день недели, который проверяется в Case-селекторе (по работе с Case читаем здесь ) и в соответствии с возращенным номером дня недели присваивает в переменную SubToCall строку, содержащую имя процедуры, которую необходимо вызвать. Далее в Application.Run передаем SubToCall как аргумент. Хочу обратить внимание на функцию Weekday — функция имеет еще второй необязательный параметр, который определяет, с какого дня недели вести счет дней. По умолчанию, счет ведется с воскресенья, поэтому константа vbMonday, в нашем примере, указывает функции, что счет необходимо начать с понедельника.
Вызов процедуры из другого модуля
VBA — язык не привередлив и снисходителен ко многим моментам, например, описание переменных (по этому поводу читайте здесь ). Тоже относится и к вызову процедур, содержащихся в разных модулях. Процедуры могут быть Public или Private (что это значит, можете ознакомиться в статье по области видимости переменных). Так вот, в случае с приватными процедурами, вызов их может происходить только в рамках общего модуля т.е. процедуры (вызываемая и вызывающая) должны находится в одном и том же модуле. Если же вызываемая процедура описана как Public, тогда она становится доступной, для вызывающих процедур, во всех модулях. В случае с Public возможно повторение имен процедур в разных модулях, но вот с вызовом будут проблемы, работа закончится с ошибкой Run-time error 1004: «Не найден макрос…» т.е. интерпретатор, в рамках всего проекта, нашел несколько доступных процедур с одинаковым именем, но не понял какую из них вызвать. Для того чтобы это избежать необходимо явно указать путь к данной процедуре. Это делается довольно просто и привычно для объектно-ориентированных языков, т.е. мы указываем название модуля, содержащего процедуру, ставим точку, и нам предлагается список всех доступных процедур (функций) или глобальных переменных. Например, Module2 содержит процедуру типа Public с именем Test. Для того чтобы ее вызвать из Module1 необходимо написать: Module2.Test.
Хочу отметить, что в больших проектах может содержаться не один десяток глобальных процедур, функций, переменных, к которым происходит обращение из различных модулей, и чтоб облегчить жизнь, себе и другим, указывайте всегда полный путь к процедуре, даже если эта процедура имеет уникальное имя.
Ну, а на этом все. В следующей статье еще захвачу один способ, это вызов процедур из других книг. А пока – пока!