ブックを別名で保存してExcelを終了させるマクロ
私の場合、(粗忽者なので)そういう経験を嫌というほどしてきたことから、「作業の終了にあたってブックを別な名前で保存してからExcelを終了する(あるいは当該ブックだけを閉じる)」というマクロをご紹介します。
なお、例によってサンプルファイルをインターネットディスクにアップロードしてあります。下記のアドレスをクリックもしくはWebブラウザに貼り付けていただくと、当該フォルダが開きます。Excel97-2003版(ファイル名の末尾が「.xls])とExcel2007-2010版(ファイル名の末尾が「.xlsm」)の2種類がありますので、お間違えのないようにどうぞ。
http://bit.ly/WkyPzs
1.マクロの記述
今回も、マクロのコードを直接書いていくので、Microsoft Visual Basic Editor を起動します。
(Excel2003以前)
「ツール」メニューの「マクロ」から「Visual Basic」をクリック。
(Excel2007以降)
リボンの「開発」タブから「Visual Basic」をクリック。
下図の画面となるので、「標準モジュール」の「Module1」をダブルクリックします。
下記のコードを画面にコピー&ペーストするか、自分で入力します。(注意:このコードはExcel2007-2010用です。Excel2003以前のものをお使いの方は、コードの一部を修正しないと使えません。その方法は後でご説明します。)
(マクロのコード))
Sub 日付入力()
'
' 日付入力 Macro
'
'
Range("j3").Value = Now
End Sub
Sub 別名で保存()
'
' 別名で保存 Macro
'
'
Call 日付入力
'エラーが発生した(キャンセルボタンを押した)場合、エラー処理を行います
On Error GoTo Err_名前を付けて保存
'別の名前でファイルを保存します
'まず、保存するファイル名を取得するための変数を定義します
Dim ファイル名 As Variant
'フィル名をつけて保存ダイヤログボックスを表示させます
'保存するファイルの種類をエクセルファイルに限定します
fileSaveName = Application.GetSaveAsFilename(fileFilter:="Microsoft Excel ブック(*.xlsm),*.xlsm")
'保存するファイル名が有効な名称であれば
If fileSaveName <> False Then
'変数にダイヤログボックスで付けた名称を代入します
ファイル名 = fileSaveName
End If
'代入した名称で保存します
ActiveWorkbook.SaveAs (ファイル名)
'ブックを閉じるときにエクセルも終了するかどうかを選択します
'選択結果を取得するための変数を定義します
Dim メッセージ2 As Integer
'メッセージボックスを表示して、選択されたボタンに応じて分岐処理を行います
メッセージ2 = MsgBox("Excelを終了せずにこのブックだけを閉じます。" & Chr(13) & Chr(13) & _
"このブックだけを閉じて引き続きExcelを使う場合は「はい」を、" & Chr(13) & _
"Excelも終了する場合は「いいえ」をクリックしてください。", vbYesNo, "作業の終了")
'「はい」を選択した場合
If メッセージ2 = vbYes Then
'ブックだけを閉じます
ActiveWorkbook.Close
'「いいえ」を選択した場合
Else
'エクセルを終了します
Application.Quit
'分岐処理を終了します
End If
'エラー処理についての記述です
Err_名前を付けて保存:
'キャンセルボタンが押されたときのメッセージを表示します
If Err.Number = 1004 Then
MsgBox "保存処理がキャンセルされました。" & Chr(13) & _
"一連の処理を中止します。"
'エラー処理を終了します
End If
End Sub
コードの入力が終わると、以下の図のようになるはずです。なお、図の中で、緑の文字列の部分は「マクロのコードについてのメモのようなもの」でマクロの動作には直接影響を与えません。ゆえに、この部分はなくてもよいのですが、後でメンテナンスをするときに何のためにそのコードを設けたのかを記録しておいた方がわかりやすいというメリットがあります。ただし、これがあると却って鬱陶しいという人もいると思うので、その辺は好き好きというものでしょう。
2.コードの説明
(1)マクロ「日付入力」
Sub 日付入力()
'
' 日付入力 Macro
'
'
Range("j3").Value = Now
End Sub
これは、そのブックを更新した日時を記録するためのコードです。セルj3に現在の日時を入力するというごく単純なコードになります。具体的には、Range("j3")はセルj3を指定するコードで、Range("j3").Value と書くことで「セルj3の値」という意味になります。また、NowというのはNow関数のことで、現在の日時を返します。すなわち、「セルj3の値は現在の日時ですよ」とExcelに教えているわけです。
Nowの代わりに、Dateを用いれば本日の日付となりますし、"私は真っ赤なリンゴです"とすれば、セルj3には「私は真っ赤なリンゴです」という文字列が入力されるようになります。
なお、Sub 日付入力()は、「日付入力」というマクロの開始を、End Subはマクロの終了を示す合図です。
2.マクロ「別名で保存」
マクロ「別名で保存」は下図のような構造になっています。
最初に、更新日時を取得するためのマクロ「日付入力」を実行させるために、Call 日付入力 というコードを記述しています。このように、Call というのは他のマクロを呼び出して実行するためのものですから、応用範囲は広いものになります。
次に、「名前をつけて保存」ダイヤログボックスを表示させるわけですが、マクロを記述する手順として、次の「エラー処理」を先に書いておきます。これは、「名前をつけて保存」ダイヤログボックスが表示されたときに、何らかの理由でキャンセルされたときにどうするかをという取り決めをしておくというもので、マクロの最初のところには、下記のように、「エラーが発生した(キャンセルボタンを押した)場合は途中のコードを無視してエラー処理のところに行きなさい」という命令を書き込むことになっています。また、エラー処理の具体的な中身は、マクロの最後のところに書くことになっています。
'エラーが発生した(キャンセルボタンを押した)場合、エラー処理を行います
On Error GoTo Err_名前を付けて保存
次に、作業したブックに「別な名前をつけて保存する」わけですが、単に「名前をつけて保存する」だけであれば、
fileSaveName = Application.GetSaveAsFilename(fileFilter:="Microsoft Excel ブック(*.xlsm),*.xlsm")だけで充分です。ここで、(fileFilter:="Microsoft Excel ブック(*.xlsm),*.xlsm")というのは、ファイルの種類をExcelのブックに限定するというものです。Excel2003以前のものをお使いの方は、この部分を「xslm」ではなく「xls]と訂正してお使い下さい。
ところが、それだと「別な名前で保存した」後で原本となるブックを閉じたり、Excelを終了させるときに、原本となるブックに加えられた変更を保存しますか?という問い合わせをしてきます。このときに「保存しない」を選択すれば原本となるブックは元のままですが、間違って「保存する」を選択してしまうと原本が改訂されてしまうことになります。
そこで、少々迂遠ですが、以下のようなコードを書くことで、最後の確認のメッセージを表示させないようにすることができ、誤操作を防ぐことができるようになります。
'別の名前でファイルを保存します
'まず、保存するファイル名を取得するための変数を定義します
Dim ファイル名 As Variant
'フィル名をつけて保存ダイヤログボックスを表示させます
'保存するファイルの種類をエクセルファイルに限定します
fileSaveName = Application.GetSaveAsFilename(fileFilter:="Microsoft Excel ブック(*.xlsm),*.xlsm")
'保存するファイル名が有効な名称であれば
If fileSaveName <> False Then
'変数にダイヤログボックスで付けた名称を代入します
ファイル名 = fileSaveName
End If
'代入した名称で保存します
ActiveWorkbook.SaveAs (ファイル名)
次に、ブックを閉じるときに、Excelもいっしょに終了させるのか、単にブックだけを閉じるのかを選択できるようにします。そのための方法として、質問に対し「はい」か「いいえ」で答えることで、その返答によって処理を分岐させるというやり方があります。以下は、そのための構文で定型的なものです。
まず、最初に、質問に対する返答を変数として扱えるようにするために、変数の型の定義を行います。ここでは、「はい」か「いいえ」のどちらかなので、整数型である「Integer」としています。
'ブックを閉じるときにエクセルも終了するかどうかを選択します
'選択結果を取得するための変数を定義します
Dim メッセージ2 As Integer
次に、メッセージボックス(「はい」か「いいえ」を選択する)の返答を先ほど定義した変数であるとするために、メッセージボックス関数を使います。
メッセージボックス関数の構文は次の通りとなります。
MsgBox(表示するメッセージ,メッセージボックスのタイプ,メッセージボックスのタイトル)
表示するメッセージは文字列となりますから最初と最後を”で囲むのがお約束です。メッセージが長いとき、途中に、Chr(13)というのは改行を指示するコードを書くことがあります。(文字列にくっつけて記述するので、実際には&Chr(13)と書きます。)こうすると、メッセージボックスが表示されたときに、メッセージはこの部分で改行されるようになります。次に、メッセージボックスのタイプですが、通常は「vbYesNo」を使います。さらに、メッセージボックスのタイトルとして、ここでは「作業の終了」という指定をしています。
なお、下記のコードの途中にある 「&_」は、1行のコードの文字数が増えて長くなると見にくくなるので、次の行に(コードを)改行しているけれども、まだ終わってはいないという意味の記号です。
'メッセージボックスを表示して、選択されたボタンに応じて分岐処理を行います
メッセージ2 = MsgBox("Excelを終了せずにこのブックだけを閉じます。" & Chr(13) & Chr(13) & _
"このブックだけを閉じて引き続きExcelを使う場合は「はい」を、" & Chr(13) & _
"Excelも終了する場合は「いいえ」をクリックしてください。", vbYesNo, "作業の終了")
以下は、メッセージボックスへの返答によって、処理を分岐させるためのコードです。If 条件 Then 処理1 Else 処理2 End If という構文になります。If関数と似ていることがおわかりいただけると思います。
'「はい」を選択した場合
If メッセージ2 = vbYes Then
'ブックだけを閉じます
ActiveWorkbook.Close
'「いいえ」を選択した場合
Else
'エクセルを終了します
Application.Quit
'分岐処理を終了します
End If
最後に、「名前をつけて保存」ダイヤログボックスが表示されたときに、「キャンセル」ボタンをクリックしたときの処理方法について記述します。ここでも、If ~Then という構文が使われています。ただし、「キャンセル」されたときの処理だけを記述すればいいので、Else以下は不要となりここでは省いてあります。
なお、Err.Number = 1004 というのは、「キャンセル」がクリックされたときのエラーコードです。エラー処理としては、「保存処理がキャンセルされました。一連の処理を中止します。」というメッセージを表示して、マクロを終了させるというものです。ここでもメッセージボックスを使っていますが、先ほどのメッセージボックスが関数(「はい」か「いいえ」の返答を取得するため)であったのに比べ、こちらの方は単にメッセンジャーとしての役割だけなので、コードの書き方が違っています。表示させるメッセージを書いているだけで、メッセージボックスのタイプ指定も省略しています。(タイプを省略すると「OK」ボタンが表示されるようになります。)
'エラー処理についての記述です
Err_名前を付けて保存:
'キャンセルボタンが押されたときのメッセージを表示します
If Err.Number = 1004 Then
MsgBox "保存処理がキャンセルされました。" & Chr(13) & _
"一連の処理を中止します。"
'エラー処理を終了します
End If
End Sub
3.まとめ
今回ご紹介したマクロは、Excelで作成したブックのパーツとして利用することができます。すなわち、ご自分で作成したブックに貼り付けることで、更新日時が自動入力され、ブックを別名で保存してから閉じることができるようになります。
今回ご紹介したマクロは、ドラクエの呪文を覚えるよりは難しいと思いますが、マクロの行数そのものは決して多いわけではないので、高校生程度の英語力と根気があれば、充分ご理解いただけるものと思います。