🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の GetSaveAsFilename — 保存せずに、保存先だけをたずねる

|

Excel VBA の GetSaveAsFilename — 保存せずに、保存先だけをたずねる

TL;DR — Application.GetSaveAsFilename は「名前を付けて保存」ダイアログを表示し、ユーザーが選んだパスを文字 列として 返します — 何かを保存することは しません。実際にファイルを書き込むには、やはり SaveAs を呼びます。 キャンセル時はブール値の False を返すので、変数は As Variant で宣言し、If path = False Then Exit Sub を確か めます。そして、ファイルの本当の形式は、ダイアログの拡張子ではなく、SaveAs に渡す FileFormat で決まります。

Sub AskThenSave()
    Dim path As Variant                        ' Variant なので、キャンセルは False を返せる
    path = Application.GetSaveAsFilename( _
           InitialFileName:="Report " & Format(Date, "yyyy-mm-dd"), _
           FileFilter:="Excel Workbook (*.xlsx), *.xlsx")
    If path = False Then Exit Sub              ' ユーザーがキャンセルした
    ActiveWorkbook.SaveAs Filename:=path, FileFormat:=xlOpenXMLWorkbook  ' 保存するのはあなた
End Sub

GetSaveAsFilename は GetOpenFilename のちょうど鏡写しです。一方は どのファイルを 開くか をたずね、こちらは どこに保存するか をたずねます。そして同じ見出しの驚き — 返すのはパスであって、ファイ ルは保存しない — を共有し、さらにファイル形式にまつわる独自の落とし穴が一つあって、見落とすと壊れて見えるファイル を生みます。GetOpenFilename のガイドを読んでいれば、ここのほとんどは見覚えがあるはずです。違いがあるのは最後の二つ の節です。

この記事で学べること

  • GetSaveAsFilename・GetOpenFilename・FileDialog を結びつける考え方
  • なぜ保存されたファイルではなく パス を返すのか — そして、まだ書かなければならない SaveAs の行
  • またもキャンセルの落とし穴:False を返すので、変数は As Variant でなければならない
  • InitialFileName で既定の名前とフォルダーを提案する方法
  • 形式の落とし穴:ユーザーが目にする拡張子は、ファイルの種類を決めるものではない
  • これを使うべきなのはいつで、FileDialog の SaveAs の種類を使うのはいつか

考え方の軸:「どこに保存?」と書かれた付箋

兄弟分と同じく、GetSaveAsFilename はユーザーに付箋を手渡します — こちらは 「どこに、どんな名前で保存する?」 と たずねます。ユーザーは参照し、名前を入力し、「保存」をクリックし、あなたは選ばれたパスを受け取ります。ディスクには 何も書き込まれません。

path = Application.GetSaveAsFilename(...)   ' パス(PATH)の文字列を返す
ActiveWorkbook.SaveAs Filename:=path         ' ファイルを書き込むのはあなた

「GetSaveAsFilename がファイルを作らなかった」という報告は、兄弟分と同じ思い違いを裏返しにしたものです。この関数 がするのは 保存先を集めること だけです。実際の保存 — ActiveWorkbook.SaveAs・Workbook.SaveCopyAs・あるいは FileSystemObject でテキストを書き込むこと — は次の行、あなたの仕事です。どこに保存 するかをたずねることと、保存することは、二つのステップです。

またしてもキャンセルの落とし穴:Dim As Variant

キャンセルの振る舞いは GetOpenFilename とまったく同じです。関数はブール値の False を返すので、変数はパスかブール値のどちらも保持できなければなりません。

Dim path As Variant      ' 正しい - パスの String かブール値の False
' Dim path As String     ' 誤り - False がテキストの "False" になり、SaveAs が False という名前のファイルを書き込む

As String だと、キャンセルの False はテキストの "False" に強制変換され、If path = False は決して発動せず、 SaveAs はご機嫌に、文字どおり False という名前のブックをカレントディレクトリに書き込みます。path As Variant と 宣言し、If path = False Then Exit Sub を確かめる — それがすべての直し方です。

InitialFileName で既定の名前を提案する

出来のよい保存ダイアログは、気の利いた名前があらかじめ入った状態で開きます。それが InitialFileName 引数です — フ ォルダーも一緒に持たせられるので、ダイアログを望んだ場所で開けます。

' 特定のフォルダーに、日付入りの名前をあらかじめ入れておく
path = Application.GetSaveAsFilename( _
       InitialFileName:="C:\Reports\Sales " & Format(Date, "yyyy-mm-dd") & ".xlsx", _
       FileFilter:="Excel Workbook (*.xlsx), *.xlsx")

名前付き引数(InitialFileName:=、FileFilter:=)を使うと、呼び出しが読みやすいままです。GetSaveAsFilename には 省略できるパラメーターがいくつもあって、位置引数のカンマは数えるのが難しくなるからです。あらかじめ入った日付入りの 名前は、マクロを仕上がったものに感じさせる小さな心配りです。

形式の落とし穴:拡張子は形式ではない

これは保存に特有の落とし穴で、ダイアログの拡張子がファイルの種類を制御すると思い込んでいる人が引っかかります。そん なことはありません。GetSaveAsFilename が返すのは 文字列 で、本当のファイル形式は SaveAs に渡す FileFormat 引数で決まります。

