Nem sempre os procedimentos executam a mesma ação quando chamados. Uma das formas de alterar seu comportamento durante a execução para produzir um resultado diferente é passando argumentos a eles.
- Introdução
- Nomear Parâmetros
- Especificar Tipo de Dados de Parâmetros
- Economia de Código
- Parâmetros Opcionais
- Parâmetros ByRef e ByVal
Introdução
Os argumentos que um procedimento aceita são definidos em sua declaração. O exemplo a seguir mostra um subprocedimento que aceita três argumentos:
Sub Mostrar(Nome, Idade, Altura)
Um procedimento pode receber até 30 argumentos.
O procedimento Mostrar
exemplificado abaixo produz um resultado de execução diferente dependendo dos valores passados aos parâmetros Nome
, Idade
e Altura
. Suponha que o subprocedimento Main
chame Mostrar
passando argumentos:
Sub Main() Mostrar "Felipe", 30, 2 End Sub Sub Mostrar(Nome, Idade, Altura) MsgBox "Seu nome é " & Nome & "." MsgBox "Sua idade é de " & Idade & "." MsgBox "Você tem " & Altura & " metros de altura." End Sub
Afinal, qual é a diferença entre argumentos e parâmetros?
Argumentos são as expressões passadas a um procedimento. Neste caso, foram passados os argumentos “Felipe”, 30 e 2. No entanto, poderiam ser passados argumentos diferentes desses a Mostrar
. Por outro lado, cada parâmetro é representado por num nome de variável dentro do procedimento que recebeu os valores dos argumentos passados.
Logo, tente entender que parâmetros são fixos, como vagas de garagem. Argumentos são os vários carros que podem parar em cada uma dessas vagas delimitadas.
Nomear Parâmetros
Adquiri o costume de utilizar a letra p como prefixo para nomear parâmetros. Dessa forma, ao bater os olhos numa variável com esse prefixo num procedimento, já sei que ela é um parâmetro. No exemplo anterior, então eu escreveria:
Sub Mostrar(pNome, pIdade, pAltura)
Especificar Tipo de Dados de Parâmetros
Assim como nas boas práticas de declaração de variáveis explicitamos seu tipo de dados, recomenda-se também especificar o tipo de dados dos argumentos:
Sub Mostrar(pNome As String, pIdade As Long, pAltura As Double)
Se o procedimento possuir muitos parâmetros e sua linha de declaração ficar muito grande, sugiro quebrar a linha fisicamente na forma que se segue:
Sub Mostrar(pNome As String, _ pIdade As Long, _ pAltura As Double)
Fixando a terminologia, você deve entender que um procedimento chama outro procedimento passando a ele argumentos. Os argumentos passados estão definidos como parâmetros no procedimento que recebe os argumentos, e então ele faz uso desses valores para produzir um resultado de execução de código.
Economia de Código
Procedimentos com parâmetros podem ser usados para economizar código. Veja o exemplo a seguir:
Sub Main() Dim FirstName As String Dim CurrentAge As Long Dim Height As Double FirstName = "Felipe" CurrentAge = 30 Height = 2 MsgBox "Nome: " & FirstName & ", idade de " & CurrentAge _ & " anos e " & Height & " metros de altura." FirstName = "Renata" CurrentAge = 32 Height = 1.73 MsgBox "Nome: " & FirstName & ", idade de " & CurrentAge _ & " anos e " & Height & " metros de altura." FirstName = "Rodrigo" CurrentAge = 35 Height = 1.87 MsgBox "Nome: " & FirstName & ", idade de " & CurrentAge _ & " anos e " & Height & " metros de altura." FirstName = "Maria" CurrentAge = 60 Height = 1.7 MsgBox "Nome: " & FirstName & ", idade de " & CurrentAge _ & " anos e " & Height & " metros de altura." FirstName = "José" CurrentAge = 60 Height = 1.8 MsgBox "Nome: " & FirstName & ", idade de " & CurrentAge _ & " anos e " & Height & " metros de altura." End Sub
Seu usarmos um procedimento com parâmetros, o código pode ser simplificado para:
Sub Main() Dim FirstName As String Dim CurrentAge As Long Dim Height As Double FirstName = "Felipe" CurrentAge = 30 Height = 2 Mostrar FirstName, CurrentAge, Height FirstName = "Renata" CurrentAge = 32 Height = 1.73 Mostrar FirstName, CurrentAge, Height FirstName = "Rodrigo" CurrentAge = 35 Height = 1.87 Mostrar FirstName, CurrentAge, Height FirstName = "Maria" CurrentAge = 60 Height = 1.7 Mostrar FirstName, CurrentAge, Height FirstName = "José" CurrentAge = 60 Height = 1.8 Mostrar FirstName, CurrentAge, Height End Sub Sub Mostrar(pNome As String, _ pIdade As Long, _ pAltura As Double) MsgBox "Nome: " & pNome & ", idade de " & pIdade _ & " anos e " & pAltura & " metros de altura." End Sub
Utilizando um procedimento auxiliar que defina parâmetros, o complicado código com várias concatenações da caixa de mensagem foi escrito apenas uma vez. Há um ganho na manutenção do código, já que se precisarmos alterar o conteúdo da caixa de mensagem, editaremos apenas uma vez, no procedimento auxiliar.
Nesse exemplo, observe que ao chamar o procedimento que possui os parâmetros, a ordem das variáveis deve seguir a ordem dos parâmetros na declaração do procedimento. Além disso, você não precisa declarar dentro do procedimento os parâmetros, pois a própria declaração do procedimento também as declara como variáveis. Pela obrigatoriedade de se passar pela ordem correta, diz-se que os argumentos foram passados por posição.
Se você tentar passar um argumento de um tipo de dados incompatível com o tipo de dados de um parâmetro, obterá um erro de tipos incompatíveis.
Argumentos Nomeados
Alternativamente, você pode passar os argumentos por nome, isto é, especificar explicitamente qual argumento cada parâmetro atribui. Para tal, utilize o símbolo := (dois pontos e símbolo de igualdade) com seus respectivos nomes e separe-os por vírgula:
Mostrar Nome:=FirstName, Idade:=CurrentAge, Altura:=Height
Quando são utilizados muitos argumentos e preciso quebrar linhas, organizo o código da seguinte forma:
Mostrar Nome:=FirstName, _ Idade:=CurrentAge, _ Altura:=Height
Uma vantagem de se passar argumentos por nome é que você pode trocar a ordem de atribuição deles, em detrimento de quando se passa por posição:
Mostrar Altura:=Height, _ Nome:=FirstName, _ Idade:=CurrentAge
Parâmetros Opcionais
Você pode criar parâmetros opcionais ao qualifica-los usando a palavra chave Optional
, e coloca-lo por último na ordem da declaração dos parâmetros. Parâmetros opcionais são aqueles que você não é obrigado a passar a um procedimento.
Veja o exemplo a seguir:
Sub Main() Mostrar "Felipe" Mostrar "Renata", 32 Mostrar "Rodrigo", , 1.87 'As linhas abaixo são equivalentes às mostradas acima, 'mas utilizando argumentos nomeados. Mostrar pNome:="Felipe" Mostrar pNome:="Renata", pIdade:=32 Mostrar pNome:="Rodrigo", pAltura:=1.87 End Sub Sub Mostrar(pNome As String, _ Optional pIdade As Long, _ Optional pAltura As Double) Dim TextMessage As String TextMessage = "Nome: " & pNome If pIdade > 0 Then TextMessage = TextMessage & ", idade de " & pIdade & " anos" End If If pAltura > 0 Then TextMessage = TextMessage & ", altura de " & pAltura & " metros" End If TextMessage = TextMessage & "." MsgBox TextMessage End Sub
Vale ressaltar que na chamada Mostrar "Rodrigo", , 1.87
foram passados apenas o primeiro e terceiro argumentos, já que o segundo parâmetro está vazio. Na verdade, o segundo parâmetro assumirá o valor inicial de seu tipo de dados, explicado na subseção a seguir.
Valor Padrão de Argumento Opcional
Você pode definir um determinado valor para um parâmetro opcional. Por exemplo: se você trabalha numa fábrica em alguns testes de rotina são feitos geralmente na parte da noite, poderia usar a função:
Sub GerarRelatório(ByVal pAmostras As Long, _ Optional ByVal pPeríodo As String = "Noturno") '...código... End Sub
Se você chamar essa função sem especificar o valor do Parâmetro pPeríodo
, o VBA considerará seu valor como “Noturno”.
Parâmetros ByRef e ByVal
Parâmetros passados com a palavra chave ByVal
(passados por valor) não podem ser alterados pela rotina chamada e argumentos ByRef
(passados por referência) podem. Se você não qualificar seus argumentos com uma dessas palavras chave, o VBA o considerará como ByRef
. Logo, as declarações abaixo são equivalentes:
Sub pProcessar(pCódigo) Sub pProcessar(ByRef pCódigo)
O exemplo a seguir ilustra a diferença entre parâmetros que são ByRef
ou ByVal
:
Sub Main() Dim Número1 As Long Dim Número2 As Long Número1 = 3 Número2 = 3 Incrementar Número1, Número2 Debug.Print "Número1=" & Número1, "Número2=" & Número2 End Sub Sub Incrementar(ByVal pNúmero1 As Long, ByRef pNúmero2 As Long) pNúmero1 = pNúmero1 + 1 pNúmero2 = pNúmero2 + 1 End Sub
A saída do programa acima nos mostrará que pNúmero1
teve seu valor preservado, mas pNúmero2
alterou.
Normalmente, não perco muito meu tempo atentando se meus parâmetros são ByRef
ou ByVal
. Costumo deixar em branco (consequentemente, são passados por referência) e tomo cuidado para não alterar o valor do parâmetro para que as alterações não reflitam no argumento passado.
Vale ressaltar que alguns objetos ou vetores não podem ser passados como valor, apenas por referência. Por exemplo, não é possível criar cópias de objetos complexos que se alocam em pontos específicos da memória do seu sistema.
Em termos de desempenho, não existem ganhos significativos quando comparamos argumentos passados como valor ou referência. Existe a falsa ideia (porém, lógica) de que ao passar como valor, se gasta mais tempo porque a estrutura de dados do argumento deve ser duplicada, ao invés de simplesmente ser passado um endereço de memória (que é o caso de passar por referência).
Deixar um comentário
Você precise estar logged in para postar um comentário.