Procedimentos: passando argumentos por valor e por referência
Uma dúvida muito comum entre usuários do VBA é com relação a
alguns termos encontrados em alguns eventos com parâmetros: ByRef e ByVal. O que significam isso e qual o seu resultado? ByRef e ByVal indicam se o parâmetro será passado por referência ou por valor,
respectivamente.
Explicando melhor: se o parâmetro for passado com ByRef, o VBA usará a referência original
da variável no processamento, ou seja, se o valor for alterado na sub-rotina ou
função, a variável original passada como argumento também terá seu valor
alterado. Caso o parâmetro for passado com ByVal,
a sub-rotina ou função receberá uma cópia do valor e quaisquer alterações não
terão impacto na variável original.
Para entender isso de uma maneira mais prática, vejamos um
código simples de exemplo:
Sub Teste()
Dim X As Integer
X = 10
Debug.Print
"Valor de X = " & X
Debug.Print
"Resultado de Dobro = " & Dobro(X)
Debug.Print
"Valor de X = " & X
End Sub
Function Dobro(ByRef Valor As Integer) As Integer
Valor = Valor * 2
Dobro = Valor
End Function
A sub-rotina Teste
associa um valor à variável X, mostra
seu resultado, mostra o resultado da função Dobro
e depois mostra o resultado de X
novamente após a função Dobro ter
sido executada. Note que o parâmetro Valor
na função Dobro foi passada como
referência (ByRef), ou seja, qualquer
alteração feita em Valor irá refletir
na variável original. Executando o código temos o seguinte resultado na área de
Verificação imediata:
Valor de X = 10
Resultado de Dobro = 20
Valor de X = 20
Como podemos ver, a variável X mudou de valor após ter sido
referenciada na função Dobro. Altere
a função para ByVal conforme abaixo:
Function Dobro(ByVal Valor As Integer) As Integer
Agora execute novamente a sub-rotina Teste e veja o resultado:
Valor de X = 10
Resultado de Dobro = 20
Valor de X = 10
Agora o valor de X
não sofreu alterações e se manteve intacto, pois foi usada uma cópia do valor
de X, não a referência original da
variável.
E se não for informado ByRef
ou ByVal, qual é a forma padrão que o
Excel utiliza? Simples de descobrir: retire da função Dobro, deixando sem
especificação se é ByRef ou ByVal e veja o resultado:
Valor de X = 10
Resultado de Dobro = 20
Valor de X = 20
O padrão no VBA é ByRef,
ou seja, utilizará a variável original passada como argumento. Isto não é um
problema se você não edita o valor do parâmetro na função ou na sub-rotina, mas
pode causar problemas se você altera o valor desse parâmetro.
E como funciona com objetos? Será que é do mesmo jeito?
Antes de conferir isso, precisamos de entender que objetos são tratados de
forma diferente. Por exemplo, quando vamos associar uma célula a uma variável
do tipo Range precisamos usar Set antes da associação, como abaixo:
Set Celula = Range("A1")
Da mesma forma, uma sub-rotina ou função que usa um objeto
como parâmetro é escrita de forma distinta. Há três maneiras de fazer a
chamada: usando Call, omitindo os
parênteses ou ainda especificando os parâmetros. Vejamos as três formas abaixo:
Call Dobro(Celula)
Dobro Celula
Dobro Intervalo:=Celula
As três formas funcionam da mesma maneira, utilize aquela
que achar melhor.
Agora vejamos o código para ver como funciona ByRef e ByVal
com objetos:
Sub Teste()
Dim Celula As Range
Set Celula =
Range("A1")
Debug.Print
"Valor da célula A1 = " & Celula.Value
Dobro Celula
Debug.Print
"Valor da célula A1 = " & Celula.Value
End Sub
Function Dobro(ByRef Intervalo As Range) As Range
Debug.Print
"Valor do intervalo recebido = " & Intervalo.Value
Intervalo.Value =
Intervalo.Value * 2
Debug.Print
"Valor do intervalo após o processamento = " & Intervalo.Value
End Function
Coloque na célula A1 o valor 10 e efetue o teste. A saída será
a seguinte:
Valor da célula A1 = 10
Valor do intervalo recebido = 10
Valor do intervalo após o processamento = 20
Valor da célula A1 = 20
O valor da célula A1 passou a ser 20. Como vimos, ByRef passa a referência e por isso tudo
funcionou como esperado. Altere a função para tratar o parâmetro por valor,
substituído ByRef por ByVal, coloque o valor 10 novamente na
célula A1 e teste. Vejamos o resultado:
Valor da célula A1 = 10
Valor do intervalo recebido = 10
Valor do intervalo após o processamento = 20
Valor da célula A1 = 20
O resultado foi exatamente o mesmo. Por que isso acontece?
No VBA (e em outras linguagens de programação) os objetos são sempre passados
como referência, ou seja, qualquer alteração feita irá refletir no objeto usado
como parâmetro. Portanto, não importa se o objeto está acompanhado de ByVal, o resultado será como ByRef.
Pedro Martins
Formado em Tecnologia em Eletrônica Digital, já trabalhou como artefinalista, eletrotécnico, programador de CLP (para máquinas industriais) e analista de sistemas em sistema bancário, programando em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.
Nenhum comentário