読者です 読者をやめる 読者になる 読者になる

【ExcelVBA】クラスのつくり方と使い方

参考になった

qiita.com

クラス書いてみた

Propertyクラスモジュール

Dim m_properties As Object


'コンストラクタ
Private Sub Class_Initialize()
    Set m_properties = CreateObject("Scripting.Dictionary")
End Sub



'--------------------------------------------------------------------------
' [Method]
' プロパティを取得します。
' プロパティキーが存在しない場合はErr.Raiseします。
'
' @param key プロパティキー
' @return プロパティキーの値
'--------------------------------------------------------------------------
Public Function Value(key As String) As String
    If Not m_properties.Exists(key) Then
        Err.Raise Number:=1001, Description:="プロパティキー「" + key + "」が設定されていません。"
    End If
    
    Value = m_properties(key)
End Function

'--------------------------------------------------------------------------
' [Method]
' プロパティを上書きします。
'
' @param sheet 対象のワークシート
'--------------------------------------------------------------------------
Public Sub PutValue(key As String, Value As String)
    m_properties.Add key, Value
End Sub


'--------------------------------------------------------------------------
' [Method]
' A列にプロパティキー、B列に値を格納したワークシートから、
' プロパティを読み込みます。
'
' @param sheet 読み込み対象のワークシート
'--------------------------------------------------------------------------
Public Sub LoadSheet(ByRef sheet As Worksheet)
    Const COLIDX_KEY = 0
    Const COLIDX_VAL = 1
    
    Dim i As Integer
    
    Dim rowend As Integer
    rowend = Cells(Rows.Count, 1).End(xlUp).Row
    
    Dim cellRef As Range
    Set cellRef = sheet.Cells(2, 1)
    
    For i = 1 To rowend
        Dim key As String, val As String
        key = cellRef.Offset(0, COLIDX_KEY).Value2
        val = cellRef.Offset(0, COLIDX_VAL).Value2
        
        If (Not IsEmpty(key) And Not IsEmpty(val)) Then
            If (m_properties.Exists(key)) Then
                Err.Raise ERR001_DUPPLICATEPROPERTY, "", "プロパティ" & key & "が重複しています"
            End If
            m_properties.Add key, val
        End If
    
        Set cellRef = cellRef.Offset(1, 0)
    Next
End Sub

感想

色々と残念。

  • いわゆるグローバル汚染を回避してカプセル化はできてる
  • が、クラス自体を管理する仕組みが全然ダメダメ。
  • コンストラクタに引数かけない
  • パッケージの概念がない
  • Newする以外にインスタンスの生成ができない?
  • というかメタっぽい使い方できない

以下のような使い方しか思いつかない。

  • Utilレベルで完結する機能を共通化する
  • 複雑な手続きが必要なDLLコールをwrapする

万が一VBAで開発しようものなら、各Sheetから直接呼ばれる処理 -> 各Class・モジュール の階層で絶対止めたい。(Model-Controllerモデル)
Class -> Classの依存関係を1階層許しただけでも破綻するのが見ている。
もしそういうことやりたければ、

  1. モジュール名に階層名を付与する規約つけて階層化する(もちろんMVCみたいに明確にレイヤーする制約付きで)
  2. APIコールを最低限にしたメソッド・関数インタフェースを定義して、モジュール切り出しや別言語(.NETやC)でDLL作る。(インタフェースの明確化と疎結合化)
  3. そんだけの規模になると、そもそもExcelは帳票として見るだけでいいんじゃないの?みたいなことを検討する。

 (Excelはただの帳票としてアプリでインポート・エクスポート機能で実装できないか)

を検討する。

もし良い代替手段があれば、それはむしろチャンスだろう。