VBA 入門

# VBA とは何ぞや?

Microsoft Office 製品に搭載されているプログラム言語。
正式名称を Visual Basic for Applications と言い、 VBA はその略語である。
Excel の自動操作や Access によるデータベースアプリケーションの開発に使用されることが多い。
なお、初めに断っておくが、 **VB(Visual Basic) や VBS(VB Script) とは全くの別物** である。
書店で参考書を探す時に間違うことの無いよう、注意されたい。

# 歴史

1993 年、 MS Excel 5.0 に搭載されたのを始まりとする。
それ以前まで使用されていた Excel 4.0 マクロに代わる後継機能として VBA が搭載された。

正式名称である Visual Basic for Applications という名前が示す通り、
その祖先はアメリカのダートマス大学で作られた教育用言語 BASIC である。
Microsoft が BASIC を基に Visual Basic を作り、
その後 Office 製品にも Visual Basic が組み込まれることになった。
こうして誕生したのが Visual Basic for Applications である。
以後、 2023 年現在に至るまで 30 年間利用され続けている。

なお、 VBA の言語仕様は VB 6.0 のまま変更がなく、 Excel や Access の機能追加に合わせたコマンドの追加だけが継続されている。
しつこいようだが、 **現代における VB 16.9 と VBA は全くの別物** である。

## 参考資料

