Why Word VBA Object Variable Reference Lost After Document Reopen
🔍 WiseChecker

Why Word VBA Object Variable Reference Lost After Document Reopen

You write a VBA macro in Word that stores a reference to a document, range, or table. After you close and reopen the document, the object variable no longer points to the expected object. This happens because VBA object variables are stored in memory and do not persist across document sessions. When you reopen the document, the variable is reset to Nothing unless you reinitialize it. This article explains the technical reason for the lost reference and shows you how to write persistent code that works correctly after a reopen.

Key Takeaways: Object Variable Persistence in Word VBA

  • Dim statement with Set: Always reinitialize object variables after reopening a document because VBA does not save object references between sessions.
  • ThisDocument object: Use ThisDocument instead of a generic Document variable to keep a stable reference to the document that contains the macro.
  • Document_Open event: Place reinitialization code in the Document_Open event to automatically restore object references when the document is reopened.

ADVERTISEMENT

Why Word VBA Object Variables Lose Their References After Reopen

VBA stores object variables in the computer’s RAM while the macro runs. When you close the document, Word unloads the VBA project and clears all variables from memory. The next time you open the document, VBA starts a fresh session. Any variable that was assigned with the Set statement is set to Nothing because the original object no longer exists in memory.

This behavior is by design. VBA variables are not saved to the document file. Only the code itself is saved. When you reopen the document, the code runs again from the beginning. If you declared a variable at module level and assigned it in a procedure, that assignment is lost. The variable remains declared but unassigned until you run code that sets it again.

The same principle applies to object variables that reference other documents, ranges, tables, or any COM object. Word does not serialize object references into the document binary. The variable is a pointer to a memory address, and that address is invalid after a close and reopen.

How VBA Stores Variables in Memory

VBA uses a call stack for procedure-level variables and a static data area for module-level variables. Module-level variables declared with Dim or Private persist as long as the VBA project is loaded. When the document closes, the VBA project unloads and all memory is released. Static variables inside a procedure also lose their values because the entire procedure’s memory is reclaimed.

Why This Matters for Your Code

If your macro assumes that a module-level object variable still holds a valid reference after a reopen, the code will fail with runtime error 91 “Object variable or With block variable not set.” This error occurs when you try to access a property or method of an object that is Nothing. The fix is to always reinitialize object variables before using them, especially after a document reopen.

Steps to Keep Object Variables Valid After Reopen

Apply these three methods to ensure your VBA code works correctly after closing and reopening the document. Each method addresses a different scenario.

Method 1: Reinitialize Variables in the Document_Open Event

  1. Open the VBA editor
    Press Alt+F11 to open the Visual Basic Editor. In the Project Explorer, double-click ThisDocument under the document’s project.
  2. Select the Document_Open event
    In the code window, choose Document from the left dropdown and Open from the right dropdown. This creates an empty Document_Open procedure.
  3. Write reinitialization code
    Inside the Document_Open procedure, assign your object variable again. For example:
    Set myDoc = ThisDocument
    Set myRange = ThisDocument.Range(Start:=0, End:=100)
  4. Declare the variable at module level
    At the top of the module, declare the variable with Dim myDoc As Document or Private myDoc As Document. Do not declare it inside a procedure if you need it to persist across multiple procedures.
  5. Test the code
    Save the document, close it, and reopen it. The Document_Open event runs automatically and reinitializes the variable. Your other procedures can now use myDoc without getting error 91.

Method 2: Use the ThisDocument Object Instead of a Variable

  1. Understand ThisDocument
    ThisDocument is a built-in object that always refers to the document containing the macro. It does not need to be assigned with Set and is always valid when the code runs.
  2. Replace your variable with ThisDocument
    Instead of Set myDoc = ActiveDocument, use ThisDocument directly in your code. For example:
    ThisDocument.Range(1, 1).Text = "Hello"
  3. Remove the module-level variable
    If you no longer need the variable, delete its declaration. This simplifies your code and eliminates the risk of an unassigned variable.
  4. Use ThisDocument for ranges and tables
    For child objects, set them relative to ThisDocument inside each procedure. Example:
    Dim tbl As Table
    Set tbl = ThisDocument.Tables(1)

Method 3: Reassign Variables at the Start of Each Procedure

  1. Declare variables locally
    Instead of module-level variables, declare them inside each procedure with Dim. This ensures they are fresh every time the procedure runs.
  2. Assign the variable at the top of the procedure
    Write Set myDoc = ThisDocument or Set myDoc = Documents.Open("C:\path\file.docx") immediately after the Dim line.
  3. Pass the variable to other procedures
    If multiple procedures need the same object, pass it as a parameter. Example:
    Call ProcessDocument(myDoc)
  4. Avoid relying on previous assignments
    Do not assume that a variable set in an earlier procedure still holds a valid reference. Each procedure that needs the object must set it.

ADVERTISEMENT

If Your Code Still Fails After Reopen

“Object variable or With block variable not set” Error on Any Procedure

This error means you are trying to use an object variable that is Nothing. Check that you have declared the variable at module level or passed it correctly. Verify that the Document_Open event is present and contains the Set statement. If the event does not fire, check that macros are enabled. Go to File > Options > Trust Center > Trust Center Settings > Macro Settings and select Enable all macros for testing.

Variable Holds a Reference to the Wrong Document

If you used ActiveDocument in the Document_Open event, it might reference a different document if multiple documents are open. Use ThisDocument instead of ActiveDocument inside Document_Open to guarantee you are pointing to the document that contains the macro. The same applies to any event procedure that runs when the document is not the active one.

Static Variables Also Lose Their Values

Variables declared with the Static keyword inside a procedure retain their values between calls within the same VBA session. After a reopen, the entire VBA project resets and static variables are cleared. If you need a value to survive a reopen, store it in a custom document property or in the Windows Registry using the SaveSetting and GetSetting functions.

Item Module-Level Variable ThisDocument Object
Persistence after reopen Lost — requires reinitialization Always valid without Set
Memory usage One pointer per variable No extra memory
Risk of error 91 High if not reinitialized None
Best use case Multiple procedures need same object Single document macros

Use module-level variables with the Document_Open event for complex macros that need to share an object reference. Use ThisDocument directly for simple scripts that only work on the document containing the macro. Always test your code after a reopen to confirm the variable is assigned.

ADVERTISEMENT