Excel&VBA解説サイト「エクセルの神髄」様出題の問題集、
「VBA100本ノック」に対する私の回答と解説のページです。
100本ノックの出題リストはこちらから
excel-ubara.com
出題:ボタンの表示名の位置へ移動
#VBA100本ノック 76本目
フォームコントロールのボタンに登録するSubを作成。
ボタン表示文字を判定し下記パターン位置へ移動します。
・シート名!セル番地 → シートのセルへ
・シート名 → シートへ
・名前定義 → ブック範囲の名前定義へ
※名前定義よりシート名を優先
移動先なしはメッセージ表示

◇ 出題ページはこちら
ソースコード
' 100本ノック076:ボタンの表示名の位置へ移動 Sub ボタンの表示名の位置へ移動する() ' ボタン以外からの実行を除外 On Error Resume Next Dim ボタン表示テキスト As String ボタン表示テキスト = ActiveSheet.Buttons(Application.Caller).Caption If Err.Number > 0 Then Exit Sub ' シート名!セルアドレス On Error Resume Next If InStr(ボタン表示テキスト, "!") > 0 Then Application.Goto Range(ボタン表示テキスト) If Err.Number = 0 Then Exit Sub End If ' シート名 On Error Resume Next Sheets(ボタン表示テキスト).Select If Err.Number = 0 Then Exit Sub ' 名前定義 On Error Resume Next Application.Goto Range(ボタン表示テキスト) If Err.Number = 0 Then Exit Sub MsgBox "ボタン表示名が正しくありません。" End Sub
解説
マクロが実行されたボタンを取得するには、
Application.Callerプロパティを参照します。
Application.Callerはボタンのオブジェクト名を返しますので、
Buttons(Callerが返すオブジェクト名)から実際のボタンを取得し、
そのCaptionをとって表示名を取得しています。
表示名からセルへの移動にはRangeプロパティを使用していますが、
Rangeプロパティは"A1"のようなセルアドレス以外に、
シート名・ブック名付きアドレス、名前定義、果ては数式まで、
Rangeを取得できるテキストなら何でも入れることができます。
' 全部ちゃんと動く Range("A1") Range("シート1!A1") Range("[ブック1.xlsx]シート1!A1") Range("名前定義1") Range("テーブル1[見出し1]") Range("INDEX(A1:C3,2,2)")
数式まで行けちゃうのはびっくりですよね。
よって今回のコードも「Range(ボタン表示テキスト)」で済んでしまうのですが、
- A1というシート名のないセルアドレスでは移動しない
- 名前定義よりもシート名の方を優先して移動する
という条件があったため細かく分岐が必要になっています。
あとはエラーの判定ですが、そこらじゅうでエラー処理が必要になる処理なので、
すべてOn Error Resume Nextからのエラー判定で統一しました。
Rnage(表示テキスト)がエラーかを判定したり、シートの存在判定をしたり、
このあたりを個別にやってもいいのですが、冗長になるだけな気がします。
コード全体でロジックに統一感があった方が読みやすくなると思いますので、
使うと決めたらOn Error Resume Nextを使い倒していいんじゃないかと思います。
余談ですがこういったキーワード系のコードはCtrl+Spaseの入力候補がでないので、
変換辞書に登録しておくのがおすすめです。
On Error Resume NextやSelect Case、Property Getなど、
気が向いたらユーザー辞書に登録してあげてください。