電子書籍の厳選無料作品が豊富!

フォームに複数のコントロールを配置したときにその選定によって条件分岐やイベント処理を行いたいときに同じようなコードを羅列する必要が生じました。コントロールをコレクション?(もしかして?クラス?<クラスは全く解っていません>)として、一くくりに扱う方法ってありますか?
ご指導のほどよろしくお願いいたします。

A 回答 (3件)

OptionButton1,OptionButton2,OptionButton3・・・の様に、末尾の数字がカウントできる場合は、


UserForm1.Controls("OptionButton" & 数字)という形で、コントロールを指定することができます。
簡単な例として、オプションボタン3つのどれかにチェックが入っているかを調べるマクロを作りました。

'-------マクロコード-------始まり
Option Explicit
Sub test()
Dim inta As Integer, stra As String
  stra = "OptionButtonにチェックが入っていません"
  For inta = 1 To 3
    If UserForm1.Controls("OptionButton" & inta).Value = True Then
      stra = "OptionButton" & inta & "にチェックが入っています"
      Exit For
    End If
  Next inta
  MsgBox stra
End Sub
'-------マクロコード-------終わり

この例では、UserForm1の中にOptionButton1~3があるとして、そのどれにチェックが入っているかをメッセージボックスで知らせます。
試される場合は、UserForm1の中にOptionButton1~3と、コマンドボタン(CommandButton1)を追加して、UserForm1に下のコードを追加して下さい。
コマンドボタンを押すと、上のマクロが実行されます。

'-------マクロコード-------始まり
Private Sub CommandButton1_Click()
  test
End Sub
'-------マクロコード-------終わり

UserForm1.Controls("OptionButton" & 数字)を応用すれば、コントロールを配列化?できます。
その為には、UserForm1で、コントロールの配列宣言を行ない、クラスモジュールで、コントロールの配列化とコントロール毎の配列番号を設定します。(この説明で合っているかな?)

以下に例を示します。
この例では、UserForm1の中にCommandButton1~8があるとして、コマンドボタンそれぞれに配列番号をインデックスとして割り振っています。
まず、UserForm1に以下のコードを記入します。

'-------UserForm1コード-------始まり
Option Explicit
Private CommandButtonNo(1 To 8) As New Class1
Private Sub UserForm_Initialize()
Dim inta As Integer
  For inta = 1 To 8
    CommandButtonNo(inta).CommandButton_Set UserForm1.Controls("CommandButton" & inta), inta
  Next inta
End Sub
'-------UserForm1コード-------終わり

次に、Class1モジュールに以下のコードを記入します。

'-------Class1コード-------始まり
Option Explicit
Private WithEvents CommandButton_Array As MSForms.CommandButton
Private intIndex As Integer
Public Sub CommandButton_Set(NewCommandButton As MSForms.CommandButton, Index As Integer)
  Set CommandButton_Array = NewCommandButton
  intIndex = Index
End Sub
Private Sub CommandButton_Array_Click()
  sub_処理 intIndex '下に説明
End Sub
'-------Class1コード-------終わり

これで、コマンドボタンを配列化できました。
Class1コードの、
「 sub_処理 intIndex '下に説明」は、標準モジュールのマクロ「sub_処理」で、コマンドボタンを押した時の処理したいマクロを記入します。
この時、「intIndex」がどのコマンドボタンを押したかを見分けるキーになります。

なお、一例として、以下に標準モジュールのマクロコードを載せます。
(UserForm1には、コマンドボタンの他にラベル「Label1」を追加してください)
この例では、CommandButton1~8に「1,2,3,4,5,10,20,30」と数字を打って、それぞれのボタンを押すと、その数字を足します。
また、一度押したボタンを再度押すとその数字を引きます。
その結果を「Label1」に表示します。
押したボタンの色も変るようにしています。

'-------標準モジュールコード-------始まり
Option Explicit
Public byta(9) As Byte
Sub sub_処理(intIndex As Integer)
Dim inta As Integer, intb As Integer
  byta(intIndex) = IIf(byta(intIndex) = 0, 1, 0)
  inta = Choose(intIndex, 1, 2, 3, 4, 5, 10, 20, 30)
  intb = Val(UserForm1.Label1.Caption)
  With UserForm1.Controls("CommandButton" & intIndex)
    If byta(intIndex) = 1 Then
      .BackColor = &H80000012
      .ForeColor = &HFFFFFF
      intb = intb + inta
    Else
      .BackColor = &H8000000F
      .ForeColor = &H80000012
      intb = intb - inta
    End If
  End With
  UserForm1.Label1.Caption = intb
