Полное руководство по VBA Sub

В этом посте представлено полное руководство по использованию VBA Sub.

Если вам нужна краткая информация о создании VBA Sub, функции, передаче параметров, возвращаемых значениях и т. д., ознакомьтесь с кратким руководством ниже.

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

Краткое руководство по VBA Sub

SubПример
Sub
Невозможно вернуть значение.
Function
Может возвращать значение или объект.
Может выполняться как функция рабочего листа.
Создание процедуры SubSub ТотСамыйКод()

End Sub
Создание функцииFunction Итог() As Long

End Function
Создание процедуры Sub с оглашением параметровSub ТотСамыйКод(ByVal Цена As Double)
Sub ТотСамыйКод(ByVal Имя As String)
Создание процедуры Function с оглашением параметровFunction Итог(Цена As Double)
Function Итог(Имя As String)
Вызов процедуры SubCall MySub
MySub
Вызов процедуры FunctionCall GetTotal
GetTotal
Вызов процедуры Sub с указанием параметровCall MySub(12.99)
MySub 12.99
Вызов процедуры Function с указанием параметровCall GetTotal(12.99)
GetTotal 12.99
Вызов процедуры Function и получение значения в переменную
(для этого нельзя использовать ключевое слово Call)
Price = GetTotal
Вызов функции и получение объектаSet coll = GetCollection
Вызов функции с параметрами и получение значения/объектаPrice = GetTotal(12)
Set coll = GetCollection(“Apples”)
Возврат значения из функцииFunction GetTotal() As Long
    GetTotal = 67
End Function
Возвращение объекта из функцииFunction GetCollection() As Collection
    Dim coll As New Collection
    Set GetCollection = coll
End Function
Выход из процедуры SubIf IsError(Range(“A1”)) Then
     Exit Sub
End If
Выход из процедуры Function If IsError(Range(“A1”)) Then
     Exit Function
End If
Частная подфункция/частная функция
(доступна для текущего модуля)
Private Sub MySub()
Private Function GetTotal()
Публичная подфункция/публичная функция
(доступно для всего проекта)
Public Sub MySub()
Public Function GetTotal()

Введение

VBA Sub – это важный компонент языка VBA. Вы также можете создавать функции, которые очень похожи на sub. Они обе являются процедурами, в которых вы пишете свой код. Однако есть и различия, и их важно понимать. В этой заметке мы подробно рассмотрим subs и functions и ответим на важные вопросы, в том числе:

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

Давайте начнем с того, что рассмотрим, что такое подфункция в VBA?

Что такое подфункция?

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

Подпрограмма/макрос – это место, куда вы помещаете строки кода VBA. Когда вы запускаете подпрограмму, выполняются все содержащиеся в ней строки кода. Это означает, что VBA выполняет их инструкции.

Ниже приведен пример пустого вложенного файла

Sub Exmpl()

End Sub

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

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

Конец Sub обозначается строкой End Sub.

Когда вы создадите Sub, вы можете добавить некоторый код, как показано в следующем примере:

Sub Exmpl()
    Range("A1") = 6
End Sub

Что такое функция?

Функция очень похожа на подфункцию. Основное отличие заключается в том, что функция может возвращать значение, а подфункция – нет. Есть и другие различия, которые мы рассмотрим, но это главное.

Обычно вы создаете функцию, когда хотите вернуть значение.

Создание функции аналогично созданию подфункции

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

В следующем примере показано, как указать возвращаемый тип

Function PerformCalc() As Long

End Function

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

Вызов подфункции или функции

Когда люди только начинают работать с VBA, они стремятся поместить весь код в одну подфункцию. Это не лучший способ написания кода.

Лучше разбить код на несколько процедур. Мы можем запускать одну процедуру из другой.

Вот пример:

Sub Main()
    ' вызывать каждую процедуру для выполнения какого-то задания
    CopyData
    AddFormulas
    FormatData
End Sub

Sub CopyData()
    ' Тут какой-то код
End Sub

Sub AddFormulas()
    ' Тут какой-то код
End Sub

Sub FormatData()
    ' Тут какой-то код
End Sub

На самом деле в VBA существует ключевое слово Call. Мы можем использовать его следующим образом:

Sub Main()
    Call CopyData
    Call AddFormulas
    Call FormatData
End Sub

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

Если вы передаете аргументы с помощью Call, то вы должны использовать круглые скобки вокруг них.

Например:

Sub Main()
    ' Если вызов не используется, то скобки не нужны
    AddValues 2, 4
    ' вызов требует круглых скобок для аргументов
    Call AddValues(2, 4)
End Sub

Sub AddValues(x As Long, y As Long)

End Sub

Как вернуть значение из функции

Чтобы вернуть значение из функции, нужно присвоить значение имени функции. Следующий пример демонстрирует это:

Function GetAmount() As Long
    ' Возвращает 55
    GetAmount = 55
Конец функции

Function GetName() As String
    ' Возвращает "Привет, мир!"
    GetName = "Привет, мир!"
End Function

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

