パソコンカレッジ スタッフのひとりごと

パソコンスクールのスタッフが、
初心者から上級者まで役立つ情報をお伝えします。

複数のコントロールのイベントを一つのプロシージャにまとめる(ExcelVBA)

2017-05-15 10:41:11 | ExcelVBA
今回は、VBAを取り上げます。

現在、生徒のU君は、VBAを勉強しています。基礎的なスキルを身につけたので、実践編へと進んでいます。
今取り組んでいる課題は、「VBAで電卓を作る」です。

みなさんも、一緒に考えてみませんか?



エクセルを起動して、ALTキー + F11キー を押します。
Visual Basic Editorが起動したら、「挿入」→「ユーザーフォーム」とクリックします。

画面に、フォームが表示されたら、以下の様にコントロールを配置します。


上部に、テキストボックス、
その下に、計20個のコマンドボタンを整然と配置します。
なお、フォーム名は、「frmCalc」としました。




このとき、注意してほしいことがあります。
数字の表示されているコマンドボタンの名前についてです。
今後の作業のために、ボタンの名前は、「任意の名前」+表示される数字 としてください。

例えば、
0と表示されたボタンは、「btn0」、
1と表示されたボタンは、「btn1」、
2と表示されたボタンは、「btn2」、
3と表示されたボタンは、「btn3」・・・という感じです。
数字の前の部分は、お好きな文字列で構いません。

今回は、b0, b1, b2, b3・・・と名前を付けてみました。

なお、数字以外のボタンは、分かりやすい名前なら何でもいいです。



さて、今日は、まず、手始めに、数字のボタンをクリックすると、
上部のテキストボックス窓に、数字を表示するところまで頑張りましょう。


普通に考えると、0~9までの数字のボタンのクリック時イベントに
コードを書くようになります。

下のような感じですね。






上の図のようなプロシージャが、9つ必要になりますね。

でも、よく見ると、各プロシージャのコードは、=の右辺が異なるだけです。

そうです。どれもみな、処理の内容は同じなのです。ただ、表示する数字だけが異なるのです。

それならば、この10個のプロシージャの処理内容を一つにまとめてしまい、
10個のどのボタンからも、この一つにまとめられたプロシージャを呼び出せば、全体がシンプルになります。

実は、そんな事が出来るのです。

Visual Basic 6 までは、この機能を「コントロール配列」と呼んでいました。

書き方は全く異なりますが、Visual Basic .NET 以降ももちろん同様の処理ができます。

ExcelVBAは、バージョン的には、VB6.x ですから、コントロール配列が使えればいいのですが、
残念ながら、この機能は搭載されていません。
従って、別の方法で実現します。その方法とは、「クラスモジュールを活用する」です。


それでは、クラスモジュールを追加しましょう。
「挿入」→「クラスモジュール」とクリックします。
(クラス名は、初期設定のClass1 のままでいきます。)

以下のようにコードを記述します。


'イベントを持つコマンドボタン型の変数を宣言
Private WithEvents Btn As MSForms.CommandButton
'ボタンの数字を格納する変数を宣言
Private Index As Integer

Public Sub NewClass(ByVal c As MSForms.CommandButton, _
ByVal i As Integer)
  'いわゆるコンストラクタ処理

  '引数のコマンドボタンを変数に格納
  Set Btn = c
  'コマンドボタンの数字を変数に格納
  Index = i
End Sub

Private Sub Btn_Click()
  'frmCalcフォームのTextBox1に、
  '変数Indexの中身を表示する

  frmCalc.TextBox1.Text = Index
End Sub


一応、画像も載せておきます。





クラスというのは、いわゆるオブジェクトの原型で、このクラスからインスタンスを生成して使用します。
(VB.NET以降は、オブジェクト指向言語になっていますので、クラスの使い方がとても重要です)

VB6でも、一応クラスは用意されているんですね。

このクラスは、コマンドボタンのイベントプロシージャを持っています。
クリック時に、フォームのテキストボックスに数字を表示する機能を持っています。

あとは、このクラスを10個の数字のコマンドボタンにひもづけてあげればいいのです。

そのためのコードを、ユーザーフォームに記述します。

以下のように記述してください。

Option Explicit

Private NumBtn(0 To 9) As New Class1


Private Sub UserForm_Initialize()
  'インスタンスの生成

  Dim i As Integer
  For i = 0 To 9
    NumBtn(i).NewClass Controls("b" & i), i
  Next

