ブックを開いたときにマクロを実行するには
ブックを開いたときにマクロを実行するには、ThisWorkbookのWorkbook_Open関数を使います。
ThisWorkbookを開き、オブジェクトボックス(コードウィンドウの左上のコンボボックス)でWorkbookを選ぶと、自動でWorkbook_Open関数が表示されます。
1 2 3 |
Private Sub Workbook_Open() // ここに実行したい処理を書く End Sub |
あとは、ブックを開く度にWorkbook_Open関数に書かれている処理が実行されます。これで終わりです。ですが、本当の問題はここからです。
自動実行の実装方法は単純です。しかし大事なのは「その処理は本当に自動実行しなければならないのか?」、自動実行が必要なのであれば「どうやって自動実行するのか?」という点です。
Workbook_Open関数は自分でブックを開かないときに使う
問題なのは、Workbook_Open関数があるブックをどうやって開くかです。エクスプローラからダブルクリックで開くと実は問題があります。
Workbook_Open関数はブックを開いたときに自動で実行してくれるという便利な点がありますが、その反面、実行してほしくないときでも必ず実行されてしまうという制約も当然含んでいます。
やってみると分かりますが、ブックを開くたびに毎度毎度、自動で実行されるというのは結構ストレスに感じます。そして結局「あー、うるさいなー・・・」となり、結局ボタンなどを用意して自分のタイミングで実行する方が使い勝手がいいことに気が付きます。
これが、あまり用途を考えずにWorkbook_Open関数を使った場合によくある失敗です。「ブックを開いたときに自動実行する」こと自体が最初は便利に感じても、しばらくすると、うるさく感じるのです。
結局、「エクスプローラでブックを開いたときに自動でちょっとやってもらう」というのは、おせっかいが過ぎたり、処理の待ち時間が発生したりと、多くの場合でイヤになって止めることになります。このようなエクスプローラからブックを開くWorkbook_Open関数の使い方は良い使い方ではない、ということです。
では、どのような使い方がよいのかというと、人の目に触れない実行方法がWorkbook_Open関数のいい使い方です。「自分が知らない間に勝手にブックが開いて、自動で何かの処理をやってくれる」状態にすることです。そして、一連の処理が終わったらブックは閉じておきます。完全な自動実行です。
例えば、PCを使っていない時間帯に勝手に処理をしてもらう、とかです。これであればストレスを感じることもありません。
自動実行させたいときだけ動く条件を用意する
先に書いた通り、「常に自動実行」するのは自動実行自体を邪魔に感じるという弊害があります。
そこで対応方法として、Workbook_Open関数が呼び出されても「ある特定の条件にある場合」にのみ自動実行するようにしておけば、エクスプローラーで開く場合は自動実行されずにストレスを感じなくて済むようになります。
ではどうしたらいいかというと、バッチファイルなど他のアプリケーションで「今から自動実行します」ということが分かる状態にしておき、それからブックを開いた場合にのみ、Workbook_Open関数の内部処理を実行するような方法が挙げられます。
ここではタスクスケジューラとバッチファイルを使った具体的な方法を紹介します。
処理順序と考え方
タスクスケジューラとバッチファイルを使う場合の処理の流れは以下のようになります。
- タスクスケジューラで指定した日時にバッチファイルを実行する。
- バッチファイルで自動実行用のテキストファイルを作成する。
- バッチファイルでマクロブックを開く。
- マクロブックのWorkbook_Open関数が実行される。自動実行用のテキストファイルがあるため、自動実行したい処理を実施する。
- 自動実行したい処理が終わったらブックを自ら閉じる。
- バッチファイルで自動実行用のテキストファイルを削除する。
バッチファイルからマクロブックを呼び出す前に「workbook-open.txt」というファイルをバッチファイルのコマンドで作成しておき、Workbook_Open関数の先頭で「workbook-open.txt」が無い場合は自動実行しない、という処理を入れておきます。そして、バッチファイルの最後に「workbook-open.txt」を削除します。このようにすると、エクスプローラーからマクロブックを開いた場合は「workbook-open.txt」が無いため自動実行が行われません。
テキストファイルの有無の条件を「テキストファイルが無い場合にのみ自動実行する」としてしまうと、テキストファイルのことを忘れたときにエクスプローラからブックを開いて自動実行が行われ、なにこれ?ということに陥る恐れがあります。自動実行はあくまでも「ある条件の場合にのみ実行する」としておいた方が安全です。
以下の例で使うファイルは3つあります。それぞれファイルの名前はなんでもいいのですが、ここではマクロブックのabc.xlsm、マクロブックを開くバッチファイルのauto.bat、自動実行判定用テキストファイルのworkbook-open.txtです。
マクロブックのabc.xlsm、マクロブックを開くバッチファイルのauto.batはどちらも同じフォルダにあるものとします。自動実行判定用テキストファイルのworkbook-open.txtはバッチファイル実行中の間だけ同じフォルダに存在します。
1. マクロブックを呼び出すバッチファイル
まずマクロブックを呼び出すバッチファイルを作成します。
バッチファイルに以下のように書きます。バッチファイルのファイル名はなんでもいいのですが、ここではauto.batとします。
1 2 3 4 5 |
set CUR_DIR=%~dp0 type null > %CUR_DIR%workbook-open.txt %CUR_DIR%abc.xlsm del %CUR_DIR%workbook-open.txt |
1行目は、変数CUR_DIRにバッチファイルがあるディレクトリのパスを示す「%~dp0」を設定します。バッチファイルがC:\abc\auto.batにあるとすれば、「C:\abc\」が変数CUR_DIRにセットされます。
2行目は、自動実行判定用のテキストファイルを作成します。最後に削除します。このファイルがある間はマクロブックのWorkbook_Open関数内で自動実行を行うような処理を入れておくためです。
3行目は、マクロブックを開きます。バッチファイルでは「C:\abc.xlsm」のようにブックのフルパスを書けば開きます。
4行目は、自動実行判定用のテキストファイルを削除します。残しておくと次にマクロブックを開いたときに自動実行と判定されるため削除します。
2. Workbook_Open関数の内容
マクロブックのThisWorkbookには以下のようにWorkbook_Open関数を書きます。
バッチファイルで作成するテキストファイルが無い場合はExit Subで処理を抜けるようにし、ある場合は自動実行したい処理を行います。
処理が終わったあとはブックを自ら閉じます。閉じる際に「保存しますか?」ダイアログを回避するためにSaveChanges:=Falseを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Private Sub Workbook_Open() '// 自動実行用ファイルが無い場合 If Dir(ThisWorkbook.Path & "\workbook-open.txt") = "" Then '// この場合はエクスプローラから開いているためブックは閉じない '// 自動実行せずに抜ける Exit Sub End If '// 自動実行したい処理をここに書く Debug.Print "abc" '// 自動実行時は処理終了後にブックを閉じる。保存しますか?ダイアログはOFF ThisWorkbook.Close SaveChanges:=False End Sub |
3. タイムスケジューラの設定
最後にタスクスケジューラの設定をします。ここでは指定日時になったらバッチファイルを実行するタスクを作成します。
コントロールパネル → 管理ツール → タスクスケジューラ を開きます。タスクスケジューラの操作メニューから「タスクの作成」を選択し、全般タブの名前を入力します。
トリガータブの新規ボタンで実行したい日時を指定します。
操作タブの新規ボタンでプログラム/スクリプトにバッチファイルのフルパスを指定します。
これで、指定した日時にバッチファイルが実行され、さらにバッチファイルからマクロブックが開かれ、Workbook_Open関数が実行されるようになります。
自動実行させたくない場合はタスクスケジューラに作成したタスクを無効にします。
Auto_Open関数は使わなくてよい
ブックを開いたときにマクロを実行する別の方法として、標準モジュールに書くAuto_Open関数もあります。
しかしAuto_Open関数は使う必要ありません。
Auto_Open関数はVBAがExcelに実装された1990年代に使われていたもので、その当時はWorkbook_Open関数がありませんでした。互換性のために残されています。
使うと問題が起こるわけではありませんが、Workbook_Open関数でやりたいことは実現できるため使う必要はないでしょう。