オブジェクト名を変化させながら使うには? (ユーザーフォーム)

Question 39.2 Previous Next
こんばんは。今週中に作成せねばならないシステムを作っておりましたところ、思いっきり壁にぶち当たり、ワラにもすがる思いで検索したところ、こちらにたどりつきました。どなたかお分かりでしたら助けてください。

ユーザーフォーム上に一週間のスケジュール表のようなものを作成しております。表頭が曜日で表側が時間になっていて、トグルボタンが 7×24個並んでいるのです。
それでそのトグルボタンのオンの数を数えるマクロを作りたいのです。1つ1つチェックするマクロを作ればいいのですが、4カ月分あるため、莫大な数となり、後のことを考えると繰り返し文でやろうと思って下記のようなマクロを作ったら、「実行時エラー424、オブジェクトが必要です」というエラーが出てしまうのです。
    a = 0
    For w = 1 To 4
        For t = 1 To 24
            onoff = "mon" & w & t
            If onoff.Value = True Then a = a + 1
        Next t
    Next w
これは不可能なのでしょうか。エクセルは97です。
ちなみに私も過去にいろいろ失敗しておりますので、これから何かあればこちらで回答などもさせていただきます。(質問もジャンジャンするかもしれませんが)
それでは、今後ともよろしくお願いいたします。
Answer   Copyright (C) 2001.3.7 永井善王
ユーザーフォーム 左図のとおり、簡単なサンプルを作ってみました。
表側は 0:00~、1:00~と 1時間きざみで 23:00~となるのでしょうが、3:00~以下は省略。
表頭は 月、火、水までで後は省略。
トグルボタンも 3つだけ作って、その他は省略しました。
本物はトグルボタンが 168個(7×24)並んだ壮観なユーザーフォームのようですね。

プロパティウィンドウ トグルボタンには、それぞれ、あらかじめオブジェクト名が付いています。その名前をそのまま使うことも可能ですし、都合の良い名前に変更して使うことも可能です。

VBE画面にユーザーフォームを表示しておいてトグルボタンをクリックすれば、プロパティウィンドウのオブジェクト名(右図参照)に、既定の名前が表示されます。そこへは、任意の名前を入力することも可能です。以下の解説では、既定の名前を使う方法で進めます。

質問にあるコードの 5行目(
If onoff.Value = True Then a = a + 1)は、トグルボタンがオンの状態であるかどうかを If文で調べようとしています。そして、「実行時エラー」が出るのは、この行と思われます。下記のようにトグルボタンのオブジェクト名をそのまま書けば、エラーは出ないはずです。なぜならば、.Value の直前には、(1)オブジェクト(この場合はトグルボタン)名か、(2)オブジェクトを参照する変数のいずれかしか許されていないからです。
    If ToggleButton1.Value Then a = a + 1
第1の問題点「実行時エラー」は、これで解決すると思います。
オブジェクト名を書く方法で 168個(7×24)のトグルボタンの状態を調べるには、If文が約 168行必要になるでしょう。おまけに 4カ月分もあるとなれば、書くだけでも嫌になってしまいます。これが第2の問題点になります。

そこで、(2)オブジェクトを参照する変数で書く方法を考えます。そうすれば、1行の IF文と、変数を変化させるための数行のコードで済むかも知れません。
オブジェクトへの参照を変数(またはプロパティ)に代入するには、Setステートメントを使います。

構文
Set objectvar = {[New] objectexpression | Nothing}

ここでは上記構文中の太字の指定項目について、変数に代入する場合だけを解説します。くわしく知りたければ、VBE画面のヘルプで見てください。
objectvar には、変数の名前を必ず指定する。
objectexpression には、オブジェクト名などを指定する。

下のコードの4行目に
Set TBName(1) = ToggleButton1 という例があります。
  = の左辺に
TBName(1) と書かれているのが変数の名前で、
  = の右辺に
ToggleButton1 とあるのがオブジェクト名です。
そして、変数
TBName(1) は、2行目の Dim ステートメントでオブジェクト型として確保されています。
'------------------------------------------------------------------------------
 トグルボタンの状態を調べて表示する
'------------------------------------------------------------------------------
Private Sub UserForm_Click()             'ユーザーフォームでクリック時に動作するマクロ
Dim TBName(24) As Object                        'オブジェクトを参照する変数

    Set TBName(1) = ToggleButton1               'オブジェクトを変数に代入する
    Set TBName(2) = ToggleButton2
    Set TBName(3) = ToggleButton3

    For t = 1 To 3                              '変数tの値が1から3になるまで
        onoff = TBName(t).Value                 'トグルボタンの状態を取得する
        If onoff Then                           'トグルボタンがオン(True)の状態なら
            a = a + 1                           '変数aに 1加える
        End If
    Next                                        '繰り返す
    MsgBox "オン(True)は全部で " & a, vbInformation, "すぐマク" 'オンの数を表示する
End Sub
'------------------------------------------------------------------------------
上記のサンプルマクロでは、トグルボタンの 1から 3までしか指定していません(4~6行目)が、実際には 168行(7×24)必要ですし、4カ月分ですから 4倍になります。
質問にあるコードの 4行目(
onoff = "mon" & w & t )は、この問題をクリアするために考えられたのかと思います。
つまり、= の右辺の
ToggleButton1 の数字部分を変化させれば、Setステートメントを 168×4行も書くことなく、わずか数行で済ませれるのではとの期待からかと思います。

そうした期待に応える Controlsコレクションを使った書き方を、読者の方からいただけました。 ご本人の快諾のもとに、下記のとおり掲載させていただきます。
Controls(オブジェクト名)を使う方法 ムラジロ~
そのままのお答えとしては、Controls(オブジェクト名)と指定する方法です。

・例えば ToggleButton1~ToggleButton672 という名前のトグルボタンの場合  672=7×24×4
'------------------------------------------------------------------------------
Dim i As Long
Dim myCnt As Long

    For i = 1 To 672
        If Controls("ToggleButton" & i).Value Then myCnt = myCnt + 1
    Next
    MsgBox myCnt
'------------------------------------------------------------------------------
・トグルボタンの名前がバラバラの場合
'------------------------------------------------------------------------------
Dim myCtrl As Control
Dim myCnt As Long

    For Each myCtrl In Controls
        If TypeName(myCtrl) = "ToggleButton" Then
        If myCtrl.Value Then myCnt = myCnt + 1
        End If
    Next
    MsgBox myCnt
'------------------------------------------------------------------------------
上記のコードは、ユーザーフォームのコード画面で記述します。標準モジュールでの記述方法は こちら
サンプルブックのダウンロードは ここをクリック  (YNxv9d44_ToggleButton.xls 66KB)
※ 一旦、ブックをハードディスクに保存し、後で改めて開いてから実行してください。

Excel VBA Macro