Troubleshooting “Object Variable Not Set” in Workbook Open Scripts
The Workbook_Open event handler runs every time the file opens. Recently, it started erroring on the second line: “Run-time error ’91’: Object variable or With block variable not set.” The macro hasn’t changed. Excel hasn’t been updated obviously. Yet a Worksheet reference that worked yesterday now returns Nothing. Workbook_Open runs early in the loading process — before all components are fully initialized, certain object references are unreliable.
Before You Start: The 60-Second Diagnostic
Three checks:
- Identify the failing line: Which object is Nothing?
- Check timing: Workbook_Open runs before some operations are complete (e.g., reference resolution, dependency loading).
- Test outside the event: Run the same code from a button after open — does it work?
Step-by-Step Solution
H2: Use ThisWorkbook, Not ActiveWorkbook
In Workbook_Open, ActiveWorkbook may not be the workbook being opened:
Wrong:
Private Sub Workbook_Open()
ActiveWorkbook.Worksheets("Data").Range("A1").Value = "Init"
End Sub
ActiveWorkbook refers to whichever workbook is “front” — could be a different workbook the user was viewing.
Right:
Private Sub Workbook_Open()
ThisWorkbook.Worksheets("Data").Range("A1").Value = "Init"
End Sub
ThisWorkbook always refers to the workbook containing the VBA code. Use it consistently in event handlers.
H2: Defer Operations Until Excel is Ready
Some objects aren’t fully initialized when Workbook_Open fires. Defer to immediately after:
Private Sub Workbook_Open()
Application.OnTime Now + TimeValue("00:00:01"), "DelayedInit"
End Sub
Sub DelayedInit()
' Now safe to access most objects
ThisWorkbook.Worksheets("Data").Range("A1").Value = "Init"
End Sub
Application.OnTime schedules the init code for 1 second later, after Excel completes its loading routines.
H2: Initialize Object Variables Explicitly
Object variables before assignment are Nothing:
Private Sub Workbook_Open()
Dim ws As Worksheet
ws.Range("A1").Value = 1 ' Error: ws is Nothing
End Sub
Fix:
Private Sub Workbook_Open()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Data")
ws.Range("A1").Value = 1
End Sub
Always Set before use.
H2: Handle Missing Sheets
If the workbook is opened with a renamed or missing sheet, Worksheets(“Data”) returns Nothing:
Private Sub Workbook_Open()
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets("Data")
On Error GoTo 0
If ws Is Nothing Then
MsgBox "Required sheet 'Data' not found. Please verify the workbook."
Exit Sub
End If
ws.Range("A1").Value = "Init"
End Sub
The On Error pattern catches the missing sheet gracefully instead of crashing the open event.
H2: Handle External Reference Failures
If Workbook_Open references external workbooks that haven’t loaded yet, the references return Nothing:
Private Sub Workbook_Open()
Dim externalWb As Workbook
Set externalWb = Workbooks("Source.xlsx") ' May not be open yet
' ...
End Sub
Defer or explicitly open the external workbook first:
Private Sub Workbook_Open()
Dim externalWb As Workbook
On Error Resume Next
Set externalWb = Workbooks("Source.xlsx")
On Error GoTo 0
If externalWb Is Nothing Then
' External not open — open it
Set externalWb = Workbooks.Open("\\corp\Source.xlsx")
End If
' Now safe to use externalWb
End Sub
This pattern handles both cases: external already open OR needs opening.
H2: Verify Add-in Status
Some object references depend on add-ins being loaded:
Private Sub Workbook_Open()
Dim solver As Object
Set solver = Application.AddIns("Solver Add-In")
' Use solver capabilities
End Sub
If Solver Add-in isn’t loaded, Application.AddIns("Solver Add-In") returns Nothing.
Check and load:
Dim solverAddin As AddIn
Set solverAddin = Application.AddIns("Solver Add-In")
If solverAddin Is Nothing Then
' Solver not installed — install or skip
ElseIf Not solverAddin.Installed Then
solverAddin.Installed = True
End If
Information Gain Box: The Hidden Event Sequence
Here is what determines what’s accessible when in Workbook_Open: Excel events fire in a specific sequence during workbook opening, and some operations only succeed after later events have completed.
The sequence (approximate):
1. Workbook_Open: file is loaded, basic structure available.
2. Workbook_AfterSave: not applicable on open.
3. Worksheet_Activate (for the initial active sheet): fires for whichever sheet was active when saved.
4. Custom UI loaded: any custom ribbon XML processed.
5. External links resolution: external workbook references attempted.
In Workbook_Open:
– ThisWorkbook is available.
– Worksheets collection is available.
– External references may not be resolved yet.
– Add-ins may not be fully loaded.
For operations requiring fully-initialized state, defer with Application.OnTime to after the full open sequence completes.
For dependencies on add-ins, check status before using:
If Application.AddIns("Solver").Installed Then
' Use Solver
Else
' Skip or alert
End If
This sequence is documented in MSDN/Microsoft Learn but rarely surfaced in tutorials. Understanding it explains why “the same code works elsewhere but fails in Workbook_Open.”
Comparison Table: Wrong Way vs. Correct Way
| Issue | Wrong Way (Error 91) | Correct Way |
|---|---|---|
| Active workbook ref | ActiveWorkbook |
ThisWorkbook |
| Early-event timing | Direct operation | Defer with Application.OnTime |
| Object initialization | Use variable without Set | Always Set before use |
| Missing sheet | Assume exists | On Error check, fall through gracefully |
| External workbook | Trust it’s loaded | Check + open if needed |
| Add-in dependency | Use Application.AddIns directly | Check Installed status first |
| Diagnostic | Trust error line | Trace back to where object should be Set |
Original Image Descriptions
Screenshot 1: Show VBA editor paused on ws.Range("A1").Value = "Init" with “Run-time error ’91’: Object variable or With block variable not set.” The Workbook_Open event is visible. The Locals pane shows ws = Nothing. Draw a red circle around ws = Nothing. Add a red annotation: “Object variable Nothing — Set must be called first.”
Screenshot 2: Show the corrected handler with the deferred Application.OnTime pattern. The init runs successfully 1 second after open. Draw a red circle around the Application.OnTime line. Add a red annotation: “Defer init by 1 second — Excel fully ready by then.”
Frequently Asked Questions
Q: Can I prevent the Workbook_Open from running on certain file opens?
A: Yes — hold Shift while opening to suppress events. For programmatic control, the calling code can set Application.EnableEvents = False before opening, then re-enable after. Useful for batch processing where you don’t want each opened workbook’s events to fire.
Q: Why does Application.OnTime sometimes fire later than expected?
A: Excel queues OnTime calls and processes them when idle. If Excel is busy (recalculating, processing other events), OnTime may delay. For precise timing, OnTime is unreliable. For “after-open initialization”, a 1-2 second delay is fine; for sub-second precision, OnTime won’t deliver.
Q: Are there event handlers that fire even earlier than Workbook_Open?
A: Workbook_Open is the first user-accessible event. Earlier (and less commonly used) hooks include Workbook_BeforeClose from a previous session, and Auto_Open subroutines (legacy, mostly replaced by Workbook_Open). For modern code, Workbook_Open is the right place for initialization logic.