OS MELHORES VÍDEOS

 

Pesquisar

sexta-feira, 23 de agosto de 2013

Declaração de Variável.

Introdução

    Variáveis são elementos temporários num código que possui informação sobre uma aplicação, procedimento ou objeto.





    A declaração de uma variável tem a finalidade de pré-avisar o compilador do VBA qual é o tipo de dado que será tratado.
No VBE, o comando para declarar uma variável é Dim:


Sub Ex01()
    
    Dim lng As Long
    
    lng = 5
    Debug.Print lng
    
End Sub
No exemplo acima, a variável lng é definida como um número inteiro longo. Obviamente, se tentarmos executar o código:
Sub Ex02()
    
    Dim lng As Long
    
    lng = "Benzadeus"
    Debug.Print lng
    
End Sub

A seguinte tela de erro será apresentada:





Esse erro foi gerado porque como lng foi declarado como um longo, se tentarmos atribuir uma string a ele, uma incompatibilidade é detectada.

Além nos números longos, existem os decimais, os inteiros, os tipos de dados não numéricos também como string e data. Para saber mais sobre os tipos de dados do VBA, clique aqui.
Declarando-se a variável var1 conforme abaixo, os códigos abaixo não retornarão erro:

Sub Ex03()
    
    Dim var1
    
    var1 = 8
    Debug.Print var1
    
End Sub

Sub Ex04()
    
    Dim var1
    
    var1 = "Felipe"
    Debug.Print var1
    
End Sub

Declarar uma variável sem especificar seu tipo tem o mesmo efeito de omitir o comando Dim:

Sub Ex05()
    
    var1 = 8
    Debug.Print var1
    
End Sub

Sub Ex06()
    
    var1 = "Felipe"
    Debug.Print var1
    
End Sub


Para esses procedimentos que não foi especificado o tipo da declaração da variável ou que a declaração foi omitida, o VBA atribui automaticamente, em tempo de execução, o tipo da variável. Por exemplo, no instante que se tenta atribuir 8 à var1, o VBA convertevar1 numa variável do tipo inteiro.
Mas não pára por aí. Considere o exemplo abaixo:


Sub Ex07()
    
    Dim var1
    
    Debug.Print TypeName(var1)
    var1 = 8
    Debug.Print TypeName(var1)
    var1 = 75000
    Debug.Print TypeName(var1)
    var1 = -8.54
    Debug.Print TypeName(var1)
    var1 = "st"
    Debug.Print TypeName(var1)
    var1 = 4
    Debug.Print TypeName(var1)

End Sub


O comando TypeName(parâmetro) retorna qual é o tipo da variável (longo, inteiro, string, double). Observe que, ao executar o código acima, o VBA converterá a variável de acordo com a necessidade.
Isso é uma vantagem? Bem, sim e não. A vantagem é que você tem uma facilidade enorme para inserir e converter os tipos de variáveis em seu código, mas à medida que este vai ficando grande, as coisas podem começar a complicar:


Sub Ex08()
    
    strApelido = "Benzadeus"
    
    Select Case strApelido
        Case "Benzadeus": lngPontos = 28
        Case "Creuza": lngPontos = 24
        Case "Doutior": lngPontos = 7
    End Select

    MsgBox _
      Prompt:=strApelido & " tem " & lngPotos & " pontos!", _
      Buttons:=vbInformation, _
      Title:="Informação"

End Sub


O simples código acima pode te deixar puto por algum tempo até você descobrir por que, ao executar o código, no MsgBox nunca aparece quantos pontos a porra do strApelido tem. Você observou que escrevi lngPotos ao invés de lngPontos? Pois é. Se num código desse tamanho já é suficiente para nos fazer perder tempo, imagina quando estamos falando de códigos de milhares de linhas. A seção a seguir explica como evitar esse tipo de equívoco.
Vale ressaltar que a omissão do tipo de dado na declaração de uma variável automaticamente a trata como uma Variant. Os códigos abaixo são semelhantes:


Sub Ex08B()
    
    Dim strMatriz

End Sub

'é equivalente a:

Sub Ex08C()
    
    Dim strMatriz As Variant

End Sub

Regras para Declaração de Variável

Existem regras para a nomenclatura de variáveis no VBA:

-Variáveis devem começar obrigatoriamente com letras, ou seja, números não são permitidos;

