Subプロシージャ
Functionプロシージャ
Propertyプロシージャ
Subステートメント~End Subステートメントで囲ま れる 実行はするけど、値は返さない 途中で抜けたいときはExit Sub を行なう Public Subはマクロの実行候補に表示されるSubプロシージャ
Public Sub TestSubProc()
Call ShowElShadaiMsg("まだ死ぬ定めではない") End Sub
Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox "神はいっている" & msg & "・・・と"
End Sub
Public Sub TestSubProc()
Call ShowElShadaiMsg("まだ死ぬ定めではない") End Sub
Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox "神はいっている" & msg & "・・・と"
End Sub
Subプロシージャの例
Subの前に
PublicまたはPrivateを指定できる 省略した場合はPublicとされる
Public Sub TestSubProc()
Call ShowElShadaiMsg("まだ死ぬ定めではない") End Sub
Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox "神はいっている" & msg & "・・・と"
End Sub
Subプロシージャの例
Subの前に
PublicまたはPrivateを指定できる 省略した場合はPublicとされる
Option Private
Public Sub TestSubProc()
Call ShowElShadaiMsg("まだ死ぬ定めではない") End Sub
Subプロシージャの例
モジュールの先頭にOption Private がある場合は、別のプロジェクトか らは実行できなくなる
Public Sub TestSubProc()
Call ShowElShadaiMsg("まだ死ぬ定めではない") End Sub
Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox "神はいっている" & msg & "・・・と"
End Sub
Private Sub ShowElShadaiMsg(ByVal msg As String) If msg = “神はしんだ” Then
Exit Sub End If
Msgbox "神はいっている" & msg & "・・・と" End Sub
Functionステートメント~End Functionステートメ ントで囲まれる 値を返せる 途中で抜けたいときはExit Functionを行なう 標準モジュールで作成したPublic Functionは数式と して使えるFunctionプロシージャ
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Functionプロシージャの例
Functionの前に
PublicまたはPrivateを指定できる 省略した場合はPublicとされる
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Functionプロシージャの例
Functionの前に
PublicまたはPrivateを指定できる 省略した場合はPublicとされる
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Sub TestFuncProcCaller() Dim rng As Range
Call Msgbox(TestFuncProc(Sheet1.Cells(2, 2))) End Sub
Public Function TestFuncProc(ByRef rng As Range) As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) _ As String
TestFuncProc = "神はいっている" _
& rng.Value & "・・・と" End Function
Public Function TestFuncProc(ByRef rng As Range) _ As String * 1024
End Function
Functionプロシージャの例
固定文字列は返せない この例はエラーになる
Public Function TestFuncProc(ByRef rng As Range) _ As String(0 to 10)
End Function
Functionプロシージャの例
固定配列は返せない この例はエラーになる
Private Function TestFuncArray() As String() Dim tmp(0 To 2) As String tmp(0) = "1" tmp(1) = "2" tmp(2) = "abc" TestFuncArray = tmp End Function
Functionプロシージャの例
可変配列は返せる。 以下のような記述はできない TestFuncArray(1) = “2”
Private Type typCat
strName As String '* 名前 lngAge As Long '* 年齢 kCatChr As eCatChar '* 性格 End Type
Private Function TestFuncType() As typCat With TestFuncType .strName = "マイケル" .lngAge = 2 .kCatChr = eCatChar_Freedom End With End Function
Private Enum eCatChar
eCatChar_Baby '* 子供っぽい eCatChar_Boss '* 親分肌
eCatChar_LoneWolf '* 一匹狼 eCatChar_Freedom '* フリーダム End Enum
Private Function TestFuncEnum() As eCatChar TestFuncEnum = eCatChar_Boss
'* コレクション
Private Function TestFuncCollection() As Collection Set TestFuncCollection = New Collection
Call TestFuncCollection.add("アカギ") Call TestFuncCollection.add("カイジ") End Function ‘ オブジェクトの呼び出し例 Dim cll as Collection Set cll = TestFuncCollection()
Public Function TestFuncProc(ByRef rng As Range) End Function
Functionプロシージャの例
戻り値の型は省略できる その場合はVariant型になるけどやるな
Public Function TestFuncProc(ByRef rng As Range) Exit Function Debug.print “以降は実行されない” End Function
Functionプロシージャの例
Exit Functionでプロシージャをぬけ ることができる
Public変数の代わりに使用できる 途中で抜けたいときはExit Propertyを行なう Get,Let,Setの3種類がある 「4変数のスコープと生存期間」で説明済みPropertyプロシージャ
Public Property Get Name() As String Name = "TEST"
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.Name End Sub
Public Property Get Name() As String Name = "TEST"
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.Name End Sub
Public Property Get Name() As String Name = "TEST"
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.Name End Sub
Public Property Get Name() As String Name = "TEST"
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.Name End Sub
Public Property Get Name() As String Name = "TEST"
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.Name End Sub
Public Property Let Name(ByVal v As String) Debug.Print "Property Let"
End Property
Public Sub TestProperty()
mdlSample.Name = "ゆっくり“ End Sub
Public Property Let Name(ByVal v As String) Debug.Print "Property Let"
End Property
Public Sub TestProperty()
mdlSample.Name = "ゆっくり“ End Sub
Public Property Let Name(ByVal v As String) Debug.Print "Property Let"
End Property
Public Sub TestProperty()
mdlSample.Name = "ゆっくり“ End Sub
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.Address
End Property
Public Sub TestProperty()
Set mdlSample.MyRange = Sheet1.Cells(2, 2) End Sub
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.Address
End Property
Public Sub TestProperty()
Set mdlSample.MyRange = Sheet1.Cells(2, 2) End Sub
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.Address
End Property
Public Sub TestProperty()
Set mdlSample.MyRange = Sheet1.Cells(2, 2) End Sub
Public Property Get PropArgs(ByVal x As Long, _ ByVal y As Long) As String PropArgs = "PropArgs Get" & x & " " & y
End Property
Public Property Get PropArgs(ByVal x As Long, _ ByVal y As Long) As String PropArgs = "PropArgs Get" & x & " " & y
End Property
Public Sub TestProperty() Dim ret As String
ret = mdlSample.PropArgs(1, 2) End Sub
Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _
" " & y & " " & msg End Property
Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _
" " & y & " " & msg End Property
Public Sub TestProperty()
mdlSample.PropArgs(1, 2) = "ゆっくり" End Sub
Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _
" " & y & " " & msg End Property
Public Sub TestProperty()
mdlSample.PropArgs(1, 2) = "ゆっくり" End Sub
Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _
" " & y & " " & msg End Property
Public Sub TestProperty()
mdlSample.PropArgs(1, 2) = "ゆっくり" End Sub
Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _
" " & y & " " & msg End Property
Public Sub TestProperty()
mdlSample.PropArgs(1, 2) = "ゆっくり" End Sub
ByValとByRef
省略可能な引数
可変引数
ByValは値渡し 引数をコピーして渡している ユーザー定義型はByValで渡せない 配列はByValで渡せない ByRefは参照渡し プロシージャの中で値を変更すると呼び出し元の変数 の中身がかわる 省略された場合はByRefになる パフォーマンスはByValより良いByValとByRefの違い
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByValProc(v) Debug.Print v
End Sub
Private Sub TestByValProc(ByVal v As Long) v = v + 1 End Sub
ByValの例
ByValを引数とするプロシージャを 実行しても呼び出し元は影響を受け ない この例ではvは1になる
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1
End Sub
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestByRefProc(v) Debug.Print v
End Sub
Private Sub TestByRefProc(ByRef v As Long) v = v + 1 End Sub
ByRefの例
ByRefを引数とするプロシージャを 実行すると呼び出し元は影響を受け てしまう この例ではvは2になる
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestNoByValByRefProc (v) Debug.Print v
End Sub
Private Sub TestNoByValByRefProc(v As Long) v = v + 1
End Sub
VBAはデフォルトは値渡しかと思った?
ざーんねん。
参照渡し
でした
Public Sub TestByValByRef() Dim v As Long
v = 1
Call TestNoByValByRefProc (v) Debug.Print v
End Sub
Private Sub TestNoByValByRefProc(v As Long) v = v + 1
End Sub
計測方法: a.Long型のByValの引数を持つ関数 b.Long型のByRefの引数を持つ関数 c.String型のByValの引数を持つ関数を1024文字の文字を指定 して実行 d.String型のByRefの引数を持つ関数を1024文字の文字を指定 して実行 ・上記関数をそれぞれ10万回実行した場合の時間を取得 ・これを10回計測する ・テスト用プロシージャは TestPerformValAndRefByVal vs ByRef
パフォーマンステスト
実験環境:
・実装メモリ(RAM) 4.00GB
・プロセッサ:
Intel® Core™ i5 CPU M450 @2.40GHz 2.40GHz ・OS:
Windows 7 Home Premium 64Bit オペレーティングシステム
・Microsoft Office Home and Business2010 バージョン 14.0.6129.5000 (32ビット)
ByVal vs ByRef
ByVal vs ByRef
パフォーマンステスト
Long型 String型(1024文字)
ByVal ByRef ByVal ByRef
1 0.015625 0.0078125 0.0859375 0.015625 2 0.015625 0.0078125 0.0859375 0.015625 3 0.0234375 0.0078125 0.0859375 0.015625 4 0.0234375 0.0078125 0.0859375 0.015625 5 0.0234375 0.0078125 0.0859375 0.015625 6 0.015625 0.0078125 0.0859375 0.015625 7 0.0234375 0.0078125 0.0859375 0.0234375 8 0.015625 0.0078125 0.0859375 0.015625 9 0.015625 0.0078125 0.09375 0.015625 10 0.015625 0.0078125 0.078125 0.015625 平均 0.01875 0.0078125 0.0859375 0.01640625 最大 0.0234375 0.0078125 0.09375 0.0234375 最小 0.015625 0.0078125 0.078125 0.015625 Long型 ByValは2.4倍 String型 ByValは5.2倍
・基本はByValを使う ・ユーザー定義型、オブジェクト、配列の場合は ByRefとする ・何千文字も格納されるような文字列な場合は ByRefにしておく ・速度をちょっとでもあげたい場合はByRef ・どっちにしろByVal,ByRefの省略は絶対しないどちらを使うべきか?
Optionalを使用することで引数を省略できる IsMissing関数は省略しているかどうか判定できる 呼び出し時に名前を指定してプロシージャを実行で きる省略可能な引数
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) End Sub
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) End Sub
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) End Sub
呼び出し例:
Call TestOptionalParam(1,,”TEST”)
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) End Sub
呼び出し例:
Call TestOptionalParam(1,p3:=”TEST”)
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) If IsMissing(p3) Then Debug.Print "p3は省略" End If End Sub
省略可能な引数の例
IsMissing関数で初期値のないバリア ント型の引数が省略されているかし らべることができる
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ ByVal p3 As Variant) End Sub
省略可能な引数の例
Optionalを指定した後の引数はかな らずOptionalを指定する必要がある この例ではエラーになる
呼び出し元ですきな数の引数を指定する C言語のprintf ParamArrayキーワードを使用する。 この配列はVariant型 この配列は最後の引数でのみ使用できる ByVal,ByRef,Optionと共には使用できない可変引数
実行例:
Call TestParamArray("ゆっくり", 100, 200, 300) Call TestParamArray("オプーナ", 100, 200)
Private Sub TestParamArray(ByVal name As String, _ ParamArray vals() As Variant)
Debug.Print name Dim i As Long
For i = LBound(vals) To UBound(vals) Debug.Print vals(i)
Next i End Sub
Private Sub TestParamArray(ByVal name As String, _ ParamArray vals() As Variant)
Debug.Print name Dim i As Long
For i = LBound(vals) To UBound(vals) Debug.Print vals(i)
Next i End Sub
実行例:
Call TestParamArray("ゆっくり", 100, 200, 300) Call TestParamArray("オプーナ", 100, 200)
実行例:
Call TestParamArray("ゆっくり", 100, 200, 300) Call TestParamArray("オプーナ", 100, 200)
Private Sub TestParamArray(ByVal name As String, _ ParamArray vals() As Variant)
Debug.Print name Dim i As Long
For i = LBound(vals) To UBound(vals) Debug.Print vals(i)
Next i End Sub
文字列でプロシージャ名を指定して実行できる
Applicationオブジェクトが提供している
Call Application.Run("TestOptionalParam", 1, 2) Dim cll As Collection
Set cll = Application.Run("TestFuncCollection")
Call Application.Run("TestOptionalParam", 1, 2) Dim cll As Collection
Set cll = Application.Run("TestFuncCollection")