この トグルラベル クラス (旧版) は 『 疑似からの脱却 』 手法へと発展していく基になったものです。
先ず、RaiseEvent を使わない クラスモジュールひとつの clsTglLabel が出来ました。 これが、2つのクラス
モジュールを親/子で使い、RaiseEvent を利用した [ clsTglLblGrp & clsTglLabelEx ] へと発展しました。
この [ clsTglLblGrp & clsTgllabelEx ] を整理して体系化したものが 『 疑似からの脱却 - clsBpca - 』です。
現状では既に必要の無くなったものですが、『疑似からの脱却』への軌跡として残しておきます。
( 2004/5/17 第 2 版 [ 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) が返ります。
一度の操作により変化した[ボタンの全て]で Change イベントが発生しますので、上記のコード
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 のコードも同じなので省略)
だけで、排他時のマウスクリックで起きる「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 ] クラスのリファレンス解説ページ
|
||
角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved. |