-O nome de uma variável não pode ter mais que 250 caracteres;

-Uma variável não pode ter o mesmo nome de um dos objetos/classes das bibliotecas referenciadas no projeto. Por exemplo, se você estar no Word, não pode chamar uma variável de Document, pois esta já existe na biblioteca Microsoft Word 14.0 Object Library, por exemplo;

-Não pode haver espaço no nome da variável. Você pode, entretanto, usar hifens ou letras maiúsculas para organizar o nome delas, como por exemplo strPrimeiroNome ou str_Primeiro_Nome;

As boas práticas de programação sugerem que deve-se usar uma terminologia organizada para não se perder nos nomes das variáveis. O final da seçã a seguir explora um pouco mais esse assunto.



Declaração de Variável Obrigatória

No VBA, existe uma forma de restringir quais são as variáveis que podem aparecer no código. Considere o código abaixo, que nada mais é o procedimento Ex08 com o comando Option Explicit e as declarações das variáveis que devem existir no código. Observe que o comando Option Explicit deve preceder todos os procedimentos e funções de um módulo:

Option Explicit
Sub Ex09()
    
    Dim strApelido As String
    Dim lngPontos As Long
    
    strApelido = "Benzadeus"
    
    Select Case strApelido
        Case "Benzadeus": lngPontos = 28
        Case "Creuza": lngPontos = 24
        Case "Doutior": lngPontos = 7
    End Select

    MsgBox _
      Prompt:=strApelido & " tem " & lngPotos & " pontos!", _
      Buttons:=vbInformation, _
      Title:="Informação"

End Sub



Se tentarmos executar o código acima, o erro será gerado:

Instantaneamente, o usuário perceberá que no local onde o VBA automaticamente sublinha, cometeu um erro de digitação.


Para ativar obrigatória a declaração de variável, no VBE, vá em Ferramentas / Opções,
Cheque Requerer Declaração de variável:






Pronto, agora todos os módulos criados pela Aplicação trará, em sua primeira linha, o comando Option Explicit.

As boas práticas de programação defendem a declaração de variável obrigatória. Então, se você quiser desenvolver aplicações sérias em VBA, ative essa opção.

Declaração por Sufixos

Caso deseje definir uma variável através de um sufixo, utilize a tabela abaixo:



Ou seja, os procedimentos Ex10 e Ex11 exemplificados abaixo têm o mesmo efeito:
Sub Ex10()

    Dim strNome As String
    Dim lngIdade As Long
    Dim dblPosição As Double

End Sub

Sub Ex11()

    Dim strNome$
    Dim lngIdade&
    Dim dblPosição#

End Sub


Pessoalmente, faço uso da topologia do Ex10. Pra quê complicar, né?
Gostaria de chamar atenção para o nome das minhas variáveis. Observe que se for do tipo String, uso o prefixo str em seu nome para definí-la. Isso é considerada boa prática de programação. 

Normalmente nomeio minhas variáveis de acordo com a tabela abaixo:




Por Que Usar Variáveis?

Considere o exemplo abaixo, código para uma aplicação em Excel:

Sub Ex12()

    Range("A1").Value = Range("B2").Value
    Range("A2").Value = Range("B2").Value * 2
    Range("A3").Value = Range("B2").Value * 3
    Range("B2").Value = Range("B2").Value * 4

End Sub


A expressão Range("B2").Value está repetindo várias vezes. Isso torna o código confuso para o depurador e, além disso, toda a vez que o objeto Range é chamado, o VBA invoca uma chamada à propriedade Value do objeto, diminuindo a velocidade de execução do programa. Uma forma de melhorar o código acima é dado no exemplo abaixo:
Sub Ex13()

    Dim lng As Long

    lng = Range("B2").Value
    
    Range("A1").Value = lng
    Range("A2").Value = lng * 2
    Range("A3").Value = lng * 3
    Range("B2").Value = lng * 4

End Sub


Primeiramente atribui-se um valor à lng. Posteriormente, basta fazer chamadas da variável.

Variáveis Locais e Variáveis Globais

Observe o código abaixo. Preste atenção que são colados códigos de dois módulos diferentes, chamados mdlLocaisGlobais emdlLocaisGlobais2:


