Ссылки на ByVal в Microsoft Forms
Ключевое слово ByVal в Microsoft Forms указывает, что аргумент передается в качестве значения; это стандартное значение ByVal в Visual Basic. Однако в Microsoft Forms можно использовать ByVal с объектом ReturnBoolean, ReturnEffect, ReturnInteger или ReturnString. В этом случае передаваемое значение не относится к простому типу данных, а является указателем на объект.
При использовании с такими объектами ByVal ссылается на объект, а не на параметры метода передачи. Каждый из перечисленных ранее объектов имеет свойство Value , которое можно задать. Вы также можете передавать это значение в функцию и из нее. Поскольку вы можете изменять значения элементов объекта, события приводят к результатам, соответствующим поведению ByRef, хотя в синтаксисе события указано, что используется параметр ByVal.
Назначение значения аргументу, связанному с ReturnBoolean, ReturnEffect, ReturnInteger или ReturnString , ничем не отличается от задания значения любого другого аргумента. Например, если синтаксис события указывает, что аргумент Cancel используется с объектом ReturnBoolean , инструкция по-прежнему действительна, как и для других типов данных.
См. также
- Контексты ключевых слов
- Справочник по Microsoft Forms
- Темы по основам Microsoft Forms
Поддержка и обратная связь
Есть вопросы или отзывы, касающиеся Office VBA или этой статьи? Руководство по другим способам получения поддержки и отправки отзывов см. в статье Поддержка Office VBA и обратная связь.
Передача аргументов по значению и по ссылке (Visual Basic)
В Visual Basic можно передать аргумент в процедуру по значению или по ссылке. Это называется механизмом передачи и определяет, может ли процедура изменить программный элемент, лежащий в основе аргумента в вызывающем коде. Объявление процедуры определяет механизм передачи для каждого параметра, указывая ключевое слово ByVal или ByRef.
Различия
При передаче аргумента в процедуру следует учитывать несколько различий, которые взаимодействуют друг с другом:
- Является ли базовый программный элемент изменяемым или неизменяемым
- Указывает, является ли сам аргумент изменяемым или неизменяемым
- Указывает, передается ли аргумент по значению или по ссылке
- Тип данных аргумента является типом значения или ссылочным типом
Выбор механизма передачи
Для каждого аргумента следует тщательно выбирать механизм передачи.
- Защита. При выборе между двумя механизмами передачи наиболее важным критерием является возможность изменения вызывающих переменных. Преимущество передачи аргумента ByRef заключается в том, что процедура может возвращать значение в вызывающий код через этот аргумент. Преимущество передачи аргумента ByVal заключается в том, что он защищает переменную от изменения процедурой.
- Производительность. Хотя механизм передачи может повлиять на производительность кода, разница обычно незначительна. Одним из исключений из этого является переданный ByVal тип значения . В этом случае Visual Basic копирует все содержимое аргумента . Таким образом, для большого типа значения, такого как структура, может быть эффективнее передать его ByRef . Для ссылочных типов копируется только указатель на данные (четыре байта на 32-разрядных платформах и восемь байтов на 64-разрядных платформах). Поэтому можно передавать аргументы типа String или Object по значению без ущерба для производительности.
Определение механизма передачи
Объявление процедуры задает механизм передачи для каждого параметра. Вызывающий код не может переопределить ByVal механизм.
Если параметр объявлен с ByRef параметром , вызывающий код может принудительно принудить механизм к ByVal , заключив имя аргумента в круглые скобки в вызове . Дополнительные сведения см. в разделе Практическое руководство. Принудительная передача аргумента по значению.
По умолчанию в Visual Basic аргументы передаются по значению.
Время передачи аргумента по значению
- Если вызывающий элемент кода, лежащий в основе аргумента, является неизменяемым элементом, объявите соответствующий параметр ByVal. Никакой код не может изменить значение неизменяемого элемента.
- Если базовый элемент является изменяемым, но вы не хотите, чтобы процедура могла изменять свое значение, объявите параметр ByVal . Только вызывающий код может изменить значение изменяемого элемента, передаваемого по значению.
Время передачи аргумента по ссылке
- Если процедуре действительно необходимо изменить базовый элемент в вызывающем коде, объявите соответствующий параметр ByRef.
- Если правильное выполнение кода зависит от процедуры изменения базового элемента в вызывающем коде, объявите параметр ByRef . Если передать его по значению или вызывающий код переопределяет ByRef механизм передачи, заключив аргумент в круглые скобки, вызов процедуры может привести к непредвиденным результатам.
Пример
Описание
В следующем примере показано, когда следует передавать аргументы по значению, а когда передавать их по ссылке. В процедуре Calculate ByVal есть параметр и ByRef . Учитывая процентную ставку rate и сумму денег, задача процедуры состоит в том, debt чтобы вычислить новое значение для debt , которое является результатом применения процентной ставки к исходному значению debt . Так как debt является параметром ByRef , новое итоговое значение отражается в значении аргумента в вызывающем коде, соответствующему debt . Параметр rate является параметром, ByVal так как Calculate не должен изменять его значение.
Код
Module Module1 Sub Main() ' Two interest rates are declared, one a constant and one a ' variable. Const highRate As Double = 12.5 Dim lowRate = highRate * 0.6 Dim initialDebt = 4999.99 ' Make a copy of the original value of the debt. Dim debtWithInterest = initialDebt ' Calculate the total debt with the high interest rate applied. ' Argument highRate is a constant, which is appropriate for a ' ByVal parameter. Argument debtWithInterest must be a variable ' because the procedure will change its value to the calculated ' total with interest applied. Calculate(highRate, debtWithInterest) ' Format the result to represent currency, and display it. Dim debtString = Format(debtWithInterest, "C") Console.WriteLine("What I owe with high interest: " & debtString) ' Repeat the process with lowRate. Argument lowRate is not a ' constant, but the ByVal parameter protects it from accidental ' or intentional change by the procedure. ' Set debtWithInterest back to the original value. debtWithInterest = initialDebt Calculate(lowRate, debtWithInterest) debtString = Format(debtWithInterest, "C") Console.WriteLine("What I owe with low interest: " & debtString) End Sub ' Parameter rate is a ByVal parameter because the procedure should ' not change the value of the corresponding argument in the ' calling code. ' The calculated value of the debt parameter, however, should be ' reflected in the value of the corresponding argument in the ' calling code. Therefore, it must be declared ByRef. Sub Calculate(ByVal rate As Double, ByRef debt As Double) debt = debt + (debt * rate / 100) End Sub End Module
См. также раздел
- Процедуры
- Параметры и аргументы процедуры
- Практическое руководство. Передача аргументов в процедуру
- Практическое руководство. Изменение значения аргумента процедуры
- Практическое руководство. Защита аргумента процедуры от изменений значения
- Практическое руководство. Принудительная передача аргумента по значению
- Передача аргументов по позиции и по имени
- Типы значений и ссылочные типы
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
VBA-Урок 9. Процедуры и функции
На данный момент, все процедуры, мы создавали, имеют тип Public , что означает, что они доступны из любого модуля.
Sub example() 'Идентична к: Public Sub example()
Чтобы сделать процедуру доступной только в определенном модуле, используется ключевое слово Private:
Private Sub example()
Запуск процедуры с середины другой процедуры
Чтобы выполнить процедуру с середины другой процедуры, просто введите ее название.
Здесь есть очень простой пример:
Private Sub warning() MsgBox "Caution . " End Sub Sub macro_test() If Range("A1") = "" Then warning '
Аргументы
Аргументы делают возможным использование значений из процедуры в под-процедуры (запомните, что по умолчанию, переменные являются доступны только по той процедуры, в которой они были объявлены).
Private Sub warning(var_text As String) MsgBox "Caution : " & var_text & " !" End Sub Sub macro_test() If Range("A1") = "" Then warning "пустая ячейка" ElseIf Not IsNumeric(Range("A1")) Then warning "нецифровое значение" End If End Sub
К процедуре "warning" был добавлен аргумент, в данном случае это переменная "var_text" с типом "String" (строка):
Private Sub warning(var_text As String)
Эта процедура требует аргумент, поэтому мы должны поставить значение после "warning", чтобы выполнить ее:
warning "пустая ячейка"
Когда мы хотим прописать несколько аргументов, тогда они должны быть отделены запятыми.
Необязательные аргументы
По умолчанию, если процедура имеет аргументы, то они должны быть обязательно проставлены, и если они не проставлены, тогда процедура не выполнится.
Необязательный аргумент может быть добавлен после обязательного, с помощью ключевого слова Optional . Например:
Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age)
Теперь эта процедура может быть выполнена с или без опционального аргумента, как здесь:
'Пример 1: отображаем фамилию: dialog_boxes last_name1 'Пример 2: отображаем фамилию и имя: dialog_boxes last_name1, first_name1 'Пример 3: отображаем фамилию и возраст: dialog_boxes last_name1, , age1 'Пример 4: отображаем фамилию, имя и возраст: dialog_boxes last_name1, first_name1, age1
Аргументы должны быть введены в правильном порядке.
Чтобы протестировать, присутствует ли опциональный аргумент в процедуре, мы используем функцию IsMissing . Эта функция совместима только с некоторыми типами функций (типа Variant) и это является решающим, так как тип необязательно аргументов не был указан в объявлении (необъявленный тип = Variant).
Здесь есть пример, который использует два фрагмента кода, которые рассматривались выше:
Sub macro_test() Dim last_name1 As String, first_name1 As String, age1 As Integer last_name1 = Range("A1") first_name1 = Range("B1") age1 = Range("C1") 'Пример 1: отображаем фамилию: dialog_boxes last_name1 'Пример 2: отображаем фамилию и имя: dialog_boxes last_name1, first_name1 'Пример 3: отображаем фамилию и возраст: dialog_boxes last_name1, , age1 'Пример 4: отображаем фамилию, имя и возраст: dialog_boxes last_name1, first_name1, age1 End Sub Private Sub dialog_boxes(last_name As String, Optional first_name, Optional age) If IsMissing(age) Then 'Если переменная age отсутствует. If IsMissing(first_name) Then 'Если переменная first_name отсутствует, тогда 'будет отображаться только фамилия MsgBox last_name Else 'В противном случае, будет отображаться фамилия и имя MsgBox last_name & " " & first_name End If Else 'Если переменная age присутствует. If IsMissing(first_name) Then 'Если переменная first_name отсутствует, тогда 'будет отображено фамилию и возраст MsgBox last_name & ", " & age & " лет" Else 'В противном случае будет отображено фамилию, имя и возраст MsgBox last_name & " " & first_name & ", " & age & " лет" End If End If End Sub
См. рисунок ниже (пример 1):

