この記事で解決できること
ブレイクポイントを設定していないのに、VBAが「コードの実行が中断されました」というメッセージで止まってしまう問題を解決します。
ブレイクポイントがない場所で止まる
症状
VBAを実行すると、ブレイクポイントを貼ってないのになぜか「コードの実行が中断されました」とメッセージボックスが表示され、「デバッグ」ボタンを押すとVBAの画面でコードが止まっている箇所が表示されます。
ところが、表示されているVBAのコードを見ても、ブレイクポイントがありません。ブレイクポイントが無いのにコードが中断しているのです。
「は?」と思い、再度実行しても、また同じ場所で止まります。「いやいや、ブレイクポイント無いんですけど。なんで止まっちゃうの?」と不思議な事象を見ることになります。
原因
この事象の原因は、過去の自分が貼ったブレイクポイントが内部的に残っているためです。通常、ブレイクポイントはデバッグ中に止めたい場所に設定します。そして、止める必要がなくなれば解除します。これが普通の使い方です。
しかし、「コードの実行が中断されました」のメッセージボックスが表示された場合は、見た目はブレイクポイントは見えないのにVBAの内部情報としてはブレイクポイントとして保持されたままになっており、「非表示のブレイクポイント」とも言うような状況に陥っています。
VBAには以下の2つの情報があります。
- 見た目の情報: VBA画面に表示されるブレイクポイントのマーク(●)
- 内部情報: VBAのシステムが保持しているブレイクポイントの位置情報
通常、この2つは一致していますが、特定の操作(後述)により内部情報だけが残ってしまうことがあります。これを「非表示のブレイクポイント」と呼べるような状態です。
解決方法は「非表示のブレイクポイント」を消せばいい、ということになります。それについて以下に説明します。
解決方法
解決方法は以下の通りです。
- 「コードの実行が中断されました」のメッセージボックスの「デバッグ」ボタンを押します。
- VBAの画面がアクティブになり、ブレイクポイントがない行が表示されます。
- VBAの画面がアクティブの状態で、Ctrl キー + Pause/Break キーを2回(2回でまた止まる場合は1回)押します。見た目上は何も起きません。
- 実行ボタンを押して続行させるか、リセット(停止)ボタンを押して処理を止めます。
- 再度マクロを実行して確認。
これで直るはずです。PCやExcelの再起動は必要ありません。
これでも直らない場合はPCの再起動をしてください。
Pause/Breakキーがない場合
ノートPCなど一部のキーボードにはPause/Breakキーがありません。その場合は、
- Fn + Ctrl + B など、機種によって異なる組み合わせを試す。
- キーボードメーカーのマニュアルで「Pause/Break」の代替キーを確認する。
- 外付けキーボードを一時的に使用する。
などを試してみてください。
発生原因
この事象が発生する原因は、Ctrlキー + Pause/Break キーで強制的に中断しているためです。
なぜ発生するのか
上にも書いていますが、ブレイクポイントの情報は見た目のブレイクポイントのマーク●の情報と、内部的にどこにブレイクポイントが設定されているか、という情報があります。
通常のデバッグ時にブレイクポイントの設定と解除というVBA画面上での操作であれば、見た目情報と内部情報が一致しますが、Ctrlキー + Pause/Break キーで強制的に中断すると、見た目情報と内部情報に乖離が起きることがあります。
ただ、Ctrlキー + Pause/Break キーを押すと必ずこの事象が発生するわけではありません。
一般的に、Ctrlキー + Pause/Break キーを押すのは、なんらかの無限ループやそれに類する長い処理を止めたい場合に使います。言い方を変えれば、普通じゃない状態のときの緊急避難としての操作です。この操作はVBAの処理に対して割り込みを行うための操作で、「無理やりでいいからVBAを止めろ」という要求になります。
しかし、以下のような状況ではVBAが割り込みを適切に処理できないことがあります。
- Windowsがその割り込みを許可できないタイミングで実行された。
- EscキーやCtrlキー + Pause/Break キーを押しながらタスクバーをいろいろクリックしまくって無理やり止める(タスク切り替えや処理停止のメッセージを連続で投げまくる)。
- 複数の割り込みメッセージが短時間に大量に送られた。
このような場合、VBA側で割り込みメッセージを適切に処理できず、「見た目の情報」と「内部情報」にズレが発生し、本件の事象が発生します。
必ず発生するわけではない
Ctrlキー + Pause/Break キーを押す度にこの事象は発生するわけではありません。というより普通は発生しません。特定の条件が重なったときに稀に発生する事象です。
Windowsのイベント処理はWindowsプログラミングの中でも面倒かつ複雑な部類で、この事象は古いExcelでも発生していたため、多分ですがVBAの既知のバグです。
まれにしか起きないのと修正が大変なので放置されているのかもしれません。
やらない方がいいこと
Application.EnableCancelKey = xlDisabledは使わない
Application.EnableCancelKey というプロパティがあります。これは、外部のキー操作による割り込みをどのように扱うかを指定するプロパティです。
「Application.EnableCancelKey = xlDisabled」 と書くと、EscキーやCtrlキー + Pause/Breakキーを押された場合に、VBAの処理を中断しなくなります。なので、本件の事象の根本原因である「Ctrl + Pause/Breakで非表示のブレイクポイントが発生する」ということがなくなります。
ただ、このプロパティを使うことは本末転倒で、むしろ、マクロ利用者による強制割り込みを拒否したいなどのよほどの意図的な目的がない限りは使わない方がいいです。
「もしかしたらCtrl + Pause/Breakキーを押すと、コードの実行を中断しました、と出るかもしれない。そのときは見えないブレイクポイントが発生してしまい、VBAを実行する度に止まってしまう。なので、そうならないようにCtrl + Pause/Breakキーは処理しないようにしよう」という考え方は目的を誤ってます。
なので、本件事象の解決のために「Application.EnableCancelKey = xlDisabled」を書くのは目的を間違ってますのでやめましょう。