Funções

Funções são procedimentos que podem retornar um valor a outro procedimento. Normalmente funções possuem parâmetros, mas não é obrigatório.


Introdução

É recomendável ler a página procedimentos antes de continuar.

O exemplo a seguir mostra como obter a hipotenusa de um triângulo retângulo:

Sub TriânguloRetângulo()
    Dim a As Double
    Dim b As Double
    Dim c As Double
  
    a = 3
    b = 4
  
    c = GetHipotenusa(a, b)
  
    MsgBox "O valor da hipotenusa de um triângulo retângulo " _
    & "com catetos " & a & " e " & b & " é " & c & "."
End Sub
 
Private Function GetHipotenusa(ByVal c1 As Double, _
                            ByVal c2 As Double)
    GetHipotenusa = ((c1 ^ 2) + (c2 ^ 2)) ^ (1 / 2)
End Function

Alternativamente, você poderia chamar a função GetHipotenusa como a seguir, como faço muitas vezes:

c = GetHipotenusa(c1:=a, c2:=b)

A terminologia adotada é que a função GetHipotenusa retornou uma valor à variável c. Se você não atribuir nenhum valor a essa variável, o valor retornado pela função será Empty.

Funções também podem retornar qualquer tipo de dados, como também objetos e vetores/matrizes.

Tenho certeza que, assim como eu, você achou ridículo utilizar uma palavra em inglês junto com uma em português na função GetHipotenusa. Pelo fato de várias linguagens de programação ser em inglês e Get remeter à ideia de que se está obtendo um valor, ela é entendida como uma palavra chave universal para qualquer programador de que analise o código e entenda que a entendida em questão retorna um valor. Mais sobre esse assunto aqui..

Especificar Tipo de Dados de Valor Retornado

Segundo as boas práticas de programação, recomenda-se declarar qual o tipo de dados que uma função retorna. No exemplo utilizado até agora, isso não foi especificado, sendo que:

Private Function GetHipotenusa(ByVal c1 As Double, _
                               ByVal c2 As Double)

 

É equivalente a:

Private Function GetHipotenusa(ByVal c1 As Double, _
                               ByVal c2 As Double) As Variant

Como em nosso exemplo estamos passando um valor a um parâmetro Double, seria uma boa ideia qualificar o retorno da função também como Double:

Private Function GetHipotenusa(ByVal c1 As Double, _
                               ByVal c2 As Double) As Double

Como agora o valor retornado está com seu tipo de dados especificado, se você sair da função sem atribuir um valor a sua variável homônima, o valor retornado será igual ao valor inicial de seu tipo de dados.

Retornar Mais de um Valor

Pode ser que você queira que sua função retorne mais de um valor. Por exemplo, suponha que você use muitas vezes funções que transformem duplas de números em seus valores ao quadrado e ao cubo, como mostra o exemplo a seguir:

Sub Main()
    Dim Num1 As Long
    Dim Num2 As Long
  
    Num1 = 6
    Num2 = 5
  
    Debug.Print "Valor inicial de Num1: " & Num1
    Debug.Print "Valor inicial de Num2: " & Num2
  
    Num1 = GetQuadrado(Num1)
    Num2 = GetCubo(Num2)
  
    Debug.Print "Valor final de Num1: " & Num1
    Debug.Print "Valor final de Num2: " & Num2
End Sub
 
Private Function GetQuadrado(ByVal pNum As Long) As Long
    GetQuadrado = pNum ^ 2
End Function
 
Private Function GetCubo(ByVal pNum As Long) As Long
    GetCubo = pNum ^ 3
End Function

Você poderia eliminar a função e em seu lugar criar um subprocedimento, passando valores como referência:

Sub Main()
  Dim Num1 As Long
  Dim Num2 As Long
  
  Num1 = 6
  Num2 = 5
  
  Debug.Print "Valor inicial de Num1: " & Num1
  Debug.Print "Valor inicial de Num2: " & Num2
  
  Transformar Num1, Num2
  
  Debug.Print "Valor final de Num1: " & Num1
  Debug.Print "Valor final de Num2: " & Num2
End Sub
 
Private Sub Transformar(ByRef pQuadrado As Long, _
                        ByRef pCubo As Long)
  pQuadrado = pQuadrado ^ 2
  pCubo = pCubo ^ 3
End Sub

Boas Práticas

Suponha que você tenha uma função que transforme toda as letras em maiúsculas, substitua _ por espaços e insira um pronome de tratamento. É uma típica função que faz transformações por etapas de a partir de um valor inicial:

Sub Main()
    Debug.Print GetFixedText("fELipe_COSta_gualBertO")
End Sub
 
Function GetFixedText(pText As String) As String
    GetFixedText = Replace(pText, "_", " ")
    GetFixedText = UCase(GetFixedText)
    GetFixedText = "Sr. " & GetFixedText
End Function

Na pequena função FixText, estou usando sua variável homônima três vezes. Numa função maior, essa repetição também pode se tornar maior, e então você terá que trocar o nome da variável várias vezes na função.

Claro que existem ferramentas de substituir texto no VBE, mas se sua função tiver um nome pequeno e comum, poderá alterar partes indesejadas do seu código. Além disso, como em funções seu nome pode se referir tanto ao nome da função como o valor de retorno, você pode ter dificuldades de interpretação ao ler o código, e a situação piora quando se utiliza a técnica de recursão.

A forma que trabalho com funções que não retornam um valor diretamente é usando uma variável temporária que possua um tipo de dados igual ao da função. Reescrevendo o exemplo anterior nesse embasamento:

Sub Main()
    Debug.Print GetFixedText("fELipe_COSta_gualBertO")
End Sub
 
Function GetFixedText(pText As String) As String
    Dim FixedText As String
    
    FixedText = pText
    FixedText = Replace(FixedText, "_", " ")
    FixedText = UCase(FixedText)
    FixedText = "Sr. " & FixedText
    
    GetFixedText = FixedText
End Function

Veja que nesse caso utilizei a variável de apoio FixedText. Por questão de lógica, essa variável de apoio tem o mesmo tipo de dados do retorno da função (String) e ela possui esse nome pois é o nome da função GetFixedText sem o prefixo Get.

Sobre Felipe Gualberto

Microsoft Most Valuable Professional (MVP) de Excel.
Esta entrada foi publicada em Tutoriais e marcada com a tag , , , , , . Adicione o link permanente aos seus favoritos.