🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

ExcelのVBA ThisWorkbook — ActiveWorkbookと同じではない理由

|

ExcelのVBA ThisWorkbook — ActiveWorkbookと同じではない理由

TL;DRThisWorkbook は、どのウィンドウをユーザーがクリックしようと、常に 実行中のコードを 抱えている唯一のブック を指します。ActiveWorkbook今いちばん手前にあるもの を指し、それは 足元で変わりえます。限定なしの Range("A1") はさらに厄介です。ブックもシートも一切名指ししないので、 その瞬間にアクティブなものに着地します。書き込みは ThisWorkbook(または自分で Set したブック変数) にアンカーし、マクロが「マウスを最後にどこでクリックしたか」に依存するのをやめさせましょう。

Sub WhereDoesItLand()
    ' ThisWorkbook = このコードが住んでいるファイル - 永遠に不動
    ThisWorkbook.Worksheets("Summary").Range("A1").Value = "Report"

    ' ActiveWorkbook = この行が走る瞬間に手前にあるもの - 気まぐれ
    Debug.Print ThisWorkbook.Name          ' 例: Macros.xlsm - 常に
    Debug.Print ActiveWorkbook.Name        ' ユーザーが最後にクリックしたもの
End Sub

この記事で学べること

  • 考え方の軸 — ThisWorkbook は不動の住所、ActiveWorkbook は動く場所
  • どのオブジェクトを指すかを言い切る3つの道具と、限定なしの参照が危険な理由
  • ThisWorkbookActiveWorkbook の違い — 信頼できるVBAで最も重要なただ一つの区別
  • 静かな罠 — 自分の席では動くマクロが、同僚の開いているファイルを壊す理由
  • 開いている別のブックを名前で参照する方法と、開いてハンドルを保持する方法
  • 意見 — すべての参照を限定し、既定は ThisWorkbook にする

考え方の軸:不動の住所であって、動く場所ではない

VBAのすべての参照は一つの問いに答えます。どの ブックか、どの シートか、どの セルか。 ThisWorkbook は最初の問いに答え、その答えを決して変えません。それは あなたが実行しているコードを 含むブック — モジュールやマクロが住んでいるファイルです。他のブックを10個開き、そのすべてをクリック して回っても、ThisWorkbook はマクロが始まったときと同じファイルを指し続けます。

ActiveWorkbook は同じ問いに、今この瞬間に手前にあるもの で答えます。それは設計からして動く標的です。 ユーザーが別のウィンドウをクリックした瞬間、あるいはあなた自身のコードが新しいファイルを開いた瞬間、 アクティブなブックは変わります。どちらも便利です — ですが両者は交換可能ではなく、片方をもう片方として 扱うことが、「マクロが間違ったファイルを編集した」というバグ一族すべての根っこです。

どのオブジェクトを指すかを言う3つの方法

ThisWorkbook は、コードに推測させる代わりに、欲しいオブジェクトを 名指しする ためにVBAがくれる 3つの道具の一つです。この3つが、マクロが信頼できるか脆いかを決め、この短いクラスターの背骨になっています。

道具 何を指すか どんなときに使うか
ThisWorkbook このコードを抱えるブック — 不動 マクロに属する設定を読む、または出力を書く
ActiveWorkbook / ActiveSheet いちばん手前にあるもの — 気まぐれ 「ユーザーが開いているもの」に対して動く汎用ツール
Worksheets(...) ブック内の名前付きシート — コレクション 特定のタブを名前・インデックス・CodeName で指定する

これらを結ぶルールはこうです。限定なしの参照は、アクティブなものへ手を伸ばします。 ブックもシートも 前に置かずに Range("A1") = 1 と書くと、VBAはその瞬間のアクティブなブックとアクティブなシートで空欄を 埋めます。それはイミディエイトウィンドウでは便利で、保存されたマクロでは破滅的です。

ThisWorkbook と ActiveWorkbook:不動か、気まぐれか

