シート上でのクリックイベントの処理

シート

シート上のシングルクリックに対応させる

 ExccelVBAでは、シート上のシングルクリックに対するイベントはありません。
 代わりにSelectionChangeイベントを使用する事になるでしょう。
 SelectionChangeイベントは、選択セルが変更された時に呼び出させるイベントになります。
 ここでは、クリックされたセルの背景色を変更するプログラムを書いてみます。

SelectionChangeイベントの基本的なプログラム

 SelectionChangeイベントのプログラムは、各シートモジュールに書きます。
 標準モジュールではないので注意してください。

 シートモジュールの上部のドロップボックスから、WorksheetSelectionChange を選択すると以下のように記述されます。

 まずはどのように反応するか試してみましょう。
 以下のように記述してください。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
    '複数選択は抜けます。
    If Target.Count > 1 Then Exit Sub
    
    '指定した範囲以外は抜けます。
    If Intersect(Target, Range("B2:E6")) Is Nothing Then Exit Sub
    
    Debug.Print Target.Row & ":" & Target.Column

End Sub

 引数の Target には、選択したセルの範囲が Range オブジェクトで送られてきます。
 Targetには複数のセルが送られてくることがありますので、その事を想定したプログラムを書くようにしましょう。
 
 Target.Count でセルがいくつ選択されているかわかります。
 今回は、複数選択を考慮しないので、もし1個より多い場合は抜けるようにします。
 
 続いて、範囲を特定します。
 SelectionChangeイベントは、セルを選択するたびに実行されることになるので、範囲を限定する事で実行速度が遅くなるのを防ぐことが期待できます。
 Intersect関数を利用すると、引数の2つのRangeの重なっているRangeが返ってきます。
 共通部分が無い場合は、Nothing が返ってくるので、その場合は抜けるようにします。
 Intersect関数については、こちらを参照してください。

 最後に、デバッグプリントでセルの行と列を表示させるようにしています。
 実行すると、B2:E6 の範囲で単一選択された場合にセルの行と列がイミディエイトウィンドウに表示されます。

背景色を変えるプログラム

 セルの背景色を変更するには、Interior.ColorIndexInterior.Color を使います。
 プログラムを以下のように書き変えて実行してみましょう。

’セルの背景色を変更するプログラム①
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
    '複数選択は抜けます。
    If Target.Count > 1 Then Exit Sub
    
    '指定した範囲以外は抜けます。
    If Intersect(Target, Range("B2:E6")) Is Nothing Then Exit Sub
    
    Debug.Print Target.Row & ":" & Target.Column
    
    If Target.Interior.ColorIndex = xlNone Then
        Target.Interior.ColorIndex = 33
    Else
        Target.Interior.ColorIndex = xlNone
    End If

End Sub

 範囲内をクリックして選択すると、背景色が変わります。背景色に色が付いているセルをクリックすると背景色が無しになります
 ただ、一度選択されたセルを2回目にクリックしても反応がありません。
 これは、選択範囲が変更されていないため、SelectionChangeイベントが実行されないからです。
 SelectionChangeイベントはクリックに反応しているのでは無いので注意してください。
 
 これを解消するためのアイデアを2つ紹介します。

1.最後に別のセルを選択させる

 一度選択されたセルを2回目に選択していも、SelectionChangeイベントは発生しませんので、プログラムの最後に別のセルを選択して終えれば、該当するセルは選択状態から外れる事になります。
 ただ、別のセルを選択した時点で、そのセルにもSelectionChangeイベントが発生するので、これを回避する必要があります。
 イベントを回避するためには、Application.EnableEvents = False を使います。
 プログラム最後には、設定を True に戻しておくのを忘れないようにしましょう。

Application.EnableEvents が False のままになるとセルの変更に反応しなくなってしまいます。こうなってしまった場合は、Excelをいったん閉じて、再度立ち上げてください。

’セルの背景色を変更するプログラム②
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    
    '複数選択は抜けます。
    If Target.Count > 1 Then Exit Sub
    
    '指定した範囲以外は抜けます。
    If Intersect(Target, Range("B2:E6")) Is Nothing Then Exit Sub
    
    If Target.Interior.ColorIndex = xlNone Then
        Target.Interior.ColorIndex = 33
    Else
        Target.Interior.ColorIndex = xlNone
    End If
    
    Application.EnableEvents = False
    
    Target.Offset(1, 0).Select '一つ下のセルを選択して2回目のクリックに対応させる
    
    Application.EnableEvents = True

End Sub

 このプログラムを実行すると、範囲内のセルをクリックすることでセルの色が変わり、下のセルを選択するようになります。
 欠点としては、以下が挙げられます。
  ・動作がなんとなく不自然になる
  ・下に移動したセルを選択しても色は変化しない
 下に移動したセルの色が変化しないのは SelectionChangeイベントが発生しないためです。

2.ダブルクリックで2回目の選択に対応する

 SelectionChangeイベントがダメなので、ダブルクリックのイベントを使う方法を試してみます。 BeforeDoubleClick というイベントがありますので、これを使ってみましょう。

 シートモジュールの上部のドロップボックスから、Worksheet、 BeforeDoubleClick を選択してコードを記述させます。

’ダブルクリックで背景色を消す
’(「セルの背景色を変更するプログラム①」を使ってください。)
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    
    '指定した範囲以外は抜けます。
    If Intersect(Target, Range("B2:E6")) Is Nothing Then Exit Sub
    
    If Target.Interior.ColorIndex <> xlNone Then
        Target.Interior.ColorIndex = xlNone
        Cancel = True
    End If

End Sub

 引数は、SelectionChangeイベントと同じように Targetに選択されたRangeが来ます。
 さらに、Cancel という引数があります。
 セルをダブルクリックすると値の編集モードになりますが、これをキャンセルするかどうかを決める事が出来ます。
 Cancel = True とすれば編集モードには移行しなくなります。

 ダブルクリックでの動作は、背景色の色を消す事のみを対象にしています。
 SelectionChangeイベントプロシージャは、「セルの背景色を変更するプログラム①」を使用してください。
 
 結果としては、セルの選択は自然なので違和感はありません。
 欠点としては、ダブルクリックで消せることをユーザーに知らせなければならない点でしょう。

まとめ

 シングルクリックに対応するイベントが無いため、SelectionChangeイベントで代用するプログラムを紹介しましたが、同じセルを2回目に選択する場合は SelectionChangeイベントが発生しないため上手くいきませんでした。
 代わりに、セルの選択を移したり、ダブルクリックのイベントを利用する形で対処してみましたがそれぞれ欠点があります。
 イベントが発生しない状況ではプログラマーは対処できないというのが正直なところです。

コメント

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