ByRef - ByVal
По умолчанию, аргументы имеют тип ByRef , что означает: если переменная передается как аргумент, ссылка на нее будет также передаваться. Иными словами, если переменная была изменена другой под-процедурой, то она также будет изменена во внешней процедуре, которая вызывает эту под-процедуру.
Sub macro_test() Dim var_number As Integer var_number = 30 calcul_square var_number MsgBox var_number End Sub Private Sub calcul_square(ByRef var_value As Integer) 'ByRef не обязательно указывать '(является значением по умолчанию) var_value = var_value * var_value End Sub
Чтобы стало понятнее, ниже есть пример того, что произойдет, если макрос будет запущен на выполнение:
var_number = 30 'Начальное значение переменной "var_number" є 30 calcul_square var_number 'Под-процедура запускается с "var_number" как аргумент Private Sub calcul_square(ByRef var_value As Integer) 'Переменная "var_value" в некоторой степени служит для быстрого доступа к переменной "var_number", 'что означает, что если переменная "var_value" изменена, переменная "var_number" будет также изменена "(и они не должны обязательно иметь одинаковое имя) var_value = var_value * var_value 'Значение переменной "var_value" изменено (и поэтому "var_number" также одновременно изменено) End Sub 'Конец под-процедуры MsgBox var_number 'Переменная "var_number" была изменена, поэтому 900 будет сейчас отображено в диалоговом окне
Второй метод заключается в использовании ByVal .
В отличие от ByRef , который передает ссылки (ярлык), ByVal передает значение, которое означает, что значение передано как аргумент не было изменено.
Ниже вы можете увидеть как предыдущий код и ByVal работают:
var_number = 30 'Начальное значение переменной "var_number" есть 30 calcul_square var_number 'Под-процедура запускается с "var_number" как аргумент Private Sub calcul_square (ByVal var_value As Integer) 'Переменная "var_value" копирует значение переменной "var_number" (2-е переменные не являются связанными) var_value = var_value * var_value 'Значение переменной "var_value" изменено End Sub 'Конец под-процедуры (в этом примере под-процедура не имеет никакого влияния ни на что) MsgBox var_number 'Переменная "var_number" не была изменена, и поэтому 30 будет отображено в диалоговом окне
Что вам нужно запомнить: используйте ByVal когда переменная не должна быть изменена .
Функции
Основным отличием между процедурой и функцией является то, что функция возвращает значение.
Вот простой пример:
Function square(var_number) square = var_number ^ 2 'Функция "square" возвращает значение "корень квадратный" End Function Sub macro_test() Dim result As Double result = square(9.876) 'Переменной result присваивается значение, которое было рассчитано функцией MsgBox result 'Отображается результат (в данном случае квадрат для 9.876) End Sub
Функция может быть использована на рабочем листе, подобно любой другой функции в Excel.
Например, чтобы получить квадрат значения, которое введенное в ячейку A1:
ByVal (Visual Basic)
Указывает, что аргумент передается по значению, поэтому вызываемая процедура или свойство не может изменить значение переменной, лежащей в основе аргумента в вызывающем коде. Если модификатор не указан, по умолчанию используется ByVal.
Так как используется по умолчанию, не нужно явно указывать ByVal ключевое слово в сигнатурах методов. Он, как правило, создает шумный код и часто приводит к тому, что ключевое слово не по умолчанию ByRef игнорируются.
Комментарии
Модификатор ByVal можно использовать в следующих контекстах:
Пример
В следующем примере демонстрируется использование механизма передачи ByVal параметров с аргументом ссылочного типа. В примере аргументом является c1 экземпляр класса Class1 . ByVal запрещает коду в процедурах изменять базовое значение ссылочного аргумента , c1 но не защищает доступные поля и свойства c1 .
Module Module1 Sub Main() ' Declare an instance of the class and assign a value to its field. Dim c1 As New Class1() c1.Field = 5 Console.WriteLine(c1.Field) ' Output: 5 ' ByVal does not prevent changing the value of a field or property. ChangeFieldValue(c1) Console.WriteLine(c1.Field) ' Output: 500 ' ByVal does prevent changing the value of c1 itself. ChangeClassReference(c1) Console.WriteLine(c1.Field) ' Output: 500 Console.ReadKey() End Sub Public Sub ChangeFieldValue(ByVal cls As Class1) cls.Field = 500 End Sub Public Sub ChangeClassReference(ByVal cls As Class1) cls = New Class1() cls.Field = 1000 End Sub Public Class Class1 Public Field As Integer End Class End Module
См. также раздел
- Удалить ByVal (правило стиля IDE0081)
- Ключевые слова
- Передача аргументов по значению и по ссылке
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
The .NET documentation is open source. Provide feedback here.
Обратная связь
Отправить и просмотреть отзыв по
