AutoHotkeyでExcel VBEにF5を送る常駐プログラムの作り方|command.txt監視でVBAと連携
- yuji fukami
- 17 時間前
- 読了時間: 6分
この記事は、VBAをStopで止めて人がF5で再開する処理を自動化するために作った、AutoHotkeyの常駐プログラム(コントローラー)のソースコードを解説するものです。「このコントローラーを何に使うのか」——つまり Power Query でのPDF連続読み込みなど、どうしても処理を止めないと進まない連続処理を自動化する全体像については、VBAのStop地点をAutoHotkeyで自動F5して連続処理するで解説しています。まずそちらを読むと、このコードが果たす役割がつかみやすくなります。
やっていることはシンプルで、VBA側が書き出すコマンドファイル(command.txt)を監視し、「再開してほしい」という指示が来たら、指定時間だけ待ってからExcelのVBエディタ(VBE)にキー操作の F5 を送る、というものです。これによって、人がVBエディタで F5 を押していた操作を、外部プログラムに肩代わりさせます。
必要な環境
このプログラムは AutoHotkey v2 で書かれています。コードの1行目に #Requires AutoHotkey v2.0 を指定しているとおり、v2系での実行が前提です。v1系とは文法が異なるため、動かす際はバージョンにご注意ください。配布しているzipには、あらかじめ実行ファイル(.exe)にコンパイルしたものを同梱しているので、AutoHotkeyを未導入でもそのまま試せます。
ソースコード全文
以下が、コントローラーの全文です。ファイル名は F5_AutoHotkey_Controller.ahk です。
冒頭の設定
まず先頭のディレクティブで、プログラム全体の動作方針を決めています。
#Requires AutoHotkey v2.0 … v2系で実行することを明示します
#SingleInstance Force … 同じプログラムが二重に起動しないようにし、起動済みなら古い方を置き換えます。F5が二重に送られる事故を防げます
#NoTrayIcon … タスクトレイにアイコンを出さず、常駐していても邪魔になりません
続く SetWorkingDir A_ScriptDir で、作業ディレクトリを自分自身のある場所に固定します。A_ScriptDir は「このスクリプト(実行ファイル)が置かれているフォルダ」を指す組み込み変数です。
そのうえで、やり取りに使う2つのファイルパスを組み立てています。
commandFile … VBA側が指示を書き込むコマンドファイル(command.txt)
logFile … 何をしたかを記録するログファイル(VbaF5Controller.log)
どちらも自分と同じフォルダに置く前提なので、VBA側からはこのコントローラーの実行ファイルのフルパスさえ分かれば、同じフォルダの command.txt に書き込むだけで指示を送れます。
メインの監視ループ
Loop { ... } が、このプログラムの心臓部です。中で何かを止める条件を書いていないので、終了指示が来るまで永久に回り続けます。ループの最後にある Sleep(200) で、0.2秒ごとに1周する間隔にしています。常時ファイルを見張りつつ、CPUを使いすぎない、ちょうどよい間隔です。
各周回では、まず if FileExist(commandFile) でコマンドファイルが存在するかを確認します。VBA側がまだ何も書き込んでいなければファイルは無いので、そのまま何もせず次の周回に進みます。
ファイルがあれば、content := FileRead(commandFile, "UTF-8") で中身をUTF-8として読み込み、すぐに FileDelete(commandFile) で削除します。読んだらすぐ消すことで、同じ指示を二度実行してしまうのを防いでいます。1回の指示につき1回だけ処理する、という作りです。
RESUMEコマンドの解析
読み込んだ内容に COMMAND=RESUME という文字列が含まれていれば、「処理を再開してほしい」という指示です。ここで2つのパラメータを用意します。
delayMs := 1000 … F5を送るまでの待機時間(ミリ秒)。初期値は1000ミリ秒(1秒)
excelPid := 0 … 対象のExcelのプロセスID。初期値は0
続く for line in StrSplit(content, "n", "r") で、コマンドファイルの中身を改行で行ごとに分割し、1行ずつ調べています。StrSplit の第2引数の改行文字で区切り、第3引数でキャリッジリターン(\r)を各行の端から取り除いています。
行に DELAY_MS= が含まれていれば、その後ろの値を待機時間として取り出します
行に EXCEL_PID= が含まれていれば、その後ろの値を対象ExcelのPIDとして取り出します
SubStr(line, StrLen("DELAY_MS=") + 1) は、「DELAY_MS= という見出しの文字数だけ飛ばして、その先(=値の部分)を取り出す」という書き方です。これで DELAY_MS=500 のような行から 500 だけを取り出せます。
つまりVBA側は、command.txt に次のような内容を書き込めば、待機時間と対象Excelを指定して再開を指示できる、という設計です。
COMMAND=RESUME
DELAY_MS=(待機ミリ秒)
EXCEL_PID=(ExcelのプロセスID)
待機してからVBEを特定する
パラメータが揃ったら、Sleep(delayMs) で指定された時間だけ待ちます。ここが重要で、VBAを止めた直後は Power Query の読み込みなどがまだ終わっていないことがあるため、少し待ってから再開させることで、確実に読み込みが完了してから次に進めます。この待機時間はVBA側から DELAY_MS で調整できます。
待機のあと、F5を送る相手のウィンドウを探します。
hwndList := WinGetList("ahk_class wndclass_desked_gsk") の wndclass_desked_gsk は、Excelの VBエディタ(VBE)ウィンドウのクラス名です。WinGetList で、このクラス名を持つウィンドウのハンドル一覧を取得します。ただし、Excelを複数起動していると、VBEウィンドウも複数見つかる可能性があります。そこで、どのVBEに送るべきかを絞り込む必要があります。
その絞り込みが for hwnd in hwndList { ... } のループです。1つずつウィンドウを見て、
pid := WinGetPID("ahk_id " . hwnd) で、そのVBEウィンドウがどのプロセス(Excel)に属しているかのPIDを取得します
if (pid = excelPid) で、VBA側から渡された対象ExcelのPIDと一致するかを判定します
一致したものが、まさに今処理を止めている当のExcelのVBEです。PIDで照合することで、別のExcelやウィンドウに誤って F5 を送ってしまう事故を避けています。
F5を送って再開させる
対象のVBEウィンドウが見つかったら、次の順で操作します。
WinActivate("ahk_id " . hwnd) … そのVBEウィンドウを前面にしてアクティブにします
WinWaitActive("ahk_id " . hwnd, , 3) … 実際にアクティブになるまで最大3秒待ちます。アクティブになる前にキーを送ると別のウィンドウに届いてしまうため、この待機が保険になります
SendEvent "{F5}" … F5キーを送信します。これがVBエディタでの「実行(続行)」にあたり、止まっていたVBAが再開します
FileAppend("Sent F5 to VBEn", logFile, "UTF-8")` … ログに「VBEにF5を送った」と追記します
SendEvent はキー入力をイベントとして送る方式で、対象ウィンドウに素直に届きやすいのが特徴です。送信できたら break でループを抜け、余計なウィンドウには送りません。
終了指示とログ
コマンドファイルの中身が COMMAND=EXIT だった場合は、FileAppend でログに終了要求を記録してから ExitApp でプログラム自体を終了します。連続処理がすべて終わったら、VBA側がこの EXIT を書き込むことで、常駐していたコントローラーをきれいに終わらせられます。
ログ(VbaF5Controller.log)には「F5を送った」「終了要求」といった記録が残るので、うまく動かないときに、そもそも指示が届いていたのか、F5まで到達していたのか、といった切り分けに役立ちます。
ダウンロード
コンパイル済みの実行ファイルを同梱したzipです。AutoHotkeyを未導入でも、解凍してそのまま試せます。
実行ファイルを含むため、取り扱いには注意し、ご利用は自己責任でお願いします。中身はこの記事で全文公開しているとおりで、怪しい動作はしていません。
まとめ
このコントローラーは、「command.txt を監視し、RESUME指示が来たら指定時間待ってから、Excel PIDで特定したVBEに F5 を送る」という、機能をひとつに絞ったシンプルな常駐プログラムです。シンプルだからこそ、VBAと組み合わせたときに挙動が読みやすく、トラブルの切り分けもしやすくなっています。
このコントローラーを使って、どうしても止めないと進まないVBAの連続処理を自動化する全体像は、VBAのStop地点をAutoHotkeyで自動F5して連続処理するで解説しています。あわせてご覧ください。
