teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

説明追記

2020/09/09 04:53

投稿

hatena19
hatena19

スコア34367

answer CHANGED
@@ -71,4 +71,105 @@
71
71
  End Sub
72
72
  ```
73
73
 
74
- いったん保存して閉じると、次回から開くとチェックボックスにクラスが関連付けられて、機能するようになります。
74
+ いったん保存して閉じると、次回から開くとチェックボックスにクラスが関連付けられて、機能するようになります。
75
+
76
+ クラスでイベントが共通化できる仕組み
77
+ ---
78
+
79
+ 変数はデータを格納することができる器と考えることができます。
80
+ クラスは、データだけでなく処理(メソッド)も持つことができるもの(オブジェクト)です。
81
+ さらにクラスは、オブジェクトなので同じものを複数生成できるという特徴があります。
82
+ 例えばエクセルのワークシートもオブジェクトの一種なので、好きなだけ追加することができますね。
83
+ クラスモジュールとはそのクラスオブジェクトの設計図と考えことができます。
84
+
85
+ たぶん、なんのことか理解できないと思いますので、実際のコードで解説します。
86
+ クラスモジュール clsLinkedCheckBoxes はすでに作成済みですね。
87
+ 設計図はできています。
88
+ 標準モジュールを追加して、下記のコードを記述してください。
89
+
90
+ ```VBA
91
+ Option Explicit
92
+ Private Chk As clsLinkedCheckBoxes
93
+
94
+ Private Sub ClassTest()
95
+ With Worksheets("Sheet1") 'チェックボックスのあるシート
96
+ Set Chk = New clsLinkedCheckBoxes 'クラスの実体を生成
97
+ Chk.SetCtrl .CheckBox45, .CheckBox1
98
+ End With
99
+ End Sub
100
+ ```
101
+ これを実行すると、CheckBox45 と CheckBox1 が連動するようになります。
102
+ 標準モジュールの先頭でクラス変数を宣言します。
103
+ プロシージャ内に記述してはダメです。プロシージャ内の変数はプロシージャの処理か終了すると消えてしまうからです。標準モジュールの先頭だとエクセルが開いてい間は存在します。
104
+
105
+ 5行目の New clsLinkedCheckBoxes というのはclsLinkedCheckBoxesの設計図をもとに実体(インスタンスといいます)を生成するという処理になります。この実体が変数Chkに格納されます。
106
+ Chk.SetCtrl はクラスに実際のコントロール(チェックボックス)を登録する処理(メソッド)です。
107
+ クラスモジュールでSetCtrlをみると、
108
+ Set Chk1 = newChk1
109
+ Set Chk2 = newChk2
110
+ というようにクラス内変数に格納してます。
111
+ これで、クラスとコントロールが紐づけられ、コントロールにイベントが発生するとクラス内に記述してあるイベントプロシージャが実行されます。
112
+
113
+ 前のコードは下記のように書くこともできます。
114
+ ```VBA
115
+ Option Explicit
116
+ Private Chk As New clsLinkedCheckBoxes
117
+
118
+ Private Sub ClassTest()
119
+ With Worksheets("Sheet1") 'チェックボックスのあるシート
120
+ Chk.SetCtrl .CheckBox45, .CheckBox1
121
+ End With
122
+ End Sub
123
+ ```
124
+
125
+ Private Chk As New clsLinkedCheckBoxes はインスタンスの生成と変数の代入を同時にしています。
126
+
127
+ クラスは複数生成することができますので、
128
+ ```vba
129
+ Option Explicit
130
+ Private Chk1 As New clsLinkedCheckBoxes
131
+ Private Chk2 As New clsLinkedCheckBoxes
132
+ Private Chk3 As New clsLinkedCheckBoxes
133
+
134
+ Private Sub ClassTest()
135
+ With Worksheets("Sheet1") 'チェックボックスのあるシート
136
+ Chk1.SetCtrl .CheckBox45, .CheckBox1
137
+ Chk2.SetCtrl .CheckBox46, .CheckBox2
138
+ Chk3.SetCtrl .CheckBox47, .CheckBox3
139
+ End With
140
+ End Sub
141
+ ```
142
+ と書けば一つの設計図をもとに複数のコントロールに同じ機能を持たせることができます。
143
+
144
+ 3つぐらいのコントロールなら上記のように必要なだけ変数を書いて、紐づけるコードも繰り返し記述すればいいのですが、複数あるときは面倒ですよね。イベントプロシージャのコントロールの数だけ書くのと大差ないのでクラスにした意味がないです。
145
+
146
+ そこで配列変数を使います。
147
+ `Private Chkes(1 to 44) As New clsLinkedCheckBoxes`
148
+ と書くとChkes(1)からChkes(44)までの44個のクラスの実体が生成されて変数に格納されます。
149
+ クラスにコントロールを登録するのはFor Nextのループでできます。
150
+
151
+ ```vba
152
+ Option Explicit
153
+ Private Chkes(1 To 44) As New clsLinkedCheckBoxes
154
+
155
+ Private Sub 複数コントロールの登録()
156
+ Dim i As Long
157
+ With Worksheets("Sheet1") 'チェックボックスのあるシート
158
+ For i = 1 To 44
159
+ Chkes(i).SetCtrl .OLEObjects("CheckBox" & i + 44).Object, _
160
+ .OLEObjects("CheckBox" & i).Object
161
+ Next
162
+ End With
163
+ End Sub
164
+ ```
165
+ これを実行すると、
166
+ CheckBox45 → CheckBox1
167
+ CheckBox46 → CheckBox2
168
+ CheckBox47 → CheckBox3
169
+ ・・・・
170
+ ・・・・
171
+ CheckBox88 → CheckBox44
172
+ というようにチェックボックスが連動するようになります。
173
+
174
+ ブックを閉じるとこの関連付けは解除されますので、つぎ開いたときに適当なタイミングでまた上記の処理を実行する必要があります。
175
+ ThisWorkbookモジュールの Workbook_Openイベントはブックを開いたときに自動で実行されますので、ここに上記のコードを記述しておけば、ブックを開くと同時にチェックボックスは連動するようになります。

2

コード追記

2020/09/09 04:52

投稿

hatena19
hatena19

スコア34367

answer CHANGED
@@ -41,4 +41,34 @@
41
41
  End If
42
42
  End Sub
43
43
  ```