' 食い違い - パスの末尾は .xlsx なのに、SaveAs には古いバイナリ形式で書けと指示している
ActiveWorkbook.SaveAs Filename:="Book.xlsx", FileFormat:=xlExcel8   ' -> きれいに開けないファイル

' 一致 - 拡張子と FileFormat が合っている
ActiveWorkbook.SaveAs Filename:="Book.xlsx", FileFormat:=xlOpenXMLWorkbook   ' .xlsx
ActiveWorkbook.SaveAs Filename:="Book.xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled  ' .xlsm

パスの拡張子と FileFormat 定数が食い違うと、Excel はある形式のバイトを、別の形式だと名乗る名前で書き込みます — そしてそのファイルは、誰かがダブルクリックするとエラーを投げます。ですから形式はコードの中で決め、それに合う FileFormat を渡しましょう。ユーザーがダイアログで見た .xlsx が何かをしてくれたとは思わないことです。複数のフィ ルターを用意しているなら、ユーザーがどれを選んだか(ダイアログを離れたときの FilterIndex で)を読み取り、それに合 う FileFormat を選びます。

GetSaveAsFilename か FileDialog の SaveAs か:制御で選ぶ

「どこに保存するかをたずねて、パスをちょうだい」なら、GetSaveAsFilename が直接的な一行の道具です。ダイアログ オブ ジェクト が欲しいとき — その .Execute メソッドのため、あるいは他の場所で使っているのと同じ .SelectedItems の読み 取りスタイルを保つため — は、msoFileDialogSaveAs を指定した FileDialog に手を伸ばします。 どこに保存するか ではなく 何を開くか をたずねるなら、鏡写しは GetOpenFilename です。三つともパスを返し、動くことはあなたに委ねます。

ExcelMaster の活用

ここでの間違いは、あとになってから姿を現すものです。ガードしなかったキャンセルから生まれた False という名前のブッ ク、そして拡張子と FileFormat が食い違ったせいで開けないファイル。どちらもマクロの実行中にはエラーを出さず — 誰か がそのファイルを使おうとしたときに表面化します。

ExcelMaster には、望む結果を伝えられま す — 「このシートを日付入りの CSV として、どこに保存するか選ばせて」 — すると、Variant によるキャンセルのガード、 気の利いた既定の名前、そして拡張子に合った FileFormat を持つ SaveAs を備えた GetSaveAsFilename の呼び出しを書い てくれます。ブックとコードはあなたの手元に残ります。

よくある質問

Excel VBA で GetSaveAsFilename を使うには?

path = Application.GetSaveAsFilename(InitialFileName, FileFilter, FilterIndex, Title) を呼びます。path As Variant で宣言し、キャンセルを捕まえるために If path = False Then Exit Sub を確かめ、それから ActiveWorkbook.SaveAs Filename:=path, FileFormat:=... で保存します。関数が返すのは選ばれたパスだけで、ファイル自体 を保存することはしません。

GetSaveAsFilename がファイルを保存しないのはなぜですか?

保存先のパスを集めるためだけのもので、何かを書き込むためのものではないからです。「名前を付けて保存」ダイアログを表示 し、ユーザーが選んだパスを返します。実際の保存は次の行で行います — ブックなら ActiveWorkbook.SaveAs Filename:=path、 テキストなら FileSystemObject です。どこに保存するかをたずねることと、保存すること は、別々のステップです。

「名前を付けて保存」ダイアログで既定のファイル名を設定するには?

InitialFileName 引数を渡します。Application.GetSaveAsFilename(InitialFileName:="Report.xlsx") です。名前だけでなく フォルダーも含められるので、"C:\Reports\Report " & Format(Date, "yyyy-mm-dd") & ".xlsx" とすれば、そのフォルダーで、 日付入りの名前があらかじめ入って、そのまま受け入れるか編集できる状態でダイアログが開きます。

GetSaveAsFilename でキャンセルを検出するには?

変数を As Variant で宣言し、If path = False Then Exit Sub を確かめます。キャンセル時、関数はブール値の False を 返し、成功時はパスの文字列を返します。As String の変数だと、False はテキストの "False" に強制変換され、そのチェ ックは決して発動せず、SaveAs は文字どおり False という名前のファイルを書き込みます。

GetSaveAsFilename を使ったあと、保存したファイルが開かないのはなぜですか?

ほとんどの場合、パスの拡張子と、SaveAs に渡した FileFormat が食い違っているからです — たとえば .xlsx の名前を FileFormat:=xlExcel8 で保存した場合です。Excel はある形式を、別の形式だと名乗る名前で書き込むので、そのファイルは 開くときにエラーになります。形式はコードの中で決め、それに合う FileFormat 定数を渡しましょう(.xlsx には xlOpenXMLWorkbook、.xlsm には xlOpenXMLWorkbookMacroEnabled)。

検証環境

検証環境: Excel 365 (Windows 11)、VBA 7.1 — 最終確認 2026-09-26。

関連ガイド: VBA GetOpenFilename · VBA FileDialog · VBA Save Workbook · VBA InputBox · VBA FileSystemObject · VBA Workbook