連絡先 Hikwareホーム
Hikware.Tech
自分用の覚え書きをそのまま公開。参考程度にどうぞ。

VBAできもちわるかったことまとめ

公開日 2024/02/25
最終更新 2024/02/25
  • 覚えておくため書き留めてみたはいいけど、よく考えたらこれただの愚痴だなと気付いてしまった小ネタの墓場。
  • 読んで役に立つことはほぼ書かれてません。

オブジェクト型に代入する場合のみ Set が必要

 VBA も他の多くの言語同様、変数の型は「値型」と「オブジェクト型」(内部的にはポインタ)に大別できるが、なぜかオブジェクト型の変数に値を代入する場合のみ Set が必要で、書き忘れるとエラー。逆にオブジェクト型以外の代入で Set と書くのもエラー。

Dim intVar As Integer  '整数などは値型
Dim strVar As String   'VBA では文字列も値型
Dim objVar As Range    'Range などメソッドやプロパティがあるのはオブジェクト型

'オブジェクト型に代入する際にのみ Set が必要
'Set を忘れるとエラーなので、そのまま動いて誤動作したりする訳ではない
Set objVar = Range("A1")

'オブジェクト型以外に代入するときは Set をつけるとエラー
'文字列や配列はオブジェクト型でなく値型なので注意
intVar = 1
strVar = "こんにちは"

 初心者には何がオブジェクト型かなんて判別つかないだろうし、他のプログラム言語に慣れてる身からしても代入方法を分ける必要性がイマイチ想像つかなくて困惑。

変数の初期値

 VBA では今のところ、Dim での変数宣言の際に任意の初期値を入れる事ができない ようなので、デフォルト以外の初期値を入れたい場合は変数宣言のあとに別途代入しないといけない。コロン : で1行に複数の文は書けるけどスマートではないなぁと。

'VBA では変数宣言と同時に任意の初期値を入れられないので2行になる
Dim price As Long
price = 100

': で1行にはまとめられるけど、変数名を2度書くのは面倒
Dim price As Integer: price = 100

 VBA ではプロシージャレベルの変数はプロシージャ開始時に所定の初期値( 0 など)で初期化されるので、その値でよければ値の初期化は不要。オブジェクト型の初期値は Nothing だが、新規オブジェクトを生成したい場合に限り、下記のように記述できる。

'新規オブジェクトを生成して代入する場合に限り、1行で記述可
Dim myList As New Collection

'他のオブジェクトを代入するならこう。1行目の時点では Nothing
Dim myList As Collection
Set myList = otherList

行の途中改行はアンダーバー

 VB は文末を示す記号がないので行末が文末となる。1行が長くなり過ぎて改行したい場合、単に改行すると文法エラーになるので、末尾にアンダーバー _ をつけて途中改行と明示する。ちょっとめんどい。

サブプロシージャを呼ぶ Call は省略できるけどなんかキモイ

 サブプロシージャを呼ぶ際、正式には Call を使って呼ぶものらしいけど省略可能。ただし引数がある場合のルールが何だかよく分からない事になってる。常にカッコありでいいだろうに、なぜカッコなしの記法なんて作ってしまったのか。昔の BASIC がそうなんだっけ?

  • Call を省略する場合、引数はカッコで囲まずに書く。囲むとエラー。
  • Call を省略しない場合、引数はカッコで囲んで書く。囲まないとエラー。
'下記のようなサブプロシージャや関数があるとして
Sub SubProc()
Sub SubProcArgs(arg1,arg2)
Function SubFunc()
Function SubFuncArgs(arg1,arg2)

'Call を省略する場合、引数はカッコで囲まずに書く
SubProc                 'OK
SubProc()               'NG カッコをつけるとエラー
SubProcArgs 1, 1        'OK
SubProcArgs(1, 1)       'NG カッコで囲むとエラー

'Call を省略しない場合、引数はカッコで囲んで書く
Call SubProc            'OK 引数なしならカッコなしも可
Call SubProc()          'OK むしろカッコつけると勝手に省かれる
Call SubProcArgs 1, 1   'NG カッコで囲まないとエラー
Call SubProcArgs(1, 1)  'OK

'Function を Call で呼んでもいいが、戻り値はどう書いても取れない
Call SubFunc            'OK
ret = Call SubFunc      'NG そんな記法はない
Call ret = SubFunc      'NG そんな記法はない

'Function も戻り値を取らない場合は Sub と同じルールになる
SubFuncArgs 1, 1        'OK
SubFuncArgs(1, 1)       'NG Callなしはカッコで囲むとエラー
Call SubFuncArgs(1, 1)  'OK
Call SubFuncArgs 1, 1   'NG Callありはカッコで囲まないとエラー

'Function の戻り値を取る場合は引数はカッコで囲まないとエラー
'というか最も関数らしいごく自然な記法
ret = SubFunc()         'OK
ret = SubFuncArgs(1, 1) 'OK
ret = SubFunc           'OK 引数なしならカッコなしでも可
ret = SubFuncArgs 1, 1  'NG この場合はカッコで囲まないとエラー

関数の戻り値がなんかキモイ

 VBA の関数は以下のように書くのだけど、戻り値は関数名に値を代入 ってのが面倒だしきもちわるい。何度代入してもいいし、一度も代入しなければ戻り値の型の初期値(Integer なら 0 など)が返る。

 戻り値の型を書かなかった場合も、省略されたのは戻り値の型だけなので、戻り値なしという訳ではない。戻り値を代入すれば Variant 型で返る。

Function 関数名(引数リスト) As 戻り値の型

    '戻り値は関数名に値を代入する。きもちわるい。
    'return と違ってこの時点で関数が終了する訳ではない
    関数名 = 戻り値
    '関数の途中で終了するならこのように
    Exit Function

    '最後まで戻り値に値を代入しなかった場合、戻り値はデフォルトの初期値
End Function