プロシージャ
プロシージャの種類 Subプロシージャ Functionプロシージャ Propertyプロシージャ
Sub プロシージャ Subステートメント~ステートメントで囲まれる 実行はするけど 値は返さない 途中で抜けたいときは Exit Sub を行なう Public Sub はマクロの実行候補に表示される
Sub プロシージャの例 Public Sub TestSubProc() Call ShowElShadaiMsg(" まだ死ぬ定めではない ") Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox " 神はいっている " & msg & " と "
Sub プロシージャの例 Public Sub TestSubProc() Call ShowElShadaiMsg(" まだ死ぬ定めではない ") Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox " 神はいっている " & msg & " と " Sub の前に Public または Private を指定できる省略した場合は Public とされる
Sub プロシージャの例 Public Sub TestSubProc() Call ShowElShadaiMsg(" まだ死ぬ定めではない ") Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox " 神はいっている " & msg & " と " Sub の前に Public または Private を指定できる省略した場合は Public とされる
Subプロシージャの例 Option Private Public Sub TestSubProc() Call ShowElShadaiMsg(" まだ死ぬ定めではない ") モジュールの先頭に Option Private がある場合は 別のプロジェクトからは実行できなくなる
Sub プロシージャの例 Public Sub TestSubProc() Call ShowElShadaiMsg(" まだ死ぬ定めではない ") Private Sub ShowElShadaiMsg(ByVal msg As String) Msgbox " 神はいっている " & msg & " と "
Sub プロシージャの例 Private Sub ShowElShadaiMsg(ByVal msg As String) If msg = 神はしんだ Then Exit Sub End If Msgbox " 神はいっている " & msg & " と "
Function プロシージャ Functionステートメント~End Functionステートメントで囲まれる 値を返せる 途中で抜けたいときは Exit Function を行なう 標準モジュールで作成した Public Function は数式として使える
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と " Function の前に Public または Private を指定できる省略した場合は Public とされる
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と " Function の前に Public または Private を指定できる省略した場合は Public とされる
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Sub TestFuncProcCaller() Dim rng As Range Call Msgbox(TestFuncProc(Sheet1.Cells(2, 2)))
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function は数式として使える
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) _ As String TestFuncProc = " 神はいっている " _ End Function & rng.value & " と "
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 可変配列は返せる 以下のような記述はできない 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 End Function
'* コレクション Private Function TestFuncCollection() As Collection Set TestFuncCollection = New Collection Call TestFuncCollection.add(" アカギ ") Call TestFuncCollection.add(" カイジ ") End Function オブジェクトの呼び出し例 Dim cll as Collection Set cll = TestFuncCollection()
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) End Function 戻り値の型は省略できるその場合は Variant 型になる けどやるな
Function プロシージャの例 Public Function TestFuncProc(ByRef rng As Range) Exit Function Debug.print 以降は実行されない End Function Exit Function でプロシージャをぬけることができる
Property プロシージャ Public 変数の代わりに使用できる 途中で抜けたいときは Exit Property を行なう Get,Let,Set の 3 種類がある 4 変数のスコープと生存期間 で説明済み
Public Property Get Name() As String Name = "TEST" End Property Public Sub TestProperty() Dim ret As String ret = mdlsample.name Property Get の例
Public Property Get Name() As String Name = "TEST" End Property Public Sub TestProperty() Dim ret As String ret = mdlsample.name Property Get の例
Public Property Get Name() As String Name = "TEST" End Property Public Sub TestProperty() Dim ret As String ret = mdlsample.name Property Get の例
Public Property Get Name() As String Name = "TEST" End Property Public Sub TestProperty() Dim ret As String ret = mdlsample.name Property Get の例
Public Property Get Name() As String Name = "TEST" End Property Public Sub TestProperty() Dim ret As String ret = mdlsample.name Property Get の例
Public Property Let Name(ByVal v As String) Debug.Print "Property Let" End Property Property Let の例 Public Sub TestProperty() mdlsample.name = " ゆっくり
Public Property Let Name(ByVal v As String) Debug.Print "Property Let" End Property Property Let の例 Public Sub TestProperty() mdlsample.name = " ゆっくり
Public Property Let Name(ByVal v As String) Debug.Print "Property Let" End Property Property Let の例 Public Sub TestProperty() mdlsample.name = " ゆっくり
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.address End Property Property Set の例 Public Sub TestProperty() Set mdlsample.myrange = Sheet1.Cells(2, 2)
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.address End Property Property Set の例 Public Sub TestProperty() Set mdlsample.myrange = Sheet1.Cells(2, 2)
Public Property Set MyRange(ByRef rng As Range) Debug.Print "MyRange Set:" & rng.address End Property Property Set の例 Public Sub TestProperty() Set mdlsample.myrange = Sheet1.Cells(2, 2)
複数の引数を持つプロパティ 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)
複数の引数を持つプロパティ Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _ End Property " " & y & " " & msg
複数の引数を持つプロパティ Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _ End Property " " & y & " " & msg Public Sub TestProperty() mdlsample.propargs(1, 2) = " ゆっくり "
複数の引数を持つプロパティ Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _ End Property " " & y & " " & msg Public Sub TestProperty() mdlsample.propargs(1, 2) = " ゆっくり "
複数の引数を持つプロパティ Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _ End Property " " & y & " " & msg Public Sub TestProperty() mdlsample.propargs(1, 2) = " ゆっくり "
複数の引数を持つプロパティ Public Property Let PropArgs(ByVal x As Long, _ ByVal y As Long, ByVal msg As String) Debug.Print "PropArgs Let" & x & _ End Property " " & y & " " & msg Public Sub TestProperty() mdlsample.propargs(1, 2) = " ゆっくり "
ByValとByRef 省略可能な引数 可変引数 引数の渡し方
ByValとByRefの違い ByVal は値渡し 引数をコピーして渡している ユーザー定義型は ByVal で渡せない 配列は ByVal で渡せない ByRef は参照渡し プロシージャの中で値を変更すると呼び出し元の変数の中身がかわる 省略された場合は ByRef になる パフォーマンスは ByVal より良い
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v Private Sub TestByValProc(ByVal v As Long) v = v + 1 ByVal の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v Private Sub TestByValProc(ByVal v As Long) v = v + 1 ByVal の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v Private Sub TestByValProc(ByVal v As Long) v = v + 1 ByVal の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v Private Sub TestByValProc(ByVal v As Long) v = v + 1 ByVal の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v Private Sub TestByValProc(ByVal v As Long) v = v + 1 ByVal の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByValProc(v) Debug.Print v ByVal の例 Private Sub TestByValProc(ByVal v As Long) v ByVal = v + を引数とするプロシージャを 1 End 実行しても呼び出し元は影響を受け Sub ないこの例ではvは1になる
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v Private Sub TestByRefProc(ByRef v As Long) v = v + 1 ByRef の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v Private Sub TestByRefProc(ByRef v As Long) v = v + 1 ByRef の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v Private Sub TestByRefProc(ByRef v As Long) v = v + 1 ByRef の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v Private Sub TestByRefProc(ByRef v As Long) v = v + 1 ByRef の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v Private Sub TestByRefProc(ByRef v As Long) v = v + 1 ByRef の例
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestByRefProc(v) Debug.Print v ByRef の例 Private Sub TestByRefProc(ByRef v As Long) v ByRef = v + を引数とするプロシージャを 1 End 実行すると呼び出し元は影響を受け Sub てしまうこの例ではvは2になる
省略したらどうなる? Public Sub TestByValByRef() Dim v As Long v = 1 Call TestNoByValByRefProc (v) Debug.Print v Private Sub TestNoByValByRefProc(v As Long) v = v + 1
VBA はデフォルトは値渡しかと思った? ざーんねん 参照渡しでした
Public Sub TestByValByRef() Dim v As Long v = 1 Call TestNoByValByRefProc (v) Debug.Print v Private Sub TestNoByValByRefProc(v As Long) v = v + 1 省略したら参照渡し
パフォーマンステスト 計測方法 : a.long 型の ByVal の引数を持つ関数 b.long 型の ByRef の引数を持つ関数 c.string 型の ByVal の引数を持つ関数を 1024 文字の文字を指定して実行 d.string 型の ByRef の引数を持つ関数を 1024 文字の文字を指定して実行 上記関数をそれぞれ 10 万回実行した場合の時間を取得 これを 10 回計測する ByVal vs ByRef テスト用プロシージャは TestPerformValAndRef
パフォーマンステスト 実験環境 : 実装メモリ (RAM) 4.00GB ByVal vs ByRef プロセッサ : 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 パフォーマンステスト 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)
省略可能な引数の例 Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant)
省略可能な引数の例 Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) 呼び出し例 : Call TestOptionalParam(1,, TEST )
省略可能な引数の例 Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ Optional ByVal p3 As Variant) 呼び出し例 : Call TestOptionalParam(1,p3:= TEST )
Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ If IsMissing(p3) Then Debug.Print "p3 は省略 " End If 省略可能な引数の例 Optional ByVal p3 As Variant) IsMissing 関数で初期値のないバリアント型の引数が省略されているかしらべることができる
省略可能な引数の例 Private Sub TestOptionalParam(ByVal p1 As Long, _ Optional ByVal p2 As Long = 5, _ ByVal p3 As Variant) 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 可変引数の例
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 可変引数の例
実行例 : 可変引数の例 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 可変引数の例
Application.Run 文字列でプロシージャ名を指定して実行できる Application オブジェクトが提供している
Call Application.Run("TestOptionalParam", 1, 2) Dim cll As Collection Run メソッド Set cll = Application.Run("TestFuncCollection")
Call Application.Run("TestOptionalParam", 1, 2) Dim cll As Collection Run メソッド Set cll = Application.Run("TestFuncCollection")
今日勉強したこと Subプロシージャ Functionプロシージャ Propertyプロシージャ 引数の指定方法 ByVal,ByRef 省略可能な引数 可変引数
プロシージャ