* [Wikipedia](https://ja.wikipedia.org/wiki/Visual_Basic_for_Applications#VBA%E3%81%AE%E6%AD%B4%E5%8F%B2)
* [窓の社](https://forest.watch.impress.co.jp/docs/serial/yajiuma/1357642.html)
* [t-hom’s diary](https://thom.hateblo.jp/entry/2016/10/03/161659)

# 開発環境の有効化

ここでは Windows 版 Excel 2016 における VBA 開発環境の有効化について記述する。
Office アプリケーションの種類やバージョン、プラットフォームとする OS の種類によっては、ここに掲載する画像とは一致しない可能性があることを初めに断っておく。

## 開発タブの有効化

Excel を起動し、「ファイル」タブを押下する。
![スクリーンショット 2023-05-06 173453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/af3f3523-c938-937a-5bd1-d999bda232c7.png)

「その他」 > 「オプション」の順に押下する。
![スクリーンショット 2023-05-06 174024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/f05b8225-e82f-ce21-8496-d970e967f667.png)

「リボンのユーザー設定」を押下し、「開発」にチェックを入れて「OK」を押下する。
![スクリーンショット 2023-05-06 174345.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/b2c0a47a-971f-f2ec-e76d-2e73fc5bdb4a.png)

リボンに追加された「開発」タブを開き、「Visual Basic」を押下する。
![スクリーンショット 2023-05-06 175012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/0e4c1b59-1f2e-7870-d772-e2ec61929706.png)

エディターが表示される。
![スクリーンショット 2023-05-06 175249.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/1495329e-f2b1-8869-6e8e-125b3113610f.png)

## セキュリティの設定変更

Excel を起動し、「ファイル」タブを押下する。
![スクリーンショット 2023-05-06 173453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/af3f3523-c938-937a-5bd1-d999bda232c7.png)

「トラストセンター」 > 「トラストセンターの設定」の順に押下する。
![スクリーンショット 2023-05-06 175811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/d1094a15-b2ad-f7ad-646c-5d92ef233bdd.png)

「マクロの設定」を押下し、「警告して、 VBA マクロを無効にする」にチェックを入れて「OK」を押下する。
なお、「警告せずに VBA マクロを無効にする」にチェックが入っていると問答無用で VBA が無効化されてしまい、せっかく書いた VBA プログラムが一切実行できなくなるので注意すること。
![スクリーンショット 2023-05-06 180047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98355/fd939b2d-6234-331f-59b9-11d136f833ff.png)

# 文法編

ここでは最低限知っておきたい言語仕様に絞って記述する。
詳しく勉強したい人は別途書籍を読むか
[Visual Basic 言語リファレンス](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/visual-basic-language-reference) を参照していただきたい。

## データ型

「データ型」とはデータの種類を表す型のことを言う。
VBA は静的型付け言語に分類される言語である為、
後述する [変数](#変数) を宣言する時や[プロシージャ](#プロシージャ) の引数や返り値を定義する時に、
データ型を宣言する必要がある。以下に代表的なデータ型を列記する。

詳細は [データ型の概要](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/data-type-summary) を参照。

### String

文字列を表すデータ型。

```vb
Dim str As String
str = "あいうえお"
```

### Integer

整数を表すデータ型。

```vb
Dim num As Integer
num = 1
```

### Single

小数を表すデータ型。

```vb
Dim num As Single
num = 3.1
```

### Boolean

真偽値(True / False)を表すデータ型

```vb
Dim bool As Boolean
bool = False
```

## 変数

「変数」とは何か値を格納しておく為の箱のようなものである。
数値や文字列などのデータに名前を付けることによって、
繰り返し利用できるようになる。

```vb:変数の定義と利用の方法
'「Dim 変数名 As データ型」の形式で変数を宣言する。
Dim int1 As Integer
Dim int2 As Integer
Dim result As Integer

'格納できる値は一つの変数につき一つだけ。
'後から上書きすることができる。
'宣言したデータ型と異なるデータを格納しようとするとエラーが発生する。
int1 = 4
int2 = 2

'例1) 足し算
result = int1 + int2 '4 + 2 が実行され、結果が変数 result へ格納される。
Debug.Print result 'コンソールへ 6 が出力される。

'例2) 掛け算
result = int1 * int2 '4 x 2 が実行され、結果が変数 result へ上書きされる。
Debug.Print result 'コンソールへ 8 が出力される。
```

詳細は [変数を宣言する](https://learn.microsoft.com/ja-jp/office/vba/language/concepts/getting-started/declaring-variables) を参照。

## 定数

何らかの理由により値を変更してほしくないデータが存在する場合に使用する。
[変数](#変数) は後から値を上書きすることができるが、
[定数](#定数) は後から値を上書きすることができない。

詳細は [定数の宣言](https://learn.microsoft.com/ja-jp/office/vba/language/concepts/getting-started/declaring-constants) を参照。

```vb:定数の定義と利用の方法
'「Const 定数名 As データ型 = 値」の形式で定数を宣言する。
Const str As String = "メッセージ"
Debug.Print str
```

## プロシージャ

「プロシージャ(procedure)」とは「手順」あるいは「手続き」を意味する単語である。
VBA は一行につき一つの処理を実行するが、複数の処理を一つにまとめておきたい時にプロシージャを使用する。

プロシージャには **値を返すことができない Sub プロシージャ** と
**値を返すことのできる Function プロシージャ** が存在する。

### Sub プロシージャ

複数の処理を一つにまとめておきたい時に使用する。
一度定義した Sub プロシージャは他のプロシージャから呼び出すことができるが、
値を返すことができない。

```vb
'引数 arg1 の値と引数 arg2 の値を足し算し、結果をコンソールへ出力する。
Public Sub printAddition(arg1 As Integer, arg2 As Integer)
    Dim result As Integer
    result = arg1 + arg2
    Debug.Print result
End Sub

'引数 arg1 の値と引数 arg2 の値を掛け算し、結果をコンソールへ出力する。
Public Sub printMultiplication(arg1 As Integer, arg2 As Integer)
    Dim result As Integer
    result = arg1 * arg2
    Debug.Print result
End Sub

'プロシージャ printAddition を実行した後、
'プロシージャ printMultiplication を実行する。
Public Sub main()
    Dim int1 As Integer
    Dim int2 As Integer
    
    int1 = 4
    int2 = 2
    
    Call printAddition(int1, int2) '足し算の結果 6 がコンソールへ出力される。
    Call printMultiplication(int1, int2) '掛け算の結果 8 がコンソールへ出力される。
End Sub
```

詳細は [Sub ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/sub-statement) を参照。

### Function

複数の処理を一つにまとめておきたい時に使用する。
一度定義した Function プロシージャは他のプロシージャから呼び出すことができ、
処理の結果として値を返すことができる。

```vb
'引数 arg1 の値と引数 arg2 の値を足し算し、
'結果を格納した変数 result を返り値として返す。
Public Function getAddition(arg1 As Integer, arg2 As Integer) As Integer
    Dim result As Integer
    result = arg1 + arg2
    getAddition = result
End Function

'引数 arg1 の値と引数 arg2 の値を掛け算し、結果を格納した変数 result を返り値として返す。
Public Function getMultiplication(arg1 As Integer, arg2 As Integer) As Integer
    Dim result As Integer
    result = arg1 * arg2
    getMultiplication = result
End Function

'プロシージャ getAddition から取得した足し算の結果をコンソールへ出力した後、
'プロシージャ getMultiplication から取得した掛け算の結果をコンソールへ出力する。
Public Sub main()
    Dim int1 As Integer
    Dim int2 As Integer
    Dim result As Integer
    
    int1 = 4
    int2 = 2
    
    '足し算
    result = getAddition(int1, int2)
    Debug.Print result
    
    '掛け算
    result = getMultiplication(int1, int2)
    Debug.Print result
End Sub
```

詳細は [Function ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/function-statement) を参照。

## 配列
同じ型の複数のデータを一つのかたまりとして扱いたい場合に使用する。
通常の [変数](#変数) では一つの変数につき一つのデータしか格納できないが、
[配列](#配列) を使用すると一つの変数の中に同じ型のデータを複数格納することができる。

```vb
'「Dim 変数名(最大数) As データ型」の形式で変数を宣言する。
'宣言した配列へ値を格納する時は「変数名(序数) = 値」の形式で記述する。
'ややこしい話だが、配列の 1 番目の序数は「0」から始まる。
'したがって下記に例示する 3 つの値を格納する配列を宣言する場合の最大数は「2」となる。
Dim strArray(2) As String
strArray(0) = "一つ目"
strArray(1) = "二つ目"
strArray(2) = "三つ目"

'配列に格納されている値を参照する時も同様に「変数名(序数)」の形式で記述する。
'なお、最大数を超えた序数を指定して値を格納したり参照するとエラーが発生する。
Debug.Print strArray(0) 'コンソールへ「一つ目」の文字列が出力される。
Debug.Print strArray(1) 'コンソールへ「二つ目」の文字列が出力される。
Debug.Print strArray(2) 'コンソールへ「三つ目」の文字列が出力される。
```

詳細は [配列の使用](https://learn.microsoft.com/ja-jp/office/vba/language/concepts/getting-started/using-arrays) を参照。

## 論理構造
### For 文

繰り返し同じ処理をループ実行させたい場合に使用する。
[配列](#配列) と併用することが多い。

```vb
Dim strArray(2) As String
Dim i As Integer

strArray(0) = "一つ目"
strArray(1) = "二つ目"
strArray(2) = "三つ目"

'ループ処理は以下の形式で記述する。
'For カウンター変数 = 最小数 To 最大数 Step 増分値
'   繰り返し実行する処理
'Next カウンター変数
For i = 0 To 2 Step 1
    'カウンター変数 i の値は処理が一回終わる毎に +1 される。
    Debug.Print strArray(i)
Next i
```

詳細は [For...Next ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/fornext-statement) を参照。

### If 文

条件に応じて処理を分岐させたい時に使用する。

```vb
'引数 arg1 の値と引数 arg2 の値を足し算し、
'結果を格納した変数 result を返り値として返す。
Public Function getAddition(arg1 As Integer, arg2 As Integer) As Integer
    Dim result As Integer
    result = arg1 + arg2
    getAddition = result
End Function

'引数 arg1 の値と引数 arg2 の値を掛け算し、結果を格納した変数 result を返り値として返す。
Public Function getMultiplication(arg1 As Integer, arg2 As Integer) As Integer
    Dim result As Integer
    result = arg1 * arg2
    getMultiplication = result
End Function

'プロシージャ getAddition から取得した足し算の結果、
'またはプロシージャ getMultiplication から取得した掛け算の結果をコンソールへ出力する。
'引数 mode へ "add" を指定した場合は足し算の結果を、
'"multi" を指定した場合は掛け算の結果をコンソールへ出力する。
'上記以外の値を指定した場合はエラーとみなし、メッセージを出力して終了する。
Public Sub main(mode As String)
    Dim int1 As Integer
    Dim int2 As Integer
    Dim result As Integer
    
    int1 = 4
    int2 = 2
    
    '条件分岐は以下の形式で記述する。
    'If 条件式1 Then
    '    条件式1が成立した場合に実行する処理
    'Else 条件式2 Then
    '    条件式1が成立せず、条件式2が成立した場合に実行する処理
    'Else
    '    いずれの条件式も成立しない場合に実行する処理
    'End If
    If mode = "add" Then
        '足し算の結果を取得する。
        result = getAddition(int1, int2)
    ElseIf mode = "multi" Then
        '掛け算の結果を取得する。
        result = getMultiplication(int1, int2)
    Else
        Debug.Print "引数 mode の値が不正です。"
        Exit Sub
    End If
    
    Debug.Print result
End Sub
```

詳細は [If...Then...Else ステートメント](https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/ifthenelse-statement) を参照。