VBAの文法まとめ

#はじめに
業務でたまにVBAを書くのですが、
文法の細かい部分を忘れていることが多いので、簡単にまとめてみました。

#モジュール
VBAにはモジュールという概念があり、5種類のモジュールが用意されています。

・シートモジュール
・ブックモジュール
・フォームモジュール
・標準モジュール
・クラスモジュール

各モジュールについては[こちら](https://ateitexe.com/excel-vba-module/)が理解しやすかったです。
当記事では標準モジュールとクラスモジュールについて記載します。

##標準モジュール
マクロで実行させたい処理をメインで記載する場所になります。
ユーザーは標準モジュール内に記載されたSubプロシージャを指定して実行することが出来ます。

###定義方法
```vb
Sub hoge()
    ' 処理
End Sub
```

##クラスモジュール
処理で使用するオブジェクトを自由に定義出来ます。
VBAでの処理をオブジェクト指向で実装したいときに使用します。

###定義方法
```vb
' オブジェクトが持つメンバー変数
Private Dim hoge As String

' オブジェクトが持つプロシージャ
Public Function GetHoge() As String
    GetHoge = hoge
End Function

Public Sub SetHoge(hoge　As String)
    Me.hoge = hoge
End Sub
```

#変数
##変数宣言
```vb
Dim 変数名 As 型
```

##代表的な型
|型名 | VBAでの表記 | 説明 |
|-------|-------|------|
|文字列型|String| 文字列 |
|ブール型|Boolean|True または False|
|バイト型|Byte|0から255の正の整数|
|整数型|Integer|	-32,768から32,767の整数|
|長整数型|Long|-2,147,483,648から2,147,483,647の整数|
|単精度浮動小数点型|Single|-3.402823E38から-1.401298E-45<br/>1.401298E-45から3.402823E38|
|倍精度浮動小数点型|Double|-1.79769313486231E308から-4.94065645841247E-324<br/>4.94065645841247E-324から1.79769313486232E308|
|通貨型|Currency|-922,337,203,685,477.5808から922,337,203,685,477.5807|
|日付型|Date|西暦100年1月1日から西暦9999年12月31日 (日付と時刻)|
|オブジェクト型|Object|オブジェクト参照するデータ型|
|バリアント型|Variant|あらゆる種類の値を保存できる型|
|ユーザー定義型|定義した型名|ユーザーが定義した型|

##値セット
```vb
hoge = 1
' または
Set hoge = New Hoge
```
オブジェクト型変数の場合、Setステートメントを使用します。

##変数宣言と初期化を一行でやる
```vb
Dim hoge As String: hoge = "hoge"
Dim hoge As Hoge: Set hoge = New Hoge
```

#演算子
##算術演算子
|演算子 | 説明 | 例 |実行結果|
|-------|-------|------|------|
|+|足し算|8 + 5|13|
|-|引き算|10 - 4|6|
|*|掛け算|3 * 5|15|
|/|割り算|8 / 5|1.6|
|¥|割り算の商|8 ¥ 5|1|
|Mod|割り算の余り|8 Mod 5|33|
|^|べき乗|6 ^ 2|36|

##比較演算子
|演算子 | 説明 | 例 |実行結果|
|-------|-------|------|------|
|<|小さい|8 < 5|False|
|<=|以下|3 <= 8|True|
|\>|大きい|8 > 5|True|
|>=|以上|3 >= 8|False|
|=|等しい|3 = 8|False|
|<>|等しくない|3 <> 8|True|

##論理演算子
|演算子 | 説明 | 例 |実行結果|
|-------|-------|------|------|
|And|論理積|8 > 4 And 2 <= 3|True|
|Or|論理和|8 > 4 Or 4 <= 1|True|
|Not|論理否定|Not 8 > 4|False|

#文字列の結合
文字列を結合する場合、「&」を使用します。

```vb
"りんご" & "," & "みかん"
```

#コメント
コメントを記述する場合、「'」を先頭文字に使用します。

```vb
' コメント
```

#プロシージャ
##プロシージャについて
プロシージャの定義方法は、FunctionまたはSubを使う2種類あります。
違いは、戻り値が返せるかどうかです。
Function：戻り値が返せる
Sub：戻り値が返せない

##定義方法

```vb
Function プロシージャ名(引数　As 引数の型) As 戻り値の型
    ' 処理
    
    プロシージャ名 = 戻り値
End Function

' Subの場合
Sub プロシージャ名(引数　As 引数の型)
    ' 処理
End Sub
```
Functionの場合、
戻り値はプロシージャ名に設定することで実装出来ます。
戻り値がオブジェクト型の場合はSetステートメントを使用します。

```vb
Set プロシージャ名 = 戻り値
```

##呼出し方法
プロシージャの呼出し方法には2通りあります。

```vb
hoge = プロシージャ名　' 戻り値がある場合
Call プロシージャ名 ' 戻り値がない場合
```

戻り値が無い場合はCallステートメントを使用します。

#条件分岐

```vb
If 条件式1 Then
    ' 処理1
ElseIf 条件式2 Then
    ' 処理2
Else
    ' 処理3
End If
```

#繰り返し
##For文
###For Next

```vb
Dim i As Integer ' インデックス用の変数

For i = 1 To インデックスの最終値 Step ループごとの加算値
    処理
Next
```
Stepは省略可能で、省略した場合はループごとに+1されます。

###For Each

```vb
Dim hoge As String

For Each hoge In hogeList
    ' 処理
Next
```

### Forを抜ける
Forの途中で処理を抜けるには「Exit For」を使用します。
For Next、For Eachの両方で使用出来ます。

```vb
For i = 1 To 3
    If i = 2 Then 
        Exit For
    End If
Next
```

###次のループに移る
VBAには他言語のようなcontinueはありません。
そのため、GoTo文で同様の動きを実現します。

```vb
Dim i As Integer

For i = 1 To 3
    If i = 2 Then
        GoTo Continue ' Continue:の行にジャンプします
    End If
    
Continue:
Next
```

##Do Loop文
###While
```vb
Do While 条件式
    処理
Loop

Do
    処理
Loop While 条件式
```

条件がTrueの場合、ループし続けます。
「Do While 条件」の場合、条件に該当しなければループ内を処理しません。
「Loop While 条件」の場合、初回のループ分は処理します。

###Until
```vb
Do Until 条件式
    処理
Loop

Do
    処理
Loop Until 条件式
```

条件がFalseの場合、ループし続けます。
「Do Until 条件」の場合、条件に該当しなければループ内を処理しません。
「Loop Until 条件」の場合、初回のループ分は処理します。

###Do Loop文を抜ける
```vb
Do Until 条件式1
    If 条件式2 Then 
        Exit Do ' Do Loopを抜ける
    End If
Loop
```

###次のループに移る
For文と同じくGoTo文で実現します。

```vb
Do Until 条件式1
    If 条件式2 Then 
        GoTo Continue ' Continue:の行にジャンプします
    End If
    
Continue:
Loop
```

#配列
##定義方法
```vb
Dim 配列名() As データ型
```

##使い方
```vb
Dim hoge(2) As String
hoge(0) = "りんご"
hoge(1) = "みかん"
hoge(2) = "バナナ"
```

##便利な関数
###LBound関数
LBoundは、配列の最小のインデックスを取得します。

```vb
LBound(配列) ' 配列の最小のインデックスを返す。
LBound(配列, 次元) ' 指定した次元の最小のインデックスを返す。
```

###UBound関数
UBound 関数は、配列の最大インデックスを返します。

```vb
UBound(配列) ' 配列の最大のインデックスを返す。
UBound(配列, 次元) ' 指定した次元の最大のインデックスを返す。
```

#コレクション
##定義方法
```vb
Dim hoges As Collection
Set hoges = New Collection
' または
Dim hoges As New Collection
```

##使用できるメソッド
コレクションには専用のメソッド・プロパティが用意されています。

###Addメソッド
インスタンス化したコレクションオブジェクトにメンバを追加します。

書式は以下の通りです。名前付き引数でitem, key, before, afterを指定出来ます。

```vb
コレクションオブジェクト. Add 追加するオブジェクト

コレクションオブジェクト. Add item := 追加するオブジェクト, key := 1, before := 1, after := 1
```

|引数名 | 必/任 | 説明 |
|-------|-------|-------|
|item|必須|追加するオブジェクトを指定します。|
|key|任意|コレクションオブジェクトの各メンバの位置を表すインデックスの代わりに重複しない文字列を指定出来ます。|
|before|任意|コレクションオブジェクト内での相対的な位置を表す値を指定します。<br/>インデックスを使用している場合、1～Countプロパティの値までの範囲を指定出来ます。<br/>beforeとafterを同時に指定することはできません。|
|after|任意|インデックスを使用している場合、1～Countプロパティの値までの範囲を指定出来ます。<br/>beforeとafterを同時に指定することはできません。|

###Itemメソッド
指定した位置または文字列に対応するコレクションオブジェクトのメンバを取得します。

```vb
コレクションオブジェクト.Item(index)
```

###Removeメソッド
コレクションオブジェクトからメンバを削除します。

```vb
コレクションオブジェクト.Remove (index)
```

##Countプロパティ
コレクションオブジェクトのメンバ数を取得出来ます。

```vb
コレクションオブジェクト.Count
```

#メッセージダイアログ
```vb
MsgBox "りんご"
```

#ブック、シート、セル操作系のchips
「hoge.xlsx」の「Sheet1」シートをアクティブ化する

```vb
Workbooks("hoge.xlsx").Worksheets("Sheet1").Activate
```

現在アクティブのブックと同フォルダに存在する「hoge.xlsx」を開く

```vb
Workbooks.Open(ThisWorkbook.Path & "\hoge.xlsx")
```

「Sheet1」シートのWorksheetオブジェクトを取得する

```vb
Worksheets("Sheet1")
```

「Sheet1」シートのA1セルに「りんご」と書き込む

```vb
Worksheets("Sheet1").Range("A1").Value = "りんご"
```

「Sheet1」シートのC5セルに「りんご」と書き込む

```vb
Worksheets("Sheet1").Cells(5, 3).Value="EXCEL VBA"
```

現在のマクロが実行されているブックのブック名を取得する

```vb
ThisWorkbook.Name
```

<!--
■Withステートメント
With output
.Type = adTypeText
.Charset = "UTF-8"
.LineSeparator = -1 '：CRLF
.Open

	        .Position = 0 'ストリームの位置を0にする
	        .Type = adTypeBinary 'データの種類をバイナリデータに変更
	        .Position = 3 'ストリームの位置を3にする
	 
	        Dim byteData() As Byte '一時格納用
	        byteData = .Read 'ストリームの内容を一時格納用変数に保存
	        .Close '一旦ストリームを閉じる（リセット）
	 
	        .Open 'ストリームを開く
	        .Write byteData 'ストリームに一時格納したデータを流し込む
	        .SaveToFile ActiveWorkbook.Path & "\dbo.ShizaiOrder.csv", adSaveCreateOverWrite
	        .Close
	    End With

■日付変換
Function DateZeroPadding(sDate As String)
Dim resultDate As String: resultDate = ""
'// 日付文字列として不正の場合は処理しない
If (IsDate(sDate) = True) Then
resultDate = Format(sDate, "mm/dd")
End If

		    DateZeroPadding = resultDate
		End Function

■列数-列アルファベットの変換
Function CNumAlp(va As Variant) As Variant '変換する関数
Dim al As String
If IsNumeric(va) = True Then '数値だったら
al = Cells(1, va).Address(RowAbsolute:=False, ColumnAbsolute:=False) '$無しでAddress取得
CNumAlp = Left(al, Len(al) - 1)
Else 'アルファベットだったら
CNumAlp = Range(va & "1").Column '列番号を取得
End If
End Function

```
Set output = New ADODB.Stream

```

-->
#参考文献

https://excel-ubara.com/vba_class/

https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/collection-object

https://ateitexe.com/excel-vba-module/

https://www.koikikukan.com/archives/2014/05/23-015555.php

https://tsware.jp/tips/tips_334.htm

https://qiita.com/Kamo123/items/a4c7749fa30d8f68df28

https://excelwork.info/excel/vbaregexpmethod/

http://chaichan.lolipop.jp/vbtips/VBMemo2009-01-072.htm

https://www.relief.jp/docs/excel-vba-if-like-instr.html

https://excel-ubara.com/excelvba1/EXCELVBA363.html