Sub WriteValues()
    Dim Amount As Long
    ' Получение значения из функции GetAmount
    Amount = GetAmount
End Sub
Function GetAmount() As Long
    GetAmount = 55
End Function

Вы можете легко проверить возвращаемое значение с помощью функции Debug.Print. Она запишет значения в окно Immediate Window (View->Immediate window из меню или нажмите Ctrl + G).

Sub WriteValues()
    ' Печать возвращаемого значения в окне Immediate Window
    Debug.Print GetAmount
End Sub

Function GetAmount() As Long
    GetAmount = 55
End Function

Использование параметров и аргументов

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

Термины “параметры” и “аргументы” часто путают:

Параметр – это переменная в объявлении подфункции/функции.
Аргумент – это значение, которое вы передаете параметру.

Sub UsingArgs()
    ' Аргументом является 56
    CalcValue 56
    ' Аргумент равен 34
    CalcValue 34
End Sub


Sub CalcValue(ByVal amount As Long)

End Sub

Вот несколько важных моментов о параметрах:

У нас может быть несколько параметров.
Параметр передается с помощью ByRef или ByVal. По умолчанию используется ByRef.
Мы можем сделать параметр необязательным для пользователя.
Мы не можем использовать ключевое слово New в объявлении параметра.
Если тип переменной не используется, то параметр по умолчанию будет вариантом.

Формат параметров

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

Формат оператора параметров следующий:

' Все переменные, кроме массивов
[ByRef/ByVal] As [Тип переменной]
' Необязательный параметр - может быть только базового типа
[Необязательный] [ByRef/ByVal] [Имя переменной] As <[Тип переменной] =
' Массивы
[ByRef][имя массива]() As [Тип переменной].

Вот несколько примеров объявления различных типов параметров:


‘ Основные типы

Sub UseParams1(count As Long)
End Sub
Sub UseParams2(name As String)
End Sub
Sub UseParams3(amount As Currency)
End Sub
' Коллекция
Sub UseParamsColl(coll As Collection)
End Sub
' Объект модуля класса
Sub UseParamsClass(o As Class1)
End Sub
' Вариант
' Если тип не указан, то это автоматически вариант
Sub UseParamsVariant(value)
End Sub
Sub UseParamsVariant2(value As Variant)
End Sub
Sub UseParamsArray(arr() As String)
End Sub

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

Множественные параметры

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

Sub LongLine(ByVal count As Long, Optional amount As Currency = 56.77, Optional name As String = "John")

Мы можем разделить строку кода с помощью символа подчеркивания (_). Это делает наш код более читабельным

Sub LongLine(ByVal count As Long _
             , Optional amount As Currency = 56.77 _
             , Optional name As String = "John")

Параметры с возвращаемым значением

Эта ошибка вызывает много разочарований у начинающих пользователей VBA.

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

Приведенный ниже код выдаст синтаксическую ошибку “Expected: end of statement”.

Sub UseFunction()
    Dim result As Long
    result = GetValue 24.99
End Sub

Function GetValue(amount As Currency) As Long
    GetValue = amount * 100
End Function

Мы должны написать это следующим образом

result = GetValue (24.99)

ByRef и ByVal

Каждый параметр является либо ByRef, либо ByVal. Если тип не указан, то по умолчанию это ByRef.

' Передача по значению
Sub WriteValue1(ByVal x As Long)
End Sub
' Передача по ссылке
Sub WriteValue2(ByRef x As Long)
End Sub
' Тип не используется, поэтому это ByRef
Sub WriteValue3(x As Long)
End Sub

Если вы не указали тип, то типом будет ByRef, как вы можете видеть в третьем примере.

Разница между этими типами заключается в следующем:

ByVal – создает копию переданной вам переменной.
Это означает, что если вы измените значение параметра, то оно не изменится при возвращении в вызывающую подфункцию/функцию.

ByRef – Создает ссылку на передаваемую переменную.
Это означает, что если вы измените значение переменной параметра, оно будет изменено при возвращении к вызывающей подфункции.

Следующий пример кода показывает это:

Sub Test()
    Dim x As Long
    ' Передача по значению - x не изменится
    x = 1
    Debug.Print "x before ByVal is"; x
    SubByVal x
    Debug.Print "x after ByVal is"; x
    ' Передача по ссылке - x изменится
    x = 1
    Debug.Print "x before ByRef is"; x
    SubByRef x
    Debug.Print "x после ByRef is"; x
End Sub
Sub SubByVal(ByVal x As Long)
    ' x НЕ ИЗМЕНЯЕТСЯ вне переданного значения ByVal
    x = 99
End Sub
Sub SubByRef(ByRef x As Long)
    ' x БУДЕТ изменяться снаружи по мере передачи ByRef
    x = 99
End Sub

Результатом этого является:
x до ByVal равен 1
x после ByVal равен 1
x перед ByRef равен 1
x после ByRef равен 99

Вам следует избегать передачи базовых типов переменных с помощью ByRef. Для этого есть две основные причины:

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

В качестве заключения

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

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Добавить комментарий