TL;DR —
Debug.Print exprは 1 行を イミディエイトウィンドウ(Immediate Window) に書き込み、 マクロをそのまま走らせ続けます。ポップアップなし、一時停止なし —MsgBoxのちょうど正反対です。だから ループが値を流していく様子を眺めるのに最適な道具になります。落とし穴はこれ。イミディエイトウィンドウは 既定で閉じています。だから第 1 位の不満 — Debug.Print が何もしない — は、ほぼ必ず「見えていない だけの出力」です。Ctrl+G で開きましょう。ログをセッションを越えて残したいなら、ウィンドウへの表示を やめて代わりに ファイルへ書き出し ましょう。
Sub DebugPrintBasics()
Dim i As Long
For i = 1 To 3
Debug.Print "row " & i, Cells(i, 1).Value ' イミディエイトウィンドウへ流れていく
Next i
Debug.Print "done" ' ポップアップなし、マクロは止まらない
End Sub
' 何も見えない? イミディエイトウィンドウが閉じています。Ctrl+G を押しましょう。
この記事で学べること
- 考え方の軸 — Debug.Print は静かでブロックしないログであって、ダイアログではない
- 力の順に並んだ 3 つの観測手段と、それぞれが答える問い
- Debug.Print が何もしていないように見える理由(と Ctrl+G での対処)
- イミディエイトウィンドウが最初の出力を黙って捨てる理由
- 式を表示すると本物の副作用が走りうる理由
- Debug.Print と MsgBox の違い、そしてログが本物のファイルになるべきとき
考え方の軸:ダイアログではなく、静かなログ
Debug.Print は ログの 1 行 です。イミディエイトウィンドウにテキストを追記し、ただちに制御を
コードへ返します — マクロは止まらず、何もポップアップせず、誰もクリックする必要がありません。この
たった 1 つの性質こそ、Debug.Print が存在する理由のすべてです。ループを診断しているとき、あなたが欲しいのは
スクロールできるパネルを 5,000 個の値が流れ去っていく光景であって、「OK」を 5,000 回クリックすることでは
ありません。
だから頭の中で立てるべき正しい問いは、決して「この値をどう 見せる か?」ではありません — 値を見せるのは
MsgBox の仕事です。問うべきは「実行を中断せずに、どう値を 記録 するか?」です。以下のすべては、この
一つの捉え方からまっすぐに導かれます。Debug.Print は決してブロックしないので、その出力は、あなたが出向いて
覗きにいく場所に住まねばなりません — そしてその場所こそ、頼むまで Excel が隠しておくウィンドウなのです。
力の順に並んだ 3 つの観測手段
Debug.Print は、はしごの最初の段です。マクロがおかしなふるまいをするとき、手がかりが足りないのでは ありません — ただ 見て いないだけです。VBA は見るための道具を 3 つ手渡してきます。それぞれが 別々の 問いに答え、それぞれが独自のやり方であなたに嘘をつきます。
| 観測手段 | 答える問い | 決まってつく嘘 |
|---|---|---|
Debug.Print |
実行中、値は何だったか? | 既定で閉じているウィンドウに出力する |
| Immediate Window | いま、この一時停止の瞬間に何が真か? | ? の問い合わせは実はコードを 実行する |
| Breakpoint + F8 | どの行で間違うのか? | ブックを閉じると消える |
受動的なものに手を伸ばせば、どの行が壊れたのか当て推量することになります。重いものに手を伸ばせば、
10,000 回の繰り返しを手でステップ実行することになります。腕の見せどころは、いま欲しいのが 値を見る ことか
行を見つける ことかを見抜くことです。Debug.Print はいちばん緩い問いに答えます — 事が済んだあとで 何が
起きたかを見せてくれる — だから最も手軽に手が伸び、最も素通りしてしまいやすいのです。
罠 1:既定で閉じているウィンドウに出力する
第 1 位の「Debug.Print が動かない」報告は、あなたのコードのバグではありません。値は書いたとおりに、 きっちり出力されています — あなたが一度も開いたことのないパネルに。
Sub WhereDidItGo()
Debug.Print "I am running fine" ' この行はちゃんと動く
End Sub ' ただ、どこへ出力されたかが見えないだけ
イミディエイトウィンドウ(Immediate Window)は、VBA エディタの中で Ctrl+G(または 表示 > イミディエイト
ウィンドウ)で開きます。それまでは、どの Debug.Print も黙って成功し、あなたは「何も起きなかった」と
結論づけます。「コードが走るか確認する」ために MsgBox を 1 つ足す前に、まずイミディエイトウィンドウを
開きましょう — 十中八九、証拠はもうそこにあります。
罠 2:ウィンドウは最初の出力を黙って捨てる
イミディエイトウィンドウは無限のログではありません。保持するのは直近の 約 200 行 だけで、それより古い 行は上へスクロールして消え去ります。小さなテストでは気づきません。10,000 行のループでは、あなたが最も 見たい行 — たいていパターンが崩れる 最初の 数行 — が、真っ先に捨てられます。
Sub LosesTheStart()
Dim i As Long
For i = 1 To 10000
Debug.Print i, Cells(i, 1).Value ' 終わる頃には 1〜9800 行目は消えている
Next i
End Sub
全部の 履歴 — すべての行を、順番どおりに、実行後も残したい — が必要なときは、Debug.Print は道具ちがいです。
テキストファイルを開いて代わりに Print # を使いましょう。バッファの上限がなく、あとで開き直せるファイルを
残します(VBA Print と Write)。Debug.Print は一目のため、ファイルは記録のためです。
罠 3:式を表示すると本物の副作用が走りうる
「ログは受動的だ」が真なのは、ログに取る対象が受動的なときだけです。Debug.Print は 引数を評価する ので、
関数の結果を表示すれば、その関数は — あらゆる結果とともに — 実行されます。
Debug.Print DeleteOldRows() ' これは行を削除してから件数を表示する
Debug.Print Cells(1, 1).Value ' これは本当に受動的 — 値を読むだけ
「いくつ削除される予定か見てみよう」と DeleteOldRows() を表示すると、実際に削除してしまいます。Debug.Print の
引数は素の変数とプロパティの読み取りにとどめ、戻り値を覗くためだけに副作用のある関数をそこへ通してはいけません。
どうしても必要なら、まず結果を変数に受けてから、その変数を表示しましょう。
Debug.Print と MsgBox
一見すると取り替えがきくように見えます — どちらも値を見せる — が、両者は正反対で、選び間違えるとそれ自体が 一種の苦しみになります。
Debug.Print |
MsgBox |
|
|---|---|---|
| マクロを止める? | いいえ、走り続ける | はい、クリックを待つ |
| 出力先 | イミディエイトウィンドウ(開発者だけ) | 画面上、誰にでも |
| ループの中では | 何千行も流し込む | 1 回ごとに 1 つのモーダルダイアログ |
| 履歴 | スクロール可能(直近 約 200 行) | OK を押した瞬間に消える |
ルールはおのずと書けます。開発中に あなた が何かを見たいなら Debug.Print。本番のユーザー が何かを見る
必要があるなら、それは本物のメッセージ — 本気の問いかけには MsgBox、あるいは進捗の通知
(VBA MsgBox)です。絶対にやってはいけないのは MsgBox でループをデバッグすること。
それこそ、5 秒の診断が 400 回の OK クリックに化ける道です。
読みやすい出力のコツ:値を ; で区切ると詰めて連結し、, で区切るとタブ位置でそろえます —
Debug.Print i; x; y と Debug.Print i, x, y の違いです。
意見:Debug.Print はログであって、ロギングシステムではない
Debug.Print は、開発中に値を眺める最速の手段として、その居場所を稼いでいます。そして、繰り返すものに
対してはほぼ必ず MsgBox より正しい答えです。しかしこれは ログの 1 行 であって、ロギングの仕組み では
ありません。出力をセッション越しに残したい、タイムスタンプを持たせたい、VBA エディタの開いていない他人の
マシンで走るマクロから出したい — そう思った瞬間、あなたはこの道具を卒業しています。
正気を保つ習慣が 2 つあります。第一に、出荷するコードからは Debug.Print を剥がすか、Const DEBUG_MODE As Boolean = False のような定数で門番をさせること。ホットなループに残したままだと、呼ばれるたびに文字列を
整形しバッファへ書き込み続けます — これは実測できる本物のコストです。第二に、一目ではなく耐久性のある記録が
要件になったら、Print # とテキストファイルに切り替えること。Debug.Print の仕事は VBA エディタを閉じた瞬間に
終わります。それを監査証跡にしようとしてはいけません。
仕事そのものがバグ探しのとき — それを説明する
本当の仕事の半分は「この値を表示する」ではなく「8,000 行の中で合計が合わなくなるただ 1 行を見つけて、その行の
何が違うのか教えて」です。200 行のマクロに Debug.Print を撒き、再実行し、切り詰められたイミディエイト
ウィンドウをスクロールし、パターンを目で組み立て直す頃には、その計器付けが修正そのものより高くついています。
ExcelMaster なら、その目的を普通の
言葉で — 「E 列が C 足す D と等しくない行をすべて見つけて、その行を見せて」 — と言うだけです。そして、
データを読み、まずファイルをバックアップし、チェックを適用し、失敗した行そのものを返す Python を生成します。
あなたは問いを説明するだけ。探すのはそれがやります。
よくある質問
VBA の Debug.Print の出力はどこへ行きますか?
VBA エディタの中の イミディエイトウィンドウ(Immediate Window) です。Ctrl+G または 表示 > イミディエイト ウィンドウ で開きます。出力はそこにしか表示されません — ワークシートにもダイアログにも現れません — だからこそ、 閉じたイミディエイトウィンドウが「Debug.Print が何もしない」ように見える通常の原因なのです。
Debug.Print が何も表示しないのはなぜですか?
ほぼ必ず、イミディエイトウィンドウが閉じているから(Ctrl+G を押す)、あるいは出力が約 200 行のバッファを
超えてスクロールし去ったから、あるいはその行に到達する前にマクロがエラーを起こしたからです。ウィンドウが
開いていることを確認し、Debug.Print "reached here" の目印を足して、コードの経路が実際に走っているかを
確かめましょう。
Debug.Print と MsgBox の違いは何ですか?
Debug.Print は静かにイミディエイトウィンドウへ書き込み、マクロを走らせ続けます。MsgBox は、閉じるまで
待つモーダルダイアログでマクロを止めます。開発中のループや値の履歴には Debug.Print を、人が実際に何かを
見たり答えたりする必要があるときにだけ MsgBox を使いましょう。
VBA で複数の値を 1 行に表示するには?
セミコロンかコンマで区切ります。Debug.Print i; x; y は値を詰めて連結し、Debug.Print i, x, y はタブ位置
(列)でそろえます。詰まった行には ;、イミディエイトウィンドウで読みやすい表には , を使いましょう。
Debug.Print を本番コードに残してもよいですか?
いいえ。剥がすか、Const DEBUG_MODE As Boolean = False のような定数で門番をさせましょう。無害に見えても、
呼ばれるたびに引数を評価し、上限のあるイミディエイトウィンドウのバッファへ書き込むので、ホットなループを
遅くします。残す必要のある出力は、代わりに Print # でファイルへ記録しましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-05.
関連ガイド: VBA Immediate Window · VBA Breakpoint · VBA MsgBox · VBA Print と Write · VBA For ループ
