Esta página explica como procedimentos conseguem acessar uma variável de acordo como ela é declarada.
Introdução
O escopo de uma variável se refere à sua acessibilidade, isto é, de quais procedimentos ela pode ser acessada e/ou alterada. Existem variáveis de nível de procedimento, nível de módulo e de nível global.
Option Explicit
em todos os módulos do seu projeto. Sem isso, esta página não faz sentido. Se não entendeu o que isso significa, a leitura da página a seguir é obrigatória: Variáveis e Constantes.Nível de Procedimento
Variáveis de nível de procedimento também são conhecidas como variáveis locais. Elas recebem esse nome porque só podem ser acessadas por instruções do procedimento que a declarou. Como o próprio nome indica, elas são declaradas dentro de um procedimento:
Sub Local1() Dim FirstName As String FirstName = "Felipe" MsgBox FirstName Local2 End Sub Sub Local2() MsgBox FirstName End Sub
Ao compilar esse código, você obterá o erro de compilação a seguir:
Isso acontece porque como FirstName
é externo ao procedimento Local2
.
Se você também declarasse FirstName
em Local2
, como mostrado a seguir:
Sub Local2() Dim FistName As String MsgBox FirstName End Sub
O código executaria, mas a caixa de mensagem ficaria em branco porque o valor dessa variável não terá nenhuma relação com seu homônimo de Local1
, a não ser de coincidirem o mesmo nome, e como o valor inicial de uma variável String
é “” (vazio), a caixa de mensagem em branco é mostrada.
Variáveis Estáticas
Variáveis estáticas, assim como variáveis de procedimento, são declaradas dentro de um procedimento. Seu comportamento é idêntico ao de uma variável de procedimento, exceto que ela conserva seu valor quando o procedimento é chamado novamente.
Para declarar uma variável estática, use a palavra chave Static
ao invés de Dim
. O código abaixo declara uma variável String
estática:
Sub Main() Static ContadorEstático As Long '... End Sub
O código a seguir ilustra a particularidade de variáveis estáticas em manter seu valor a cada nova chamada de procedimento:
Private Sub Main() Debug.Print "Primeira execução de 'IncrementarValores':" IncrementarValores Debug.Print "Segunda execução de 'IncrementarValores':" IncrementarValores Debug.Print "Terceira execução de 'IncrementarValores':" IncrementarValores End Sub Private Sub IncrementarValores() Dim ContadorNormal As Long Static ContadorEstático As Long ContadorNormal = ContadorNormal + 1 ContadorEstático = ContadorEstático + 1 Debug.Print "Valor de variável normal: " & ContadorNormal Debug.Print "Valor de variável estática: " & ContadorEstático Debug.Print End Sub
A saída do programa é mostrada a seguir:
Primeira execução de 'IncrementarValores': Valor de variável normal: 1 Valor de variável estática: 1 Segunda execução de 'IncrementarValores': Valor de variável normal: 1 Valor de variável estática: 2 Terceira execução de 'IncrementarValores': Valor de variável normal: 1 Valor de variável estática: 3
Observe que variável ContadorNormal
tem seu valor reiniciado a cada chamada de IncrementarValores
, enquanto ContadorEstático
mantém seu valor.
Procedimentos Estáticos
Se você quiser que todas as variáveis de um módulo sejam estáticas, utilize a palavra chave Static antes de declarar um procedimento. Logo, a instrução a seguir:
Sub MostrarContadores() Static FirstName As String Static FelipeCount As Long Static RenataCount As Long FirstName = "Felipe" FelipeCount = FelipeCount + 1 RenataCount = RenataCount + 5 End Sub
É equivalente a:
Static MostrarContadores() Dim FirstName As String Dim FelipeCount As Long Dim RenataCount As Long FirstName = "Felipe" FelipeCount = FelipeCount + 1 RenataCount = RenataCount + 5 End Sub
Em ambos os casos, todas as variáveis serão estáticas.
Nível de Módulo
Variáveis de nível de módulo podem ser acessadas de qualquer procedimento de um módulo, mas não por outros módulos. Elas devem ser declaradas na seção de declaração do módulo, antes de todos os procedimentos. Tomando como base o exemplo anterior, veja o código abaixo:
Option Explicit Dim FirstName As String Sub Exemplo1() FirstName = "Felipe" MsgBox FirstName Exemplo2 End Sub Sub Exemplo2() MsgBox FirstName End Sub
Exemplo2
é capaz de acessar a variável FirstName
porque ela é de nível de módulo.
msFirstName
. m de nível de módulo, e s de String.Se você declarar uma variável local com o mesmo nome de uma variável de módulo desse módulo, o VBA dará prioridade de acesso à variável local.
Nível Global
Variáveis globais (ou públicas) podem ser acessadas por qualquer procedimento de um projeto. Variáveis públicas são declaradas com a instrução Public
e sua declaração deve estar na seção de declaração.
A figura a seguir mostra a declaração de uma variável pública e o subprocedimento Main
atribui um valor a ela. Em seguida, chama-se um subprocedimento de outro módulo para exibir o valor dessa variável.
Se você tiver uma variável de módulo e uma de global com o mesmo nome, o VBA dará prioridade à de nível de módulo. Logo, o VBA dá prioridade a acessar variáveis de mesmo nome na seguinte ordem: locais, de módulo e globais.
PublicVariables
. Dessa forma, você manterá seu projeto organizado.Preservação de Estado de Variáveis
Você deve ficar atento porque, com exceção de variáveis locais, o VBA preserva o valor de uma variável ao terminar a execução de um programa. Então, se você executar o programa novamente, essas variáveis terão um valor inicial igual ao que tinham quando o programa terminou pela última vez.
Observe o código a seguir:
Public Pública As Long Dim Módulo As Long Private Sub Main() Static Estática As Long Dim ProcedimentoLocal As Long Pública = Pública + 1 Módulo = Módulo + 1 Estática = Estática + 1 ProcedimentoLocal = ProcedimentoLocal + 1 Debug.Print "Pública: " & Pública Debug.Print "Módulo: " & Módulo Debug.Print "Estática: " & Estática Debug.Print "Procedimento/Local: " & ProcedimentoLocal End Sub
Se executa-lo pela primeira vez, você obterá na Janela de Verificação Imediata:
Pública: 1 Módulo: 1 Estática: 1 Local: 1
Executando o mesmo subprocedimento novamente, obterá:
Pública: 2 Módulo: 2 Estática: 2 Local: 1
Mais uma vez:
Pública: 3 Módulo: 3 Estática: 3 Local: 1
É fácil ver que com exceção da variável local, todas as outras preservaram seu valor na execução.
Perda de Estado de Variáveis
A propriedade de manter o estado das variáveis só é verdadeira se você não fizer “grandes” alterações no seu código entre uma execução e outra de macros. Por exemplo, se você executar a macro anterior algumas vezes, seleciona-la por completo no VBE, apagá-la (tendo copiado antes) e colar o mesmo código novamente no mesmo lugar, a saída do programa será:
Pública: 1 Módulo: 1 Estática: 1 Local: 1
Todas as variáveis – não só locais – foram reiniciadas. O nome desse fenômeno é Perda de Estado.
Note que utilizei o termo “grandes” alterações, mas não é bem isso. O VBE perde o estado das variáveis, normalmente, quando você exclui um procedimento ou declarações de variáveis. Se você fizer algumas alterações no código que não envolva declarações, não obterá esse efeito.
É possível habilitar um alerta para que você seja notificado toda vez que fizer uma alteração que implicará na perda de estado das variáveis. Para tal, clique no menu Ferramentas >> Opções >> guia Geral >> caixa de seleção Notificar antes de perda de estado:
Reiniciar Valores de Variáveis
Você deve ficar atento que enquanto estiver tempo de design trabalhando no seu projeto, não fazer premissas que todas as variáveis são reiniciadas ou já possuem determinado valor, conforme subseção anterior.
Tenho o hábito de reiniciar os valores de todas variáveis que não sejam locais. O exemplo a seguir mostra um pouco disso:
Public glLastRow As Long Dim msName As String Sub Main() Dim dtBirth As Date glLastRow = 0 msName = "" '...continuação do programa End Sub
Note que não há necessidade de reiniciar o valor de dtBirth
, porque ela é uma variável local e já perde seu estado naturalmente a cada nova execução do procedimento em que se encontra.
Em programas grandes, para evitar confusão, costumo criar um procedimento só para reiniciar variáveis que tem a propriedade de manter seu estado, como mostra o exemplo a seguir:
Public Global1 As Long Public Global2 As Long Dim Módulo1 As String Private Sub Main() ReiniciarVariáveis '...código do programa End Sub Sub ReiniciarVariáveis() Global1 = 0 Global2 = 0 Módulo1 = "" End Sub
Deixar Um Comentário
Você precise estar logged in para postar um comentário.