今回は、クラスモジュールを追加して異なる種類のオブジェクトも同時に扱ってみる。それにともないクラスモジュールに変更を加えた。
コード 1 は、前回使用したクラスモジュール LED である。変数名・プロシージャ名を整理し、外部から参照が不要なものは Private で宣言するように修正を行った。また、LED に属性を渡すプロシージャ SpecSet から、LED を描画するプロシージャ make を呼び出すようにして操作をまとめた。make は外部から操作することがなくなったので Private で宣言するようにした。
Private で宣言した変数やプロシージャは、クラスモジュールの外からアクセスできなくなり、不要な操作を防ぐことでクラスを堅牢にできる。
コード 2 は、新たに追加したクラスモジュール BAR である。指定したセルにプログレスバーを表示するクラスモジュールで、動作を確認するだけの簡易な内容となっており、精度などは考慮していない。
コード 3 の標準モジュール main には、新しく作成したオブジェクト BAR に関連するコマンドを追加した。また、Loop の中で、起動してからの経過時間(秒)を BAR に渡し、プログレスバーを表示している。
コード 1.クラスモジュール LED
' LEDの属性(構造体のフィールドに相当)
Private R As Integer ' LEDを配置するセルの行番号
Private C As Integer ' LEDを配置するセルの列番号
Private Col As Long ' LEDの表示色
Private T_on As Long ' LEDの点灯時間(ミリ秒)
Private T_off As Long ' LEDの消灯時間(ミリ秒)
Private T_st As Long ' LEDが点灯開始した時間(ミリ秒)
Private Flg As Integer ' タイマー監視フラグ 1:監視中 0:監視中でない
' LEDの属性を設定する
Sub SpecSet(LED_Row As Integer, LED_Column As Integer, LED_Color As Long, LED_Time_On As Long, LED_Time_Off As Long)
R = LED_Row
C = LED_Column
Col = LED_Color
T_on = LED_Time_On
T_off = LED_Time_Off
Flg = 0
make 'クラスモジュール内の make を呼び出す
End Sub
' LEDの初期描画
Private Sub make()
With Cells(R, C)
.Font.Color = Col ' フォントの色を設定
.Value = "*" ' 初期値は消灯マークを設定
.HorizontalAlignment = xlCenter ' 文字をセルの中央寄せに設定
.Interior.Color = vbBlack ' セルの背景色を黒に設定
End With
End Sub
' LEDの点滅処理
Sub Blink()
Dim Now_ms As Long
Now_ms = Timer * 1000
If Flg = 0 Then ' タイマー監視中か
T_st = Now_ms ' 点灯開始時間を保持
Flg = 1 ' タイマー監視開始
End If
Select Case Now_ms
Case Is < T_st + T_on
Cells(R, C).Value = "●"
Case Is < T_st + T_on + T_off
Cells(R, C).Value = "*"
Case Else ' T_st + T_on + T_off <= Now_ms
Flg = 0 ' タイマー監視終了
End Select
End Sub
コード 2.クラスモジュール BAR
' プログレスバーの属性
Private R As Integer ' バーを配置するセルの行番号
Private C As Integer ' バーを配置するセルの列番号
Private Max As Long ' 最大値
Sub SpecSet(BAR_row As Integer, BAR_column As Integer, BAR_max As Long)
R = BAR_row
C = BAR_column
Max = BAR_max
End Sub
Sub update(num As Long)
Dim filled As Long
filled = 10 * (num Mod (Max + 1)) / Max
Cells(R, C).Value = String(filled, "#") & String(10 - filled, "-")
End Sub
コード 3.標準モジュール
Sub main()
' LED クラスのインスタンスを生成
Dim LED1 As New LED
Dim LED2 As New LED
Dim LED3 As New LED
' BAR クラスのインスタンスを生成
Dim BAR1 As New BAR
Dim BAR2 As New BAR
' LEDの属性を設定 (引数: 行, 列, 色, 点灯時間ms, 消灯時間ms)
LED1.SpecSet 1, 1, vbRed, 500, 500 '1行1列, 赤色, 点灯0.5秒, 消灯0.5秒
LED2.SpecSet 2, 2, vbYellow, 200, 200 '2行2列, 黄色, 点灯0.2秒, 消灯0.2秒
LED3.SpecSet 3, 3, vbGreen, 100, 100 '3行3列, 緑色, 点灯0.1秒, 消灯0.1秒
'BARの属性を設定(引数:行, 列, 最大値)
BAR1.SpecSet 5, 1, 100
BAR2.SpecSet 6, 1, 10
' Stop ' 実行を一時停止(F5で続行する)
' LEDの点滅ループ
Dim Start_time As Long
Dim Progress As Long
Start_time = Round(Timer)
Do
LED1.Blink
LED2.Blink
LED3.Blink
Progress = Round(Timer) - Start_time
BAR1.update Progress
BAR2.update Progress
DoEvents
Loop
End Sub
これらのコードを実行すると、図 1 のとおり BAR クラスは、LED の点滅とは異なる動きを示し、オブジェクト指向の「多様性」と「独立性」を体験できる。LED と BAR はそれぞれ異なる目的を持ちながらも、同じようにクラスとして定義され、同じループ内で独立して動作する。これは、オブジェクト指向における「異なる型のオブジェクトが共存し、それぞれの責務を果たす」ことの実例と言える。

VBA によりオブジェクト指向を体験する連載はこれで終わる。当初は、5回で終える予定だったが、もう1回追加して Arduino による複数の LED を点滅させるプログラムを作成して完結することにした。
VBA で得た知見が C++ においても活用できることを確認できるだろう。