画像をクリックしたら画像のあるセルに現在時刻を書き込むマクロ

クリックされた図形のあるセルを取得する

前置き

「画像をクリックしたら、その画像のあるセルに現在時刻を書き込むようなことってできない?」と言われたのでやったことがあった。

Excelで勤怠管理の一覧表を作って、出勤時と退勤時にその日の欄にある画像をクリックするだけで時刻を書き込めるように、ということらしい。

ちょこちょこっとggってみると、こんなのが引っかかった。なるほど、画像にマクロを登録して、そのマクロの中でApplication.Callerというプロパティの値を取得すれば、マクロの呼び出し手、すなわちマクロを登録した画像そのものが取得できるわけだな。ややこしい言い方ですまん。

あと、こういうのも引っかかってくる。

コチラによると、shapeオブジェクトにはTopLeftCellという非常に便利なプロパティがあり、

オブジェクトの左上端にあるセルを表す Range オブジェクトを返します

ということだ。

前置きが長くなったけど、要するに、

  1. セルの中に画像を置く
  2. クリックされた画像の左上端のあるセルに現在時刻を書き込むマクロを作る
  3. 画像に(2)で作ったマクロを登録する

というやり方でいけるはず。

マクロの作成

Application.Callerプロパティ、shapeオブジェクトのTopLeftCellプロパティという非常に便利なものがあるおかげで、めちゃくちゃ簡単なコードでいけそう。

リスト1

標準モジュールに次のコードを書く。

Option Explicit

Sub setTimeByButtonClick()
  Dim strAddress As String
  With ActiveSheet
    strAddress = _
      .Shapes(Application.Caller).TopLeftCell.Address    '……(1)'
    .Range(strAddress).Value = Now()    '……(2)'
  End With
End Sub

なんと、たったのこれだけw

リスト1の説明

まず、Application.Callerがこのマクロの呼び出し元のオブジェクト名を返すから、Shapesコレクションのインデックス(?)のところにApplication.Callerを入れてやることで、マクロ呼び出し元画像オブジェクト(*)を取得することができる。

んで、(*)のTopLeftCellプロパティは、オブジェクトの左上端にあるセルを表す Range オブジェクトを返しますということなので、そのAddressプロパティを取得してやれば、セルの番地が得られることになる。

ごく短いコードだけど、ここまでを理解しておくことが前提かな。

  • (1)では、上記のように、
    クリックされた画像オブジェクトの取得→画像オブジェクトの左上端のあるセルの取得→セルのアドレス文字列を取得
    の順でクリックされた画像のあるセルのアドレスを取得して変数strAddressに格納している。
  • (2)では、Rangeプロパティの引数に(1)で取得したアドレス文字列を指定してセルを取得し、そのValueプロパティにNow関数によって現在日時をセットしている。

(2)でTimeではなくNowにしたのは、日付が変わってから退勤する場合に備えるため。

実行

f:id:akashi_keirin:20170330214307j:plain

画像をクリックすると、

f:id:akashi_keirin:20170330214315j:plain

時刻が無事に書き込まれた。

おわりに

ごく短いコードだったけれど、知っておくと便利な要素が結構詰まっている気がする。

@akashi_keirin on Twitter