$が付くVBA関数
VBA関数の中にはLeft$関数のように$が付くものがあります。
先に答えを書いてしまいますが、$がない関数を使ってください。
$ありを使うとNull判定処理が必要になるのが主な理由です。$ありの関数は「文字列を返す」という意味です。これは過去のBASIC時代の考え方でマークに意味を持たせていたことに由来します。$は文字列、%は整数、&は長整数などです。このマークの考え方がVBAにも残っていることが$ありの関数に繋がっています。
VBAでは変数にマークを付けることが出来ます。
String型には$、Integer型に%、Long型に&、Single型に!、Double型に#、Currency型に@を付けて、「Dim str$」とか「Dim cnt&」などと記述する「型宣言文字」があり、マークから型を推論できるようになっています。
型宣言でAs Stringなどと書かなくても$を付けるとString型と認識されます。実際に各マークを付けたVBAのコードもちゃんと動作します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Sub valueMarkTest() Dim s$ Dim i% Dim lng& Dim sng! Dim dbl# Dim dec@ s$ = "abc" i% = 3 lng& = 111111111 sng! = 0.1 dbl# = 1E-24 dec@ = 123.456 Debug.Print "s$:" & s$ Debug.Print "i%:" & i% Debug.Print "lng&:" & lng& Debug.Print "sng!:" & sng! Debug.Print "dbl#:" & dbl# Debug.Print "dec@:" & dec@ End Sub |
実行結果
1 2 3 4 5 6 |
s$:abc i%:3 lng&:111111111 sng!:0.1 dbl#:1E-24 dec@:123.456 |
しかし今ではこんな書き方をすることはまず無いでしょう。
私は見たことありません。
ここで書いたのが初めてです。
$がある関数とない関数の違い
$がある関数とない関数の違いは定義を見ると分かります。
文字列操作系の$が付く関数を定義も含めて挙げてみます。
17個あります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Function Chr$(CharCode As Long) As String Function ChrB$(CharCode As Byte) As String Function ChrW$(CharCode As Long) As String Function Format$(Expression, [Format], [FirstDayOfWeek As VbDayOfWeek = vbSunday], [FirstWeekOfYear As VbFirstWeekOfYear = vbFirstJan1]) As String Function LCase$(String As String) As String Function Left$(String As String, Length As Long) As String Function LeftB$(String As String, Length As Long) As String Function LTrim$(String As String) As String Function Mid$(String As String, Start As Long, [Length]) As String Function MidB$(String As String, Start As Long, [Length]) As String Function Right$(String As String, Length As Long) As String Function RightB$(String As String, Length As Long) As String Function RTrim$(String As String) As String Function Space$(Number As Long) As String Function String$(Number As Long, Character) As String Function Trim$(String As String) As String Function UCase$(String As String) As String |
$がついていない関数は以下になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Function Chr(CharCode As Long) Function ChrB(CharCode As Byte) Function ChrW(CharCode As Long) Function Format(Expression, [Format], [FirstDayOfWeek As VbDayOfWeek = vbSunday], [FirstWeekOfYear As VbFirstWeekOfYear = vbFirstJan1]) Function LCase(String) Function Left(String, Length As Long) Function LeftB(String, Length As Long) Function LTrim(String) Function Mid(String, Start As Long, [Length]) Function MidB(String, Start As Long, [Length]) Function Right(String, Length As Long) Function RightB(String, Length As Long) Function RTrim(String) Function Space(Number As Long) Function String(Number As Long, Character) Function Trim(String) Function UCase(String) |
$がついていない関数は戻り値が定義されていません。これは書き忘れではなく未定義になります。未定義ということはVariant型を返すということです。
つまり、$が付く関数はString型で返し、$が付かない関数はVariant型で返すという違いになります。また、$が付く関数は引数にNullを渡すと「実行時エラー94(Nullの使い方が不正です。)」が発生しますが、$が付かない関数はエラーになりません。
その他、$が付く関数やプロパティ
他にも以下の関数やプロパティがあります。考え方は上と同様です。
1 2 3 4 5 6 7 8 9 |
Function Command$() As String Function CurDir$([Drive]) As String Property Date$ As String Function Environ$(Expression) As String Function Error$([ErrorNumber]) As String Function Hex$(Number) As String Function Oct$(Number) As String Function Str$(Number) As String Property Time$ As String |
$ありと$なしの処理速度の違い
$あり関数と$なし関数では処理速度がどれぐらいあるのかを調べてみると、多少、$あり関数の方が速いようです。
以下のコードを$ありとなしでそれぞれ10回ずつ実行したのですが、$ありの平均が約58ミリ秒、$なしの平均が約70ミリ秒でした。ループ回数を30000000回でやっても$ありが約1.6秒、$なしが約2.1秒と同様の傾向で、$あり関数の方が速いようです。
ただ、何千万回という相当数のループ回数を回しても体感上の差が出ないため、業務で使うようなVBAの場合はほとんど差はありません。メモリ効率はいいかもしれませんが、最近のPCではまず関係ありません。
$あり関数はNull判定の考慮が必要になることを考えると、PCの性能が上がっている現状ではこれからも$あり関数を使う必要性がまずないと思われます。
なお、以下の処理の計測には「VBAでミリ秒やマイクロ秒の計測を行う」で紹介しているミリ秒計測の関数を使っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
Sub dollarTest() Dim milliStart As Double Dim milliEnd As Double Dim milliDiff As Double Dim i As Long Dim a As String Dim frequency As LARGE_INTEGER Dim s As String s = "123456789012345678901234567890123456789012345678901234567890" '// 更新頻度を取得 Call QueryPerformanceFrequency(frequency) '// 処理前の時間を取得 milliStart = GetMilliSecondEx(frequency) '// 計測対象の処理 For i = 0 To 1000000 a = Left$(s, 20) 'a = Left(s, 20) Next '// 処理後の時間を取得 milliEnd = GetMilliSecondEx(frequency) '// 処理前後の差を取得 milliDiff = milliEnd - milliStart Debug.Print milliDiff & "ミリ秒(Left" End Sub |