VBAでオブジェクト指向を理解する
第5回 複数のオブジェクトを制御する

今回は、クラスモジュールを追加して異なる種類のオブジェクトも同時に扱ってみる。それにともないクラスモジュールに変更を加えた。

コード 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 はそれぞれ異なる目的を持ちながらも、同じようにクラスとして定義され、同じループ内で独立して動作する。これは、オブジェクト指向における「異なる型のオブジェクトが共存し、それぞれの責務を果たす」ことの実例と言える。

図 1. 種類の異なるオブジェクト

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

シェアする

  • このエントリーをはてなブックマークに追加

フォローする