Por que a Referência de Variável de Objeto VBA do Word é Perdida Após Reabrir o Documento
🔍 WiseChecker

Por que a Referência de Variável de Objeto VBA do Word é Perdida Após Reabrir o Documento

Você escreve uma macro VBA no Word que armazena uma referência a um documento, intervalo ou tabela. Depois de fechar e reabrir o documento, a variável de objeto não aponta mais para o objeto esperado. Isso acontece porque as variáveis de objeto VBA são armazenadas na memória e não persistem entre sessões do documento. Ao reabrir o documento, a variável é redefinida para Nothing a menos que você a reinicialize. Este artigo explica o motivo técnico da perda de referência e mostra como escrever código persistente que funcione corretamente após uma reabertura.

Principais Conclusões: Persistência de Variáveis de Objeto no VBA do Word

  • Instrução Dim com Set: Sempre reinicialize variáveis de objeto após reabrir um documento, pois o VBA não salva referências de objeto entre sessões.
  • Objeto ThisDocument: Use ThisDocument em vez de uma variável genérica Document para manter uma referência estável ao documento que contém a macro.
  • Evento Document_Open: Coloque o código de reinicialização no evento Document_Open para restaurar automaticamente as referências de objeto quando o documento for reaberto.

ADVERTISEMENT

Por que as Variáveis de Objeto VBA do Word Perdem Suas Referências Após Reabrir

O VBA armazena variáveis de objeto na RAM do computador enquanto a macro é executada. Quando você fecha o documento, o Word descarrega o projeto VBA e limpa todas as variáveis da memória. Na próxima vez que abrir o documento, o VBA inicia uma nova sessão. Qualquer variável que foi atribuída com a instrução Set é definida como Nothing porque o objeto original não existe mais na memória.

Esse comportamento é proposital. As variáveis VBA não são salvas no arquivo do documento. Apenas o código é salvo. Quando você reabre o documento, o código é executado novamente desde o início. Se você declarou uma variável no nível do módulo e a atribuiu em um procedimento, essa atribuição é perdida. A variável permanece declarada, mas não atribuída, até que você execute um código que a defina novamente.

O mesmo princípio se aplica a variáveis de objeto que referenciam outros documentos, intervalos, tabelas ou qualquer objeto COM. O Word não serializa referências de objeto no binário do documento. A variável é um ponteiro para um endereço de memória, e esse endereço se torna inválido após fechar e reabrir.

Como o VBA Armazena Variáveis na Memória

O VBA usa uma pilha de chamadas para variáveis de nível de procedimento e uma área de dados estática para variáveis de nível de módulo. Variáveis de nível de módulo declaradas com Dim ou Private persistem enquanto o projeto VBA estiver carregado. Quando o documento fecha, o projeto VBA é descarregado e toda a memória é liberada. Variáveis estáticas dentro de um procedimento também perdem seus valores porque toda a memória do procedimento é recuperada.

Por que Isso é Importante para Seu Código

Se sua macro assume que uma variável de objeto de nível de módulo ainda contém uma referência válida após uma reabertura, o código falhará com o erro de tempo de execução 91 “Variável de objeto ou variável With block não definida”. Esse erro ocorre quando você tenta acessar uma propriedade ou método de um objeto que é Nothing. A solução é sempre reinicializar as variáveis de objeto antes de usá-las, especialmente após reabrir o documento.

Passos para Manter Variáveis de Objeto Válidas Após Reabrir

Aplique estes três métodos para garantir que seu código VBA funcione corretamente após fechar e reabrir o documento. Cada método aborda um cenário diferente.

Método 1: Reinicializar Variáveis no Evento Document_Open

  1. Abra o editor VBA
    Pressione Alt+F11 para abrir o Editor Visual Basic. No Explorador de Projetos, clique duas vezes em ThisDocument no projeto do documento.
  2. Selecione o evento Document_Open
    Na janela de código, escolha Document no menu suspenso esquerdo e Open no menu suspenso direito. Isso cria um procedimento Document_Open vazio.
  3. Escreva o código de reinicialização
    Dentro do procedimento Document_Open, atribua sua variável de objeto novamente. Por exemplo:
    Set meuDoc = ThisDocument
    Set meuIntervalo = ThisDocument.Range(Start:=0, End:=100)
  4. Declare a variável no nível do módulo
    No topo do módulo, declare a variável com Dim meuDoc As Document ou Private meuDoc As Document. Não a declare dentro de um procedimento se precisar que ela persista entre vários procedimentos.
  5. Teste o código
    Salve o documento, feche-o e reabra-o. O evento Document_Open é executado automaticamente e reinicializa a variável. Seus outros procedimentos agora podem usar meuDoc sem obter o erro 91.

