即効テクニック |
マクロを実行するとき、アクティブセルや選択範囲がどの位置にあるかを知ることは重要です。 たとえば次のコードは、アクティブセルが属するリスト全体に格子の罫線を引きますが、アクティブセルがリストの外に置かれた状態で実行すると失敗します。
Sub Sample1() ActiveCell.CurrentRegion.Borders.LineStyle = True End Subこのマクロは「アクティブセルがリスト内にあるはずだ」という前提で作成されていますが、不特定多数のユーザーに提供するマクロでは、こうしたプログラマの「勝手な思いこみ」が予期せぬバグを産む原因になります。 アクティブセルの位置を知るにはいくつかの方法があります。 最も簡単な方法の一つはアクティブセルのアドレスを調べることです。 セルのアドレスはAddressプロパティで取得できますが、普通に指定すると「$A$1」のように絶対参照形式が返ります。 相対参照形式のアドレスを取得したい場合はAddressプロパティの引数を指定します。Sub Sample2() MsgBox ActiveCell.Address(False, False) End Subまた、Addressプロパティの引数ExternalにTrueを指定することで「[Book1]Sheet1!$A$1」のようにブック名やシート名を取得することも可能です。Sub Sample3() MsgBox ActiveCell.Address(External:=True) End Subアクティブセルが任意のセル範囲内に置かれているかどうかは、アクティブセルの行と列を調べることで判定できます。 次のコードは、アクティブセルが1〜5行目かつA〜C列に置かれているかどうかを判定します。Sub Sample4() With ActiveCell If 1 <= .Row And .Row <= 5 Then If 1 <= .Column And .Column <= 3 Then MsgBox "正しい範囲です" End If End If End With End Subこのように、RowプロパティやColumnプロパティを使ってアクティブセルの位置を特定することができますが、実はもっと簡単な方法があります。 ApplicationオブジェクトのIntersectメソッドは、引数に指定した複数のセル範囲が共有するセル範囲を返します。 このIntersectメソッドを使うことで、アクティブセルが特定のセル範囲内に存在するかどうかを調べることができます。 次のコードは、アクティブセルがセル範囲A1:C5内にあるかどうかを判定します。Sub Sample5() Dim rc Set rc = Application.Intersect(ActiveCell, Range("A1:C5")) If rc Is Nothing Then MsgBox "A1:C5の範囲外です" Else MsgBox "A1:C5内に置かれています" End If End SubIntersectメソッドは、共有するセル範囲が存在する場合はそのRangeオブジェクトを返し、存在しない場合はNothingを返します。 上記のSample5では、共有するセル範囲の位置が重要ではないので、返り値がNothingかどうかを判定しています。 ワークシートのSelectionChangeイベントと併用することで、アクティブセルの移動可能範囲を制限することも可能です。 次のコードは、アクティブセルがセル範囲A1:C5の外に移動しようとすると、注意のメッセージを表示して、アクティブセルをセル範囲A1:C5内に戻します。Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim c As Long, r As Long If Application.Intersect(Target, Range("A1:C5")) Is Nothing Then MsgBox "A1:C5の外には移動できません", vbExclamation r = WorksheetFunction.Min(Target.Row, 5) c = WorksheetFunction.Min(Target.Column, 3) Cells(r, c).Select End If End Sub