VBA入門【プログラマー向け最小限スタイル】

# 始まり

誰かがこう言っていました。

**「この世界には２種類の人間がいる。
他の言語を学んでから Excel VBA に出会う人間と、
そうでない人間だ。」**

# こんな人に向けて書きました

この記事は前者のために書かれた内容です。
後者は他の言語をマスターしてから来ていただくことをお勧めします。

高水準言語を既に学んだ人が１日で基本を理解するための記事です。

特にDotNet系やPython、Java系、C#系などの

高水準言語を既に学んだ人はVBAの文法を学ぶコストは低いです。

他の言語を学んでからVBAに来た場合に、
「これさえ理解すれば後は公式リファレンスを
読みながらコーディングするだけ！」
みたいなレベルになれるようにしました。

文法とか型の種類とか、他言語との違いは、読むのも書くのも面倒なので、
「困ったらぐぐる」スタイルでいきましょう。
これぞ新世代エリートのスタイルです。（書くのをサボりたいだけ）

# こんな人が書きました

どうも、[ShortArrow](https://qiita.com/ShortArrow) です。最近、VBA にコンストラクタが無いことに、改めてイラっとしました。

# いにしえのIDEとの出会い

「ExcelはVBAというものでプログラミングができるらしい。」
という情報を得たあなたは、「どこでコードを書くの？」と思うはずです。

その場所を開くには`Alt`+`F11`というショートカットキーが、
鍵となります。

Excelを開いたら、ショートカットキー`Alt`+`F11`を使ってください。
この時に現れる、いにしえのIDEをVBEと呼びます。

# プロジェクトツリー

上記でご紹介したVBEの中で、`Ctrl`+`r`を使うと、プロジェクトツリーが開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/9b840a4c-2ba2-e9bd-3100-ead7986294ae.png)

:::note
<code>hoge</code>とか<code>foo</code>、<code>bar</code>だと味気ないので「なんかてきとう」にしました。
:::

# HelloWorld

## モジュールの作成

このツリー上で、「標準モジュール」を挿入してみたりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/f8d9a738-3321-0ff2-e9ff-4359dfbbae08.png)
そんなこんなで、`/VBAProject/標準モジュール/Module1`が作成できたでしょうか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/4e763832-ed69-e177-e135-24384d8e4a0f.png)

:::note info
標準モジュールの実体は拡張子が<code>.bas</code>、クラスは<code>.cls</code>、フォームは<code>.frm</code>です。
:::

## 初めてのSubプロシージャの作成

このModule1をダブルクリックすると、コード入力画面にカーソルが移動します。
そこで下記のコードを入力します。

```vb:Module1.bas
Sub EnterTheVbaWorld()
    Debug.Print("Hello Leagacy World!!")
End Sub
```

## 実行

入力出来たら、ショートカットキー`Ctrl`+`g`を使ってイミディエイトウィンドウを開きましょう。
そして、先ほど書いたコードにカーソルを合わせて、ショートカットキー`F5`を押してください。
`F5`キーはカーソル位置のSubプロシージャを実行します。

:::note info
Subプロシージャとは「戻り値のない関数」と思っておけば、２～３日はOK！
:::

## 結果

イミディエイトウィンドウに下記が表示されたら成功です。

```vb:イミディエイトウィンドウ
Hello Legacy World!!
```

# セルの操作

## Subプロシージャの追記

先ほどのModule1に下記を追記します。

```vb:Module1.bas
Sub MoveCellValue()
    ThisWorkBook.Sheets("Sheet1").Cells(1,2)=ThisWorkBook.Sheets("Sheet1").Cells(1,1)
End Sub
```

## セル操作の実行

先ほどと同様に、`F5`キーで実行します。
この時、`Sub MoveCellValue()`から最後の`End Sub`の間にカーソルがある状態で実行してください。

## セル操作の結果

シート名「`Sheet1`」のセル「`$A$1`」の内容が、シート名「`Sheet1`」のセル「`$B$1`」にコピーされます。

# 人に使ってもらう

さて上記を実験した後、まだ機能は２個しかありません。
それでも、せっかく作ったVBAコードです。
「ぜひ周りの一般ピーポーの方たちに使っていただきたい。」
「それに、フィードバックを得たほうが成長できる！」

## 一般ピーポーはVBEを見たがらない

そんな思いを形にする方法は大きく３つあります。
いずれもVBEを開かずにマクロを実行するための手法です。

- 図形のクリックをトリガーにする方法
- 組み込みイベントをトリガーにする方法
- ワークシート関数として利用する方法

## 図形のクリックをトリガーにする方法

なんでもいいので図形を挿入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/9ae9e99d-323e-26b3-1886-8f233070b519.png)
その図形を右クリックして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/d4ac81ee-46fb-a115-d2fe-b3bb4fb1db48.png)
「マクロの登録」をしようとすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/8177176e-0924-b14b-d13b-67243923571a.png)
どのマクロを登録するのか選ぶことが出来ます。
一覧から選択してOKボタンを押すだけです。

