はもちくわ

コードについて自分なりの解釈を書いてます。

【ExcelVBA】1つのプロシージャでボタンごとに処理を変える方法

 

複数のボタンに同じ1つのプロシージャを登録し、押されたボタンによって処理を変える方法のご紹介です。

ボタンによって処理を変える方法で最初に思いつくのは、ユーザー定義関数を引数によって処理を変えるように作成しておき、ボタンごとにプロシージャを準備し、それぞれ関数に渡す引数を変える方法じゃないでしょうか?
この方法は本当によく使いますが、例えばボタンによって足すか、引くかを変えるだけみたいな、処理自体が単純で簡単な場合、ボタンごとにわざわざプロシージャを作って処理するのは、労力に対して対価がなさすぎて、ちょっと抵抗ありません?(笑)もう、関数でいいじゃん!ってなっちゃうみたいな(笑)

そのように感じるのは私だけかも知れませんが、こんな方法もあるよってことで、よかったら参考にしてみてください!

では、説明のために次のようなサンプルを作っていきます。

C3セルに日付の書式設定をしておいて、そのセルの上に画像のようなフォームコントロールのボタンを5つ配置します。
ボタンは押されるごとに、それぞれ次のような処理をさせます。

  • -1週:表示された日付から−7日する。
  • -1日:表示された日付から−1日する。
  • 今日:表示に関わりなく今日の日付を表示する。
  • +1日:表示された日付から+1日する。
  • +1週:表示された日付から+7日する。

この仕組み、、、、私、めっちゃ使うんですよね(笑)

はい、それでは、作成していきます。
まず、どのボタンが押されたのか?を、何で判定させるのかといいますと、ボタンの「名前」を使います。
これはボタンに表示されている文字列ではなく、選択時に左上へ表示されたり、Excelのリボンにある双眼鏡マーク「検索と選択」で見ることができる名前の方です。
それでは、早速、「検索と選択」から名前一覧を表示させましょう。

他に図形やフォームコントロールがなければ上のように番号が飛ぶこともなく、綺麗に名前が並ぶと思います。
名前の番号は、作成した順番で振られていくので、どのボタンがどの名前になるかはしっかり確認して使う必要があります。名前の確認は、名前を選択すればボタン自体も画面で選択されるので、1つ1つ確認しながら作業しましょう。

さて、次の作業で名前を使っていくので、ボタンに合わせて名前を変えていこうと思うのですが、このように綺麗に名前が並ぶなら、名前の変更はしなくても良さそうに思えます。ですが、実際は配置を考えながら追加、削除を繰り返して、ツールを作成していくことがほとんどだと思いますので、名前が綺麗に揃うことなんてあまり無いですよね。
また、マクロの入ったシートをコピーする運用はあまりしないと思いますが、もし、コピーするような運用をする場合、このように自動割り振りされた名前は、使っているフォームの数で再度割り振りされてしまいます。なので、自動割り振りの名前を元に、コードを書いていると、名前とコードがずれて、VBAが使えなくなることがあります。
なので、名前を使う仕組みの時は、名前をつけ変えることをお勧めします。
それでは次のように名前を変えていきます。
「day」という名前の後に0〜4までの数字を振ります。

名前の変更は、一覧から該当の名前をダブルクリックすれば、名前が編集可能になるので変更します。上の画像では番号が綺麗に並んでますが、実際はボタンを作成した順番によって配置が変わると思いますので、このサンプルを作成してみようと思っている方は、それぞれ次のように名前を対応させてください。

  • 今日:day0
  • +1日:day1
  • +1週:day2
  • -1日:day3
  • -1週:day4

はい、これで下準備は完了です。
それでは、標準モジュールに「day_change」というプロシージャを作成します。プロシージャは「Sub」で始まるアレですね。
まずは、ボタンを判定するために「名前」を取得してみます。実は、これがとても簡単(笑)

Application.Caller

はい、これだけです!かんた〜ん!!
で、、先ほど、末尾の数字でボタンを分けました。なので文字列操作をして末尾だけ抜き出しましょう!

x = Val(Right(Application.Caller,1))

末尾なので、このように一番右側から1文字抜き出せばいいですね。
そして、抜き出したままの文字列で扱っても問題ないのですが、、、あとあと比較判断に使う時、数字だから数値として比較したら、期待した結果と違って、エラーの原因がわけわからなくなるという事態は避けたいので、Valでくくって数値化しておきます。

あとは、変数xに入れた数値によって処理を変えるコードを書いて終わりっす。こうすれば、ボタンの名前を変えるだけで同じプロシージャを使えるわけです。コードが少ないうちはいいですが、多くなってくるとこういった使い回しできる仕組みは重宝します。

それでは、最後にサンプルコードを書いて終わりします。


    Sub day_change()
    
    Dim x as Integer,dd as Range
    
    'ボタンによって処理を変えるための処理
    x = Val(Right(Application.Caller,1)'0:今日,1:+1日,2:+7日,3:-1日,4:-7日

    Set dd = Activesheet.Range("C3")
    
    ’今日以外のボタンが押されてセルが空白もしくは0の時は処理を終わる
    If x<>0 And (dd.Value = "" or dd.Value = 0 )then 
       Msgbox "基準となる日付がありません。”,VbOkonly,"基準日エラー"
       Exit Sub
    End if
    
    Select Case x
         Case 0
              dd = Format(Now(),"yyyy/mm/dd")’時間は邪魔なのでカット
         Case 1
              dd = dd + 1’ dd.Value + 1と一緒です。
         Case 2
              dd = dd + 7
         Case 3
              dd = dd - 1
         Case 4
              dd = dd - 7
         Case Else
              dd = "" '想定外のときは空白いれておく
    End Select
    
    End Sub

コードはこれだけです。
コード中の黄文字は注釈ですので、処理の動きには関係ありません。使う時は外しても大丈夫です。

はい、あとは、このプロシージャを全てのボタンに登録して完成です。

 

いかがでしたでしょうか?何かヒントになったり、役にたったりしたでしょうか?
さらにですね、これ応用が効きまして、別のシートなんかでも同じような処理をしたいなって思うことありません?
そういときは、上のコード内に、変数ddへセルを代入している箇所あるじゃないですか。この代入の前に、アクティブになっているシート名を取得して、名前によって代入するセルを変えるんです。すると、このプロシージャだけで使い回しができるってわけですね〜。例えばこんな感じ


    Select Case ActiveSheet.Name
         Case "その1"
             Set dd = Worksheets("その1").Range("A1")
         Case "その2"
             Set dd = Worksheets("その2").Range("C3")
    End Select

ね、便利〜。
それでは今回はここまでです。
次回は入力したことをなかったことにする「安藤」、、、もとい、「アンドゥ(Undo)」っぽい動きをさせるコードを書きます。このまえ作ったツールで使ったのでご紹介です。なんちゃってではありますが、これも便利なのでよかったら、、、、それではまた。

追記
サンプルコードの−7のところ、、、+7になってましたね。読み返してたら気が付きました。すみません。。。