TL;DR —
.Saveは、いま持っているファイルを上書きします。.SaveAsは新しいファイル や形式を書き出し、正しいFileFormat番号を渡さなければブックからマクロを剥ぎ取ります。 マクロ有効の.xlsmには、.xlsx形式(51)ではなくxlOpenXMLWorkbookMacroEnabled(52)が 必要です。
Sub SaveAsMacroWorkbook()
Application.DisplayAlerts = False ' 上書きプロンプトを事前承認する
ThisWorkbook.SaveAs _
Filename:="C:\Reports\Q1.xlsm", _
FileFormat:=xlOpenXMLWorkbookMacroEnabled ' 52 = .xlsm、VBA を保持する
Application.DisplayAlerts = True ' すぐに元へ戻す
End Sub
保存はマクロができるいちばん単純なことに見えて、ブックオブジェクトモデル全体で最も鋭い
データ損失の罠を隠しています — 間違った FileFormat は、一言の警告もなくあなたのコードを
消します。 本記事は、それを防ぐたった一つの区別の上に組み立てられています — Save は
いま持っているファイルを保ち、SaveAs は新しいファイルを作り、そして新しいファイルは形式が
拡張子と一致して初めて正しくなる、ということです。
この記事で学べること
- 考え方の軸 —
Saveはその場でコミットし、SaveAsは新しいファイルを書き出し、FileFormatを必要とする - マクロを食う罠 —
.xlsmを.xlsxの形式番号で保存すると VBA がすべて剥がれる - 一度も保存していないブックへの
.Saveが名前を付けて保存ダイアログを出して無人マクロをハングさせる理由 DisplayAlertsが上書きプロンプトをミュートボタンではなく事前承認に変えるしくみwb.Saved = Trueが本当にすること(変更なしと印づける)と、しないこと(ファイルを書き込む)SaveCopyAsとExportAsFixedFormatに手を伸ばすべき場面
考え方の軸:Save はコミットし、SaveAs は作る
2 つの動詞、2 つの仕事です。
.Saveは、ブックの既存ファイルをその場で、無言で上書きします。ダイアログなし、 新しい名前なし。Ctrl+Sです。ブックがすでにディスク上にファイルを持っているときだけ 機能します。.SaveAsは、ブックを新しいパスや新しいファイル形式へ書き出します。File > Save Asです。ファイルを作るので、その形式を知る必要があります — そしてそこに罠が住んでいます。
ThisWorkbook.Save ' 現在のファイルを上書きする
ThisWorkbook.SaveAs "C:\Reports\Copy.xlsx", xlOpenXMLWorkbook ' 新しい .xlsx を書き出す
以下のすべては、このたった一つの分岐から生まれる帰結です。
マクロを食う罠:FileFormat は拡張子と一致しなければならない
これが、Excel が自分のコードを「失った」と人に思わせる失敗です。マクロを含むブックを、 素のブックの形式番号で保存してしまうのです。
ThisWorkbook.SaveAs "C:\Reports\Q1.xlsm", xlOpenXMLWorkbook ' 51 = .xlsx = マクロなし
xlOpenXMLWorkbook(51)は .xlsx 形式で、.xlsx は VBA を保持できません。Excel は
ファイルを書き込み、モジュールもマクロも一つ残らず無言で捨てます — たとえファイルを
.xlsm と名付けていても。すると拡張子は「マクロ有効」と言い、中身は「マクロなし」と言う
状態になり、Excel は警告するか、きれいに開くのを拒み、あなたのコードは消えています。
ルールはシンプルです — FileFormat 番号は拡張子と一致しなければならない。 実際に使う
のは 4 つです。
' FileFormat 定数(と、その数値):
' xlOpenXMLWorkbook = 51 .xlsx (マクロなし)
' xlOpenXMLWorkbookMacroEnabled = 52 .xlsm (マクロを保持)
' xlExcel8 = 56 .xls (旧 97-2003)
' xlCSV = 6 .csv (1 シート、値のみ)
ブックがコードを持つなら、.xlsm に 52 でなければなりません。迷ったら、生の数値ではなく
名前付き定数を使いましょう — xlOpenXMLWorkbookMacroEnabled は、52 のように打ち間違える
ことができません。
一度も保存していないブックへの Save はダイアログを出す
.Save は既存のファイルを上書きします — けれど Workbooks.Add で作ったブックには、まだ
ファイルがありません。そこへ .Save を呼んでも、どこへ書けばよいか分からないので、Excel は
名前を付けて保存ダイアログにフォールバックします — これが無人実行のマクロをすべて
ハングさせます。新しいブックを初めて書き込むときは、必ず明示的なパスと形式を付けた
.SaveAs を使いましょう。
Dim wb As Workbook
Set wb = Workbooks.Add
' wb.Save ' 新規ブックでは NG - 名前を付けて保存ダイアログが出る
wb.SaveAs "C:\Reports\New.xlsx", xlOpenXMLWorkbook ' 正解 - 初回はパスを渡す
wb.Save ' これで .Save が効く - ファイルが存在する
上書きプロンプトはミュートボタンではなく事前承認
すでに存在するパスへの SaveAs は、モーダルの「ファイルは既に存在します。置き換えますか」
プロンプトを出します。無人で走らせるには、それを抑止します。
Application.DisplayAlerts = False
wb.SaveAs "C:\Reports\Q1.xlsm", xlOpenXMLWorkbookMacroEnabled
Application.DisplayAlerts = True
これは正直に読みましょう — DisplayAlerts = False を設定することは、質問を黙らせるので
はなく、既定 — はい、置き換える — で答えることです。あなたは、そのパスに既にあった
ものを何であれ上書きすることを、事前に承認したのです。これはまさに
VBA DisplayAlerts が述べる論点です — 警告を隠しているのでは
なく、破壊的な既定にあらかじめ同意しているのです。次のプロンプトまで無言で自動確認されない
よう、すぐ次の行で DisplayAlerts = True に戻しましょう。
Saved = True は変更なしと印づける。保存はしない
wb.Saved は「変更あり」フラグです — False は「未保存の変更がある」を意味します。閉じる
ときのプロンプトを抑えるために、次の小技を見かけます。
wb.Saved = True ' Excel に「未保存の変更なし」と伝える - ファイルは書き込まない
wb.Close ' 「変更を保存しますか」プロンプトなしで閉じる
これは便利ですが、何をするのかは正確に知っておきましょう — 閉じるときのプロンプトが出ない
ように、変更ありの状態について Excel に嘘をつくのです。ディスクには何も書き込みません。
本当に変更を残したかったのなら、wb.Saved = True はそれを捨てます。変更なしと印づけること
と保存することは別の操作です — 混同しないでください。
SaveCopyAs と PDF:SaveAs にそっくりな 2 つ
SaveAs に見えて、そうではない仕事が 2 つあります。
SaveCopyAsは、ブック自身のパスや変更ありの状態を変えずに、バックアップコピーを ディスクへ書き出します。「変更する前にファイルをスナップショットしておく」ための正しい 道具です。ライブのブックは元の名前を保ち、開いたままだからです。ThisWorkbook.SaveCopyAs "C:\Backups\before-run.xlsm" ' コピーを外へ。元は無傷PDF は
SaveAsの形式ではありません。 「SaveAs PDF」というものは存在しません — PDF への 書き出しは別のメソッド、ExportAsFixedFormatです。ThisWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\Reports\Q1.pdf"
正直な結論:どの保存を使うか
.Save— すでにファイルを持つブックへ変更をコミットする。日常のケース。.SaveAs path, FileFormat— 新しいファイルを書くか、形式を変換する。つねに明示的なFileFormatを渡し、拡張子と一致させる —.xlsmなら52、.xlsxなら51、.csvなら6。.SaveCopyAs— ライブのブックには触れないバックアップのスナップショット。ExportAsFixedFormat— PDF/XPS 出力。保存形式ではない。
譲れない一点 — ブックがコードを持つなら、それは xlOpenXMLWorkbookMacroEnabled を付けた
.xlsm です。「マクロはどこへ行った?」というチケットはすべて、この番号が間違っている
のです。そして自動実行でのあらゆる SaveAs は、その周りに DisplayAlerts = False が —
そして直後の復元が — 必要です。上書きプロンプトがジョブをハングさせたり、もっと悪いことに、
次のファイルにまで無言で答えられたりしないように。
ExcelMaster の活用
保存のステップは、動いているマクロが静かに成果を破壊する場所です — 間違った FileFormat は
VBA を消し、新規ブックへの .Save はダイアログでハングし、戻し忘れた DisplayAlerts は次の
プロンプトを自動確認し、Saved = True は残したかった変更を捨てます。どれも小さな細部。
どれもデータを失います。
ExcelMaster は、
構造からして保存を正しくします。「各地域のシートを、それぞれマクロ有効ブックとして保存して」
と頼めば、xlOpenXMLWorkbookMacroEnabled を付けた .SaveAs を書き、上書きを DisplayAlerts
のオフ/オンのペアで囲み、名前を変えるのではなくバックアップが欲しいときは SaveCopyAs を
使い、.Save はすでにパスを持つブックにだけ使います。あなたは欲しいファイルを説明するだけ。
コードとデータを守る形式は、それが選びます。
よくある質問
VBA で Save と SaveAs の違いは何ですか?
.Save は、ブックの既存ファイルをその場で、無言で、ダイアログなしに上書きします — Ctrl+S
と同じです。.SaveAs は、ブックを新しいパスや新しいファイル形式へ書き出し、FileFormat
引数を必要とします。すでに存在するファイルへ変更をコミットするなら .Save を、新しい
ファイルを作るか形式を変換するなら .SaveAs を使いましょう。
ブックを保存したら VBA がマクロを消したのはなぜですか?
マクロ入りブックを、.xlsx の形式番号 xlOpenXMLWorkbook(51)で保存したからです。.xlsx
形式は VBA を保存できないので、ファイルを .xlsm と名付けていても Excel はモジュールを一つ
残らず無言で捨てます。マクロ有効ブックは xlOpenXMLWorkbookMacroEnabled(52)で保存し、
コードを保持しましょう。
VBA で上書きプロンプトなしにブックを保存するには?
SaveAs の前に Application.DisplayAlerts = False を設定し、直後に True へ戻します。これ
は「ファイルは既に存在します。置き換えますか」プロンプトに既定(はい、置き換える)で答える
ので、プロンプトが出ません。既存ファイルの上書きを事前承認したことになるので、それが本当に
望みかどうかを確かめてください。
VBA で wb.Saved = True は何をしますか?
ブックの「変更あり」フラグを「未保存の変更なし」に設定し、閉じるときに「変更を保存しますか」
プロンプトが出ないようにします。ディスクには何も書き込みません。もし本当に未保存の変更
があれば、Saved = True はそれを捨てます。変更を残すには、.Save を呼ぶか、
SaveChanges:=True で閉じましょう。
VBA でブックを PDF として保存するには?
PDF は SaveAs の形式ではありません。ExportAsFixedFormat を使います:
ThisWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\Reports\Q1.pdf"。名前を
変えずにブック自身の素のバックアップコピーを書き出すなら、代わりに SaveCopyAs を使い
ましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-20。
関連ガイド: VBA Open Workbook · VBA Close Workbook · VBA DisplayAlerts · VBA Workbook_BeforeSave Event · VBA ScreenUpdating