ここに表示されて登録処理が可能なのは、Publicで引数のないSubプロシージャのみです。
SubはデフォルトでPublicですが、Privateを付けてカプセル化することもできます。
また、Functionプロシージャは表示されず、登録できません。

## 組み込みイベントをトリガーにする方法

上記のプロジェクトツリーでThisWorkBookとかSheet1とかをダブルクリックすると、
コード入力エリアの上の部分が下記画像のようになると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/a5591cc9-9f52-5cb6-fd1c-ee7b121b0097.png)
これを、いろいろ切り替えて遊んでみると、コードが自動生成されます。
自動生成されたコードは、不要なら`Delete`や`Backspace`で消して大丈夫です。
その生成されるコードの中には、

```vb:ThisWorkBook.cls
Private Sub Workbook_Open()

End Sub
```

というものがあったりします。
この中にコードを記述すると、Excelファイルが開いたときに実行されるようになります。

```vb:ThisWorkBook.cls
Private Sub Workbook_Open()
    MsgBox "Event Trigger!!"
End Sub
```

こうすると、Excelファイルを開いたときに
「Event Trigger!!」というメッセージボックスが表示されます。

他にも、キー入力や、セル選択などをトリガーにしたコードを自動生成できます。
いろいろ試してみてください。

## ワークシート関数として利用する方法

Publicで戻り値のあるFunctionプロシージャは、セル内で数式として利用することが出来ます。

例えば、Module1に、下記のように記述するとします。

```vb:Module1.bas
Function One() As Variant
    One=1
    Exit Function
End Function
```

これで、OneというFunctionプロシージャはワークシート関数として利用することが出来ます。

例えば、「`$F$2`」セル内に`=One()`と入力すると、`1`が表示されます。

# 保存方法

VBAが記載されたExcelファイルは、いつもの「`.xlsx`」という拡張子では保存できません。
「`.xlsm`」という拡張子で保存してください。
Excelを再起動した後に、もう一度VBEを開くと保存したコードを見ることが出来ます。

# 締め

ここまで出来れば、Arduinoで言うと「Lチカ」ができたようなものです。
折り紙で言うと「山折り」ができたくらいで、
裁縫で言うと「玉止め」ができるくらいでしょうか。

# 今後

基本的にVBAを学ぶことはお勧めしません。[YO OFFICE](https://github.com/OfficeDev/generator-office)など、よりモダンな方法を検討してみることをオススメします。基本的にExcelファイルは、SQLなどへ入れるための情報の前処理やちょっとした計算ツールとしての利用を行ない、Excelファイルへの入出力はPythonやPowerShellで行うことを推奨します。Pythonがいい理由については、[こちら](https://qiita.com/k_maki/items/eed5497c704c2ca91699)をご覧ください。また、PowerShellについては、[ImportExcel](https://github.com/dfinke/ImportExcel)をご確認ください。

そのうえで、どうしてもExcel内部で完結したい場合に限ってVBAを利用しましょう。

## 学習

この先を学ぶには、[Office TANAKA](http://officetanaka.net/index.stm)がオススメです。
Google検索で「TANAKA VBA ファイルを開く」などのキーワードで検索するとヒットします。
こちらのサイトの記事は、いずれも物事の本質をとらえた濃いものです。
セミナーなども開催されているようですが、私の場合は無料記事だけで完全マスターできました。

より高度になってくると、[Excel VBA リファレンス](https://docs.microsoft.com/ja-jp/office/vba/api/overview/excel)をみるのが確実だし速いです。
言い換えると、出来る限り早く[Excel VBA リファレンス](https://docs.microsoft.com/ja-jp/office/vba/api/overview/excel)を読めるようになるべきです。

また、早い段階でテスト駆動開発という手法を取り入れることをオススメします。
コードの品質がが上がり、開発速度が非常に上がるので損しません。
下記のIDEの強化でも触れていますが、RubberDuckを利用すると手軽にテストできます。

## IDEの強化

「VBEって過去の遺産感が強すぎて」「普段はvscodeを使ってるから、差を感じてツライ」という場合には、
[RubberDuck](https://rubberduckvba.com/)をお勧めします。また、VSCode拡張機能もあるので是非お試しください。

- [VBA開発環境をモダンにする - RubberduckとVBEThemeColorEditorの紹介](https://qiita.com/mochimo/items/e9be36619a76e15bc898)
- [VBAにはユニットテストやリファクタリング機能がない・・・そんなふうに考えていた時期が俺にもありました](https://qiita.com/mima_ita/items/3629006163d0a7fa6e55)
- [VSCode拡張機能](https://github.com/Mikoshiba-Kyu/vscode-barretta)

それでは皆さん、VBAで最高のExcelライフをお楽しみください。