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

  【 擬似からの脱却 】  [ Breakthrough in the Pseudo-Control Arrays ]

[ clsBpca の 軌跡 ] [ 前頁 , 次頁 , §1 , §2 , §3 , §4 , §5 , §6 , §7 , §8 , §9 , §10 , §11 , §12 ]
[ 汎用クラス , トグルラベル クラス , Focus クラス , クラス アドイン , カレンダークラス ] [ 質問はメール]

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

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

====================================================================
    clsBpcaTglLbl クラス 利用方法  ( リファレンス
====================================================================
  アドイン化したクラスモジュールを利用する場合は下記のインポート作業は不要です。

      2004/6/10 第3 版より、Excel97用クラスも、Excel2000用と同様にクラスの2重適用形態に変更して使い易くしました。
      それに伴い、クラス名も他の「Bpca シリーズクラスモジュール」に合わせて変更しました。 旧 [第 2 版] は こちら
            Excel2000以上用
                  旧[ clsTglLblGrp ]  →  新[ clsBpcaTglLbl ]    ,    旧[ clsTglLabelEx ] →  新[ clsBpcaTglLblCh ]
            Excel97用
                  旧[ clsTglLabel ]    →  新[ clsBpcaTglLbl97 ] & [ clsBpcaTglLbl97Ch ]

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

      Excel97 の場合は、[clsBpcaTglLbl97 ] & [clsBpcaTglLbl97Ch ] を使います。

      クラス定義 および サンプルブック [ Bpca_TglLbl_V41.zip ]  ( 99KB )  
            ( 2004/6/10  Ver3.0 )
            ( 2004/6/23  Ver3.1 )  [clsBpcaTglLbl97]モジュールの 『手直し』 が不要になりました。
            ( 2005/3/10  Ver3.2 )  解説文・クラスソース・サンプルソースにおいて、オブジェクト定義時での[New]指定を止めて、
                                             Initialize 時にインスタンス生成(Set ステートメント)するように修正しました。
            ( 2011/4/15  Ver4.0 )  クラスの機能変更はありません。Ver1.0 から引き継いでいた古いプログラム構造を見直しただけです。
                                             (Item プロパティを【既定のプロパティ】にしました。記載漏れ 2014/7/22)
            ( 2014/7/22  Ver4.1 )  各プロパティで Index引数のエラーチェック(>0)が抜けていたのを修正しました。
                                             getIndex プロパティを追加しました。

          アドイン化しました [ 2005/3/8 初版 ] [ 2014/7/22  Ver 2.30  最新版で再構築 ]

  2.以降、サンプルブックの例をもとに解説します。ここでは、Excel2000以上用の[clsBpcaTglLbl ]に
      ついて解説します。Excel97用については、後程 Excel2000用とは異なる部分のみ解説します。

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

      Video Capture ( Bpca_TglLblForm1.mp4   1.0MB )

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

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

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

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


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


    '[New]キーワード付きのSetステートメント必須
    Set clsTglLbl_Week2 = New clsBpcaTglLbl
    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()
    clsTglLbl_Week1.Clear        ' クラスの終了処理
    clsTglLbl_Week2.Clear
    Set clsTglLbl_Week1 = Nothing
    Set clsTglLbl_Week2 = Nothing
  End Sub

  5.ボタンの状態(オン/オフ:凹凸)は、[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 のコードも同じなので省略)

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

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

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

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


 7.[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 のコードも同じなので省略)

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

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

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

      [Index]引数にはクリックしたラベルの番号(Add メソッドで登録した順番[1〜])
      [Btn_Label]引数にはクリックしたラベルのラベルオブジェクト
      [Btn_Value]引数にはクリックした結果のオン/オフ(True/False)  が返ります。
  '[clsBpcaTglLbl]では、クラス内部で配列化しつつ、イベント処理できる
  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 のコードも同じなので省略)

