Developer

【ExcelVBA】ブックのイベント③「Workbook_BeforeSave」
2022.08.31
Lv1

【ExcelVBA】ブックのイベント③「Workbook_BeforeSave」

ブックのイベント③「Workbook_BeforeSave」

ブックのイベントを利用したマクロを作成するには、VBEのプロジェクトエクスプローラーで「ThisWorkbook」をダブルクリックします。
今回は「Workbook_BeforeSave」を紹介します。

このイベントは、ブックを保存しようとしたときに必ず実行されます。
上書き保存と名前を付けて保存のどちらのときにも実行され、プロシージャ内でどちらを行ったかがわかるようになっています。
また、引数を操作することでその保存しようとした操作を取りやめることもできます。
使用例としては、保存するときに自動的に別ファイルとしてバックアップを行うことや、特定の項目が入力されていない場合に保存できなくするといったことができます。

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    '' ここに処理を書く
End Sub

引数は「SaveAsUI」と「Cancel」の2つありそれぞれ以下のような機能があります。
「SaveAsUI」この引数が「True」となっているときは「名前を付けて保存」を行ったことを表し、「False」となっているときは「上書き保存」を行ったことを表します。
「Cancel」この引数に「True」を代入することで保存しようとした操作を取りやめることができます。デフォルトは「False」

サンプルプログラム

「Workbook_BeforeSave」イベントを使用したサンプルプログラムです。
これは業務上とても重要なファイルで定期的にバックアップすることにしました。
また、ファイルの変更記録を残しどのような修正が行われたかを後から追いかけることができるようにしています。
上書き保存の場合は、ファイル名の末尾に年月日と時分秒を付け、別のファイルとして保存します。
名前を付けて保存の場合は、元のファイルは上書きされていないためバックアップする必要はありません。

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
 
    Dim path As String
    Dim name As String
    Dim ext As String
    
    '' 上書き保存の場合
    If SaveAsUI = False Then
        '' 開いているブックのパス
        path = ThisWorkbook.path
        
        '' バックアップファイル名
        '' ファイル名の末尾に年月日を付与する
        name = Left(ThisWorkbook.name, InStrRev(ThisWorkbook.name, ".") - 1) & "_" & Format(Now(), "yyyymmdd_hhnnss")
        
        '' 拡張子
        ext = Right(ThisWorkbook.name, InStrRev(ThisWorkbook.name, ".") - 1)
        
        '' 開いているブックのコピーを保存する
        ThisWorkbook.SaveCopyAs filename:=path & "\" & name & ext
    End If

End Sub

文字列の操作用にLeft関数、Right関数を使用しています。
「Left関数」文字列の左から数えて指定した数の文字を返します。
「Right関数」文字列の右から数えて指定した数の文字を返します。

同様の関数としてMid関数も非常によく使いますので合わせて押さえておきましょう。
「Mid関数」文字列から指定した文字数の文字列を返します。切り出す文字の1文字目の場所(start)と切り出す文字数(length)を指定します。

また、指定した文字(ここでは「.」)の位置を探すためにInStrRev関数を使用しています。
「InStrRev関数」文字列の中から指定した文字列を後方から検索し、最初に見つかった文字位置を返します。

同様の関数としてInStr関数も非常によく使います。
「InStr関数」文字列の中から指定した文字列を前方から検索し、最初に見つかった文字位置を返します。

関数名 機能概要 公式サイト(リンク)
Left 文字列の左から数えて指定した数の文字を返します。 関数リファレンス(Left関数)
Right 文字列の右から数えて指定した数の文字を返します。 関数リファレンス(Right関数)
Mid 文字列から指定した文字数の文字列を返します。 関数リファレンス(Mid関数)
InStrRev 文字列の中から指定した文字列を後方から検索し、最初に見つかった文字位置を返します。 関数リファレンス(InStrRev関数)
InStr 文字列の中から指定した文字列を前方から検索し、最初に見つかった文字位置を返します。 関数リファレンス(InStr関数)

このExcelを上書き保存を行うと開いているブックと同じフォルダに次々に新しいファイルが作成されていきます。

名前を付けて保存を行った場合は、新しいファイルが作成されていません。

まとめ

「Workbook_BeforeSave」はブックのイベントのうちの1つで、保存を行う前に実行される
引数のCancelにTrueを設定することで保存操作を取りやめることができる
引数のSaveAsUIの値を参照することで上書き保存か名前を付けて保存かを場合分けすることができる

確認問題

次のプログラムは保存する前に実行されるイベントプロシージャの一部です。
「名前を付けて保存」を行ったときに、第1引数のSaveAsUIにはどんな値が代入されているでしょうか。

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    '' ここに処理を書く
End Sub
答え

「SaveAsUI」引数が「True」となっているときは「名前を付けて保存」を行ったことを表し、「False」となっているときは「上書き保存」を行ったことを表します。

次回も、引き続き「ブックのイベントについて」です。