HOME > 即効テクニック > Excel VBA > セル操作関連のテクニック > 非連続のセルが選択されているか判定する

即効テクニック

セル操作関連のテクニック

非連続のセルが選択されているか判定する

(Excel 97/2000/2002/2003/2007)

マクロで操作するセル範囲を、コードの中で特定するのではなく、マクロを実行するつど、ユーザーに選択してもらうことがあります。 そうしたマクロでは、まずユーザーが任意のセル範囲を選択して、その状態でマクロを実行します。 VBAのコードでは、選択されているセル範囲をSelectionで操作します。

Sub Sample1()
  Dim c As Range
  For Each c In Selection
    c.Formula = "=" & c.Offset(0, -1).Address & "*2"
  Next c
End Sub
上のコードは、選択したセルに、左隣のセルを2倍する計算式を入力します。 このように、ユーザーが選択したセルを操作するマクロでは、いくつか注意すべきポイントがあります。 ひとつは「セルが選択されているかどうか確認する」ことです。 VBAのSelectionは"選択されたオブジェクト"を表しますので、ユーザーがグラフを選択した状態で実行すると、Selectionはグラフになります。 Selectionがセル(Rangeオブジェクト)であることを前提とするマクロでは、処理の前に「SelectionがRangeオブジェクトかどうか」を確認します。
Sub Sample2()
  Dim c As Range
  If TypeName(Selection) <> "Range" Then
    MsgBox "セルを選択してから実行してください"
    Exit Sub
  End If
  For Each c In Selection
    c.Formula = "=" & c.Offset(0, -1).Address & "*2"
  Next c
End Sub   
セルが選択されているかどうかを確認するには、TypeName関数にSelectionを渡します。 TypeName関数の返値が"Range"だったら、セルが選択されています。 それ以外の返り値が返った場合は、セルではないオブジェクトが選択されています。 上のマクロは、セルが選択されていなかったときメッセージを出して終了します。 もっと積極的に、もしセルが選択されていなかったとき、セルの選択に戻すには次のように ActiveCell.Activate を実行します。 ActiveCell.Select では選択範囲が解除されてしまうので注意が必要です。
Sub Sample3()
  Dim c As Range
  If TypeName(Selection) <> "Range" Then
    ActiveCell.Activate
  End If
  For Each c In Selection
    c.Formula = "=" & c.Offset(0, -1).Address & "*2"
  Next c
End Sub   
ユーザーが選択したセルを操作するマクロでは、もうひとつ注意すべき点があります。 それは、非連続のセル範囲が選択されていないかということです。 マクロの処理によっては、ユーザーの選択したセル範囲が1つでないと困る場合もあるでしょう。 逆に、必ず2つの非連続範囲を選択してから実行してもらいたいときがあるかもしれません。 そのように、選択されている範囲がいくつあるかを調べるにはAreasコレクションを使います。
Sub Sample4()
  Dim c As Range
  If TypeName(Selection) <> "Range" Then
    ActiveCell.Activate
  End If
  If Selection.Areas.Count > 1 Then
    MsgBox "非連続のセル範囲が選択されています"
    Exit Sub
  End If
  For Each c In Selection
    c.Formula = "=" & c.Offset(0, -1).Address & "*2"
  Next c
End Sub   
連続した1つの範囲が選択されていると、AreasコレクションのCountプロパティは1を返します。 もし、連続していない2つのセル範囲が選択されていたら2です。 Areasコレクションのメンバは、それらの"選択されているセル範囲"ですから、次のように1つめの選択範囲だけを操作することもできます。
Sub Sample5()
  Dim c As Range
  If TypeName(Selection) <> "Range" Then
    ActiveCell.Activate
  End If
  If Selection.Areas.Count > 1 Then
    For Each c In Selection.Areas(1)
      c.Formula = "=" & c.Offset(0, -1).Address & "*2"
    Next c
  End If
End Sub