エクセルでファイルの存在確認を行う定番VBAコードがあります。
Dir関数やFileExistsです。
問題はその先、開く,保存,閉じる,作成,削除の5つの場面でのコードを紹介します。
こんにちは、じゅんぱ店長(@junpa33)です。
エクセルVBAでファイル処理を行う時、操作したい目的のファイルが既にあるのかどうかを、調べなければいけないことが多くあります。
ファイルの存在を調べるには、VBA関数のDir関数、または、FSO(FileSystemObject)を利用するというのが主な方法になります。が、いろいろ調べてみて「このコードを使えば “True”、なければ”False”となります」とは分かるのですが、・・・。
ファイルの存在を調べてわかる答えから、先のVBAコードを知りたいというのが本音です。
この記事では場面別に、ファイルの存在確認のその後がどのようにつながってゆくのか?そのVBAマクロのコードを紹介しています。お悩みの問題への一助になればと、参考にしてみてください。
- ブックの知識
- ブックの操作
- ワークブックを開くOpenメソッドの書き方 Excelマクロ
- VBA ブック名の取得法4つの解決策を詳しく解説
- VBA 開く,保存,閉じる,作成,削除 ブックの存在確認後のコード記述
- ファイルの保存に年月日+時刻を付けて管理する
- VBA 保存先フォルダをダイアログ指定で変数化
- 新規ブック5つの保存法。AddとSaveAsの使い方がわかる
- セル値を使いブック名として保存。統一フォームに有用
- VBA シートをブックから切り出し名付け保存する
- ブック名に作成者名を付加。 プロパティ変更とファイル保存
- 不要フォルダを削除する2種類のコードの作成
- 要らないファイルを自動削除するコードの作成
- ワークブックを閉じる12のパターン使い分け VBA最速理解
- ピンポイントでファイルを完全に削除するマクロ(コピペ可)
コンテンツ
ファイルの存在確認を行う事は重要
ちょっと ” くどい系 ” の話になりますが、
なぜ、ファイルの存在確認をする必要があるのか?
それは何といってもVBAプログラムをエラーストップさせないためです。
指定のファイルが正常に選択されないと、エクセルでアラートメッセージが表示されたり、VBAコード進行中にエラーメッセージが表示されたりしてしまいます。
マクロを本番実行した時に、マクロが途中で止まって、今までの作業労力が全てムダになったりということも考えられます。
本当の不測に事態のために、”エラーを無視するVBAコード”を埋め込むことも出来ます。
それでは、処理コードがジャンプされてしまい、場合によっては逆にマクロを実行しても何も処理されないということにもなります。
また、何処がバグが発生しているのかも分からなくなります。
なので、ファイルの存在確認はやはりかなり重要です。
存在確認の定番VBAコード
まず最初にファイルの存在を調べる定番のVBAを確認しておきます。
ファイルの存在確認を行うVBAコードは、主に使われているもので、2つの方法があります。
- 「Dir」VBA関数
- 「FileSystemObject」の「FileExists」メソッド
の2つです。
「Dir」 VBA関数を使った存在確認コード
Sub ブックの存在確認1()
Dim BkName, BkPath As String
BkName = "Book1.xlsm"
BkPath = ThisWorkbook.Path & "\" & BkName
If Dir(BkPath) <> "" Then
MsgBox BkName & " は存在します。"
Else
MsgBox BkName & " は存在しません。"
End If
End Sub
このファイルの存在確認のVBAコードのポイントは、以下の部分です。
- If条件文で、ファイルが存在していれば 〇〇〇 の作業をして存在していなければ ✖✖✖ の作業をする。
- Dir関数は、指定のファイルパス位置に確かにファイルがあれば、そのファイル名を、存在しなければ「” ”」を戻り値で返す
FileSystemObject を使った存在確認コード
「FileSystemObject」の「FileExists」メソッドを利用します。
Sub ブックの存在確認2()
Dim BkName, BkPath As String
Dim FSO As Object
BkName = "Book1.xlsx"
BkPath = ThisWorkbook.Path & "\" & BkName
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(BkPath) Then
MsgBox BkName & " は存在します。"
Else
MsgBox BkName & " は存在しません。"
End If
Set FSO = Nothing
End Sub
- ファイルシステムオブジェクトを宣言しセットします。
- FileExistsメソッドは、ファイルが存在していれば「True」を存在していなければ「False」を返します。
ファイルの存在確認が必要な「開く,保存,閉じる,作成,削除」
ファイルを操作する場面で一番気になるのが、「開く」「保存」「閉じる」「作成・追加」「削除」する時です。
これらの操作場面では、ファイルの存在確認コードを使って、ファイルの状態確認と、その後に続けるVBAコードのつなぎ方を整合性の有る様に記述しておくことが必要になります。
また、そのものズバリの ” ファイルの存在確認をするVBAコード ” を必ず使うという訳でもありません。
この5つの場面についてそれぞれにVBAコードのモデル例を紹介していきます。
場面1、ファイルを開く時
VBAで作業上、新たに特定のファイルを開く必要がある場合が多くあります。
そういった場合には、開きたいファイルがあるかどうかチェックが必要があります。
さらに、それがすでに開かれているファイルであれば、「2重開きになりますよ!確認メッセージ」が表示されます。
また、無いファイルを開こうとしているかもしれません。
フォルダの場所が決まっていてその中のファイルを開く場合と、保存されているフォルダを選びながら必要なファイルを開く場合などケース分けを考えたVBAコード作りも必要です。自ずとVBAコードも変わってきます。
- 開きたい目的のファイルが存在するか?
- 目的のファイルは既に開かれていないか?
- ファイルの存在する場所は決まっているか?
場面2、ファイルを保存する時
ファイルを編集した後、そのファイルを閉じる時にもファイルの存在をチェックする必要があります。
ファイルの保存を行いたい場合は、作業条件の分岐が多くなりVBAコード作成の難易度の一段アップ感があります。
- 同名のファイルが既に存在していないか?
- どのフォルダに保存したいのか?
- 同名のファイルがある場合に置き換えて保存(上書き保存)するのか?
- 別名で保存したい時はどういう方法を取るのか?
場面3、保存オプションでファイルを閉じる時
デフォルトではファイルを閉じるときに、ファイル編集を行っていると保存メッセージが表示されて、上書き保存するかどうかを選択することになります。
また、他にも開いているエクセルブックがあるかどうかを調べる必要があります。
- ファイルを編集した場合に、そのファイルの扱いをどうするか(上書き保存か別名保存か)?
- Windows上で開いているファイル(ブック)が、自分自身(マクロ実行ブック)以外にあるかどうか?
場面4、ファイルを作成・追加する時
ファイルを新規作成する時に付けるファイル名がすでに存在する名前かどうかを調べる必要があります。
ただそれは、名前を付けて保存ダイアログを使うことで同名重複のチェックを行うことが出来ます。
それとは別に、ファイル名のチェックをしなければいけないもう一つの別の理由があります。
- すでにそのファイル名は存在していないか?
- マクロ有効ブックとして保存するのか?
場面5、ファイルを削除する時
ファイルを削除する時も、目的のファイルが存在するかどうかを調べることが必要になります。
- 目的のファイルはそこに存在するか?
- マクロ実行ブックは削除できない。では削除する方法は?
- Windows上で開いているファイルはどうすれば削除できるか?
場面に合わせたそれぞれのVBAコード
それでは、「開く」「保存」「閉じる」「作成」する場合のVBAコード組み立てを詳しく見ていきます。
ファイルを開く時に確認するVBAコード
注意しておくポイントへの対応
この場合は、定番コード解説通りに、そのファイルまでのパスを設定記述で解決します。
この場合、その都度変わるフォルダを毎回指定してあげます。
「毎回指定する」とは 「毎回利用ユーザーとやり取りをする」
ということなので、ダイアログボックス、入力ボックスかユーザーフォームを利用するということになります。
その中で一番お手軽なのが、「組み込みダイアログ」を利用する方法です。
マクロ実行中、前にも同じ作業をしていた場合、まだそのファイルを保存終了していない場合があります。エクセルより重複OPENのメッセージが表示されることがあります。
既に開かれているファイル(ブック)名を調べて、今開こうとしているファイル名と同じものがあるかどうかを調べる必要があります。
ファイルオープンダイアログ(Dialogs(xlDialogOpen))を使う
この方法は、ブック名の取得の記事で紹介しています。
Sub ブックの存在確認3()
Dim flag As Boolean
ChDir ThisWorkbook.Path & "\保存資料"
flag = Application.Dialogs(xlDialogOpen).Show
If flag = False Then
MsgBox "キャンセルされました"
Exit Sub
End If
End Sub
ファイル(ブック)を開くのダイアログですので、ボタンは「開く」と「キャンセル」の配置になっています。
もちろん「開く」ボタンを押せば、ダイアログで指定したファイルが開かれることになりますが・・・
このファイルオープンのダイアログを使った場合、先に同じファイルが開かれ編集されていた場合は
重複確認メッセージが表示されてしまいます。ここで、「いいえ」を選択するとプログラムエラーでVBAコードがストップします。
つまりこの方法では、エクセルの方で、重複確認を自動で行ってくれるということです。(ただし必ず対策するコードは必要です。)
この重複確認メッセージを表示させないためには、ファイルを開いて編集する毎に ” 必ず上書き保存 ” を行うことです。
このファイルオープンのダイアログを使う場合は、ファイルを開き編集するごとに上書き保存と覚えておきましょう。
ファイル名取得のダイアログ(GetOpenFilename)を使う
このダイアログは、ファイル名を取得するだけの機能です。
ファイル名を取得した時点で、Windows上で、すでに開かれているファイルかどうかをチェックし、まだ開かれていないファイルであればOpenメソッドを実行します。
「GetOpenFilename」でファイル名取得のダイアログを表示し、開くファイルを指定。
既に開かれているファイルかどうかをチェックし、開かれていなければ、Openを実行します。
Sub ブックの存在確認4()
Dim BkName As Variant
Dim wb As Workbook
ChDir ThisWorkbook.Path & "\保存資料"
BkName = Application.GetOpenFilename(filefilter:= _
"Excelファイル,*.xls*", Title:="ファイル選択")
If BkName <> False Then
For Each wb In Workbooks
If wb.Name = Dir(BkName) Then
MsgBox "このファイルは、すでに開かれています"
Exit Sub
End If
Next
Workbooks.Open BkName
Else
MsgBox "キャンセルされました"
Exit Sub
End If
End Sub
Sub ブック名取得4a()
Dim wb As Workbook
Dim BkName As String
For Each wb In Workbooks
If wb.Name = BkName Then ・・・
Next
End Sub
Windows上に開いているファイル名とダイアログで指定したファイル名を比較するわけですが、
ダイアログ指定したファイル名は、フルネームで取り出されることになります。
なので、パスの無いファイル名にするためには、「Dir関数」で編集する必要があります。
ファイルの存在確認を行う場合は、まずファイル名を取得することが必要です。そして、そのファイル名についての存在確認をした上で、次の適宜な処理を行うようにします。
ファイルを保存する時に確認するVBAコード
注意しておくポイントへの対応
VBAコード的には少々長めのものになりますので、これからはコード作成順に紹介していきます。
まず最初に、保存先のフォルダをコード化できないと始まりません。
なので、保存先のフォルダパスを取得します。
ファイルダイアログで「msoFileDialogFolderPicker」を利用してフォルダを指定しフォルダパスを取得します。
Sub ブックの存在確認5()
Dim FolPath As Variant
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = 0 Then
MsgBox "キャンセルされました。"
Exit Sub
End If
FolPath = .SelectedItems(1)
End With
End Sub
この指定のフォルダを取得した後にVBAコードに生かすべき注意ポイントとして
をユーザー側とやり取りしながら、保存作業を行います。
自動で別名の名前を付けるVBAコードはいろいろ考えられますが、
一番メジャーな方法として保存年月日と日付を名前に付加する方法です。
今回は、
別名で保存する場合の「別名」は自動名付けとして、「ブック名+年月日+時間」で出来るだけファイルが、同名重複を起こさないように設定します。
自動の名付けで(ほぼ)完璧に同名重複を避けたい場合は、「時間」を秒まで設定します。
この別名作成はFunctionプロシージャーで記述しています。
Function NewBkname() As Variant
Dim TM, YMD
Dim Lng As Long
Dim NakName As String
Lng = InStrRev(ThisWorkbook.Name, ".")
NakName = Left(ThisWorkbook.Name, Lng - 1)
TM = Format(Now, "hhnn")
YMD = Format(Date, "yymmdd")
NewBkname = NakName & YMD & "_" & TM & ".xlsm"
End Function
ユーザー側が、「上書き保存」「別名保存」「何もしない(中止する)」を選べる様にしないといけません。
それには一番簡単には、答え(戻り値)を取得できるメッセージボックス関数を利用します。
Sub ブックの存在確認5()
Dim FolPath, FoFleName As Variant
Dim BkName As Variant
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = 0 Then
MsgBox "キャンセルされました。"
Exit Sub
End If
FolPath = .SelectedItems(1)
End With
BkName = FolPath & "\" & ThisWorkbook.Name
Dim Fso, Fol, F As Object
Dim Ans1, Ans2 As Integer
Ans1 = MsgBox("このファイルの保存作業を続けますか?" _
, vbYesNo + vbInformation, "保存作業継続確認")
If Ans1 = 7 Then Exit Sub
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Fol = Fso.getfolder(FolPath)
For Each F In Fol.Files
If F.Name = Dir(BkName) Then
Ans2 = MsgBox("すでに同名のファイルが存在します" & vbCrLf & _
"上書き保存の場合は「はい」" & vbCrLf & _
"編集日時付加で別名保存の場合は「いいえ」" & vbCrLf & _
"作業を中止する場合は「キャンセル」" & vbCrLf & _
"をクリックしてください", _
vbYesNoCancel + vbInformation, "保存方法確認")
Exit For
End If
Next
If Ans2 = 6 Then
Application.DisplayAlerts = False
ThisWorkbook.SaveAs BkName
Application.DisplayAlerts = True
MsgBox "保存完了しました!", vbInformation, "保存完了"
Exit Sub
ElseIf Ans2 = 7 Then
ThisWorkbook.SaveAs FolPath & "\" & NewBkname
MsgBox "保存完了しました!", vbInformation, "保存完了"
Exit Sub
ElseIf Ans2 = 2 Then
Exit Sub
End If
ThisWorkbook.SaveAs BkName
MsgBox "保存完了しました!", vbInformation, "保存完了"
End Sub
このプロシージャー(マクロ)を実行するとこのように保存されます。(別名での保存を実行)
ファイルを閉じる時に確認するVBAコード
ファイルを終了するときは、単に終了することだけではありません。
ファイルを閉じるときの作業はファイルを保存する時の操作と近似です。
先に紹介しました「ファイルを保存の時に確認するVBAコード」の実行後に、を付け加えるだけでもこの課題は90%完了します。
ThisWorkbook.Close SaveChanges:=False
ただし後の10%は、Windows上で他にも開いているブックがあるかないかの存在確認が必要になります。
注意しておくポイントへの対応
先のファイルの保存の場合とは異なって今回は、VBAコード設計として、
別名でのファイル保存をユーザーが「任意の名前で」保存できるようにします。
ユーザー側でファイル名を入力してもらう形にしてみます。
Sub ブックの存在確認6()
Dim Ans3 As Integer
Dim FF, FFa, FFb, FFc As String
Dim BkName As Variant
Ans3 = MsgBox("ファイルを閉じします。" & vbCrLf & _
"編集内容を上書き保存の場合は「はい」" & vbCrLf & _
"編集内容を名前を付けて保存する場合は「いいえ」" & vbCrLf & _
"保存しないで終了する場合は「キャンセル」" & vbCrLf & _
"をクリックしてください", _
vbYesNoCancel + vbInformation, "終了方法確認")
If Ans3 = 6 Then
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
ElseIf Ans3 = 7 Then
FFa = "Excel ブック,*.xlsx,Excel マクロ有効ブック,*.xlsm,"
FFb = "Excelバイナリブック,*.xlsb,Excel97-2003ブック,*.xls,"
FFc = "CSVカンマ区切り,*.csv,すべてのファイル,*.*"
FF = FFa & FFb & FFc
BkName = Application.GetSaveAsFilename(filefilter:=FF, _
FilterIndex:=2, Title:="名前の変更保存")
If BkName = "False" Then
Exit Sub
End If
ThisWorkbook.SaveAs BkName
ElseIf Ans3 = 2 Then
End If
If Workbooks.Count > 2 Then
ThisWorkbook.Close False
Else
Application.Quit
End If
End Sub
埋め込みダイアログの「名前を付けて保存ダイアログ」を使用します。さらに、ファイルを閉じる時点で、「ThisWorkbook」を閉じることになるので、開いているファイルが他にある時とない時で閉じるVBAコードを変えています。個人用マクロブックが存在している場合はマクロ実行のThisWorkbookだけ開いていても、ファイル数のカウントが2になることに注意します。
ファイルを作成・追加する時に確認するVBAコード
ファイル(ブック)を新規作成や追加するときは、その作成作業自体にはファイル名の問題は介在しません。
ファイル名の確認についての問題が起こるのは、新規作成で編集したファイル(ブック)の保存作業を行う時です。
ここで紹介するコードは、埋め込みダイアログを利用しますので、VBAとしてはファイルの存在確認のコードは記述していません。保存先に同名のファイルがあるかどうかは、見ればわかるレベルだからです。
むしろ、
新規ファイル(ブック)を保存する場合に、保存するファイルをマクロ有効ブックで保存する場合には注意が必要になります。
注意しておくポイントへの対応
SaveAsメソッドにマクロを有効にする引数の設定が必須になります。
このVBAコード設定をしないと「保存不可のエラーメッセージ」が表示され、マクロがSTOPしてしまいます。
なので、拡張子xlsmで保存するのか、それ以外で保存するのかを区別してコード作成が必要になります。Functionプロシージャーで記述します。
Sub ブックの存在確認7()
Dim Nwb As Workbook
Dim FF, FFa, FFb, FFc As String
Dim BkName As String
Set Nwb = Workbooks.Add
Nwb.Worksheets(1).Range("A1") = "編集作業をする"
FFa = "Excel ブック,*.xlsx,Excel マクロ有効ブック,*.xlsm,"
FFb = "Excelバイナリブック,*.xlsb,Excel97-2003ブック,*.xls,"
FFc = "CSVカンマ区切り,*.csv,すべてのファイル,*.*"
FF = FFa & FFb & FFc
BkName = Application.GetSaveAsFilename(filefilter:=FF, _
FilterIndex:=2, Title:="名前の変更保存")
If BkName = "False" Then
Exit Sub
Else
If nomalmacro(BkName) = "xlsm" Then
ActiveWorkbook.SaveAs BkName, xlOpenXMLWorkbookMacroEnabled
Else
ActiveWorkbook.SaveAs BkName
End If
End If
End Sub
Function nomalmacro(N As String) As Variant
nomalmacro = Right(N, 4)
End Function
ファイルを削除する時に確認するVBAコード
注意しておくポイントへの対応
現在Windows上で開いているブックを削除するためには、その開いているブックを一旦閉じる必要があります。
ただし、自分自身(マクロ実行ブック)は閉じたりさらに削除することは出来ません。
もう一つ、個人用マクロブックも現存の開いているブックとして認識されます。削除不可ブックですので、こちらも削除対象から外さないとエラーストップしてしまいます。
Windows上で開かれているエクセルファイルを削除します。
ThisWorkbookと個人用マクロブックは直接削除することは出来ません。
Sub ブックの存在確認8()
Dim wb As Workbook
Dim BkName As String
For Each wb In Workbooks
With wb
If .Name <> ThisWorkbook.Name And .Name <> "PERSONAL.XLSB" Then
Application.DisplayAlerts = False
BkName = .FullName
.Close SaveChanges:=False
Kill BkName
Application.DisplayAlerts = True
End If
End With
Next
End Sub
最初に、マクロ実行ブックはその削除対象のフォルダ内にはないものとします。
削除したいファイルのあるフォルダのパスを取得して、そのフォルダにあるファイルが現在開かれているかどうかを調べます。
開かれているファイルがあれば保存せずに閉じた上で、そのフォルダ内のファイルをすべて削除します。
Sub ブックの存在確認9()
Dim FolPath, FoFleName As Variant
Dim BkName As Variant
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = 0 Then
MsgBox "キャンセルされました。"
Exit Sub
End If
FolPath = .SelectedItems(1)
End With
Dim Fso As Object
Dim FsoF As Object
Dim wb, wbf As Object
Set Fso = CreateObject("Scripting.FileSystemObject")
Set FsoF = Fso.getfolder(FolPath)
For Each wb In Workbooks
If wb.Path = FolPath Then
wb.Close False
End If
Next
For Each wbf In FsoF.Files
Application.DisplayAlerts = False
Kill wbf.Path
Application.DisplayAlerts = True
Next
Set Fso = Nothing
Set FsoF = Nothing
End Sub
まとめ
いろいろな場面でのVBAコードを紹介しました様に、単にファイルが存在するかどうかTRUEとFALSEだけでは、やりたいことのためには全く不十分だとお分かりいただけたと思います。
マクロコードの進行に対して、どれだけのケースを想定できるかによって、それを対策できるかによって、エラー停止を防止できる精度が上がってきます。
ファイルの存在確認はそのための一番最初の単なる分岐点でしかありません。むしろ、その後のVBAコード設計が大切になります。
エクセルVBAを独習するのに参考書は欠かせません。 参考書選びは自分に合った「相棒」にできるものを選んでいきたいです。
エクセルVBAの独習でおすすめ参考書を7冊選ぶ。良書との出会いは大切です今回の記事はここまでです。 最後までご覧いただき有難うございました。
<記事内容についての告知>
VBAコードの記述記事においては、その記述には細心の注意をしたつもりですが、掲載のVBAコードは動作を保証するものではりません。 あくまでVBAの情報の一例として掲載しています。 掲載のVBAコードのご使用は、自己責任でご判断ください。 万一データ破損等の損害が発生しても当方では責任は負いません。
アンケートでポイ活しよう!!
アンケートに答えれば答えるほど ”使える” ポイントがたまります。