【ExcelVBA・マクロ】ThisWorkbookとActiveWorkbookの違い|複数ブック操作で起こる不具合を防ぐ方法【コピペOK】

ExcelVBA

ExcelVBAでマクロを書いていると、「昨日まで正常に動いていたのに、他のブックを開いたら急におかしな動作をする」というトラブルに遭遇したことはないでしょうか。その多くは、ThisWorkbookActiveWorkbookの違いを正しく理解していないことが原因です。

この記事では、この2つのオブジェクトの違いを基本から解説し、実際に不具合が起きるパターンと、その防止策をサンプルコード付きで紹介します。マクロを配布する予定がある方や、複数ブックを同時に扱う処理を書く方は特に押さえておきたい内容です。

スポンサーリンク
スポンサーリンク

ThisWorkbookとは

ThisWorkbookは、そのVBAコードが書かれているブック自身を指すオブジェクトです。マクロがどのブックから実行されたか、どのブックがアクティブになっているかに関わらず、常に同じブックを参照します。

Sub ShowThisWorkbookName()
    Dim wb As Workbook
    Set wb = ThisWorkbook
    MsgBox wb.Name & " はこのマクロが書かれているブックです"
End Sub

例えば、アドインやマクロ付きのテンプレートブックを配布する場合、ユーザーが他のブックを開いた状態でマクロを実行することもあります。そうした状況でも「自分自身のブック」を確実に操作したいときはThisWorkbookを使います。

ActiveWorkbookとは

ActiveWorkbookは、現在アクティブになっている(前面に表示されている)ブックを指すオブジェクトです。ユーザーの操作やコードの実行によって、参照先が変わります。

Sub ShowActiveWorkbookName()
    MsgBox ActiveWorkbook.Name & " が現在アクティブなブックです"
End Sub

例えば、複数のブックを開いている状態でユーザーが別のブックのウィンドウをクリックすると、ActiveWorkbookが指すブックも切り替わります。マクロを実行しているブックと、ActiveWorkbookが同じとは限らない点に注意が必要です。

不具合が起きる典型パターン

以下のコードは、集計用のブック(マクロ本体)から、別の作業ブックのデータを読み込んで保存する処理です。一見問題なさそうですが、ActiveWorkbookを使っているために不具合の原因になります。

Sub SaveDataBad()
    ' 作業ブックのデータを集計してから保存するつもり
    Call ImportData

    ' ここで保存したいのは「集計用マクロブック」のはず
    ActiveWorkbook.Save
End Sub

ImportDataプロシージャの中で別のブックをアクティブにする処理(Workbooks.OpenWindows(...).Activateなど)が実行されていた場合、このActiveWorkbook.Saveは集計用ブックではなく、直前に操作していた別の作業ブックを保存してしまいます。ユーザーの環境によって開いているブックの数や順序が異なるため、開発時には再現せず、配布後に「保存されない」「違うファイルが上書きされた」といった不具合として発覚しやすいパターンです。

修正版:ThisWorkbookで明示的に指定する

保存対象が「マクロが書かれているブック自身」であることが分かっている場合は、ThisWorkbookを使うことで、他のブックの状態に影響されない安全なコードになります。

Sub SaveDataGood()
    Call ImportData

    ' マクロが書かれているブックを明示的に保存する
    ThisWorkbook.Save
End Sub

こうすることで、ImportDataの中でどれだけ他のブックをアクティブにしても、保存対象は常に集計用ブックに固定されます。

ActiveWorkbookが役立つ場面

反対に、「ユーザーが今操作しているブックに対して処理したい」という場合はActiveWorkbookが適しています。例えば、アドインから呼び出して「現在開いている作業ブックに書式を適用する」ようなツールでは、ActiveWorkbookを使うのが自然です。

Sub FormatActiveSheet()
    ' アドインから呼び出し、今ユーザーが作業しているブックに適用する
    With ActiveWorkbook.ActiveSheet
        .Rows(1).Font.Bold = True
        .Rows(1).Interior.Color = RGB(220, 230, 241)
    End With
End Sub

このように、「マクロ自身のブックを操作したいのか」「ユーザーが今見ているブックを操作したいのか」を意識して使い分けることが重要です。

Workbooksコレクションでブック名を直接指定する方法

複数ブックを扱う処理では、ThisWorkbookActiveWorkbookだけに頼らず、Workbooksコレクションでブック名を直接指定する方法も有効です。どのブックがアクティブかに関係なく、対象を確実に指定できます。

Sub SaveSpecificWorkbook()
    Dim targetBook As Workbook

    On Error Resume Next
    Set targetBook = Workbooks("集計データ.xlsx")
    On Error GoTo 0

    If targetBook Is Nothing Then
        MsgBox "対象のブックが開かれていません"
        Exit Sub
    End If

    targetBook.Save
End Sub

処理の途中で複数のブックを開いたり閉じたりする複雑なマクロほど、名前で明示的に指定する方法が安全です。

まとめ

  • ThisWorkbookはマクロが書かれているブック自身を常に指す
  • ActiveWorkbookは現在アクティブなブックを指し、状況によって変化する
  • 複数ブックを扱う処理でActiveWorkbookを使うと、意図しないブックを操作してしまう不具合につながりやすい
  • 「自分自身のブック」を確実に操作したい場合はThisWorkbook、「ユーザーが今見ているブック」を操作したい場合はActiveWorkbookを使う
  • さらに確実に対象を指定したい場合はWorkbooks("ブック名")で明示する

この2つの違いを意識するだけで、複数ブックを扱うマクロの安定性は大きく向上します。ぜひ自分のマクロを見直すきっかけにしてみてください。

スポンサーリンク
スポンサーリンク
ExcelVBA
シェアする
いがぴをフォローする

コメント

タイトルとURLをコピーしました