Método 2: Usar o Objeto ThisDocument em Vez de uma Variável

  1. Entenda o ThisDocument
    ThisDocument é um objeto interno que sempre se refere ao documento que contém a macro. Ele não precisa ser atribuído com Set e é sempre válido quando o código é executado.
  2. Substitua sua variável por ThisDocument
    Em vez de Set meuDoc = ActiveDocument, use ThisDocument diretamente em seu código. Por exemplo:
    ThisDocument.Range(1, 1).Text = "Olá"
  3. Remova a variável de nível de módulo
    Se você não precisar mais da variável, exclua sua declaração. Isso simplifica seu código e elimina o risco de uma variável não atribuída.
  4. Use ThisDocument para intervalos e tabelas
    Para objetos filhos, defina-os em relação a ThisDocument dentro de cada procedimento. Exemplo:
    Dim tbl As Table
    Set tbl = ThisDocument.Tables(1)

Método 3: Reatribuir Variáveis no Início de Cada Procedimento

  1. Declare variáveis localmente
    Em vez de variáveis de nível de módulo, declare-as dentro de cada procedimento com Dim. Isso garante que elas sejam novas toda vez que o procedimento for executado.
  2. Atribua a variável no topo do procedimento
    Escreva Set meuDoc = ThisDocument ou Set meuDoc = Documents.Open("C:\caminho\arquivo.docx") imediatamente após a linha Dim.
  3. Passe a variável para outros procedimentos
    Se vários procedimentos precisarem do mesmo objeto, passe-o como parâmetro. Exemplo:
    Call ProcessarDocumento(meuDoc)
  4. Evite confiar em atribuições anteriores
    Não presuma que uma variável definida em um procedimento anterior ainda contém uma referência válida. Cada procedimento que precisar do objeto deve defini-lo.

ADVERTISEMENT

Se Seu Código Ainda Falhar Após Reabrir

“Variável de objeto ou variável With block não definida” em Qualquer Procedimento

Esse erro significa que você está tentando usar uma variável de objeto que é Nothing. Verifique se você declarou a variável no nível do módulo ou a passou corretamente. Confirme que o evento Document_Open está presente e contém a instrução Set. Se o evento não for disparado, verifique se as macros estão habilitadas. Vá em Arquivo > Opções > Central de Confiabilidade > Configurações da Central de Confiabilidade > Configurações de Macro e selecione Habilitar todas as macros para teste.

Variável Mantém uma Referência ao Documento Errado

Se você usou ActiveDocument no evento Document_Open, ele pode referenciar um documento diferente se vários documentos estiverem abertos. Use ThisDocument em vez de ActiveDocument dentro de Document_Open para garantir que você está apontando para o documento que contém a macro. O mesmo se aplica a qualquer procedimento de evento que seja executado quando o documento não está ativo.

Variáveis Estáticas Também Perdem Seus Valores

Variáveis declaradas com a palavra-chave Static dentro de um procedimento retêm seus valores entre chamadas dentro da mesma sessão VBA. Após uma reabertura, todo o projeto VBA é redefinido e as variáveis estáticas são limpas. Se você precisar que um valor sobreviva a uma reabertura, armazene-o em uma propriedade de documento personalizada ou no Registro do Windows usando as funções SaveSetting e GetSetting.

Item Variável de Nível de Módulo Objeto ThisDocument
Persistência após reabrir Perdida — requer reinicialização Sempre válida sem Set
Uso de memória Um ponteiro por variável Sem memória extra
Risco de erro 91 Alto se não reinicializada Nenhum
Melhor caso de uso Vários procedimentos precisam do mesmo objeto Macros de documento único

Use variáveis de nível de módulo com o evento Document_Open para macros complexas que precisam compartilhar uma referência de objeto. Use ThisDocument diretamente para scripts simples que funcionam apenas no documento que contém a macro. Sempre teste seu código após uma reabertura para confirmar que a variável foi atribuída.

ADVERTISEMENT