これは記憶に焼き付けるべき区別です。あなたのマクロが Macros.xlsm に住んでいて、ユーザーは Sales.xlsx も開いており、ボタンを押すときにそちらを見ている、と想像してください。

Sub FixedVsFickle()
    ThisWorkbook.Worksheets(1).Range("A1").Value = "written by the macro"
    ' ^ 常に Macros.xlsm に着地する。このコードが住んでいるファイル

    ActiveWorkbook.Worksheets(1).Range("A1").Value = "written by the macro"
    ' ^ Sales.xlsx に着地する。ユーザーが見ていたのがそれだから
End Sub

見た目は同じコード、着地するのは別々のファイル。ターゲットが「マクロが属するファイル」— 設定シート、 ログ、ツールに同梱される出力タブ — のとき、ThisWorkbook が正直な選択です。ActiveWorkbook が正しいのは、 本当に「ユーザーが手前に持ってきたもの」を意味するときだけです。どちらを意図したか迷ったなら、あなたが 意図したのは ThisWorkbook です。それは、あなたを驚かせられない唯一のものだからです。

知っておく価値のある親戚関係:ThisWorkbook は常にアクティブなものとは限らず、常に最初に開かれたものとも 限りません。単に、コードを持つものです。Macros.xlsm のマクロが Report.xlsx を開くと、新しいファイルが ActiveWorkbook になりますが、ThisWorkbook は微動だにしません。

静かな罠:自分の席では動き、相手の席では壊れる

このバグが実際に出荷される経緯はこうです。あなたはブックを1つ — 自分のもの — だけ開いてマクロを書き、 テストします。ブックが1つのとき、アクティブなブックは あなたの ブックなので、限定なしの Range("A1")ThisWorkbook で限定したものは同じ挙動になります。すべてのテストが通ります。

やがて同僚が、ブックを3つ開いた状態でそれを実行します。いまや「アクティブ」は彼らが見ていたものであり、 限定なしの書き込みは 彼らの ファイルに着地し、あなたのマクロは触れるはずのなかったレポートのセルを 黙って上書きします。エラーは出ません — コードは書かれたとおり「アクティブなものに書き込む」を正確に実行 しただけです。直し方は On Error ハンドラーではありません。ブックを名無しのままにするのをやめることです。

' もろい - ユーザーが最後にクリックしたものに依存する
Range("A1").Value = total

' 堅牢 - 毎回、ブックとシートを名指しする
ThisWorkbook.Worksheets("Summary").Range("A1").Value = total

参照を限定すれば、マクロはどの席でも、いくつファイルを開いていても同じ挙動になります。だからこそ、 ブックレベルのVBAで最も価値ある習慣はこれです。RangeCells の呼び出しを、ブックとシートを前に 置かずに漂わせてはいけません。

開いている別のブックを名前で参照する

ときには本当に 別の ブックが必要になります — ユーザーが開いたデータファイルや、あなた自身が開くものです。 ActiveWorkbook を経由して幸運を祈ってはいけません。名指しするか、ハンドルを保持してください。

Sub TalkToAnotherFile()
    Dim src As Workbook

    ' すでに開いている? ファイル名(拡張子つき)で取得する
    Set src = Workbooks("Sales.xlsx")

    ' まだ開いていない? 開いて、Open が返すハンドルを保持する
    Set src = Workbooks.Open("C:\Data\Sales.xlsx")

    ' これで参照はすべて明示的 - どのファイルかを推測しない
    Debug.Print src.Worksheets("Jan").Range("A1").Value
    ThisWorkbook.Worksheets("Summary").Range("A1").Value = _
        src.Worksheets("Jan").Range("A1").Value
End Sub

2つのルールがこれを安全にします。第一に、Workbooks("Sales.xlsx") はファイル名を 拡張子つきで 必要とし、ファイルはすでに開いていなければ Subscript out of range を投げます。第二に、Workbooks.Open は開いたブックを 返します — それを同じ行で Set 変数に受け取れば、「今どれがアクティブか」を尋ねる 必要が二度となくなります。自分で Set したブック変数は、ThisWorkbook よりさらに優れています。不動で かつ どのファイルを意味するかが明示的だからです。