10.[clsBpcaTglLbl]クラスは、ボタンの状態が変化した際に『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    ' 薄緑

  '[clsBpcaTglLbl]では、クラス内部で配列化しつつ、イベント処理できる
  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 のコードも同じなので省略)

  (補) Init メソッドを実行する事により、Changeイベントを使わなくても、ボタンの凹凸による
          色の変更を自動化できます。
 
     一度の操作により変化した[ボタンの全て]で Change イベントが発生しますので、上記のコード
      だけで、排他時のマウスクリックで起きる「2つのボタンのオン化/オフ化という同時変化」にも対
      応している事になります。

11.(10)項では、イベントサンプルとして、ボタンカラーの変更を Change イベントによって行いま
      したが、『第2版』において、ボタンカラーの自動変更 および ボタンの初期状態(凹凸)の指定
      を行なう [ Init ] メソッドを追加しました。

      サンプルブックでは「子フォーム」の方で使っていますので参考にしてください。
      Video Capture ( Bpca_TglLblForm2.mp4   0.7MB )

  Set clsTglLbl_年代 = New clsBpcaTglLbl
  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 clsBpcaTglLbl
  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
 

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

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

13.このサンプルは『曜日』ボタンなので、インデックス番号を表すものとして[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

====================================================================
    Excel97用 clsBpcaTglLbl97 クラス 利用方法
====================================================================
  ここでは、Excel97用の[clsBpcaTglLbl97 ]クラスを利用する場合に、上記までの解説の内で、異なる
  部分のみ解説します。

14.インポートするクラスモジュールは
          [ clsBpcaTglLbl97 ] および [ clsBpcaTglLbl97Ch ]
      の2つです。クラスオブジェクト定義の際には、下記のように『 WithEvents 』を付けません
  '【1】[排他]有りサンプル
  Private clsTglLbl_Week1 As clsBpcaTglLbl97

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

15.ボタン用のラベルコントロールをクラスに登録する方法については同じですが、97用では、
      Rgstメソッドに[Caller ] [GrpId ]の引数が2つ増えます
      [Caller ]には、クラスの利用元である『UserForm』を指定します(実際には[ Me ]を記述します)。
      (Ver3.1 で、[Caller]引数の属性が、String型からObject型に変わり、指定内容も[ Me ]だけになりました)
      [GrpId ]には、1UserForm内で複数のクラスオブジェクトを利用する場合に、各々の識別コ
      ードを文字列で指定します。この[GrpId]は、次項「イベント通知受領プロシジャー」で必要
      になります。
  Private Sub UserForm_Initialize()
  Dim i As Integer
    vntWeek = Array ("", "日", "月", "火", "水", "木", "金", "土")
  '-------------------------------------------------------------
  '【1】 [clsBpcaTglLbl97]を使った「排他」有りサンプル


    '[New]キーワード付きのSetステートメント
    Set clsTglLbl_Week1 = New clsBpcaTglLbl97
    With clsTglLbl_Week1
      .Add lblSun1
        (中略)
      .Add lblSat1
      .Rgst True, Me, "Week1"       '[True]指定で[排他あり]
    End With
  '-------------------------------------------------------------
  '【2】 [clsBpcaTglLbl97]を使った「排他」無しサンプル


    '[New]キーワード付きのSetステートメント
    Set clsTglLbl_Week2 = New clsBpcaTglLbl97
    With clsTglLbl_Week2
      .Add lblSun2
        (中略)
      .Add lblSat2
      .Rgst False, Me, "Week2"      '[False]指定で[排他なし]
    End With
  End Sub

  Private Sub UserForm_Terminate()
    clsTglLbl_Week1.Clear        ' クラスの終了処理
    clsTglLbl_Week2.Clear
    Set clsTglLbl_Week1 = Nothing
    Set clsTglLbl_Week1 = Nothing
  End Sub

16.[clsBpcaTglLbl]クラスでは、マウスクリック時と、ボタン状態変化時に、[RaiseEvent ]ステー
      トメントを使って[clsBpcaTglLbl]クラス専用のカスタムイベントを発生させています。これはVBA
      システムを通して、利用元のUserFormモジュール内にある[クラスオブジェクト名+アンダーバー
      +イベント名]という綴りのプロシジャーの起動に繋がります。

      Excel97 の場合、ラベルのClick イベントを取得する所までは出来ます(ラベルコントロール
      定義でのWithEvents 宣言)が、それを利用元へ送り出すカスタムイベントが作れません。
      (Excel97 では、[RaiseEvent ]ステートメントが使えない為)
      そこで、VBAシステムによる仲介の代わりに、
            『上位モジュール内に受付窓口となるルーチンを設け』
            『下位モジュールでは直接その窓口へ通知を送る』
      という風にします。

      そうなれば当然「窓口を決めておく」必要がありますので、その名前を
            【 clsBpcaTglLbl97__Event
      と固定にします(アンダーバーを2つ繋げているのは万が一にも名前の重複を避ける為です)。

      上位(UserForm)では、この名前で Sub プロシジャーを定義(Public )しておけば、下位
      ( clsBpcaTglLbl97 クラス)から直接通知が届くという流れになります。

     UserFormモジュールの外から、UserFormモジュール内のプロシジャーをCall するには、
           Call  UserForm参照.xxxxxx( 引数リスト )
      という風にUserFormオブジェクトで参照する必要があります(但し、UserForm参照を設定する
      オブジェクト変数は[Object 型] )。そこで、前項で説明したRgst メソッドの[Caller ]プロパティ
      の内容によって下記のように記述します([ clsBpcaTglLbl97 ] )
(補足説明)
    MsForms.UserForm型の場合
    下記のようにオブジェクト変数の参照でサブルーチンを呼び出す事ができません。
          Dim MyForm As MsForms.UserForm
          Call  MyForm.clsBpcaTglLbl97__Event ( 引数リスト )    ×

   しかし、[MyForm]をObject型で定義すると可能になります。
          Dim MyForm As Object
          Call  MyForm.clsBpcaTglLbl97__Event ( 引数リスト )    

  Ver3.1 では、[Caller ]引数をString 型から、Object 型に変更しました。Rgst メソッドで
  記述する内容も Me.Name から Me のみになりました。
  これにより、Ver3.1 では、[ clsBpcaTglLbl97 ]モジュールを『手直し』する必要が無くな
  りました。

 

      【 [clsBpcaTglLbl97]クラスモジュールから、イベントを呼び元へ上げる処理 】

  '===============================================================
  '===== イベント通知共通プロシジャー ==================================
  '===============================================================
  ' ※ [clsBpcaTglLbl97]クラスでは、呼び元のUserFormに用意してある
  '           通知受領サブ[clsBpcaTglLbl97__Event]    <名称固定>
  ' をCallする事でイベント発生を通知する
  ' (通知受領サブは、名前の重複を防ぐ為に敢えてアンダーバーを2つ繋げている)
  '   EventId : "Click" or "Change"


  Private Sub Raise_Event _
          ( ByVal EventId As String, ByVal Index As Integer, _
            ByVal Btn_Label As MSForms.Label, ByVal Btn_Value As Boolean)

      Call MyCaller.clsBpcaTglLbl97__Event _
                      (MyGrpId, EventId, Index, Btn_Label, Btn_Value)
      '※[MyCaller]は[Object]型のUserFormオブジェクトです。
      '   [MsForms.UserForm]型では、サブルーチンを参照できません。

  End Sub


      上記 の仕組みによって、呼び元のUserFormでは[clsBpcaTglLbl97 ]クラスからイベントを通知
      して貰えます。UserForm側には、決まった名前である
            clsBpcaTglLbl97__Event
      という[Public Sub]プロシジャーを用意します(複数のUserformから利用する場合であっても、
      個々のUserFormモジュール内での名前は全て同じです)。
      利用元で、クリックイベント/チェンジイベントが必要ない場合であっても、このイベント通知受領
      用の窓口ルーチン自体は記述する必要があります。その場合は「処理を記述しない、空ルーチ
      ン」として下さい(サンプルブックの[frmTglLbl97_2]モジュール参照)。


      自UserForm上に複数のグループが有っても、[clsBpcaTglLbl97 ]クラスから通知を受け取るルー
      チンは、この1つだけです。そこで、引数で受け取る[グループID]によって、下記のように、各グル
      ープの『イベント用プロシジャー』へ振り分けてやる必要があります(実際には、97用では、イベン
      トプロシジャーではなく、単に Call によって呼ばれる普通の Sub プロシジャーです)。

      【 ユーザーフォーム側で直す部分 】

  '===============================================================
  '=====  イベント通知受領プロシジャー(Public)  ==========================
  '===============================================================
  '※ [clsBpcaTglLbl97]クラスでは、[clsBpcaTglLbl97]クラスに登録した
  ' コントロールのイベントは、全てのグループが、この
  '      通知受領プロシジャー[clsBpcaTglLbl97__Event]    <名称固定>
  ' を通して送られてくる。
  ' [GrpId]によって、所定のグループ別のイベントプロシジャーに分岐させる。
  ' (通知受領プロシジャーは、名前の重複を防ぐ為に敢えてアンダーバーを2つ繋げている)


  Public Sub clsBpcaTglLbl97__Event _
          (ByVal GrpId As String, ByVal EventId As String, _
           ByVal Index As Integer, ByVal Btn_Label As MSForms.Label, _
           ByVal Btn_Value As Boolean )
    Select Case GrpId
        Case "Week1"
            Select Case EventId
                Case "Click"
                    Call clsTglLbl_Week1_Click ( Index, Btn_Label, Btn_Value )
                Case "Change"
                    Call clsTglLbl_Week1_Change ( Index, Btn_Label, Btn_Value )
            End Select
        Case "Week2"
            Select Case EventId
                Case "Click"
                    Call clsTglLbl_Week2_Click ( Index, Btn_Label, Btn_Value )
                Case "Change"
                    Call clsTglLbl_Week2_Change ( Index, Btn_Label, Btn_Value )
            End Select
  '     Case "xxxx"
  '         Select Case EventId
  '             Case "Click"
  '                 Call xxxx_Click ( Index, Btn_Label, Btn_Value )
  '             Case "Change"
  '                 Call xxxx_Change ( Index, Btn_Label, Btn_Value )
  '         End Select

        Case Else
    End Select
  End Sub
 

====================================================================
    [ clsBpcaTglLbl ] [ clsBpcaTglLbl97 ] クラス リファレンス
====================================================================
  アドイン化したクラスモジュールを利用する場合は下記のインポート作業は不要です。

          Excel2000 以上では[ clsBpcaTglLbl ]クラスが利用できます。
          [ clsBpcaTglLbl ]クラスを使う場合は、一緒に[ clsBpcaTglLblCh ]クラスもインポートする必要があります。


          Excel97 では[ clsBpcaTglLbl97 ]クラスを使って下さい(Excel2000 以上 と Excel97 の両方で使う場合を含む)。
          [ clsBpcaTglLbl97 ]クラスを使う場合は、一緒に[ clsBpcaTglLbl97Ch ]クラスもインポートする必要があります。


          [ clsBpcaTglLblCh/clsBpcaTglLbl97Ch ]クラスは、各々[ clsBpcaTglLbl/clsBpcaTglLbl97 ]クラスの下位クラスです
          (ユーザーサイドで直接このクラスを使うことはありません)。

          下記で[ object ]の部分には、clsBpcaTglLbl/clsBpcaTglLbl97 クラスを定義したオブジェクト変数を記述します。
          尚、[ 2K ]表記は clsBpcaTglLbl 用[ 97 ]表記は clcBpcaTglLbl97 用無印は共通 です。

        このクラスは Win32-API を使っていないので x64 でも動作します

定  義
[ 2K ]
UserForm モジュールの宣言セクション(モジュールの先頭)で、下記のように定義します。

    Private  WithEvents  object  As  clsBpcaTglLbl

    ( object )
      任意の名前を指定して下さい。

    [ Initialize ] イベントプロシジャーにて下記のようにしてクラスのインスタンスを作成します。
        Set  object  =  New  clsBpcaTglLbl
    アドイン化したクラスを利用している場合は、New キーワードを使わずに下記のようにします。
           Set  object  =  CreateBpcaTglLbl ( )
      (CreateBpcaTglLbl 関数は、クラスアドイン で用意してある関数です)



[ 97 ]
UserForm モジュールの宣言セクション(モジュールの先頭)で、下記のように定義します。
WithEvents は付けません

    Private  object  As  clsBpcaTglLbl97

    ( object )
      任意の名前を指定して下さい。

    [ Initialize ] イベントプロシジャーにて下記のようにしてクラスのインスタンスを作成します。
        Set  object  =  New  clsBpcaTglLbl97
    アドイン化したクラスを利用している場合は、New キーワードを使わずに下記のようにします。
           Set  object  =  CreateBpcaTglLbl97 ( )
      (CreateBpcaTglLbl97 関数は、クラスアドイン で用意してある関数です)



メソッド
object .Add    ラベル コントロール オブジェクト

    トグルラベルボタンとして使うラベルコントロールを[ clsBpcaTglLbl ] [ clsBpcaTglLbl97 ]クラスに追加する
    メソッドです。[ object ]グループとして、ひとまとめにするラベル全てに対して、 Add メソッドを繰り返し、最
    後に Rgst メソッドで登録します。

    Add メソッドで登録した順に、コントロール番号が 1 から割り当てられます。この番号が、各種イベント/プロ
    パティ において [ Index ] として扱われます。

    ( ラベル コントロール オブジェクト )
      トグルラベルボタンとして使う、ラベルコントロールオブジェクトを指定します。
 

[ 2K ]
object .Rgst    Exclusive

    Add メソッドで追加したコントロールの登録処理を行なうメソッドです。Add メソッドを繰り返した後に
    行ないます。

    ( Exclusive )
      [True]を指定すると「排他あり」、[False]を指定すると「排他なし」になります。
 

[ 97 ]
object .Rgst    Exclusive , Caller , GrpId

    Add メソッドで追加したコントロールの登録処理を行なうメソッドです。Add メソッドを繰り返した後に
    行ないます。

    ( Exclusive )
      [True]を指定すると「排他あり」、[False]を指定すると「排他なし」になります。

    ( Caller )
      このコードを記述している UserForm モジュールの「UserForm 」を指定します。
      実際には、[ Me ]を指定して下さい。

    ( GrpId )
      複数のコントロール配列グループ(= 複数の[ object ])を使用する場合、そのグループを区別する
      「文字列」を指定します。1グループしか使わないならば「空文字: "" 」でも構いません。
 

object .Clear 

    クラスの解放などの終了処理です。
    UserForm の[Terminate ]イベントで必ず実行して下さい。


object .Init    OnColor , OffColor , InitValue

    [トグルラベル]ボタンの、オン/オフ時の ボタンカラーを OnColor / OffColor で指定すると、クラス側で
    オン/オフ時に自動的に色を変更します。

    Array 関数に True/False を並べたものを、InitValue に指定する事で、ボタンの初期状態を設定できます。

    ( OnColor / OffColor )
      オン(凹)の時のボタンカラーとオフ(凸)の時のボタンカラーを指定します。
      ( vbRed , vbBlue ) や ( vbButtonFace , vbWindowText ) 等のカラー定数 もしくは RGB 関数、
      16進数で指定します。

    ( InitValue )
      Array 関数によるVariant 配列(True / False)を指定します。Array 関数内に、先頭から順に、ボタン番号
      順で、オン(True )・オフ(False )を並べて指定します。ボタン番号は「1〜」、Array 関数による配列の引数
      は「0〜」からでズレていますが、気にせずに Array 関数には先頭から並べてください。
      ボタン数より多く並べた部分は無視されます。ボタン数より少ない場合は、残りの部分が初期状態設定され
      ません(凹凸 と ボタンカラー)。

      排他指定の場合、True を複数指定しても有効になるのは最初のものだけです。。
 

object .OnValueSet    [ Index ]

    [トグルラベル]ボタンをオン(凹)状態にするメソッドです。
    Index 引数の指定で「グループ全体 / 個別のボタン1つ」という使い分けが出来ます。
    排他あり の場合には、下記のようになります。
        ・ グループ全体に対して実行しても機能しません(ボタン状態は変化しません)
        ・ ボタンを指定して実行すると、既にオン(凹)状態のボタンが存在する場合は、そのボタンは
           オフ(凸)状態に変わります

    ( Index )
      ボタン番号(Add メソッドで追加した順番に、1 からの連番)を指定します。
      「排他あり」の場合、それまでオン(凹)だったボタンはオフ(凸)に変わります。
      「排他なし」の場合、省略 もしくは ゼロ を指定すると、[ object ]グループの全てのボタンがオン(凹)
      になります。
       「排他あり」の場合には、省略/ゼロ としても機能しません。
 

object .OffValueSet    [ Index ]

    [トグルラベル]ボタンをオフ(凸)状態にするメソッドです。
    Index 引数の指定で「グループ全体 / 個別のボタン1つ」という使い分けが出来ます。
    排他有無に係わり無く、指定したボタンはオフ(凸)状態になります。

    ( Index )
      ボタン番号(Add メソッドで追加した順番に、1 からの連番)を指定します。
      指定したボタンはオフ(凸)になります。
      省略 もしくは ゼロ を指定すると、[ object ]グループの全てのボタンがオフ(凸)になります。
 

下記メソッドは、[ clsBpcaTglLblCh/clsBpcaTglLbl97Ch ]クラスが、発生したイベントを[ clsBpcaTglLbl/
 clsBpcaTglLbl97 ]クラスへ上げる為に使うメソッドです。ユーザーサイドで使う事はありません。

    RaiseChange , RaiseClick
 

プロパティ
object .GrpEnabled    [ = Boolean ]

    [ object ]グループ全ボタンの「マウスによる操作可否」の状態を表します。値の設定と取得が可能です。

    ( 値の取得 )
      [ object ]グループの全ボタンがマウス操作「可」の場合、GrpEnabled は True を返します。
      全ボタンがマウス操作「不可」、もしくは、一部のボタンが「不可」の場合、GrpEnabled は False を
      返します。

    ( 値の設定 )
      True を設定すると全ボタンがマウス操作「可」になります。
      False を設定すると全ボタンがマウス操作「不可」になります。
 

object .GrpValue    ( [ Index ] ) [ = Variant ( Integer / Boolean / #NA) ]

    [ object ]グループのボタンの「オン(凹)/オフ(凸)」状態を表します。
    個別のボタンの状態(オン/オフ)と、グループ全体で「何番目がオン」という情報を取得できます。
    値の取得のみ可能です。

    ( Index )
      ボタン番号(Add メソッドで追加した順番に1 からの連番)を指定します。省略可。

    ( 値の取得 )
      Index にボタン番号を指定した場合、
          そのボタンのオン/オフが True / False で返ります。
          ボタン番号がグループ内のボタン数を越えている場合はエラー値(#N/A)が返ります。

      Index を省略 もしくは ゼロ を指定 した場合
          ・全てのボタンがオフならば ゼロ が返ります。
          ・「排他あり」の場合(オンはひとつだけ可)、オン状態のボタン番号が数値で返ります。
          ・「排他なし」の場合、
                オン状態のボタンがひとつだけならば、そのボタン番号(1〜)が返ります。
                複数のボタンがオンの場合は[ -1 ]が返ります。
 

object .Item    ( Index ) [ = MsForms.Label ]

    [ object ]グループのボタンを構成する ラベルコントロールオブジェクトを返します。
    UserForm モジュール側で、ボタンに使っているラベルコントロールを配列として操作する場合に
    利用します。値の取得のみ可能です。

    ( Index )
      ボタン番号(Add メソッドで追加した順番に1 からの連番)を指定します。

    ( 値の取得 )
      Index に指定したボタン番号のラベルコントロールオブジェクトを返します。
      ボタン番号が「1〜ボタン数」の範囲外の場合は、[ Nothing ]が返ります。

    Item プロパティ は 【既定のプロパティ】 として定義されているので、[ .Item ] を省略して
           object ( 1 ).BackColor
    という風に記述する事ができます。
 

object .Count   [ = Integer ]

    [ object ]グループのボタンを構成する ラベルコントロールオブジェクトの数を返します。
    値の取得のみ可能です。

    ( 値の取得 )
      Add メソッドで登録したラベルコントロールの数を数値で返します。
      この値は「ボタン番号」の最大値でもあります。
 

object .getIndex    ( CtrlName )   [ = Integer ]  

    [ object ]グループのコントロール配列に登録されているコントロールオブジェクトの中から、
    コントロール名に対する Index の値(コレクション内で登録されている位置番号) を返します。
    値の取得のみ可能です。

    ( CtrlName )
      コントロール名を指定します。

    ( 値の取得 )
      コントロール名から、各プロパティで必要な Index の値を返します。
      未登録名の場合は [ -1 ] を返します。
 

イベント
Private Sub object_Click
          ( ByVal Index As Integer, ByVal Btn_Label As MSForms.Label, ByVal Btn_Value As Boolean )

    [トグルラベル]ボタンをマウスでクリックした際(Change イベントの後)に発生します。
    [トグルラベル]ボタンとして使っているラベル自体の本来のクリックイベントもUserFormモジュール内に記述
    している場合は、ラベル本来のクリックイベントので発生します(ラベル本来のクリックイベントの時点では、
    未だボタン状態は変わっていませんので、注意して下さい)。

    ( Index )
      クリックした[トグルラベル]ボタンの番号(Add メソッドで登録した順に1から割当てられます)が返ります。
      番号は[ object ]単位で割当てられます。

    ( Btn_Label )
      クリックした[トグルラベル]ボタンのラベルコントロールオブジェクトが返ります。

    ( Btn_Value )
      クリックした結果のボタン状態(オン:凹/オフ:凸)が、True / False で返ります。

    利用元で、トグルラベルボタンのクリックイベント処理が必要なければ、利用元モジュール内に、
          この[ object_Click ]プロシジャーを記述する必要はありません


(補) clsBpcaTglLbl97 クラスの場合、正確に言えば「イベントプロシジャー」ではありません。
        下記の『イベント通知受領プロシジャー』 から Call される「普通のサブプロシジャー」です。

 

Private Sub object_Change
          ( ByVal Index As Integer, ByVal Btn_Label As MSForms.Label, ByVal Btn_Value As Boolean )

    [トグルラベル]ボタンのオン(凹)/オフ(凸)状態が変化した際に発生します。マウスクリックが起因で変化
    した場合は、Click イベントの前に発生します。
    一度の操作(マウスクリック/メソッド実行)で発生する Change イベントは一回だけとは限りません。その
    一度の操作によって「状態が変化した」ボタン全てについて続けて発生します。
    例えば、[排他あり]でマウスクリック(凸→凹)した場合では、クリックしたボタンの他に「今までオン(凹)
    だったボタン」の状態も変化しますので、この2つボタンに対して Change イベントが「都合 2回」続けて
    発生します。Click イベント発生は、これら一連の Change イベントが全て発生した後になります。

    ( Index )
      状態の変化した[トグルラベル]ボタンの番号(Add メソッドで登録した順に1から割当てられます)が返
      ります。番号は[ object ]単位で割当てられます。

    ( Btn_Label )
      状態が変化した[トグルラベル]ボタンのラベルコントロールオブジェクトが返ります。

    ( Btn_Value )
      状態が変化した結果のボタン状態(オン:凹/オフ:凸)が、True / False で返ります。

    利用元で、トグルラベルボタンのチェンジイベント処理が必要なければ、利用元モジュール内に、
          この[ object_Change ]プロシジャーを記述する必要はありません


(補) clsBpcaTglLbl97 クラスの場合、正確に言えば「イベントプロシジャー」ではありません。
        下記の『イベント通知受領プロシジャー』 から Call される「普通のサブプロシジャー」です。

 

イベント通知 受領プロシジャー( clsBpcaTglLbl97 のみ)
[ 97 ]
clsBpcaTglLbl97 クラスの場合、利用側のUserForm モジュール内に、下記のプロシジャーを用意する
必要があります。


プロシジャー名は 固定 です(clsBpcaTglLbl97 と Event の間のアンダーバーは、2つ並べます)。複数の
UserForm で利用する場合は、各々のUserForm モジュール内に1つずつ用意する必要があります。

イベントが発生した際に、UserForm側が[ clsBpaTglLbl97 ]クラスからイベント発生の通知を受け取る為の
窓口ルーチンです。ここから、[ GrpId , EventId ] の内容によって、各イベント処理ルーチン(上記)へ
分岐していきます。

下記のプロシジャー名で [ Ctrl ]部分は任意です。 GrpId で指定した文字列 または そのグループの
object の名前などにすると良いでしょう。

Public Sub clsBpcaTglLbl97__Event _
    ( ByVal GrpId As String, ByVal EventId As String, ByVal Index As Integer, _
      ByVal Btn_Label As MSForms.Label, ByVal Btn_Value As Boolean )

    Select Case GrpId
        Case "xxxx"    ' Rgst メソッドで指定した GrpId 文字列
            Select Case EventId
                Case "Click"
                    Call Ctrl_Click ( Index, Btn_Label, Btn_Value )
                Case "Change"
                    Call Ctrl_Change ( Index, Btn_Label, Btn_Value )
            End Select

        Case "yyyy"
            Select  EventId
                Case  ‥‥‥
                Case  ‥‥‥
            End Select

        Case Else
    End Select
End Sub


    ( GrpId )
      UserForm上で、複数のグループが有る場合でも、この窓口ルーチンは『唯1つ』です。どのグループ
      に対する通知なのかが返りますので、この[GrpId ]によって、各グループのイベント処理ルーチン へ
      振り分けて下さい。

    ( EventId )
      どのイベントが発生したのかが、"Click" または "Change" の文字列で返りますので、この[EventId ]によって、
      各イベント処理ルーチン へ振り分けて下さい。

    ( Index )
      イベントが発生したコントロールの番号(Add メソッドで登録した順に、1から設定されます)が返ります。
      そのまま、各コントロールのイベント処理ルーチンへ引き継いで下さい。

    ( Btn_Label )
     イベントが発生したラベルコントロールのオブジェクト参照が返ります。
      そのまま、各コントロールのイベント処理ルーチンへ引き継いで下さい。

    ( Btn_Value )
      イベントが発生した結果のボタン状態(凹/凸)が[True/False]で返ります。
      そのまま、各コントロールのイベント処理ルーチンへ引き継いで下さい。


[Ver3.1] では、『手直し』が不要になりました。
clsBpcaTglLbl97モジュールは一切修正する必要はありません。

 




[ 前頁 , 次頁 , §1 , §2 , §3 , §4 , §5 , §6 , §7 , §8 , §9 , §10 , §11 , §12 ]
[ 汎用クラス , トグルラベル クラス , Focus クラス , クラス アドイン , カレンダークラス ] [ 質問はメール]


【 擬似からの脱却 】  [ Breakthrough in the Pseudo-Control Arrays ]


 Home   Back Page   Next Page

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

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