Excel VBA入門 ～その4 基礎2～

VBAが嫌いな人が書いたVBA入門記事その4です。初心者の人も最低限だけ身に付けてPythonに移行しましょう。→[VBAユーザーのためのPython入門 ～xlwingsでExcelからPythonを呼び出す～](https://qiita.com/k_maki/items/9efdb70f69d6f3b00f80)

**記事一覧**

- [Excel VBA入門 ～その1 Excel VBAとは～](https://qiita.com/k_maki/items/eed5497c704c2ca91699)
- [Excel VBA入門 ～その2 最初のプログラム～](https://qiita.com/k_maki/items/47d6299ecbb293b01f5a)
- [Excel VBA入門 ～その3 基礎1～](https://qiita.com/k_maki/items/852fd4babfd3031b6d72)
- Excel VBA入門 ～その4 基礎2～
- [Excel VBA入門 ～その5 Tips～](https://qiita.com/k_maki/items/575b6c6c7ec22581061c)
- [Excel VBA入門 ～その6 アンチパターン～](https://qiita.com/k_maki/items/c40c0eab5af4984f08a2)

# オブジェクトとは
プログラミング全般で言うオブジェクトとは、**データ**（**属性/プロパティ**）と**手続**（**メソッド**）を一つのまとまりとして持つデータ構造。よりプログラムを効率的に作成するための仕組みで、多くのプログラミング言語がこの機能を使えるようにしている。ただし、VBAのオブジェクト対応は中途半端なため、既存オブジェクトは使えるが、まともに作ることはできない。

オブジェクトとプロパティ/メソッドの例:

- [Rangeオブジェクト](https://docs.microsoft.com/ja-jp/office/vba/api/excel.range%28object%29)
	- プロパティ
		- [Address](https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.address): セル範囲の場所を表す値を返す。
			```VB
			Range("A1:B3").Address '"A1:B3"を返す。
			```
		- [Value](https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.value): セルの値を返す。
			```VB
			Range("A1:B3").Value '2次元なので配列を返す。
			```
	- メソッド
		- [Select](https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.select): セルを選択する
			```VB
			Range("A1:B3").Select
			```
		- [Clear](https://docs.microsoft.com/ja-jp/office/vba/api/excel.range.clear): セルの値をクリアする。
			```VB
			Range("A1:B3").Clear
			```

- [Workbookオブジェクト](https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook)
	- プロパティ
		- [Worksheets](https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.worksheets): [Worksheet](https://docs.microsoft.com/ja-jp/office/vba/api/excel.worksheet)のコレクション（これもオブジェクト！）を返す。
			```VB
			Dim ws as Worksheet
			For Each ws in Workbook.Worksheets
				'各ワークシートに対する処理
			Next
			```
	- メソッド
		- [Close](https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.close): ワークブックを閉じる。
			```VB
			Workbook.Close(SaveChanges:=True) 'ブックを保存して閉じる
			```

# 配列とコレクション
## 配列
[配列](https://www.sejuku.net/blog/38356)とは同じデータ型を決まった数だけ格納したデータのこと。

```VB
Dim 配列名(要素数) As データ型 '配列の宣言

Dim 配列名 As Variant
Redim 配列名(要素数) As データ型 '要素数を可変にする（=要素数に変数を使う）には、Variant型で宣言し、再度Redimで宣言する

Ubound(配列名) '配列の要素数を取得
```

使用例

```VB
'選択した範囲のセルの行ごとの和を配列arryに格納する
Dim rg as Range
Set rg = Selection

Dim arry as Variant
Redim arry(rg.Rows.count) As Double

Dim i as Long
For i = 1 to Ubound(arry)
	arry(i) = sum(rg.Rows(i))
Next
```

## コレクション
[コレクション](https://excel-ubara.com/excelvba1/EXCELVBA358.html)とは、同じデータ型を任意の数だけ格納したデータのこと。自分で定義するよりも、親オブジェクトのプロパティから取得することが多い。例えば、WorkbookオブジェクトのWorksheetsコレクション（Worksheet型を要素とするコレクション）や、ListObjectオブジェクトのListRowsコレクション（ListRow型を要素とするコレクション）など。●●sコレクションの要素は●●となっていることが多い。

```VB
Dim ws as Worksheet
For Each ws in Workbook.Worksheets
	'各ワークシートに対する処理
Next
```
プロパティやメソッドの使い勝手が配列よりも良いため、こちらを使う方が楽な場合が多い。


# 関数定義
コードが大きくなった場合、関数を使うことで可読性・保守性を高めることができる。

```VB
Function 関数名（引数1 As 引数1の型, 引数2 As 引数2の型, …） As 戻り値の型
	'処理
	'…

	関数名 = 戻り値 '関数名に戻り値を代入して返す
End Function
```

## 関数定義のメリット
- 同じ処理の抽出: コピペの修正盛れを防ぐ
- 入力・出力の明確化: この処理で必要なものと得られるものを明示
- 処理のカプセル化: 不要な中間変数等を外に出さない

関数を使う前

```VB
Sub test()
	Dim rg1 as Range, rg2 as Range
	Dim sqSum1 as Double, sqSum2 as Double
	Dim cll as Range

	Set rg1 = Sheet1.Range("A1:C2")
	sqSum1 = 0
	For Each cll in rg1
		sqSum1 = sqSum1 + cll.Value^2
	Next

	Set rg2 = Sheet1.Range("D1:F2")
	sqSum2 = 0
	For Each cll in rg1	'スペルミス
		sqSum2 = sqSum2 + cll.Value^2
	Next

	debug.print sqSum1 + sqSum2
End Sub
```

関数を使った後

```VB
Funciton sqSum(rg as Range) as Double
	Dim cll as Range
	Dim rtn as Double

	rtn = 0
	For Each cll in rg
		rtn = rtn + cll.Value^2
	Next
	sqSum = rtn
End Function

Sub test()
	debug.print sqSum(Sheet1.Range("A1:C2")) + sqSum2(Sheet1.Range("D1:F2"))
End Sub
```



# エラー処理
以下のコードで、`On Error Resume Next`から`On Error GoTo 0`の間で生じたエラーを無視する。

```VB
On Error Resume Next
処理1
処理2
…
On Error GoTo 0
```

VBAのエラー処理はしょぼいのでいろいろ諦める（`On Error GoTo 行ラベル`は使わない）。



# 参照設定	
参照設定を行うことで標準以外の機能を使えるようになる。参照設定はファイル単位で行う必要があることに注意。

参照設定を行うには、VBE -> メニューバー「ツール」 -> 参照設定で使いたい機能のチェックをオンにする。よく使う機能は「Microsoft Scripting Runtime」。コレクションよりも便利なDictionaryや、ファイル操作ができるFileSystemObjectが含まれる。