End Sub
'-------標準モジュールコード-------終わり

#この回答に載せているそれぞれのコードの先頭の空白は、全角にしています。
#もし、コピーして使用される場合は、全角空白を半角に直してください。
#だらだらと、長く書いてすみません。

この回答への補足

>だらだらと、長く書いてすみません。
勿体無いお言葉!!有難う御座います。大変ためになります。っと本来ならば言いたいのですが、全体を理解するには今の実力では、超~難解です。しかし、いつの日か必ず解読しご指導の内容を自分のものにしたいと考えています。何気なくふと思いついた質問だったのですが、とんでもなく奥深いことだったのですね?正直言って皆さんが凄く努力して努力して習得された知識を惜しげもなく披露されご指導頂けることに心から感謝いたします。特に、オブジェクトにControls("OptionButton" & inta)などと、数式が使えることは目から鱗が落ちました。(落ちるほどの実力はありませんが!)即、実際に役立てて行きたいと思います。有難う御座いました。今後ともよろしくお願いいたします。このご指導のために費やした時間を考えると短文でそっけないお礼しか出来ないことをお詫び申し上げます。有難う御座いました。

補足日時:2005/11/26 00:11
    • good
    • 0

こんにちは。

Wendy02です。

1つは、フォームのイニシャライズ時に、

例えば、

Dim TextBoxes As New Collection

TextBoxes.Add 個々のコントロール

で入れて行く方法で、もう1つは、クラスを扱う方法です。

Mougで紹介されている
http://www.moug.net/skillup/opm/opm08-05.htm
擬似コントロール配列の作成

私は、正直なところ、この両方とも、一体、何のために、そんな面倒なことをしなければならないのか、良く分らないです。しょせん、VBのようには使えないとすれば、単にテクニックだけしかないような気がします。

とはいえ、VBAの勉強や練習では、絶対一度はやってみる必要はあると思います。上級テクニックの1つですからね。

(私は、絶対使わないわけではありませんから、誤解しないでくださいね。以下でも触れているように、必要なときもありますから)

実際のコードで、私は、
単に、コントロール名をなるべくユニーク(一意)なものにし、その名前の最後を数字にしてあげれば、そんなに困ることははありません。

Dim i As Integer
For i = 1 To 10
 Me.Controls("TextBox" & i).Text = CStr(i)
Next

このようにして切り抜けています。

ただ、イベントの時は、そうはいきませんね。統一化できませんから、その場合はクラスが必要になります。

しかし、以前、プロ?の人の実際のオープンにされたコードをみたら、どうしていたかというと、同じコードをコピー&ペーストしていましたから、私も、実務的には、基本に沿って凝ったことや複雑なことは、なるべくしないようにしています。

この回答への補足

いつも、いつも、いつも有難うございます。
今回のご指導も心を打たれました。日本の文化として、一つのものを極める技術力の高さと国民資質があると聞いたことがあります。日本刀などその頂点と思いますが、結局!機関銃には勝てないわけですし、槍10本で一気に突かれたらかわすことは難しいでしょう?(意味のないたとえかも知れません?すみません。)また、あとで読み返した時に意味がわからなかったり、改変の時に融通が効かなかったりと・・・!色々弊害もありそうで・・?ご指導通り、シンプルが一番いいと言う点に一人で、妙に納得してしまいました。と、同時に技術力アップのためには考えることも必要である。心に命じます。有難うございました。

補足日時:2005/11/25 23:55
    • good
    • 0
この回答へのお礼

追伸!今回3名の方から、貴重なご指導を受けましたが、せめてものお礼の気持ちを表す点数の持分が2つしかありませんので、今回は、ご勘弁のほど、お詫び申し上げます。今後ともよろしくお願いいたします。

お礼日時:2005/11/26 00:14

下記のサイトを見ると参考になるかも知れません。



参考URL:http://www.h3.dion.ne.jp/~sakatsu/Breakthrough_P …

この回答への補足

早速のご指導有難うございます。
感謝、感謝の限りです。でも、正直言って、禁断の土地への案内状を頂いた感じです。(笑)
VBAを最近始めたばかりで、ヘルプの見方がなんとなく判ってきたのですが、もう少し上をと考えていましたが、もう少し今の場所で自己研鑽に励みます。何にも判っていないことを判りました。教えて頂いたサイトは、今後じっくりと熟読し必ず自分のものにしたいと思います。本当に、本当に有難うございました。
後に、ご報告することもあろうかと思いますので、補足の欄を利用させて頂き、お礼を申し上げます。
有難うございました。

補足日時:2005/11/25 23:49
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!