'********MÓDULO MDLLOCAISGLOBAIS1********
Dim lMódulo As Long
Public lGlobal As Long

Sub PrincipalLocaisGlobais()

    Dim lProcedto As Long

    lProcedto = lProcedto + 1
    lMódulo = lMódulo + 1
    lGlobal = lGlobal + 1
    
    Debug.Print "lProcedto: ", lProcedto
    Debug.Print "lMódulo: ", lMódulo
    Debug.Print "lGlobal: ", lGlobal

End Sub

Sub AuxiliarLocaisGlobais()
    
    'A linha abaixo compila porque a variável é definida
    'como Global (Public)
    Debug.Print "lGlobal: ", lGlobal
    
    'A linha abaixo compila porque a variável é definida
    'no nível do Módulo:
    Debug.Print "lMódulo: ", lMódulo
    
    'A linhas abaixo geraria erro de compilação porque a variável
    'lProcedto é no nível do Procedimento PrincipalLocaisGlobais
    'Debug.Print "lProcedto: ", lProcedto

End Sub
'********FIM MÓDULO MDLLOCAISGLOBAIS1********

'********MÓDULO MDLLOCAISGLOBAIS2********
Sub OutroMódulo()

    'A linha abaixo compila porque a variável lGlobal é definida
    'como Global (Public):
    Debug.Print "lGlobal: ", lGlobal
    
    'As linhas abaixo gerariam erro de compilação porque a variável
    'lMódulo é definida no nível do módulo mdlLocaisGlobais1 e a
    'Variável lProcedto é definida no nível do Procedimento PrincipalLocaisGlobais
    'Debug.Print "lMódulo: ", lMódulo
    'Debug.Print "lProcedto: ", lProcedto

End Sub

'********FIM MÓDULO MDLLOCAISGLOBAIS2********
Nesse exemplo temos um total de três variáveis declaradas: são elas lProcedtolMódulo e lGlobal.
lProcedto é o que se diz de uma variável declarada no nível do Procedimento (ou Função). Ou seja, apenas chamadas ou alterações da variável dentro do Procedimento a que ela se encontra (que é o PrinipalLocaisGlobais) são compiladas pelo VBA.

lMódulo é o que se diz de uma variável declarada no nível do Módulo. Logo, todos os procedimentos dentro do módulomdlLocaisGlobais1 podem ler ou alterar valores dessa variável. Ela está declarada no nível do módulo porque ela se encontra nas primeiras linhas do módulo, antes do cabeçalho do primeiro Procedimento, fora de qualquer Procedimento.

lGlobal é o que se diz de uma variável declarada no nível Global (ou Público). Qualquer Procedimento ou Função do projeto pode ler ou alterar seu valor. Ela está declarada no nível Global porque se encontra nas primeiras linhas do módulo, antes do cabeçalho do primeiro Procedimento, fora de qualquer Procedimento e possui, ao invés do prefixo Dim, o prefixo Public.
Observe que, ao executar a rotina PrincipalLocaisGlobais, a , a saída será:

lProcedto:     1 
lMódulo:       1 
lGlobal:       1 


Caso seja executado o Procedimento AuxiliarLocaisGlobais, a saída será:
lGlobal:       1 
lMódulo:       1 

Se for executado o Procedimento OutroMódulo, presente no Módulo mdlLocaisGlobais2, a saída será:
lGlobal:       1 


Com isso, torna-se claro como que os níveis de declaração das variáveis afetam as permissões de leitura e alteração que os Procedimentos tem sobre cada variável.



Valor de Algumas Variáveis é Preservado

Num primeiro momento, como mostrado acima, ao ser executada a rotina PrincipalLocaisGlobais, a saída foi:

lProcedto:     1 
lMódulo:       1 
lGlobal:       1 


Vamos experimentar executar essa rotina novamente e ver qual será a saída:

lProcedto:     1 
lMódulo:       2 
lGlobal:       2 


Rodando mais uma vez:

lProcedto:     1 
lMódulo:       3 
lGlobal:       3 


Note que o valor das variáveis lMódulo e lGlobal incrementa, e o valor de lProcedto não. Isso ocorre porque variáveis declaradas no nível do módulo ou globais preservam seus valores na memória mesmo após o término da execução da rotina. Já, variáveis no nível do Procedimento são resetadas a cada vez que o Procedimento é chamado.


