Excel
– VBA: Passagem de Parâmetros por Valor e por Referência
Neste tutorial apresentarei informações e exemplos
detalhados sobre um dos pontos que mais causa dúvidas aos
programadores VBA no Excel:
Passagem
de parâmetros para funções e procedimentos
Você verá, detalhadamente, as diferenças entre
a passagem de parâmetros por valor (ByVal) e por referência
(ByRef).
Pré-requisitos: Para acompanhar esta lição
você deve dominiar os conceitos apresentados nos seguintes
treinamentos:
"Curso
de Excel Básico" e no
"Curso
de Excel Avançado e VBA".
Nota: Este tutorial faz parte do Curso de Programação
VBA e Criação de Aplicativos no Excel, que terá
cerca de 650 páginas e estará disponível para
aquisição no formato de arquivo .PDF a partir de 15
de Dezembro.
Passagem de parâmetros no VBA:
Você já sabe que ao declarar uma função
ou procedimento, é possível declarar um ou mais argumentos.
Ao utilizar uma função ou procedimento, você
deve informar os valores para os argumentos, na mesma ordem em que
foram definidos durante a declaração da função
ou procedimento. Este processo é conhecido como passagem
de parâmetros para a função ou procedimento,
ou seja, ao chamar a função ou procedimento, passamos
valores que serão utilizados pelo código da função
ou procedimento.
Existem duas maneiras diferentes de fazer a passagem dos parâmetros
e é importante para o programador, entender exatamente a
diferença entre estas duas maneiras:
Passagem por Valor - ByVal
Passagem por Referência - ByRef
Este conceito é muito importante e vamos entendê-lo
através de alguns exemplos simples. Inicialmente vamos ver
o que acontece quando utilizamos o tipo de passagem padrão,
que é o tipo ByVal, onde apenas o valor do parâmetro
é passado para a função/procedimento.
Passagem de parâmetros por Valor –
ByVal:
Este é o método padrão, ou seja, ao declarar
os argumentos de uma função/procedimento, não
é preciso usar a palabra ByVal, pois automaticamente, os
argumentos assumem a opção ByVal. As duas declarações
a seguir são equivalentes:
Public
Sub DobraValor(Num As Integer)
Ou
Public
Sub DobraValor(ByVal Num As Integer)
Na segunda declaração, explicitamente, estou utilizando
a opção ByVal, para indicar que o parâmetro
Num será passado por valor.
Mas o que significa
a passagem de um parâmetro por valor??
Significa que o procedimento receberá apenas o valor do parâmetro
e não uma referência ao endereço de memória
onde está armazenado o valor do parâmetro. Com isso,
quaisquer alterações que sejam feitas no valor do
parâmetro, dentro do procedimento, não afetarão
o valor original, o qual será o mesmo de antes da chamada
da função/procedimento. Em resumo, apenas o valor
é passado para a função/procedimento, este
valor é utilizado pelo código da função/procedimento,
sem afetar o valor original do parâmetro.
Para exemplificar este conceito, considere o código a seguir,
onde tenho uma função principal chamada
SubTeste,
na qual declaro uma variável MeuValor, do tipo Integer, inicializo
esta variável e passo ela, por valor, como parâmetro
para o procedimento
DobraValor:
Public Sub SubTeste()
Dim MeuValor As Integer
MeuValor = 5
MsgBox "Valor original de MeuValor: " & MeuValor
' Chamo o procedure DobraValor
DobraValor (MeuValor)
MsgBox "Valor de MeuValor Após a Execução:
" & MeuValor
End Sub
Public Sub DobraValor(ByVal Num As Integer) MsgBox
"Valor recebido como parâmetro:" & Num
Num = Num * 2 MsgBox
"Valor duplicado:" & Num
End Sub |
A seguir apresento uma descrição, passo-a-passo, da
execução do procedimento SubTeste:
1. Inicialmente é feita a declaração da variável
MeuValor como sendo do tipo Integer, esta variável é
inicializada com o valor 5 e é exibida uma caixa de mensagens
com o valor desta variável. Isso é feito pelas linhas
de código a seguir:
Dim MeuValor As Integer
MeuValor = 5
MsgBox "Valor original de MeuValor: " & MeuValor
O resultado destas três linhas de código está
indicado a seguir:
2. Em seguida é feita uma chamada ao procedimento DobraValor,
passando como parâmetro o valor da variável MeuValor.
Observe que o que é passado para o procedimento DobraValor
é apenas o valor contido em MeuValor (por isso que é
uma passagem por Valor, ou seja do tipo ByVal); não é
passada uma referência ao endereço de MeuValor na memória
do comutador. Com a passagem por valor, o procedimento DobraValor
apenas poderá utilizar o valor recebido, em seus cálculos,
mas não poderá alterar o valor da variável
MeuValor, na memória do computador. Em resumo, o procedimento
DobraValor, recebe o valor 5, o qual fica associado ao argumento
Num do procedimento. A linha a seguir indica a chamada do procedimento
DobraValor:
DobraValor (MeuValor)
3. Ao fazer uma chamada ao procedimento DobraValor, a execução
se desloca para a primeira linha de código deste procedimento.
Na chamada, o valor da variável MeuValor foi passado como
parâmetro. Este valor será associado ao argumento Num,
do procedimento DobraValor, ou seja, dentro do procedimento DobraValor
Num = 5. Inicialmente será executado o primeiro comando do
procedimento DobraValor:
MsgBox "Valor recebido como
parâmetro:" & Num
Este comando produz a mensagem indicada a seguir:
esta mensagem confirma o fato de o valor 5 estar associado com o
argumento Num, durante a execução do procedimento
DobraValor.
4. Em seguida, o valor de Num é multiplicado por 2 e o resultado
armazenado em Num:
Num = Num * 2
5. O próximo passo é exibir o valor de Num, ainda
dentro do procedimento DobraValor:
MsgBox "Valor duplicado:"
& Num
Este comando produz a mensagem indicada a seguir:
este resultado confirma que a variável Num foi duplicada.
Mas como estaria o valor original da variável MeuValor? É
o que você descubrirá no item a seguir.
6. Após encerrada a execução do procedimento
DobraValor, a execução é deslocada de volta
para o procedimento SubTeste, para primeira linha após a
chamada do procedimento DobraValor( )
MsgBox "Valor de MeuValor
Após a Execução: " & MeuValor
Este comando produz a mensagem indicada a seguir:
Observe que o valor da variável MeuValor não foi alterado
pela execução do procedimento DobraValor. Isso confirma
a passagem de parâmetro por valor, ou seja, o procedimento
DobraValor recebeu apenas o valor da variável MeuValor. Com
isso, os comandos do procedimento DobraValor não irão
alterar o valor da varável MeuValor, pois o procedimento
não tem acesso ao endereço de memória da variável
MeuValor, ao contrário, tem acesso apeanas a uma cópia
do valor desta variável.
Na prática, ao passar um parâmetro por valor, você
passa apenas uma cópia do valor da variável e é
nesta cópia que a função/procedimento chamado
trabalha, sem afetar o valor original da variável passada
como parâmetro.
Passagem de parâmetros por Referencia
– ByRef:
Para poder atuar/alterar o valor original, a função/procedimento,
tem que receber o parâmetro por referência – ByRef,
ou seja, a função/procedimento tem que receber uma
referência ao endereço de memória da variável
passada como parâmetro e não uma simples cópia
do valor da variável (que é o que acontece na passagem
ByVal).
Ao receber um parâmetro por referência (ByRef), as alterações
que a função/procedimento fizer, serão feitas
diretamente na variável original, pois agora, a função/procedimento
tem acesso ao endereço da variável na memória
e não mais apenas uma cópia do seu valor. Para que
um procedimento possa receber um parâmetro por referência,
você deve utilizar a palavra ByRef, conforme o exemplo a seguir:
Public Sub DobraValor(ByRef Num
As Integer)
Para exemplificar este conceito, considere o código a seguir,
onde tenho uma função principal chamada
SubTeste,
na qual declaro uma variável MeuValor, do tipo Integer, inicializo
esta variável e passo ela, por referência, como parâmetro
para o procedimento
DobraValor:
Public Sub SubTeste()
Dim MeuValor As Integer
MeuValor = 5
MsgBox "Valor original de MeuValor: " & MeuValor
' Chamo o procedure DobraValor
Call DobraValor(MeuValor)
MsgBox "Valor de MeuValor Após a Execução:
" & MeuValor
End Sub
Public Sub DobraValor(ByRef
Num As Integer)
MsgBox "Valor recebido como parâmetro:"
& Num
Num = Num * 2
MsgBox "Valor duplicado:" & Num
End Sub |
Observe que a única diferença neste código,
em relação ao exemplo anterior, é o uso de
ByRef, na declaração do argumento Num, do procedimento
DobraValor.
A seguir apresento uma descrição, passo-a-passo, da
execução do procedimento SubTeste:
1. Inicialmente é feita a declaração da variável
MeuValor como sendo do tipo Integer, esta variável é
inicializada com o valor 5 e é exibida uma caixa de mensagens
com o valor desta variável. Isso é feito pelas linhas
de código a seguir:
Dim MeuValor As Integer
MeuValor = 5
MsgBox "Valor original de MeuValor: " & MeuValor
O resultado destas três linhas de código está
indicado a seguir:
2. Em seguida é feita uma chamada ao procedimento DobraValor,
passando como parâmetro o valor da variável MeuValor.
Observe que o que é passado para o procedimento DobraValor
é uma referência (devido ao uso de ByRef na declaração
do procedimento DobraValor) a variável MeuValor. Com isso,
as alterações feitas pelo procedimento DobraValor,
irão afetar o valor original da variável, conforme
comprovaremos nos próximos passos.
DobraValor (MeuValor)
3. Ao fazer uma chamada ao procedimento DobraValor, a execução
se desloca para a primeira linha de código deste procedimento.
Na chamada, o valor da variável MeuValor foi passado como
parâmetro. Este valor será associado ao argumento Num,
do procedimento DobraValor, ou seja, dentro do procedimento DobraValor
Num = 5. Inicialmente será executado o primeiro comando do
procedimento DobraValor:
MsgBox "Valor recebido como
parâmetro:" & Num
Este comando produz a mensagem indicada a seguir:
esta mensagem confirma o fato de o valor 5 estar associado com o
argumento Num, durante a execução do procedimento
DobraValor.
4. Em seguida, o valor de Num é multiplicado por 2 e o resultado
armazenado em Num, o que na prática está também
afetando o valor da variável MeuValor, conforme você
comprovará mais adiante:
Num = Num * 2
5. O próximo passo é exibir o valor de Num, ainda
dentro do procedimento DobraValor:
MsgBox "Valor duplicado:"
& Num
Este comando produz a mensagem indicada a seguir:
este resultado confirma que a variável Num foi duplicada.
Mas como estaria o valor original da variável MeuValor? É
o que você descubrirá no item a seguir.
6. Após encerrada a execução do procedimento
DobraValor, a execução é deslocada de volta
para o procedimento SubTeste, para primeira linha após a
chamada do procedimento DobraValor( )
MsgBox "Valor de MeuValor
Após a Execução: " & MeuValor
Este comando produz a mensagem indicada a seguir:
Observe que o valor da variável MeuValor foi alterado pela
execução do procedimento DobraValor. Isso confirma
a passagem de parâmetro por refer~encia, ou seja, o procedimento
DobraValor recebeu uma referência ao endereço de memória
da variável MeuValor. Com isso, os comandos do procedimento
DobraValor irão alterar o valor da varável MeuValor,
pois o procedimento tem acesso ao endereço de memória
da variável MeuValor, ao contrário, do que acontece
na passagem por valor, quando o procedimento tem acesso apenas a
uma cópia do valor da variável passada como parâmetro.
Conclusão:
Neste tutorial você aprendeu sobre a diferença entre
a passagem de parâmetros por valor – ByVal e por referência
– ByRef. Na passagem por valor é passado apenas uma
cópia do valor da variável. Os comandos executados
dentro do procedimento/função chamado não irão
alterar o valor original da variável. Já na chamada
por referêncai, o endereço da variável, na memória,
é passado para o procedimento/função que foi
chamado. Com isso, as alterações feitas pelo procedimento,
na variável, irão alterar o valor original da variável,
pois estão atuando diretamente sobre esta variável,
ou melhor, no endereço de memória da variável.
É isso.
Nota: Este tutorial faz parte do Curso de Programação
VBA e Criação de Aplicativos no Excel, que terá
cerca de 650 páginas e estará disponível para
aquisição no formato de arquivo .PDF a partir de 15
de Dezembro.