Typeは次のように使える。

以下、標準モジュールでの例。
'【Typeの例】
Type typeShohin
sCD As String
sName As String
lTanka As Long
dCreateDate As Date
End Type


Sub Test1()
'いくつも同じ型を使いたいなら、別名で定義すればよい。

Dim typIn As typeShohin
Dim typOut As typeShohin

'通常の変数と同様、配列にもできる。
Dim typWk() As typeShohin

'修飾子がついて初めて変数として使える。これによりコードの可読性は高まる
typIn.sCD = "11111"
typIn.sName = "忘年会セット(竹)"
typIn.lTanka = 100000

'項目をごっそりコピーできる
typOut = typIn

'参考まで With も使える
With typIn
.sCD = "11112"
.sName = "忘年会セット(梅)"
.lTanka = 200
End With

' (以下略)

'関数の戻り値の型としても使える(Publicで定義必要など条件あり)
' など・・
End

End Sub

例として適切かどうかは疑問だが、上記のようには使える。

ただ、以下のような項目は行いたいという話は実務経験上あった。
・定義時に初期値を設定したい
・値を入れたときにチェックしたい
・値を出すときに形式を変換したい

これをTypeで行うと処理を個別に用意してやる必要があるし、その処理の記述場所をどこにしよう、などということにも頭を使わなければいけなくなる。面倒なことになる。というのは、Typeはあくまでもデータのひとくくりを定義しただけ容れ物に過ぎないからだ。
しかし、クラスモジュールを使えば、その容れ物に一工夫し、該当するデータに付随した処理もまとめることができるのだ。

以下のようなクラスモジュールをClassTestという名で作る。
Propertyを使っているので、なれていない人は読みにくいかもしれない。簡単にいえば、データの取り出しと設定を同じ定義名でできるものであり(これは通常の変数と同じ)、かつその際に処理を付加できるものである(これは通常の変数にはできない)。
Let が値の設定の定義/Getで値の取得の定義である。クラスモジュールの呼び出し用のソースコードがクラスモジュールの下にある。そこに★マークで簡単なコメントを入れておいたのでそこを手がかりに参考にして欲しい。
'【データクラスの例】 クラス名:classTest
Private Type typeShohin
sCD As String
sName As String
lTanka As Long
dCreateDate As Date
End Type

Private typ As typeShohin

'コンストラクタ(クラスモジュールをNewした際に自動的に実行されるモジュール)
Private Sub Class_Initialize()
typ.sCD = "00000"
typ.sName = ""
typ.lTanka = 0
typ.dCreateDate = Now
End Sub

'一般ケース
'CD
' 設定
Public Property Let S_CD(sVal As String)
typ.sCD = sVal
End Property

' 取り出し
Public Property Get S_CD() As String
S_CD = typ.sCD
End Property

'S_NAME
' 設定
Public Property Let S_NAME(sCD As String)
typ.sCD = sCD
End Property

' 取り出し
Public Property Get S_NAME() As String
S_NAME = typ.sCD
End Property

'(中略)

'値が範囲外ならエラーを出すケース
'TANKA
' 設定
Public Property Let TANKA(lVal As Long)
If lVal < 0 Then
MsgBox ("単価がマイナスです")
ElseIf lVal = 0 Then
MsgBox ("単価がゼロです")
Else
typ.lTanka = lVal
End If
'簡単な例。実務ではエラーチェックを切り出し、エラーを呼び出し元に通知させ、
'例外処理をさせる必要がある

End Property

' 取り出し
Public Property Get TANKA() As Long
TANKA = typ.lTanka
End Property



'形式変換があるケース
'CRE_DATE
' 設定
Public Property Let CRE_DATE(dDated As Date)
typ.dCreateDate = dDated
End Property

' 取り出し
Public Property Get CRE_DATE() As Date
CRE_DATE = typ.dCreateDate
End Property

' 別形式で取り出し
Public Property Get CRE_DATE_YYYYMMDD() As String
CRE_DATE_YYYYMMDD = Format(typ.dCreateDate, "YYYYMMDD")
End Property

上記クラスモジュールを利用する標準モジュールは例えば以下の通り。

Sub Test1

Dim typIn As ClassTest
Dim typOut As ClassTest

'通常の変数と同様、配列にもできる。
Dim typWk() As ClassTest

Set typIn = New ClassTest
Set typOut = New ClassTest

MsgBox ("初期値 商品コード : " & typIn.S_CD)
MsgBox ("初期値 作成日   : " & typIn.CRE_DATE)
'★値取得時にはProperty Get が動作する
MsgBox ("初期値 作成日別形式: " & typIn.CRE_DATE_YYYYMMDD)

'修飾子がついて初めて変数として使える。これによりコードの可読性は高まる
typIn.S_CD = "11111"
typIn.S_NAME = "忘年会セット(竹)"

'★値設定時にはProperty Let が動作する
'単価エラー マイナス
typIn.TANKA = -1
'単価エラー ゼロ
typIn.TANKA = 0

typIn.TANKA = 100000


'この形式だと項目をコピーしようとすると落ちてしまう
' typOut = typIn

'参考まで With も使える
With typIn
.S_CD = "11112"
.S_NAME = "忘年会セット(梅)"
.TANKA = 200
End With


' (以下略)

'関数の戻り値の型としても使える(Publicで定義必要など条件あり)
' など・・

Set typIn = Nothing
Set typOut = Nothing

End Sub

・定義時に初期値を設定したい
・値を入れたときにチェックしたい
・値を出すときに形式を変換したい
については実装が可能となった。

なお、クラスモジュールでごちゃごちゃしているなあ、と感じるだろう。しかし、メインルーチンに付加したモノは確認用で、流れ自体はほとんど変更していない、という点に注目して欲しい。
プログラムのメンテナンスで、処理の流れを追いにくく影響度が読み切れないことほど悲惨なケースはない。いかに枝葉の処理と幹の処理を分け、枝葉のクラスモジュールは枝葉らしく、幹のクラスモジュールは幹らしく、きちんと役割分担をさせられるか、がメンテナンス性の高いプログラミングになるかのカギといえるだろう。

さて、次回は上記の「項目がコピーできない」問題を解決しよう。