アナログCPU:5108843109

ゲームと音楽とプログラミング(酒と女とロックンロールのノリで)

ThisWorkBookとActiveWorkBook

ThisWorkBookとActiveWorkBookの違いと使い分けについて。

簡単に書くと、

  • ThisWorkbookはその処理が記述されているブック
  • AcitveWorkbookは現在アクティブになっているブック

です。

例えばブックを2つ開き(ブックA、ブックB)、
ブックAに

Range("A1") = "hoge"

という処理を行うマクロを作り、ブックBで実行すると…
ブックBのA1セルに「hoge」と書かれます。

どのブック、そしてどのシートで実行しても、
実行したところのA1セルが対象になります。

これ、コワくないですか?

意図的にそうしたいならいいんですけど、
常にマクロが書かれたブックに対して実行したい場合は、
処理中にうっかり他のブックをアクティブにすると
途中でアクティブにしたブックに処理が入って…ということもあり得ます。

別の観点としては、
特に複数のブックやシートを使うようなマクロで指定を忘れると、可読性がかなり落ちます。
バグ発生の可能性も大幅に高くなります。

少々面倒でも、どのブックのどのシートに対して処理をしたいのか
きちんと明示していきたいものです。

どうせなので、最後に色々サンプルを。
以下、説明中では、マクロが書かれたブックをA、マクロを実行するブックをBとします。

ブックとシートの指定方法とその結果いろいろ

' アクティブブック×アクティブシート(後者推奨)
' →ブックBのアクティブシートに書かれる
Range("A1") = "hoge1"
ActiveWorkbook.ActiveSheet.Range("A2") = "hoge2"

' マクロの書かれたブック×アクティブシート
' →ブックAのアクティブシートに書かれる
ThisWorkbook.ActiveSheet.Range("A3") = "hoge3"

' アクティブブック×特定のシート(後者推奨)
' →ブックBの指定されたシートに書かれる
Sheets("Sheet1").Range("A4") = "hoge4"
ActiveWorkbook.Sheets("Sheet2").Range("A5") = "hoge5"

' マクロの書かれたブック×特定のシート
' →ブックAの指定されたシートに書かれる
ThisWorkbook.Sheets("Sheet1").Range("A6") = "hoge6"

アクティブブックを使うにしても…

主旨からやや離れますが、このへんも落とし穴です。
下記のTest1とTest2がブックAにあるとき、これらをブックBで実行したときの違いは分かりますか?

Public Sub Test1()

    ActiveWorkbook.ActiveSheet.Range("B1") = "fuga1"
    ThisWorkbook.Activate
    ActiveWorkbook.ActiveSheet.Range("B2") = "fuga2"

End Sub

Public Sub Test2()

    Dim wsSheet As Worksheet
    Set wsSheet = ActiveWorkbook.ActiveSheet

    wsSheet.Range("B1") = "fuga1"
    ThisWorkbook.Activate
    wsSheet.Range("B2") = "fuga2"

End Sub

答え合わせするとこうなります。

Public Sub Test1()

    ' アクティブブック(ブックF)に書き込み
    ActiveWorkbook.ActiveSheet.Range("B1") = "fuga1"
    ' ブックEをアクティブにする
    ThisWorkbook.Activate
    ' アクティブブック(ブックE)に書き込み
    ActiveWorkbook.ActiveSheet.Range("B2") = "fuga2"

    ' →ブックFに「fuga1」、ブックEに「fuga2」と書き込まれる

End Sub

Public Sub Test2()

    ' wsSheetという変数にアクティブブック(ブックF)を突っ込む
    Dim wsSheet As Worksheet
    Set wsSheet = ActiveWorkbook.ActiveSheet

    ' wsSheet(ブックF)に書き込み
    wsSheet.Range("B1") = "fuga1"
    ' ブックEをアクティブにする
    ThisWorkbook.Activate
    ' wsSheet(ブックF)に書き込み
    wsSheet.Range("B2") = "fuga2"

    ' →ブックFに「fuga1」「fuga2」と書き込まれる

End Sub