End Sub

一応、画像も載せておきます。




モジュールレベルの変数NumBtnを宣言します。型は、Class1 となっております。
このClass1は、先程つくったクラスのことですよ。
でも、よく見ると、As のあと、Class1 の前に Newというキーワードがあります。
これが重要です。このNew を付けることによって、クラスは実体をもつようになります。(インスタンスと言います)

なお、NumBtn(0 To 9) の、かっこの部分は配列を示しています。
つまり、この変数は、10個の部屋を持つ変数なのです。
配列にしたのは、このインスタンスにボタンを登録する際に、コードを効率的に記述するためです。
(インスタンスを一つ生成するだけなら、配列にする必要はありません)


UserFormの初期化イベントの際に、このインスタンスに数字のコマンドボタンを登録しています。
UserForm_Initialize() の中をご覧ください。

NumBtn(0)には、コマンドボタンb0 を登録します。
コードで書くと、
NumBtn(0).NewClass Controls("b0"), 0
となります。

NewClass によって、コマンドボタンb0 と 数字の 0 をインスタンスに登録し、
ボタンをクリックしたときに、クラスで記述したクリック時イベントが実行されるようになります。


今回は、繰り返し処理によって、コマンドボタンのb0 から b9 までをインスタンスに登録しています。

これで、仕込みは終了です。

このフォームには、各数字ボタンのクリック時イベントが記述されていないことを確認してください。





それでは、フォームを表示して、数字のボタンを押してみましょう。

1 のボタンを押すと、上部のテキストボックスに 1 と表示されます。
同様に、2 のボタンを押せば、 2 と表示されます。






VBAって奥が深いですね。

奥が深いと言えば、エクセルって色々な機能があって、使い方によってはまるで手品(マジック)のようになるんですよね。

VBAをからめると、さらにドッキリ度がアップします。親子のやり取りを通じて、そんなエクセルの面白さが満載の本が、

子どもの“プログラミング的思考"をグングン伸ばす本

この本、おすすめですよ(^^)



だい

コメント (28)    この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« ExcelVBAの練習 ユーザーフ... | トップ | 宛名を変えて自動的に連続印... »
最新の画像もっと見る

28 コメント

コメント日が  古い順  |   新しい順
すごいぃ~~♪ (てくてく君)
2011-04-29 19:51:34
VBAでクラスって使えることは知っていたけど使ったことがないです~♪

この先の展開をすごく楽しみにしていますので頑張ってください~
てくてく君さんへ (だい)
2011-05-10 16:13:49
励ましのコメントありがとうございます。
続編頑張ります。
公開は未定です。。。
またご訪問ください。
教えて 下さい (アンポン端)
2015-10-24 02:57:46
今回紹介の事を{ユーザーフォーム上のチェックボックス}
ではなくて『ワークシート上のチェックボックス』で行いたいのですが、、、その場合のクラスモジュール等への宣言内容や組み込み方法を知りたいのですが、、、
アンポン端さんへ (だい)
2015-10-27 12:29:28
コメントありがとうございます。

近いうちにブログの記事でアップしますね。
それまで、お待ちください。
Unknown (kaoaru)
2019-02-22 12:50:08
UsetFormとfrmCalcがいりまじってます。
どちらかに統一しないとエラーとなります。

VBAでコントロール配列ができないことがわかり、この記事にたどり着きました。ありがとうございます。
VB6では悩まずに済んだことでしたが、あまりたくさんのボタンを配置すると初期化に時間がかかるのですが、クラスモジュールのほうが効率的だったのかも?と思う出来事です。
Btn_Click()に入らない、、、 (かい)
2019-04-05 09:41:49
Btn_Click()に入っていかないのですが、どうやったらイベントに入れますか?
各ボタンを配列に登録しても、ボタン押下時にイベントを何も設定していないので入らないことが当然といえば当然のように見えます、、、

WithEventsでクラスを作れば自動的にBtn_Click()がクリック時に呼び出されるなんて事があるんでしょうか><
スシロー (くまさんチャンネル)
2019-12-05 11:03:44
本文が読みにくいです。
できればでいいので、改善してください。
Unknown (onodera rinn)
2019-12-05 11:43:11
彼女とデートいきまsy
わからない (ああ)
2019-12-06 13:46:03
ならないです
わからない (ああ)
2019-12-06 13:46:25
ならないです

コメントを投稿

ExcelVBA」カテゴリの最新記事