VBA не так прост и прост, как думают многие люди (в основном те, кто считает его забавным языком сценариев, написанным wanna-be-developers). Иногда он позволяет писать ByVal
, но он следует своим собственным правилам и принимает аргумент ByRef
, просто чтобы успокоить вас и убедиться, что вы не допустите ошибки.
Увидел ответ от @tigeravatar здесь, и я решил не писать под ним комментарий, а объяснить в другом посте, почему он неправильный и опасный, поскольку объяснять его как комментарий было бы сложно.
Если вы попытаетесь написать Stop
строку здесь из ответа:
Sub Macro1()
'Declare variables
Dim ws1 As Worksheet
Dim ws2 As Worksheet
'Assign variables to worksheet objects
Set ws1 = Worksheets(4)
Set ws2 = Worksheets(8)
'Call the second sub and pass the worksheet variables to it
Call Macro2(ws1, ws2)
End Sub
Sub Macro2(ByVal arg_ws1 As Worksheet, ByVal arg_ws2 As Worksheet)
'Reference the accepted arguments (in this case worksheet variables) directly:
MsgBox arg_ws1.Name
Stop
MsgBox arg_ws2.Name
'This will result in an error because you're using the passed argument incorrectly:
MsgBox ActiveWorkbook.Sheets(arg_ws1).Name '<-- Results in error
End Sub
Запустите ответ и дождитесь окончания строки:
![enter image description here](https://i.stack.imgur.com/6utxB.png)
Если arg_ws1
был взят Val, то, если кто-то меняет имя 8-го рабочего листа, в то время как Stop
горит, тогда оно все равно должно принять старое имя. Это ByVal
, помнишь? Ну, давай и смени имя. Затем продолжите с F5 . Какое имя ты получаешь? Зачем?
Ответ из-за способа вызова Sub с круглыми скобками в аргументах. Эти силы ByVal
и игнорируют все, что написано явно.