【 擬似からの脱却 】 [ Breakthrough in the Pseudo-Control Arrays ]
[ clsBpca の 軌跡 ] [ 前頁 , 次頁 , §1 , §2 , §3 , §4 , §5 , §6 , §7 , §8 , §9 , §10 , §11 , §12 ]
[ 汎用クラス , トグルラベル クラス , Focus クラス , クラス アドイン , カレンダークラス ] [ 質問はメールへ ]
( 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) が返ります。
一度の操作により変化した[ボタンの全て]で Change イベントが発生しますので、上記のコード
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イベントを使わなくても、ボタンの凹凸による
色の変更を自動化できます。
だけで、排他時のマウスクリックで起きる「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 ]
|
||
角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved. |