ロゴ(青) Excel/VBA Tips ロゴ(緑)

Tips10B: Toggle/Option/CheckBoxの特徴を良いとこ取りした
                            フラグ系ボタン[トグルラベル]クラスモジュール


    この トグルラベル クラス (旧版)『 疑似からの脱却 』 手法へと発展していく基になったものです。
    先ず、RaiseEvent を使わない クラスモジュールひとつの clsTglLabel が出来ました。 これが、2つのクラス
    モジュールを親/子で使い、RaiseEvent を利用した [ clsTglLblGrp & clsTglLabelEx ] へと発展しました。
    この [ clsTglLblGrp & clsTgllabelEx ] を整理して体系化したものが 『 疑似からの脱却 - clsBpca - 』です。

    現状では既に必要の無くなったものですが、『疑似からの脱却』への軌跡として残しておきます。

 ( 2004/5/17 第 版 [ Ver2.0 ] )    最新の [ Ver 4.0 ] は こちら

  UserForm で使うフラグ系コントロールには、下記の3つがありますが、どれにも一長一短が
あります。そこで、それら短所をカバーしつつ「長所のみを良いとこ取り」するようなボタンを
ラベルコントロールを使って実装するクラスモジュールを紹介します。
トグルボタン  (ToggleButton)
・ 凹凸形状のボタンでオン/オフを表現。
・ 同じボタンのクリックでオン/オフが切り替わる。
・ グループ化して排他処理する事ができない
・ キャプションの左/上側に余白が有る為に、バランスを考えると、どうしてもボタン自体のサイズが
   大きくなる
 
チェックボックス  (CheckBox)
・ チェックマーク欄と横に並ぶキャプション文字で構成。
・ 同じボタンのクリックでオン/オフが切り替わる。
・ グループ化して排他処理する事ができない
・ コントロールの形状から、縦に並べる配置向き。
・ キャプション文字の色変更は出来るが、チェックマーク欄の色変更は出来ない
 
オプションボタン  (OptionButton)
・ 黒点マークと横に並ぶキャプション文字で構成。
・ グループ化して排他処理できる。
同じボタンをクリックしても[オン⇒オフ]に戻せない(他の同一グループのボタンをクリックすると
   排他機能によりオフになる)。
一度オンにした後、グループが「全てオフ」という状態は、マニュアルでは無理で、VBAからの
   操作が必要。
・ コントロールの形状から、縦に並べる配置向き。
・ キャプション文字の色変更は出来るが、黒点マークの色変更は出来ない
トグルラベル クラス  (ToggleLabel )
・ ラベルコントロールで作っており、オン/オフは凹凸形状で表現している。
・ VBAからの操作はクラスモジュールによりブラックボックス化されていますので普通のコントロール
   と同じ様に扱えます。
・ ラベルで作っているので、トグルボタンのようなキャプション[左/上]に余白がありません。そのおか
   げで、コンパクトなボタンになります。
・ 排他処理させる事も可能。
・ 同じボタンのクリックでオン/オフが切り替わる。その為に、排他処理時でも[全てオフ]状態にする
   事が可能。
・ 全体の[Enabled]プロパティを一度に設定する機能あり。
・ 「何番目のボタンがオン」というグループの値(ボタン番号:数値)を設定/取得できる。
 
ラベルを使ってトグルボタンを模するには、ラベルのClick イベント時に、
        SpecialEffect プロパティ
            fmSpecialEffectRaised (凸) fmSpecialEffectSunken (凹)
と交互に切り換えれば出来ます。排他処理を加えるには、凸→凹にする際に、同一グル
ープ内の他ボタンを全て凸に変更させます。
 しかし、毎回[SpecialEffect ]プロパティを操作するコードを記述すのは大変ですので、
簡単に使えるようにクラスモジュール化しました。

