Ссылки на 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 и обратная связь.
Передача параметров по значению (ByVal) и по ссылке (ByRef)
Итак, каждой процедуре присваивается уникальное название — имя процедуры. Кроме того, для процедуры четко устанавливается перечень входных и выходных аргументов (входных и выходных параметров). Прежде чем определять процедуру, необходимо четко представить, что процедура делает, что она должна получать в результате работы и какие результаты возвращать. Параметры, перечисляемые в скобках при описании процедуры, называются формальными параметрами (перед такими параметрами обязательно ставится ключевое слово ByVal или ByRef (тип вызова данного параметра) и после имени параметра указывается тип значений данного параметра). Параметры, которые указываются при вызове процедуры, называются фактическими. Таким образом передача параметров в процедуру из вызывающей процедуры может осуществляться двумя способами: по значению (ByVal) или по ссылке (ByRef). Обычно по значению передаются входные параметры, а по ссылке — выходные.
Входной параметр процедуры — это переменная, значение которой при вызове процедуры должно быть установлено до начала работы процедуры и который участвует в работе процедуры. Перед таким параметром ставится ключевое слово ByVal (передача по значению). В этом случае в процедуру передается не сама переменная, а ее копия. В момент вызова процедуры для хранения формального параметра в ней создается локальная переменная, которая получает копию значения фактического параметра, а после окончания работы процедуры эта локальная переменная уничтожается. Поэтому изменение формального параметра в процедуре не затрагивает фактический параметр, так как изменяется не сама переменная, а ее копия и таким образом все изменения, сделанные в переменной, переданной по значению, не передаются обратно в вызывающую процедуру.
Выходной параметр процедуры — это переменная, которая получает свое значение в результате работы процедуры. Использование ключевого слова ByRef указывает, что переменные должны быть переданы в процедуру по ссылке. Это значит, что процедура не создает локальную переменную под формальный параметр, а получает доступ к области памяти, в которой хранится фактический параметр, т.е. получает его адрес. Поэтому все изменения, сделанные в рамках процедуры, будут производиться прямо с теми же ячейками памяти, в которых хранится фактический параметр, и следовательно переданы обратно в вызывающий код.
При выборе способа передачи параметра (по ссылке или по значению) решающий критерий — может ли этот параметр изменять свое значение в процедуре.
Вот некоторые рекомендации о том, когда следует использовать ByVal. а когда — ByRef:
- • использовать ByVal тогда, когда требуется, чтобы процедура не изменяла передаваемую в нее через аргумент переменную;
- • использовать ByRef тогда, когда требуется разрешить процедуре изменять передаваемую в нее переменную;
- • когда сомневаетесь, используйте ключевое слово ByVal, так как в этом случае фактический параметр гарантированно не будет изменен в ходе выполнения процедуры.
Однако так как при передаче по значению происходит копирование объекта, данные большого объема (например, многомерные массивы) более эффективно передавать по ссылке.
Структуру программного кода, оператор присваивания и выражения мы уже разобрали. Для реализации алгоритмов линейной структуры необходимо знать, как может быть реализован в VB ввод исходных данных и вывод результатов.
Передача аргументов по значению и по ссылке (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, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Byval vba что это
Давайте посмотрим как определить событие выбора определной ячейки. Первое — это надо определить, что вообще что-то выбрали. Для этого создайте книгу. Запустите редактор VBA и щелкните на листе. Для данного листа будет создана функция SelectionChange, если ее нет, то у Вас всегда есть возможность ее выбрать. Теперь впишите код сообщения в функцию, чтобы увидеть, что происходит.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range) MsgBox Target.Address End Sub
У Вас теперь есть возможность щелкать по ячейкам конкретного листа, я еще раз повторяю и вы получите сообщение с адресом ячейки. Сообщение выбора ячейки обрабатывается локально. А что если у нас надо обрабатывать это сообшение с трех листов и желательно вместе. Для этого нужно создать модуль и в нем процедуру обработки. Я пока поместил туда просто вывод информационного окна.
Public Sub Selection_Cell(ByVal Addres As String, ByVal List As String) MsgBox Addres + " " + List End Sub
И соотвественно надо пересылать туда данный с каждого листа.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range) Selection_Cell Target.Address, Target.Worksheet.Name End Sub
Вот с этого момента можно вставлять вызов функции Selection_Cell на каждый лист в ответ на реакцию выделения.
Но это еще не все. Дело в том, что передается объект типа RANGE, то есть нет разницы передана одна ячейка или диапазон. Но при выделении диапазона внутрь него может попасть и наша ячейка. Итак, нам надо бы анализировать диапазон. Давайте договоримся, что нам надо обязательно отловить момент выделения ячейки $A$1. Вот на всех листах. У нас для этого все есть. Процедура общая, в которой есть адрес. И реакция на выделение на каждом листе. Смотрим код:
Public Sub Selection_Cell(ByVal Addres As String, ByVal List As String) On Error GoTo Ends Dim Test As Range Dim Find As Range Dim Result As Range Dim x As Integer Set Find = Range("$A$1") Set Test = Range(Addres) Set Result = Intersect(Test, Find) x = Result.Count MsgBox "$A$1" Ends: End Sub
Идея простая. Мы имеем переданный диапазон Test и нужный Find. Как узнать, что один включает другой . Вызовем операцию пересечения Intersect. Результатом будет диапазон, который содержит пересечение. Так вот если искомая нам ячейка в нем есть, то нормально, а если нет, то обращение к Count вызовет ошибку. Этим мы и воспользовались.