TL;DR —
wb.Closeon a workbook with unsaved changes shows the modal "Do you want to save your changes?" dialog — which freezes an unattended macro forever. Answer it in code with theSaveChangesargument:
Sub CloseWithoutPrompt()
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Reports\March.xlsx")
' ... read what you need ...
wb.Close SaveChanges:=False ' answer the prompt in code - no dialog, no hang
Set wb = Nothing ' the reference is dead after Close
End Sub
Closing is where a batch macro that ran perfectly all night is found the next morning still stuck on a dialog
box, having processed one file out of two hundred. wb.Close does not just shut a workbook — it asks a
question, and if you do not answer it in code, Excel asks the user, and the user is not there. This guide is
built on that one idea: SaveChanges is your answer, and every close bug is a version of forgetting to give
it.
What you'll learn
- The mental model —
Closeasks "save changes?"; theSaveChangesargument is your answer in code - The number-one hang — closing a dirty workbook with no
SaveChangesfreezes an unattended macro - The mirror danger —
SaveChanges:=Falsediscards silently, so decide deliberately - Why the object variable is dead the instant you close, and reading it errors
wb.Close(one workbook) vsApplication.Quit(all of Excel), and the invisibleEXCEL.EXEtrap- Why close-with-save inherits every Save trap
The mental model: Close asks a question — answer it in code
When a workbook has unsaved changes, wb.Close cannot just close it — Excel does not know whether you want
those changes kept. So it does what it does for a human: it pops the "Do you want to save your changes?"
dialog and waits. That is fine when a person is sitting there. In a macro, you are the one who has to answer,
and you answer with the SaveChanges argument:
wb.Close SaveChanges:=False ' close and DISCARD unsaved changes
wb.Close SaveChanges:=True ' SAVE first, then close
wb.Close ' no answer - Excel asks the USER (the prompt)
Give the answer in code and the dialog never appears. Omit it on a dirty book and you are back to the prompt.
The number-one hang: no SaveChanges on a dirty workbook
This is the failure behind "my scheduled macro never finished." The macro opens a file, changes something —
even a recalculation or a Worksheet_Change handler marks the workbook dirty — and then:
wb.Close ' dirty book, no SaveChanges -> "save changes?" dialog -> hangs forever
There is no one at the keyboard to click Yes or No, so the macro sits on that modal dialog indefinitely. The
whole batch stalls behind it. The fix is to always pass SaveChanges on any Close that might run
unattended:
wb.Close SaveChanges:=False ' read-only processing: discard, never prompt
If you remember one line from this page, make it wb.Close SaveChanges:=False for anything you only read.
The mirror danger: False discards silently
SaveChanges:=False is the cure for the hang, and it is also its own trap. It throws away unsaved changes
with no undo and no confirmation. If the macro actually did work you meant to keep, SaveChanges:=False
deletes it silently. So decide on purpose:
- Only read the file?
wb.Close SaveChanges:=False— nothing to keep, never prompt. - Wrote results you want kept?
wb.Close SaveChanges:=True— orwb.Savefirst, thenwb.Close SaveChanges:=False, which is clearer because the save and the close are separate, visible steps.
The prompt exists to stop a human from losing work. When you suppress it with an argument, you take on that responsibility.
The reference is dead after Close
Once wb.Close runs, the workbook is gone from memory and the variable wb points at nothing. Touching it
throws an error:
wb.Close SaveChanges:=False
MsgBox wb.Name ' ERROR - wb no longer refers to an open workbook
So read everything you need before you close, and set the variable to Nothing afterward to make the
intent explicit:
Dim finalName As String
finalName = wb.Name ' capture BEFORE closing
wb.Close SaveChanges:=False
Set wb = Nothing ' the reference is dead; say so
MsgBox "Closed " & finalName
Close a workbook vs quit Excel — and the invisible EXCEL.EXE
wb.Close closes one workbook. Application.Quit closes Excel itself. They are not interchangeable,
and two edge cases bite:
ThisWorkbook.Closecloses the workbook whose macro is running. Any code after that line may not execute. Close other workbooks from a macro; close your own last, or not at all.- Closing the last workbook can leave an invisible
EXCEL.EXErunning. If your code still holds a reference to anApplicationorWorkbookobject when the last window closes, Excel cannot fully shut down and lingers as a ghost process in Task Manager. Release your references (Set wb = Nothing,Set xlApp = Nothing) so the process can exit. This is the classic bug behind "Excel keeps running after my macro ends."
Close-with-save inherits every Save trap
wb.Close SaveChanges:=True runs a Save on the way out — so it inherits every trap from
VBA Save Workbook:
- On a never-saved book, close-with-save has no path and falls back to the Save As dialog (hangs). Give
it a path with
SaveAsfirst, or close withSaveChanges:=Falseif you do not need it kept. - On a macro workbook saved with the wrong FileFormat, close-with-save can re-raise the macro-stripping
warning. If code matters, the file is
.xlsm.
When in doubt, split the steps: wb.Save (or wb.SaveAs path, format) on its own line, then
wb.Close SaveChanges:=False. Two visible operations beat one that silently does both.
The honest verdict: the batch-loop pattern
Everything above collapses into one reliable shape. In a folder loop, open and close inside the loop so you never accumulate open workbooks holding file locks:
Dim name As String
name = Dir("C:\Reports\*.xlsx")
Do While name <> ""
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Reports\" & name)
' ... read the totals ...
wb.Close SaveChanges:=False ' answer in code every iteration
Set wb = Nothing
name = Dir ' next file
Loop
SaveChanges:=False is the default for read-only processing; SaveChanges:=True when you wrote results.
Never rely on the prompt, always answer it, read before you close, and release the reference. Do that and the
close step — the one that quietly stalls unattended jobs — becomes the boring, reliable end of every file you
open.
How ExcelMaster helps
The close step is deceptively dangerous: forget SaveChanges and a scheduled macro hangs on a dialog; pass
False when you meant True and finished work vanishes; hold a stray reference and Excel lingers as a ghost
process. These are the bugs that only show up at 3 a.m. when no one is watching.
ExcelMaster writes the close the way a
careful automation engineer would. Describe the job — "process every file in this folder and close each
without saving" — and it opens with Set wb = Workbooks.Open(...), reads what it needs before closing, passes
an explicit SaveChanges on every wb.Close, releases the reference with Set wb = Nothing, and never leaves
a workbook open or an Excel process ghosted. No hang, no silent data loss.
Frequently asked questions
How do I close a workbook without saving in VBA?
Pass SaveChanges:=False: wb.Close SaveChanges:=False. This answers the "save changes?" prompt in code with
"no," so the dialog never appears and the workbook closes discarding any unsaved changes. It is the correct
close for read-only processing where there is nothing to keep.
Why does my macro hang when it closes a workbook?
Because you called wb.Close on a workbook with unsaved changes without a SaveChanges argument. Excel shows
the modal "Do you want to save your changes?" dialog and waits for a click that never comes in an unattended
run. Always pass SaveChanges:=False or SaveChanges:=True on any close that runs without a person watching.
What is the difference between wb.Close and Application.Quit?
wb.Close closes a single workbook and leaves Excel running. Application.Quit closes Excel entirely,
including every open workbook. Use Close to finish with one file in a loop; use Quit only when your code
launched its own Excel instance and needs to shut it down.
Why does Excel keep running after my VBA macro closes the workbook?
Your code still holds a reference to a Workbook or Application object, so Excel cannot fully shut down and
lingers as an invisible EXCEL.EXE process. Release the references — Set wb = Nothing and
Set xlApp = Nothing — after closing, so the process can exit cleanly.
Can I read a workbook's properties after closing it in VBA?
No. Once wb.Close runs, the workbook is out of memory and the variable no longer refers to anything;
wb.Name or wb.Sheets will error. Capture whatever you need into variables before calling Close, then
Set wb = Nothing.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-20.
Related guides: VBA Open Workbook · VBA Save Workbook · VBA Workbook_BeforeClose Event · VBA DisplayAlerts · VBA DoEvents