(利用方法)
  1.このページでは[clsTglLblGrp ]クラスと[clsTglLabelEx ]クラスの両方を使う方法を解説します
      (尚、この方法の場合、Excel97 では利用できません)。

      Excel97 では、RaiseEvent ステートメントと同様の動きを代替手法で実現した[clsTglLabel ]
      クラスを使う事になります。
            [clsTglLabel ]クラスの利用方法

  2.下記のサンプルブックをダウンロードして、
            クラスモジュール[clsTglLblGrp ] & [clsTglLabelEx ]
      の2つを各自のブックにインポートしてください([clsTglLabelEx]クラスは、ユーザーサイドでは
      使用しません。[clsTglLblGrp]クラス内で使用するクラスです。)。
      クラスモジュールの内容は一切変更する必要はありません。

            サンプルブック( ToggleLabel_V2.zip  118KB )    2004/5/17 第 2 版

            [ clsTglLblGrp ] [ clsTglLabelEx/clsTglLabel ] クラス   リファレンス解説ページ

  3.以降、サンプルブックの例をもとに解説します。
      ・先ず、UserFormにトグルラベル用のラベルコントロールを配置します(サンプルでは曜日
        ボタンを例にしてます)。
      ・サンプルフォームでの、ボックスには、この[トグルラベル]クラスのクリックイベントを受けて、
        クリックしたボタンと値が表示されます。
      ・『Value 』ボタンは、グループ全体のオン/オフ状態をMsgBoxに表示します。
      ・『Enabled 』ボタンは、グループ全体のEnabledプロパティを切り換えます。
      ・『All On/Off 』ボタンは、グループ全体を一度に[ON/OFF]に設定します。


  4.UserFormのモジュール宣言セクションにて、[clsTglLblGrp]クラスを参照する変数を定義
      します。イベント処理をする為に「WithEvents 」キーワードを付けます。
      WithEvents を指定するので[New]キーワードは指定できません。その為に、最初の参照
      の前に、[New]キーワードを付けたSet ステートメントでクラスのインスタンスを作成する必
      要があります。
  '【1】[排他]有りサンプル
  Private WithEvents clsTglLbl_Week1 As clsTglLblGrp

  '【2】[排他]無しサンプル
  Private WithEvents clsTglLbl_Week2 As clsTglLblGrp

  5.Initialize イベント内で、用意したラベルコントロールを[clsTglLblGrp]クラスに登録します。
      変数定義の際に[New]キーワードを付けていないので、クラスオブジェクトへの操作をする
      前に、[New]キーワードを付けたSetステートメントで[clsTglLblGrp]クラスへのインスタンスを
      生成する必要があります。

      [clsTglLblGrp]クラスに対して、
            Add メソッドで、ラベルコントロールをクラス内に登録
      した後、最後に
            Rgst メソッドで、クラス内でのコレクション化(配列化)を指示
      します。Rgst メソッドの引数に[True ]を指定すると【排他あり】[False ]を指定すると
      【排他なし】
