VBAの特徴

VBAはC言語などとは異なる点があります。

引数がデフォルトで参照渡し

VBAで関数に引数を渡す場合、デフォルトでは参照渡しになってしまいます。つまり呼び出された関数で呼び出した側の関数の変数を変更できてしまうという問題があります。

例えば、次のプログラムを実行した場合、表示されるのはbbbになります。

Sub uMain()
    Dim a As String
 
    a = "aaa"
    uSub a
    MsgBox a
End Sub

Sub uSub(a As String)
    a = "bbb"
End Sub

そのため、SubやFunctionで引数を定義する場合、意図的に参照渡しをしないのであれば、引数定義の際にByValをつけることが必須です。原則、引数定義にはByValをつけると思っていたほうが良いでしょう。

次の定義でaaaが表示されるようになります。

Sub uSub(ByVal a As String)
    a = "bbb"
End Sub


デフォルトプロパティの使用

オブジェクトにはデフォルトプロパティをもつものがあり、オブジェクを参照した場合、そのデフォルトプロパティへの参照に置き換えられる場合があります。

例えば、RangeオブジェクトにはValueというプロパティがあり、これがデフォルトプロパティになっています。これを使うと次のようにValueプロパティの記述を省略することが可能です。

Sub uMain()
    ActiveWorkbook.ActiveSheet.Range("A1") = "aaa"
End Sub

これだけだと省略してもしなくてもと感じるかもしれませんが、セルからセルへの代入となるとこれが2倍になります。

また、ListObjectのItemプロパティの場合には効果が大きいです。受け取ったテーブルの金額列の1行目の値を表示するコードを基本通りに書くとこうなります。

Sub uSub(ByVal uList As ListObject)
    MsgBox uList.ListColumns.Item("金額").DataBodyRange.Item(1).Value()
End Sub

デフォルトプロパティを使って指定すると次のように簡潔になります。

Sub uSub(ByVal uList As ListObject)
    MsgBox uList.ListColumns("金額").DataBodyRange(1)
End Sub

ListColumnsもDataBodyRangeもItemがデフォルトプロパティなので、その指定を省略できるということです。上ではValueプロパティも省略しています。


オブジェクトとそれ以外の変数で代入の仕方が異なる

VBAでは、オブジェクトのアドレスを代入する場合とそれ以外を代入する場合で代入の仕方が異なります。

次は、RangeプロパティをString型のuString変数に代入する場合と、Rangeオブジェクト型のuCell 変数に対する代入する場合の違いです。

Sub uSub()
    Dim uString As String
    Dim uCell As Range

    uString = Range("A1")
    Set uCell = Range("A1")

    uCell.Interior.Color = vbRed
End Sub

uStringに対しては、Rangeプロパティの値が代入されています。

それに対してSetステートメントを使ったuCellに対してはRangeプロパティのアドレスが代入されています。

その結果、次の行で、uCellの色を変更することが出来ています。Setステートメントを使うことによりアドレスを代入するか、値を代入するかが違ってくるのでこの使い分けはとても注意する必要があります。


戻り値を得るかどうかで関数の呼び方が異なる

VBAは戻り値を得る場合には引数にカッコを付けて呼び出します。しかし、戻り値を得ない場合にはカッコを付けてはいけません。

次のuAddファンクションの呼び出し方はいずれもエラーで、「コンパイルエラー、修正候補:ステートメントの最後」、が表示されます。

Sub uMain()
    Dim a As Long
    Dim b As Long
    Dim c As Long

    c = uAdd a, b
    uadd(a,b)
End Sub

Function uAdd(ByVal uA As Long, ByVal uB As Long) As Long
    uAdd = a + b
End Function

VBAを使い始めた頃に結構ハマるところなので注意が必要です。


SubとFunction

VBAでは、戻り値を返さない関数はSubプロシージャー、返す関数にはFunctionを使います。

このあたりはPascal言語も同様だったと記憶しています。


バリアント型

VBAにはVariant型という何でもかんでも代入できて便利ではあるけれど問題もある変数型があります。

変数に対して型指定をしないと、このバリアント型になってしまいます。

バリアント型は問題を引き起こしやすいしインテリセンスが効かず開発効率も損ねるので型指定をすることを強くおすすめします。

これはOption Explicitのところで説明します。


With ステートメント

オブジェクトを指定することで、withからend withまでの間は、指定したオブジェクトから相対的にプロパティやメソッドを指定できるステートメントです。

以下の例では、uCellを指定して、そのプロパティを設定しています。

Sub uSub()
    Dim uCell As Range
 
    Set uCell = Range("A1")
 
    With uCell
        .Interior.Color = vbRed
        .Formula = "=B1*2"
        .Font.Italic = True
        .Font.Bold = True
    End With
End Sub

withがわかりにくいから使用禁止という人もいるようですが、それは相対パスがわかりにくいから使用禁止というようなものです。

慣れの問題で、慣れれば簡潔にコードを書くことが出来ます。簡潔に書けるということは、それだけタイプミスなどの問題も回避できるということです。

コメント

アクセス数の多い投稿

セキュリティ対策ソフトのノートンが詐欺ソフトまがいになってしまってショック

ZIPファイルを開こうとすると、展開を完了できません、と言われる

Excel 2019 クエリが原因で日本語入力の一文字目が勝手に確定する

オカムラ家具のOAチェアー、コンテッサを分解清掃

Excelのテーブルに行や列を挿入する際のエラー

突然滅茶苦茶遅くなったPCがWindows Updateのキャッシュクリアで復活

ChatGPTが日本語からVBAのコードを生成できてたまげる

Windows セキュリティーのビックリマークが消えない

Power Automate Desktopでブラウザでダウンロードしたファイルを処理する

Excel VBAからODBCを使ってデータを簡単に取得する