RSS

Выполнение процедур в 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. Теперь нам остается только связать нашу процедуру (макрос) с этим пунктом. Для этого, в контекстном меню настройки элемента «Настраиваемая команда меню» т.е. уже «Имя пользователя и дата», выбираем пункт «Назначить макрос» и выбираем нашу процедуру из списка:

назначить макрос, пункт в меню Excel

Все. Жмем ОК и закрываем окно «Настройка». Тестируем, меню Данные — Имя пользователя и дата, получаем сообщение:

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

Выполнение процедуры из другой процедуры

Самый распространенный способ вызова (выполнения) процедуры это вызов процедуры из другой процедуры. Существует три способа вызова:

  1. Ввод названия процедуры и ее аргументы через запятую (если есть аргументы). Самый распространенный способ. В прошлых статьях мы уже вызывали таким способом процедуры, например «Создание расширенного списка выбора».
  2. Ввод ключевого слова Call, после, ввод названия процедуры и аргументов, только в этом случае, аргументы необходимо заключить в скобки.
  3. Вызов с использованием метода 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

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

Sub GetWeekDay()
 
 Dim SubToCall As String ‘переменная содержащая имя процедуры

   Select Case Weekday(Now, vbMonday)
     Case 1 To 5: SubToCall = «Работаем»
     Case 6 To 7: SubToCall = «Отдыхаем»
   End Select
   
   Application.Run SubToCall
   
End Sub

Обратите внимание, имя вызываемой процедуры присваивается в текстовую переменную  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.

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

Ну, а на этом все. В следующей статье еще захвачу один способ, это вызов процедур из других книг. А пока – пока!