44
- あとはチェックボックスオブジェクトの宣言と、クラスのチェックボックスとシート上のチェックボックスを関連付けるメソッド SetCtrl を記述するだけです。
44
+ あとはチェックボックスオブジェクトの宣言と、クラスのチェックボックスとシート上のチェックボックスを関連付けるメソッド SetCtrl を記述するだけです。
45
+
46
+ クラスとチェックボックスを関連付ける
47
+ ---
48
+ > これを画像の場合だと45から88までのプロシージャをクラスモジュールで作れればいいようなのですが、どうすればいいかわかりません。
49
+
50
+ CheckBox45 → CheckBox1
51
+ CheckBox46 → CheckBox2
52
+ CheckBox47 → CheckBox3
53
+ CheckBox48 → CheckBox4
54
+ ・・・・
55
+ ・・・・
56
+ CheckBox88 → CheckBox44
57
+ というようなペアになっているということですね。
58
+ ThisWorkbookのモジュールに下記のように記述してください。
59
+
60
+ ```vba
61
+ Private Chkes(1 To 44) As New clsLinkedCheckBoxes
62
+
63
+ Private Sub Workbook_Open()
64
+ Dim i As Long
65
+ With Worksheets("Sheet1") 'チェックボックスのあるシート
66
+ For i = 1 To 44
67
+ Chkes(i).SetCtrl .OLEObjects("CheckBox" & i + 44).Object, _
68
+ .OLEObjects("CheckBox" & i).Object
69
+ Next
70
+ End With
71
+ End Sub
72
+ ```
73
+
74
+ いったん保存して閉じると、次回から開くとチェックボックスにクラスが関連付けられて、機能するようになります。

1

コード追記

2020/09/07 21:01

投稿

hatena19
hatena19

スコア34367

answer CHANGED
@@ -4,4 +4,41 @@
4
4
 
5
5
  [VBA - コード中で生成されたコマンドボタンの処理の指定|teratail](https://teratail.com/questions/288841)
6
6
 
7
- 上記は、ラベルとコマンドボタンがワンセットになってます。
7
+ 上記は、ラベルとコマンドボタンがワンセットになってます。
8
+
9
+ クラスモジュールの書き方
10
+ ---
11
+ メニューの[挿入]-[クラスモジュール]をクリックしてクラスモジュールを追加します。
12
+ オブジェクト名を「clsLinkedCheckBoxes」とします。(機能の分かり安い名前にするといいでしょう。)
13
+ 下記のように記述します。
14
+
15
+ ```vba
16
+ Private WithEvents Chk1 As MSForms.CheckBox
17
+ Private Chk2 As MSForms.CheckBox
18
+
19
+ Public Sub SetCtrl(newChk1 As MSForms.CheckBox, newChk2 As MSForms.CheckBox )
20
+ Set Chk1 = newChk1
21
+ Set Chk2 = newChk2
22
+ End Sub
23
+
24
+ Private Sub Chk1_Click()
25
+ If Chk1.Value = False Then
26
+ Chk2.Value = False
27
+ Chk2.Enabled = False
28
+ Else
29
+ Chk2.Enabled = True
30
+ End If
31
+ End Sub
32
+ ```
33
+ 現状のチェックボックスのイベントプロシージャと比べると Chk1_Click の部分はほぼ同じということが分かると思います。
34
+ ```vba
35
+ Private Sub CheckBox45_Click()'45が画像左上のチェックボックス、1がその右 連番で下に行って1列飛ばしで生成される
36
+ If CheckBox45.Value = False Then
37
+ CheckBox1.Value = False
38
+ CheckBox1.Enabled = False
39
+ Else
40
+ CheckBox1.Enabled = True
41
+ End If
42
+ End Sub
43
+ ```
44
+ あとはチェックボックスオブジェクトの宣言と、クラスのチェックボックスとシート上のチェックボックスを関連付けるメソッド SetCtrl を記述するだけです。