意見:すべてを限定し、既定は ThisWorkbook

マクロのすべての参照は、そのブックとシートを名指しすべきで、既定のブックは ThisWorkbook にすべきです。 限定なしの参照は、持つ価値のある「短いコード」ではありません — それは、行が走るまさにその瞬間に正しい ファイルがアクティブである、という賭けであり、その賭けは、誰かがファイルを2つ以上開いてマクロを実行した 日に負けます。

規律は小さく、見返りは永遠です。ターゲットがあなたのツールに属するなら ThisWorkbook に手を伸ばし、 特定の別ファイルを意味するなら Workbook 変数を Set し、ActiveWorkbook は「ユーザーが手前に持って いるもの」が本当に正しいターゲットである稀なケースのために取っておきます。ブックを前に置かない裸の Range は、未宣言の変数とまったく同じように、未完成の行として扱ってください。

本当の仕事が、正しいブックを選ぶことより大きいとき

参照を正しくするのは前提条件にすぎません。実際の仕事はたいてい、その上に載るロジックです — この2つの ファイルを突き合わせる、先月分の行を引っ張る、地域ごとに合計してサマリーへ入れる。それを手で書くとは、 ブック参照 ループ エッジケース 、毎回正しく仕上げるということです。 ExcelMaster なら、結果を普通の 言葉で説明するだけ — 「Sales.xlsx をこのファイルのサマリータブと比べて、一致しない行に印を付けて」 — で、 まずブックをバックアップしたうえでコードを書いて実行し、すべての参照をあなたの代わりに限定します。あなたは どのファイルを指すかを述べるだけ。この記事が扱っている配管は、ExcelMaster が引き受けます。

よくある質問

VBAのThisWorkbookとActiveWorkbookの違いは?

ThisWorkbook は常に実行中のコードを含むブックを指し、決して変わりません。ActiveWorkbook は行が走る 瞬間にいちばん手前にあるブックを指し、ユーザーが別のウィンドウをクリックしたり、コードが新しいファイルを 開くたびに変わります。マクロ自身のファイルを意味するなら ThisWorkbook を、本当に「ユーザーが手前に 持っているもの」を意味するときだけ ActiveWorkbook を使ってください。

ThisWorkbookは常にアクティブなブックですか?

いいえ。ThisWorkbook はコードを抱えるファイルで、アクティブなブックは手前にあるものです。両者が 一致するのは、たまたまマクロ自身のファイルが手前にあるときだけです。別のブックがアクティブになった瞬間 — ユーザーがクリックした、あるいはマクロが開いた — 2つは別々のファイルを指します。

VBAで別のブックを参照するには?

すでに開いているなら、ファイル名と拡張子を付けて Workbooks("Name.xlsx") を使います。開いていないなら Set wb = Workbooks.Open("C:\path\Name.xlsx") を使います — これはブックを返すので、ハンドルを保持 できます。あとはアクティブなブックに頼る代わりに、その変数を通してすべての参照を限定してください。

マクロが間違ったブックに書き込むのはなぜですか?

ほぼ必ず、RangeCells の呼び出しの前にブックがなく、行が走るときにアクティブなものへ着地するから です。ファイルを1つ開いてテストする間は動き、複数開いていると同僚のファイルに書き込みます。参照を ThisWorkbook かブック変数で限定すれば、毎回正しいファイルに着地します。

ThisWorkbookはアドインでも使えますか?

はい、そしてまさにそこでこそ真価を発揮します。アドインでは ThisWorkbook はアドインファイル自身を指し、 ユーザーのデータは別のブックにあります。アドイン自身のリソースには ThisWorkbook を、ユーザーのデータには Set したブック変数(または意図的に ActiveWorkbook)を使ってください。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-07.

関連ガイド: VBA ActiveWorkbook · VBA Worksheets · VBA Workbook · VBA Range · VBA Dim