ExcelVBA関数集(一部)

※この記事は https://kunosu.qrunch.io/entries/ZmeqpIYn39VrS9XF に移動しました。

---

注意

* 本記事は `[CtrL]` + `[F]` での検索前提で書かれています。
* 全ての関数は載っていません。

## 定数 `Const`

```vb
Const 定数名 As String = "記載したページだけから参照できる定数"
Public Const 定数名 As String = "ブック全体から参照できる定数"
```

## 関数を作成する
### 値渡し `ByVal` / 参照渡し `ByRef`

* 値渡し：呼び出し元は変更されない
* 参照渡し：呼び出し元も変更される（C言語のポインタのようなもの）
* 未指定の場合は「参照渡し」になる

```vb
Sub func(ByVal 値渡し As String, ByRef 参照渡し As String)

End Sub
```

### 戻り値がない関数の呼び出し

```vb
Call func(x, y)
```

### 戻り値

```vb
Function func() As 戻り値の型
	func = 戻り値
End Function
```

### 関数を途中で終了して呼び出し元へ戻す

```vb
if 何か判定 Then
	Exit Sub
End If
```

### 例外処理

※GoTo文を使うため、あまり多用しないこと

```vb
Sub func()
	On Error GoTo ErrorHandler  'エラー発生でErrorHandlerへ飛ぶ

	'処理を書く

	Exit Sub
ErrorHandler:
	'-- 例外処理
	Debug.Print "【例外発生】"
	Application.ScreenUpdating = True   '画面の更新を再開
End Sub
```


## 値が日付か判定

```vb
if IsDate(Cells(1,2)) Then
	'B1が日付の時の処理
End If
```

## 条件分岐

### 等しい

* `==` は使えない
* `=` で判定

### 否定 `Not`

* `!=` は使えない
* `<>` で判定
* 下記の判定方法もあります

```vb
if Not(判定) Then

End If
```

### Switch文

```vb
Select Case x
	Case 1
		'x == 1のときの処理
	Case 2
		'x == 2のときの処理
	Case Else
		' どれでもない時
End Select
```

## ループ
### while文

```vb
Do While 条件
	'真の間繰り返し
Loop
```

#### while文を途中で抜ける

```vb
Exit Do	'breakは使えない
```

### for文

```vb
For i = 0 To 10
	'11回繰り返す
Next i
```

#### for文を途中で抜ける

```vb
Exit For
```

## デバッグする

イミディエイトウィンドウに値を表示させる

* `Debug.Print` の出力先
* 表示方法：メニューの `表示` > `イミディエイト ウィンドウ`

```vb
Debug.Print(変数名)
Debug.Print "文字列";変数名;"文字列" '文字列と組合せて出力
```

### イミディエイトウィンドウをクリアする

普通に編集できるため、`Ctrl` + `A` で全選択して `Del`

## インクリメント/デクリメント

`i++` のような機能はないので、普通に足す/引くしかないです

## 複数行をまとめてコメントアウト

* 編集ウィンドウの `コメント ブロック` をクリック
* 編集ウィンドウの表示方法
	* `表示` > `ツールバー` > `編集` をチェック

## With文（変数を省略）

```vb
With ワークシート
	.Cell() 'ワークシート.Cell()と同じになる
End With
```

## セル
### セルから値を取得して変数に代入

```vb
Dim 変数名 As String
変数名 = Cells(1, 2).Value  ' B2の値を文字列で得る
```

### セルの内容が変更された時に実行 `Worksheet_Change`

* 対象のワークシートのモジュールに下記を記入
* マクロによるセルの変更があっても実行されるため、下手すると無限ループになります

```vb
Private Sub Worksheet_Change(ByVal Target As Range)
	Dim changeCells As Range	'変更監視範囲

	'変更監視範囲を「A1:C100」に指定
	Set changeCells = Application.Intersect(Target, Range(Cells(1,1), Cells(100, 3)))

	'未変更or空白なら無視
	If (changeCells Is Nothing) Or (Cells(Target.Row, Target.Column) = "") Then
		Exit Sub
	End If

	func(Target.Item(1))	'変更があったセルに対して処理を行う(関数呼び出し)
End Sub
```

### 指定セルから一番下のセルを得る

* `Ctrl` + `↓` で移動するセルと同じ場所になる
* `xlUp` で上になる

```vb
Cells(1, 2).End(xlDown) 'B1から一番下のセル
```

### 指定セルから一番右のセルを得る

* `Ctrl` + `→` で移動するセルと同じ場所になる
* `xlToLeft` で左になる

```vb
Cells(1, 2).End(xlToRight) 'B1から一番右のセル
```

### セルを検索 `Find`

* `what:=` 検索対象
* `LookIn:=` 検索対象の種類を指定
* **検索失敗時の処理**を記述すること

| 名前         | 種類 |
|--------------|---|
| `xlValues`   | 値 |
| `xlFormulas` | 数式 |
| `xlComments` | コメント |

```vb
Dim foundCell As Range   '検索結果のセルを格納
foundCell = Range("B:B").Find(what:="あ", LookIn:=xlValues)	'値として「あ」を含むセルをB列から検索

If (foundCell Is Nothing) Then	'検索失敗時の処理
	MsgBox "「あ」は存在しません"
Else
	'検索対象が見つかったときの処理
End If
```

### 空白を判定する

いくつか判定方法があります

```vb
Dim cell As Range   '判定対象のセル

'cellにエラー値(#NAなど)が含まれる場合エラーになる
If cell = "" Then
End If

'何も入っていない空白を確認したい場合
If IsEmpty(cell) Then
End If

'関数の結果で空白の場合も確認したい場合1
If CStr(cell.Value) = "" Then
End If

'関数の結果で空白の場合も確認したい場合2
If cell.Text = "" Then
End If
```
## 配列

### 配列を宣言・初期化

```vb
Dim 配列名(サイズ) As 型名
Erase 配列名	'初期化
```

初期化の値

| 型名        | 値 |
|-------------|---|
| 数値        | 0 |
| 文字        | `""` (空) |
| オブジェクト | `Nothing` |
| バリアント   | `Empty` |

### 配列のループ

```vb
Dim 要素 As Variant '必ずバリアント型で宣言すること

For Each 要素 In 配列名()
	'配列の各値が「要素」に代入された状態で処理される
Next 要素
```

### 配列のサイズ

```vb
UBound(配列名)
UBound(配列名, 次元)	'2次元以上の配列のとき指定
```

## 行を挿入

```vb
Rows(2).Insert '2行目に挿入
Range("B2").EntireRow.Insert 'B2セルへ挿入
```

## 変更の取り消し

* `Ctrl` + `Z` と同じ動作
* マクロで変更したものは戻せない

## マクロの軽量化

`Application.EnableEvents` を変更することでイベント(セルの編集)の監視を止めることができる

```vb
Application.EnableEvents = False	'イベントを無視する
Application.Undo	'変更の取り消し
'・・・
'なんか処理する
'・・・
Application.EnableEvents = True 'イベント監視を再開
```