O programador pode ter problemas em suas rotinas caso ele deseje sempre que uma rotina inicie com todos os parâmetros limpos. Para contornar essa situação, uma das idéias é fazer como abaixo:


Sub PrincipalLocaisGlobais_Limpar()
    lMódulo = 0
    lGlobal = 0
    
    '...resto do código
End Sub


O código acima deve estar no início da rotina do programa: as variáveis que retêm seus valores são zeradas manualmente.

Declarações Estáticas

Suponha que você queria manter o valor de uma variável toda vez que ela for executada. Podemos usar o prefixo de declaração Staticao invés de Dim. Observe o exemplo abaixo:
Sub Principal()
    
    Debug.Print "---Antes---"
    Estático
    
    Debug.Print "---Depois---"
    Estático

End Sub

Sub Estático()

    Dim lDinâmica As Long
    Static lEstática As Long

    lDinâmica = lDinâmica + 8
    lEstática = lEstática + 8
    
    Debug.Print "lEstática: " & lEstática
    Debug.Print "lDinâmica: " & lDinâmica

End Sub


A rotina Estático é chamada duas vezes. Imprime-se a saída da rotina após ser executada pela primeira e pela segunda vez. A saída é mostrada abaixo:

---Antes---
lEstática: 8
lDinâmica: 8
---Depois---
lEstática: 16
lDinâmica: 8


A variável lEstática é definida com a palavra Static. Isso significa que o VBA preserva na memória o valor da variável quando finda a execução da rotina.

O único problema nesse caso é que além de preservar o valor da memória ao sair da rotina, o VBA também preserva quando finda a execução de todas as rotinas. Isto é, os valores das variáveis estáticas são preservados e se você tentar executar a mesma rotina novamente, terá como resultado:

---Antes---
lEstática: 24
lDinâmica: 8
---Depois---
lEstática: 32
lDinâmica: 8

e, se executar ainda novamente:

---Antes---
lEstática: 40
lDinâmica: 8
---Depois---
lEstática: 48
lDinâmica: 8

...e assim por diante.

O que aconteceu é que na primeira vez que a rotina foi executada o valor da variável era igual ao seu valor na última execução da rotina. Para zerar uma variável estática no início de uma rotina, sugiro fazer algo como mostrado a seguir:


Dim blResetarEstático As Boolean

Sub Principal()
    
    blResetarEstático = True
    
    Debug.Print "---Antes---"
    Estático
    
    Debug.Print "---Depois---"
    Estático

End Sub

Sub Estático()

    Dim lDinâmica As Long
    Static lEstática As Long

    If blResetarEstático = True Then
        lEstática = 0
        blResetarEstático = False
    End If
    
    lDinâmica = lDinâmica + 8
    lEstática = lEstática + 8
    
    Debug.Print "lEstática: " & lEstática
    Debug.Print "lDinâmica: " & lDinâmica

End Sub


Observe que existe uma variável no nível de Módulo chamada blResetarEstático. Ela começa como True e, quando a rotina Estático é executada pela primeira vez, zera-se o valor de lEstática e atribui-se False a blResetarEstático. Agora, lEstática será zerada novamente apenas quando a rotina Principal for executada novamente.

Um comentário:

  1. Fala companheiro, td bem?

    Bom, fiz a função que retorna uma string no
    formato de um numero complexo. No entanto, em outra célula
    eu coloco a formula IMABS (que calcula o módulo de um complexo)
    e o excel dá um erro como se não esperasse uma string.
    A questão é, como converter um tipo string no tipo complexo do excel.

    string em IMABS

    Public Function MANDELBROT(ByVal parte_real As Double, ByVal parte_imaginaria As Double, ByVal iteradas As Long) As String

    Dim i As Long
    Dim z1 As String
    Dim c As String
    Dim z As String
    Dim p As String

    c = Application.WorksheetFunction.Complex(parte_real, parte_imaginaria)
    z1 = Application.WorksheetFunction.Complex(0, 0)

    For i = 1 To iteradas
    p = Application.WorksheetFunction.ImProduct(z1, z1)
    z = Application.WorksheetFunction.ImSum(p, c)
    z1 = z
    Next

    MANDELBROT = z

    End Function


    Abraços,
    geniltonc@gmail.com

    ResponderExcluir