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
ThisDocumentem vez de uma variável genéricaDocumentpara 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_Openpara restaurar automaticamente as referências de objeto quando o documento for reaberto.
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
- 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. - 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 procedimentoDocument_Openvazio. - Escreva o código de reinicialização
Dentro do procedimentoDocument_Open, atribua sua variável de objeto novamente. Por exemplo:Set meuDoc = ThisDocument
Set meuIntervalo = ThisDocument.Range(Start:=0, End:=100) - Declare a variável no nível do módulo
No topo do módulo, declare a variável comDim meuDoc As DocumentouPrivate meuDoc As Document. Não a declare dentro de um procedimento se precisar que ela persista entre vários procedimentos. - Teste o código
Salve o documento, feche-o e reabra-o. O eventoDocument_Opené executado automaticamente e reinicializa a variável. Seus outros procedimentos agora podem usarmeuDocsem obter o erro 91.
Método 2: Usar o Objeto ThisDocument em Vez de uma Variável
- 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 comSete é sempre válido quando o código é executado. - Substitua sua variável por ThisDocument
Em vez deSet meuDoc = ActiveDocument, useThisDocumentdiretamente em seu código. Por exemplo:ThisDocument.Range(1, 1).Text = "Olá" - 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. - Use ThisDocument para intervalos e tabelas
Para objetos filhos, defina-os em relação aThisDocumentdentro 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
- Declare variáveis localmente
Em vez de variáveis de nível de módulo, declare-as dentro de cada procedimento comDim. Isso garante que elas sejam novas toda vez que o procedimento for executado. - Atribua a variável no topo do procedimento
EscrevaSet meuDoc = ThisDocumentouSet meuDoc = Documents.Open("C:\caminho\arquivo.docx")imediatamente após a linhaDim. - Passe a variável para outros procedimentos
Se vários procedimentos precisarem do mesmo objeto, passe-o como parâmetro. Exemplo:Call ProcessarDocumento(meuDoc) - 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.
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.