セルをクリックした時に始まるVBA

2018.12.17マクロ、VBA

作成したマクロやVBAを起動するときは表示タブのマクロからマクロを実行することになりますが、その他にも様々なアクションによってマクロやVBAを起動させることができます。
今回は汎用性の高いセルをクリックしたときに始まるVBAを紹介します。

イベント

セルを選択したりシートを切り替えたりする普通のExcelの操作をした時に、VBAを始めるようにすることを「イベント」と呼びます。
セル選択イベント、シート切り替えイベントと呼びます。
セルの選択やシートの切り替えによってイベントを始動させることを、種火で火をつけるようなイメージでもあることから、「発火」させると言います。
イベントには様々な種類があります。
削除した時に発火するイベントや、ダブルクリックをした時に発火するイベントなどが用意されています。

セルをクリックしたときに発火するイベント

セルをクリックしたときに発火するようにするためには、ワークシート上の選択が変わったとき、と指定します。
では早速そのVBAを次の手順で作成しましょう。
シートの見出しを右クリックし、コードの表示をクリックします。

コードの表示

するとVBAを編集できるVBEが立ち上がります。

VBE起動

左上のプロジェクトから、今表示されているシート名が選択されていることを確認します。今回は新規ブックなのでSheet1が選択されています。

Sheet1

記録したマクロや自作したVBAはモジュールに記録しますが、シートに対するイベントのVBAは、モジュールではなく実際に操作するシートに記述します。
編集領域の上の方に下向きの三角がクリックできるようになっていますので、この中からWorksheetを選択します。

Worksheet

その右の下向き三角から選択できるボックスが実際のイベント内容なのですがワークシートを指定した状態でSelectionChangeが選ばれています。今回はこのWorksheet_SelectionChangeイベントを使います。日本語にするとワークシート内の選択を切り替えるという意味になります。

SelectionChange

 

動作内容の記述

既に編集領域には自動的に次のように入力されています。

Subの自動作成

End Subの前に実際の動作内容を記述していきます。
今回はクリックしたセルに対して「〇」を入力するようなVBAとします。
クリックしたセルは「Target」です。
そのTargetの値は、Target.Valueです。そこに「〇」が入るようにしますので、次のような命令文になります。

Target.Value = "〇"

また、〇を入力する前に、Targetが範囲選択になった場合、複数のセルが選ばれてしまいます。あくまで一つのセルが選択された場合のみ処理したいので選択されたセルの数が1以上だったら処理を止めるということをします。
選択されているセルの数はTargetの数なので、Target.Countで調べることができるので、もしその数が1を超えていたら処理を終了するIf構文を使います。

If Target.Count > 1 Then End

選択されているセルが1個をこえていたらその場で処理は終了、そうでなければ選択したセルに〇を入力すると言う次のVBAをEnd Subの前に入力します。

If Target.Count > 1 Then End
Target.Value = "〇"

動作内容

では、実際にシート1の今選択されている以外のセルをクリックしてみましょう。
クリックするたびに〇が入力されます。

〇の表示

 

〇が入力されたり消えたりするように改造

今度はクリックしたセルの内容が〇ならばその〇を消し、空白ならば〇を記入するという動作になるように改造します。
もしも、Targetの値が〇ならばTargetの値に空白を入力、そうでなければTargetの値に〇を入力という動作になります。
「Targetが〇ならば」は次のようなVBAになります。

If Target.Value = "〇" Then

「Targetを空白にする」は次のようなVBAになります。

Target.Value = ""

「そうでなければ」はVBAではIfとセットで次のようになります。

Else

「Targetを〇にする」は次のようなVBAになります。

Target.Value = "〇"

ここでもしも(If)の終了になるので、終わりの宣言をします。

End If

ここまで繋げて次のようになります。

If Target.Value = "〇"Then
Target.Value = ""
Else
Target.Value = "〇"
End If

If Target.Count > 1 Then EndからEnd Subの間を上記のVBAとします。

〇のIf構文

セルをクリックして〇のセルが空白になり、空白のセルが〇になることを確認します。
今選択されているセルをクリックしても選択されたとはExcelは認識できないので、交互にクリックしていきましょう。

必ず選択できるようにする

現在選択されているセルをクリックしても選択が変わったわけではないので、イベントは発火しません。しかし、それでは使いにくい場合もあるでしょう。
そこで、上記のVBAが動作したら最後にセルA1がアクティブセルになるようにします。そのVBAは、セルA1をアクティブにするので、次の通りです。

Range("A1").Active

しかし、少し困った動作にもなります。
このVBA内のセルA1をアクティブにする動作でも、Excelはセル選択が変わったと認識してしまい、イベントが発火して、またその中でセルA1を選択して発火し、またその中でセルA1を選択して発火しということが無限に起きてしまいます。
セルA1を選択するときだけ、発火しないように設定しなければなりません。
発火を止めるには次のVBAでイベント発火を無効(False)にする必要があります。

Application.EnableEvents = False

選択が終わったら次のVBAでイベントを有効(True)にします。

Application.EnableEvents = True

次のVBAをEnd Subの前に入力します。

Application.EnableEvents = False
Range("A1").Active
Application.EnableEvents = True

セルA1を選択

実際に操作してみると、セルをクリックするたびに〇が表示されたり消えたりします。
その都度セルA1を選択しますが、選択されたことで再度イベントは発火しません。

セルA1に戻る

 

どこのセルがクリックされたか

どこのセルがクリックされたかは、Targetに対する縦位置と、横位置を求めます。
縦位置はTarget.Row、横位置はTarget.Columnで求めることができます。
では、縦位置をセルA3、横位置をセルA5に表示します。

Range("A3").Value = Target.Row
Range("A5").Value = Target.Column

上記のVBAをIf Target.Count > 1 Then Endの後に入力します。

縦横の座標を求める

動作させてみると、クリックするたびにセルA3にクリックした場所の縦位置、セルA5に横位置が表示されます。

縦横の表示

 

クリックしたときに反応する範囲の設定

この状態だとこのシートのどこをクリックしても反応します。ところがこのようなケースで使う場合、反応させたいセル範囲があります。
その設定方法はVBAでIfを使ってTargetがその範囲かどうか判断し、もしもその範囲ではなかったらその時点で動作を止めるようにします。
例えばB1からE10までの範囲だけで反応させたい場合は、次のようなIf文になります。

If Not (Target.Row >= 1 And Target.Row <= 10 And Target.Column >= 2 And Target.Column <= 5) Then End

1行目から10行目までで2列目から5列目までの範囲以外だったら処理を終了するという文です。
上記のVBAをIf Target.Count > 1 Then Endの後に入力します。

範囲の指定

動作させてみると、クリックするのがB1からE10までの範囲以外だったら反応しなくなります。

まとめ

今回は、セルをクリックしたことによって動作するVBAについて解説しました。
Sheet1のVBAは次の通りです。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then End
If Not (Target.Row >= 1 And Target.Row <= 10 And Target.Column >= 2 And Target.Column <= 5) Then End
Range("A3").Value = Target.Row
Range("A5").Value = Target.Column
If Target.Value = "〇" Then
  Target.Value = ""
Else
  Target.Value = "〇"
End If
Application.EnableEvents = False
Range("A1").Select
Application.EnableEvents = True
End Sub

このような操作の流れの中で、何かの操作をきっかけに始まるVBAの場合、VBAはシートに記述しなければならないところがポイントです。
今回の方法を応用すれば、クリックした行の内容によって処理済みなどの情報をいずれかの列に記録することができるので、今まで目で見て確認し処理済みと記録していた操作が、大幅に効率化されるということにつながります。

Back to top