TL;DR — 未保存の変更があるブックへの
wb.Closeは、モーダルの「変更を保存しますか」 ダイアログを出します — これが無人マクロを永遠に凍りつかせます。それにはコードで、SaveChanges引数を使って答えましょう。
Sub CloseWithoutPrompt()
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Reports\March.xlsx")
' ... 必要なものを読む ...
wb.Close SaveChanges:=False ' コードでプロンプトに答える - ダイアログなし、ハングなし
Set wb = Nothing ' Close のあと、この参照は死んでいる
End Sub
閉じる処理は、一晩じゅう完璧に走っていたバッチマクロが、翌朝、200 ファイルのうち 1 つを
処理したきりダイアログボックスの前で立ち往生している、という形で見つかる場所です。
wb.Close はただブックを閉じるのではありません — 質問をするのです。そしてあなたが
コードで答えなければ、Excel はユーザーに訊き、そのユーザーはそこにいません。本記事は
このたった一つの考えの上に組み立てられています — SaveChanges はあなたの答えであり、
あらゆる close のバグは、それを渡し忘れた一形態にすぎない、ということです。
この記事で学べること
- 考え方の軸 —
Closeは「変更を保存しますか」と訊く。SaveChanges引数がコードで答えるあなたの返事 - ナンバーワンのハング — 変更ありのブックを
SaveChangesなしで閉じると無人マクロが凍る - 裏返しの危険 —
SaveChanges:=Falseは無言で破棄するので、意図して決める - 閉じた瞬間にオブジェクト変数が死ぬ理由、そしてそれを読むとエラーになること
wb.Close(1 冊のブック)対Application.Quit(Excel 全体)、そして見えないEXCEL.EXEの罠- 保存して閉じると、あらゆる Save の罠を受け継ぐ理由
考え方の軸:Close は質問をする — コードで答える
ブックに未保存の変更があると、wb.Close はただ閉じることができません — その変更を残したい
のかどうかを、Excel は知らないからです。だから人間に対してするのと同じことをします —
**「変更を保存しますか」*ダイアログを出して待つのです。人がそこに座っているならそれでよい。
マクロでは、答えなければならないのはあなた*で、あなたは SaveChanges 引数で答えます。
wb.Close SaveChanges:=False ' 閉じて、未保存の変更を破棄する
wb.Close SaveChanges:=True ' 先に保存してから閉じる
wb.Close ' 答えなし - Excel はユーザーに訊く(プロンプト)
コードで答えを渡せば、ダイアログは決して現れません。変更ありのブックでそれを省けば、また プロンプトに逆戻りです。
ナンバーワンのハング:変更ありのブックに SaveChanges がない
これが「スケジュールしたマクロが終わらなかった」の裏にある失敗です。マクロがファイルを開き、
何かを変え — 再計算や Worksheet_Change ハンドラーですらブックを変更ありにします — そして。
wb.Close ' 変更ありのブック、SaveChanges なし -> 「変更を保存しますか」ダイアログ -> 永遠にハング
キーボードの前で「はい」も「いいえ」もクリックする人がいないので、マクロはそのモーダル
ダイアログの前に無期限に座り込みます。バッチ全体がその後ろでつかえます。直し方は、無人で
走りうるあらゆる Close で必ず SaveChanges を渡すことです。
wb.Close SaveChanges:=False ' 読み取りだけの処理:破棄する、決してプロンプトを出さない
このページから一行だけ覚えるなら、読むだけのものには wb.Close SaveChanges:=False に
してください。
裏返しの危険:False は無言で破棄する
SaveChanges:=False はハングの治療薬であり、同時にそれ自身の罠でもあります。それは元に
戻す手段も確認もなしに、未保存の変更を捨てます。 もしマクロが実際に、残したかった仕事を
していたなら、SaveChanges:=False はそれを無言で消します。だから意図して決めましょう。
- ファイルを読むだけ?
wb.Close SaveChanges:=False— 残すものはない、決してプロンプト を出さない。 - 残したい結果を書き込んだ?
wb.Close SaveChanges:=True— あるいは先にwb.Save、 それからwb.Close SaveChanges:=False。保存と close が別々の見える手順になるので、 こちらのほうが明快です。
プロンプトは、人間が仕事を失うのを止めるために存在します。それを引数で抑止するとき、その 責任を引き受けるのはあなたです。
Close のあと参照は死んでいる
wb.Close が走ると、ブックはメモリから消え、変数 wb は何も指さなくなります。それに触れる
とエラーになります。
wb.Close SaveChanges:=False
MsgBox wb.Name ' エラー - wb はもう開いているブックを指していない
だから閉じる前に必要なものをすべて読み、そのあと変数を Nothing に設定して意図を
はっきりさせましょう。
Dim finalName As String
finalName = wb.Name ' 閉じる前に取得する
wb.Close SaveChanges:=False
Set wb = Nothing ' 参照は死んでいる。そう明言する
MsgBox "Closed " & finalName
ブックを閉じる対 Excel を終了する — そして見えない EXCEL.EXE
wb.Close は1 冊のブックを閉じます。Application.Quit はExcel そのものを閉じます。
両者は交換可能ではなく、2 つの落とし穴が噛みついてきます。
ThisWorkbook.Closeは、そのマクロが走っているブックを閉じます。 その行より後の コードは実行されないかもしれません。マクロからはほかのブックを閉じ、自分自身は最後に、 あるいはまったく閉じないこと。- 最後のブックを閉じると、見えない
EXCEL.EXEが走り続けることがあります。 最後の ウィンドウが閉じるときにコードがまだApplicationやWorkbookオブジェクトへの参照を 握っていると、Excel は完全にシャットダウンできず、タスクマネージャーの中にゴースト プロセスとして残ります。参照を解放しましょう(Set wb = Nothing、Set xlApp = Nothing) — そうすればプロセスは終了できます。これが「マクロが終わっても Excel が動き続ける」の 裏にある古典的なバグです。
保存して閉じると、あらゆる Save の罠を受け継ぐ
wb.Close SaveChanges:=True は、閉じる途中で Save を走らせます — だから
VBA Save Workbook のあらゆる罠を受け継ぎます。
- 一度も保存していないブックでは、保存して閉じてもパスがないので、名前を付けて保存
ダイアログにフォールバックします(ハングする)。先に
SaveAsでパスを与えるか、残す 必要がなければSaveChanges:=Falseで閉じましょう。 - 間違った FileFormat で保存したマクロブックでは、保存して閉じるときにマクロ剥がしの
警告が再び出ることがあります。コードが大事なら、ファイルは
.xlsmです。
迷ったら、手順を分けましょう — wb.Save(または wb.SaveAs path, format)を独立した行に、
それから wb.Close SaveChanges:=False。見える 2 つの操作は、無言で両方をこなす 1 つより
勝ります。
正直な結論:バッチループのパターン
以上のすべては、一つの信頼できる形にまとまります。フォルダーループでは、ファイルロックを 握った開いたままのブックをためこまないよう、ループの内側で開いて閉じます。
Dim name As String
name = Dir("C:\Reports\*.xlsx")
Do While name <> ""
Dim wb As Workbook
Set wb = Workbooks.Open("C:\Reports\" & name)
' ... 合計を読む ...
wb.Close SaveChanges:=False ' 反復ごとにコードで答える
Set wb = Nothing
name = Dir ' 次のファイル
Loop
SaveChanges:=False は読み取りだけの処理の既定、SaveChanges:=True は結果を書き込んだとき。
プロンプトに寄りかからず、つねに答え、閉じる前に読み、参照を解放する。そうすれば、無人
ジョブを静かに止めるあの close のステップは、あなたが開いた
どのファイルにとっても、退屈で信頼できる終わりになります。
ExcelMaster の活用
close のステップは、見かけによらず危険です — SaveChanges を忘れればスケジュールした
マクロがダイアログでハングし、True のつもりで False を渡せば仕上げた仕事が消え、迷子の
参照を握れば Excel がゴーストプロセスとして居座ります。これらは、誰も見ていない午前 3 時に
だけ姿を現すバグです。
ExcelMaster は、
慎重な自動化エンジニアが書くように close を書きます。ジョブを説明すれば — 「このフォルダーの
全ファイルを処理して、それぞれ保存せずに閉じて」 — それが Set wb = Workbooks.Open(...) で
開き、閉じる前に必要なものを読み、すべての wb.Close に明示的な SaveChanges を渡し、
Set wb = Nothing で参照を解放し、ブックを開いたままにも Excel プロセスをゴースト化する
こともありません。ハングなし、無言のデータ損失なし。
よくある質問
VBA で保存せずにブックを閉じるには?
SaveChanges:=False を渡します:wb.Close SaveChanges:=False。これは「変更を保存しますか」
プロンプトにコードで「いいえ」と答えるので、ダイアログは決して現れず、ブックは未保存の変更を
破棄して閉じます。残すものがない読み取り専用の処理には、これが正しい close です。
ブックを閉じるときにマクロがハングするのはなぜですか?
未保存の変更があるブックに対して、SaveChanges 引数なしで wb.Close を呼んだからです。
Excel はモーダルの「変更を保存しますか」ダイアログを出し、無人実行では決して来ないクリックを
待ちます。人が見ていない状態で走るあらゆる close では、つねに SaveChanges:=False か
SaveChanges:=True を渡しましょう。
wb.Close と Application.Quit の違いは何ですか?
wb.Close は 1 冊のブックを閉じ、Excel は走ったままです。Application.Quit は、開いている
すべてのブックを含めて、Excel を丸ごと閉じます。ループの中で 1 つのファイルを終えるには
Close を、コードが自前の Excel インスタンスを起動してそれをシャットダウンする必要がある
ときにだけ Quit を使いましょう。
VBA マクロがブックを閉じても Excel が動き続けるのはなぜですか?
コードがまだ Workbook や Application オブジェクトへの参照を握っているため、Excel が
完全にシャットダウンできず、見えない EXCEL.EXE プロセスとして残るからです。閉じたあとに
参照を解放しましょう — Set wb = Nothing と Set xlApp = Nothing — そうすればプロセスは
きれいに終了できます。
VBA でブックを閉じたあと、そのプロパティを読めますか?
いいえ。wb.Close が走ると、ブックはメモリから消え、変数はもう何も指さなくなります。
wb.Name や wb.Sheets はエラーになります。必要なものは Close を呼ぶ前に変数へ取得し、
それから Set wb = Nothing しましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-20。
関連ガイド: VBA Open Workbook · VBA Save Workbook · VBA Workbook_BeforeClose Event · VBA DisplayAlerts · VBA DoEvents
