TL;DR —
ActiveWorkbookは今いちばん手前にあるブック、ActiveSheetはその中で今見ているタブです。 どちらも 動く標的 です。ユーザーが別の場所をクリックした瞬間 — あるいはあなた自身のコードが何かを 選択した瞬間 — 変わります。だからこそ、Sheets("Jan").SelectしてからSelection.Value = 1という 古典的な記録マクロのパターンは、とても脆いのです。代わりにシートとセルを 直接 参照し、どうしても アクティブなオブジェクトを使うなら、行ごとに取りに行くのではなく 一度だけ 変数に読み込んでください。
Sub ActiveIsAMovingTarget()
' もろい:選択してから「選ばれているもの」に対して動く
Worksheets("Jan").Select
Range("A1").Select
Selection.Value = 100 ' フォーカス次第で完全に変わる
' 堅牢:シートとセルを名指しし、選択しない
ThisWorkbook.Worksheets("Jan").Range("A1").Value = 100
End Sub
この記事で学べること
- 考え方の軸 — アクティブなオブジェクトは住所ではなく、動く標的
- オブジェクトを名指しする3つの道具と、その中でアクティブなオブジェクトが占める位置
ActiveWorkbookとThisWorkbook、そしてアクティブなほうがあなたを驚かせる理由SelectとActivateのアンチパターンと、マクロ記録がそれを教えてしまう理由- アクティブなオブジェクトに対して動くのが本当に正しい判断となる場面
- 意見 — アクティブは一度だけ読み、あとは直接参照する
考え方の軸:住所ではなく、動く標的
ActiveWorkbook と ActiveSheet は、特定の ファイルやタブの名前ではありません。それらは 位置 の
名前です — 「今いちばん手前にあるもの」。その位置は動きます。ユーザーが別のウィンドウをクリックすれば
動き、ファイルを開くマクロが動かし、.Select や .Activate を呼ぶあなた自身のコードの1行が動かします。
標的が動くので、「今アクティブなのは何か」と問い続けるコードは、実のところ「マウスはどこを指しているか」を
問うています — そして、それは信頼できるマクロが依存すべき問いではありません。
それを 住所 と対比してください。ThisWorkbook.Worksheets("Jan").Range("A1") は、ファイル・シート・
セルをはっきり名指しします。何がアクティブかを気にしません。ブックレベルのVBAの技術とは、まるごと、
位置より住所を選ぶことなのです。
3つの参照の道具の中のアクティブなオブジェクト
アクティブなオブジェクトは、1つの行がどのオブジェクトに作用するかを言うためにVBAがくれる3つの道具の 一つです。それぞれがいつ正しいかを知ることが、このクラスターの背骨です。
| 道具 | 何を指すか | 落とし穴 |
|---|---|---|
| ThisWorkbook | このコードを抱えるブック — 不動 | 間違ったファイルには決してならないが、別の ファイルにもならない |
ActiveWorkbook / ActiveSheet |
今いちばん手前にあるもの | フォーカスが動くたびに動く — あなた自身の .Select を含めて |
| Worksheets(...) | ブック内の名前付きシート | 名前・インデックス・CodeName を知っている必要がある |
アクティブなオブジェクトがその居場所を得るのは、ただ1つの仕事のためです — 「ユーザーが今見ているもの」に 対して動くべき 汎用ツール、つまり整形アドインや、ボタンに割り当てた手早いユーティリティです。特定の ファイルや特定のシートに属するものについては、住所がアクティブなオブジェクトに毎回勝ちます。
ActiveWorkbook と ThisWorkbook:あなたを驚かせるほう
ActiveWorkbook と ThisWorkbook は鏡写しです。ThisWorkbook はマクロ自身の
ファイルに固定され、ActiveWorkbook はユーザーに追従します。両者が一致するのはブックが1つだけ開いている
間だけで、まさにそれが、テスト中には違いが隠れ、本番で現れる理由です。
Sub Mirror()
Debug.Print ThisWorkbook.Name ' コードを持つファイル - 常に同じ
Debug.Print ActiveWorkbook.Name ' 手前のファイル - 開いているどれでもありうる
End Sub
名前を付けておく価値のある2つ目の驚きがあります。ActiveWorkbook は Nothing になりえます。すべての
ブックのウィンドウが隠れているか、VBAエディターだけが表示されている場合、アクティブなブックは存在せず、
それに触れるとエラーになります。ThisWorkbook は常に存在します。コードがどちらを信頼すべきか迷ったら、
消えられないほうを信頼してください。
Select と Activate のアンチパターン
マクロ記録をオンにし、タブをクリックし、セルをクリックし、値を入力すると、こう書かれます。
Sheets("Jan").Select
Range("A1").Select
ActiveCell.Value = 100
記録されたマクロはすべて .Select と .Activate から組み立てられます。記録機能が見ているのが、文字どおり
あなたのその操作だからです。動くので初心者はそれを残し — そして3つの問題にぶつかります。遅い
(選択のたびに画面が再描画される)、もろい(後続のすべての行が Selection / ActiveCell に寄りかかる
ので、迷子の1クリックやフォーカスを奪う1つの MsgBox で脱線する)、そして ユーザーが見ていないシートに
対しては、その表示を引きずり回さずには動けない。
治療法は、選択をまるごと飛ばして、意味するものを名指しすることです。
' アンチパターン - 選択してから選択範囲に対して動く
Sheets("Jan").Select
Range("A1").Select
Selection.Value = 100
' 直接 - 1行、フォーカス変更なし、どのシートでも動く
ThisWorkbook.Worksheets("Jan").Range("A1").Value = 100
本物のコードで .Select や .Activate が必要になることは、ほとんどありません。稀な例外は、最後に
ユーザーを特定のシートに残しておきたいとき、あるいは本当に選択を必要とするAPIのときです。それ以外は
すべて、オブジェクトを直接参照すべきです。
アクティブなオブジェクトに対して動くのが本当に正しいとき
アクティブなオブジェクトは常に間違いというわけではありません — 既定 として間違いなのです。マクロが、 「ユーザーが開いているものに対してこれをやる」ことを目的まるごととする汎用ツールのときは、まさに正解 です — 現在の選択範囲を整形するユーティリティ、アクティブなシートにハウススタイルを適用するもの、手前の ブックをPDFに書き出すものなど。そうした場合、アクティブなオブジェクト こそ 意図したターゲットであり、 ブック名をハードコードするほうがバグになります。
それでもなお、先頭で 一度だけ 変数に読み込み、その変数を通して作業してください。そうすればターゲットが マクロの途中でずれることがありません。
Sub FormatWhateverIsOpen()
Dim ws As Worksheet
Set ws = ActiveSheet ' ターゲットを今この場で一度だけ捉える
ws.UsedRange.Font.Bold = False
ws.Range("A1").Value = "Reviewed"
' ...ここから先はもう「アクティブ」に依存しない...
End Sub
意見:アクティブは一度だけ読み、あとは直接参照する
ActiveWorkbook や ActiveSheet に手を伸ばすのは、「ユーザーが手前に持っているもの」が本当にあなたの
意味するものであるときだけにしてください — そしてそのときは、最初の行で変数に捉え、生きたアクティブ
オブジェクトには二度と触れないでください。それ以外のすべては、オブジェクトを名指しします — 自分の
ファイルには ThisWorkbook、特定の別ファイルには Set したブック変数、シートには限定した
Worksheets(...)。記録機能が渡してきたマクロからは .Select と .Activate を消してください。それらは、
マクロが意味を言う代わりにフォーカスに寄りかかっている、最も明確な唯一のサインです。
こうしたことを一切、手で管理したくないとき
記録したマクロから .Select をすべて取り除き、すべての参照を限定するように書き直すのは、まさに「やる
価値はあるが面倒」な片付けです。
ExcelMaster は、普通の言葉の
結果 — 「ユーザーが見ているものを変えずに、先月分の合計をこのファイルのサマリータブに置いて」 — を受け取り、
直接的で限定されたコードを書き、ブックをバックアップして、実行します。あなたは結果を説明するだけ。
生成されるコードは、たまたまアクティブなものに決して依存しません。
よくある質問
ActiveWorkbookとThisWorkbookの違いは?
ActiveWorkbook は行が走る瞬間にいちばん手前にあるブックなので、ユーザーやコードがフォーカスを変える
たびに変わります。ThisWorkbook は実行中のコードを含むブックで、決して変わりません。マクロ自身の
ファイルには ThisWorkbook を、意図的に「ユーザーが手前に持っているもの」を意味するときだけ
ActiveWorkbook を使ってください。
VBAでSelectとActivateを避けるには?
選択する代わりに、オブジェクトを直接参照します。Range("A1").Select してから Selection.Value = 1 を、
1行の ThisWorkbook.Worksheets("Jan").Range("A1").Value = 1 に置き換えてください。Worksheet 変数を
一度だけ Set してそれを通して作業すれば、どの行も現在選択されているものに依存しなくなります。
マクロでActiveSheetが危険なのはなぜですか?
動く標的だからです。それは行が走るときに手前にあるタブであり、ユーザーがクリックして離れたり、あなた
自身のコードが別の何かをアクティブにしたりすると変わります。ActiveSheet を取りに行き続けるマクロは、
エラーを一切出さずに間違ったシートに対して動きえます。一度だけ変数に捉えるか、シートを直接名指しして
ください。
アクティブシートを変数に設定するには?
マクロの先頭で Dim ws As Worksheet としてから Set ws = ActiveSheet とし、以後は ws を使います。
アクティブなシートを一度だけ読むと、ターゲットが固定され、マクロの途中でずれなくなります。これが、
アクティブなオブジェクトが本当に意味するものであるときの、安全な使い方です。
実際にActiveWorkbookを使うべきなのはいつですか?
マクロが、特定のファイルではなく、ユーザーが開いているものに対して動くことを意図した汎用ツール — 整形
ツール、手早いユーティリティ、書き出しボタン — のときです。そうした場合、ActiveWorkbook が意図した
ターゲットです。特定のファイルに結びつくものには、代わりに ThisWorkbook かブック変数を使ってください。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-07.
関連ガイド: VBA ThisWorkbook · VBA Worksheets · VBA ActiveSheet · VBA Range · VBA Worksheet