となります。
  Private Sub UserForm_Initialize()
  Dim i As Integer
    vntWeek = Array ("", "日", "月", "火", "水", "木", "金", "土")
  '-------------------------------------------------------------
  '【1】 [clsTglLblGrp]を使った「排他」有りサンプル


    '[New]キーワード付きのSetステートメント必須
    Set clsTglLbl_Week1 = New clsTglLblGrp
    With clsTglLbl_Week1
      .Add lblSun1
      .Add lblMon1
      .Add lblTue1
      .Add lblWed1
      .Add lblThu1
      .Add lblFri1
      .Add lblSat1
      .Rgst True        '[True]指定で[排他あり]
    End With
  '-------------------------------------------------------------
  '【2】 [clsTglLblGrp]を使った「排他」無しサンプル


    '[New]キーワード付きのSetステートメント必須
    Set clsTglLbl_Week2 = New clsTglLblGrp
    With clsTglLbl_Week2
      .Add lblSun2
      .Add lblMon2
      .Add lblTue2
      .Add lblWed2
      .Add lblThu2
      .Add lblFri2
      .Add lblSat2
      .Rgst False      '[False]指定で[排他なし]
    End With
  End Sub

  Private Sub UserForm_Terminate()
    Set clsTglLbl_Week1 = Nothing
    Set clsTglLbl_Week2 = Nothing
  End Sub

  6.ボタンの状態(オン/オフ:凹凸)は、[GrpValue]プロパティで取得します。その際、引数に
      ボタン番号(ボタン番号は[Add]メソッドで登録した順に1から割り当てられます)を指定する
      か否かで、2種類の使い方が出来ます。
        ・ボタン番号を指定
            指定したボタン番号のオン/オフ状態が[True/False]で返ります。
        ・ボタン番号を省略/ゼロ
            個々のボタンのオン/オフではなく、グループ全体での状態が数値で
                a) 排他指定の場合
                        オン(凹)のボタン番号(全てオフならばゼロ)
                b) 排他していない場合
                        [全てオフ:ゼロ] [1個だけオン:オンのボタン番号] [複数オン: -1 ]
            という風に返ります。
  Private Sub cmdValue1_Click()
  Dim i As Integer
  Dim strWK As String
    '[GrpValue]の引数を[0/省略]すると、
    '排他[有り]では、オンのボタン番号(全オフ:ゼロ)
    '排他[無し]では、全オフ:ゼロ , 1個だけオン:オンのボタン番号 , 複数オン:(-1)

    strWK = "(" & clsTglLbl_Week1.GrpValue & ") "

    For i = vbSunday To vbSaturday    ' vbSunday(1) 〜 vbSaturday(7)
      If (clsTglLbl_Week1.GrpValue( i ) = True) Then
        strWK = strWK & "■"
      Else
        strWK = strWK & "□"
      End If
    Next i
    MsgBox strWK      ' ( n ) □□□□■□□ というメッセージ
  End Sub

  (clsTglLbl_Week2 のコードも同じなので省略)

  7.ボタンの状態をVBAからオン/オフ(凹凸)するには、[OnValueSet / OffValueSet]メソッド
      にボタン番号を指定して行ないます。
      排他指定の場合、[OnValueSet]メソッドを実行すると、それまでオン(凹)になっていたボタンは
      オフ(凸)になります。
      ボタン番号を省略/ゼロにすると、グループ全体を一度で[ON/OFF]に出来ます([排他]指定
      の場合、OnValueSetメソッドでボタン番号を省略/ゼロにしてもボタンの状態は変わりません)。
  '火曜をオン(排他なので、オン中の他ボタンはオフになる)
  clsTglLbl_Week1.OnValueSet vbTuesday
  '金曜をオフ(排他に係わり無く、指定したボタンはオフになる)
  clsTglLbl_Week1.OffValueSet vbFriday

  '全体をオン(排他なので効果なし)
  clsTglLbl_Week1.OnValueSet
  '全体をオフ(排他に係わり無く、全ボタンはオフになる)
  clsTglLbl_Week1.OffValueSet

  '火曜をオン(排他ではないので、オン中の他ボタンはそのまま)
  clsTglLbl_Week2.OnValueSet vbTuesday
  '金曜をオフ(排他に係わり無く、指定したボタンはオフになる)
  clsTglLbl_Week2.OffValueSet vbFriday

  '全体をオン(排他ではないので、全ボタンはオンになる)
  clsTglLbl_Week2.OnValueSet
  '全体をオフ(排他に係わり無く、全ボタンはオフになる)
  clsTglLbl_Week2.OffValueSet


 8.[GrpEnabled ]プロパティにTrue/False を指定する事で、グループ全体の操作可否
    設定できます。
  Private Sub cmdTrue1_Click()
    clsTglLbl_Week1.GrpEnabled = True
  End Sub

  Private Sub cmdFalse1_Click()
    clsTglLbl_Week1.GrpEnabled = False
  End Sub

  (clsTglLbl_Week2 のコードも同じなので省略)

 9.サンプルブックでは使っていませんが、[Item ]プロパティを使うと、Userformモジュール内に
    コレクションを用意しなくても、グループ内のボタン(ラベルコントロール)を配列として扱えます。
  Dim  i  As Integer
  'ボタンを非表示にする
  For  i  = 1 To clsTglLbl_Week1.Count
    clsTglLbl_Week1.Item( i ).Visible = False
  Next i
 

10.[clsTglLblGrp]クラスは、ボタンをマウスクリックした際に『Click イベント』を発生させます。
      Click イベントは、次項解説の Change イベントの後に発生します

      このイベント内で、クリックしたボタンに対して、何らかの操作を行なう場合は、[Btn_Label]
      を通して行なう事が出来ます。

      [Index]引数にはクリックしたラベルの番号(Add メソッドで登録した順番[1〜])
      [Btn_Label]引数にはクリックしたラベルのラベルオブジェクト
      [Btn_Value]引数にはクリックした結果のオン/オフ(True/False)  が返ります。
  '[clsTglLblGrp]では、クラス内部で配列化しつつ、イベント処理できる
  Private Sub clsTglLbl_Week1_Click _
            (ByVal Index As Integer, _
             ByVal Btn_Label As MSForms.Label, _
             ByVal Btn_Value As Boolean)
    lblClick1.Caption = vntWeek(Index) & ":" & Btn_Value
  End Sub

  (clsTglLbl_Week2 のコードも同じなので省略)

11.[clsTglLblGrp]クラスは、ボタンの状態が変化した際に『Change イベント』を発生させます。
      Change イベントは、マウスクリックや OnValueSet/OffValueSet メソッドにより、ボタンの状態
      (オン:凹/オフ:凸)が変化(凹⇔凸)した際に発生します。
      Change イベントの発生は、1回の操作(クリックやメソッド実行)に対して1回とは限りません。
      その操作によって状態が変化した全てのボタンに対する Change イベントが繰り返し発生
      します。
      例えば、排他有りの場合に、クリックでボタンをオンにすれば、そのボタンの他に、それまで
      オンだったボタン(オフに変わります)の2つで Change イベントが続けて発生します(2つの
      Change イベントが発生した後に、クリックしたボタンに対する Click イベントが発生します)。

      このイベント内で、状態の変化したボタンに対して、何らかの操作を行なう場合は、[Btn_Label]
      を通して行う事が出来ます。

      [Index]引数には状態の変化したラベルの番号(Add メソッドで登録した順番[1〜])
      [Btn_Label]引数には状態の変化したラベルのラベルオブジェクト
      [Btn_Value]引数には状態変化した後のオン/オフ(True/False)  が返ります。
  Private Const cstON As Long = vbWhite
  Private Const cstOFF As Long = &HC0FFC0    ' 薄緑

  '[clsTglLblGrp]では、クラス内部で配列化しつつ、イベント処理できる
  Private Sub clsTglLbl_Week1_Change _
            (ByVal Index As Integer, _
             ByVal Btn_Label As MSForms.Label, _
             ByVal Btn_Value As Boolean)
    If (Btn_Value = True) Then
      Btn_Label.BackColor = cstON
    Else
      Btn_Label.BackColor = cstOFF
    End If
  End Sub

  (clsTglLbl_Week2 のコードも同じなので省略)
     一度の操作により変化した[ボタンの全て]で Change イベントが発生しますので、上記のコード
      だけで、排他時のマウスクリックで起きる「2つのボタンのオン化/オフ化という同時変化」にも対
      応している事になります。

12.(11)項では、イベントサンプルとして、ボタンカラーの変更を Change イベントによって行いま
      したが、『第2版』において、ボタンカラーの自動変更 および ボタンの初期状態(凹凸)の指定
      を行なう [ Init ] メソッドを追加しました。
      サンプルブックでは「子フォーム」の方で使っていますので参考にしてください。
  Set clsTglLbl_年代 = New clsTglLblGrp
  With clsTglLbl_年代
      .Add lblAge10
      .Add lblAge20
      .Add lblAge30
      .Add lblAge40
      .Add lblAge50
      .Rgst True      '[True]指定で[排他あり]
      .Init vbYellow, vbDesktop, Array( False, False, True, False, False )
  End With

  Set clsTglLbl_科目 = New clsTglLblGrp
  With clsTglLbl_科目
      .Add lbl国語
      .Add lbl算数
      .Add lbl理科
      .Add lbl社会
      .Add lbl英語
      .Rgst False        '[False]指定で[排他なし]
      .Init vbCyan, vbButtonFace, Array( True, False, True, True, False )
  End With
 

13.(10) (11)項で説明したように、この[clsTglLblGrp]クラスでは、同一グループ内の複数のボタン
      (ラベル)に対するイベント処理を、UserFormモジュール内に
            『 たった、ひとつのイベントプロシジャー
      を記述するだけで済ませる事ができます。従来はクラスモジュール内にイベントプロシジャー
      を記述する「見掛け上の、ひとつのイベントプロシジャー」で対応して来ました(UserFormモ
      ジュール内にイベントプロシジャーは書かない)。

      VBA/UserFormでの「擬似コントロール配列」を越え、VB並に「コントロール配列」に準ずる
      記述/操作が可能な、この手法の解説は
            特集記事 : 『擬似』からの脱却
      を参照してください。

14.このサンプルは『曜日』ボタンなので、インデックス番号を表すものとして[vbSunday(1) 〜
      vbSaturday(7)]を使いました。このようにインデックス番号には、直接番号を記述せず、意味
      の判る定数名を利用した方がコードの可読性が高くなります。Excel2000以上ならば列挙型
      (Enum)が便利です。Excel97では列挙型が利用できないのでConst 定数を使って下さい。
  Private Enum en科目
    en国語 = 1
    en算数 = 2
    en理科 = 3
    en社会 = 4
    en英語 = 5
  End Enum

 Private Const cst国語 As Integer = 1
 Private Const cst算数 As Integer = 2
 Private Const cst理科 As Integer = 3
 Private Const cst社会 As Integer = 4
 Private Const cst英語 As Integer = 5

[ clsTglLblGrp ] [ clsTglLabelEx/clsTglLabel ] クラスのリファレンス解説ページ



 Home   Back Page   Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved.