今回のアドバイスは「VBAもっといい感じに書けないかな?」ってパターンを想定している。初心者の場合は【超入門】VBAはIf文For文を覚えれば『破壊的』に使える理由から見てみるといい。
さっそくだが、あなたにコードの可読性が高く改修しやすいVBAコードが書けるようになる9つのアドバイスを紹介していこう。
アドバイス 1: Private を使いわける
1つのモジュール内でしか使わないFunctionやSubプロシージャ、Property。他のモジュールで使うことがないならPrivateを最初につけること。
Privateを使うとつぎのメリットがある。
- 1つのモジュール内でしか使わないことがパッと見でわかるため可読性が高い
- 他のモジュールから参照できなくなるためムダなバグがなくなる
- 改修時に1つのモジュールだけ影響範囲を考えればいい、バグの特定がしやすい
たとえばつぎのように書くことで「あ~この関数( or プロシージャ)はこのモジュールでしか使わないんだな。」ってことが一瞬でわかる。
' -- Main.bas モジュール -- ' Private がついてないので、他のモジュールから Call で呼び出せる Sub mainProcess() Call somethingProcess() End Sub ' Private がついているので、書いてあるモジュール内でしか関数が使えない Private Function somethingFunction() As String End Function ' Private がついているので、書いてあるモジュール内でしか Call で呼び出せない Private Sub somethingProcess() End Sub
アドバイス 2: 変数は使う直前に書く
めっちゃ重要。変数はなるべく使う直前に書く(宣言)こと。変数のスコープ(広さ)が狭いほうが可読性が高く、修正や改修がしやすい。
とくにVBAでは、なぜかSubプロシージャの最初で変数をズラッとならべてるコードが多い。コードを読むのがストレスになるので使う直前に変数を書く(宣言)すること。
たとえば悪い例といい例を見てみよう。
' -- 悪い例 -- よくあるコード Sub process() Dim ws1 As Worksheet Dim ws2 As Worksheet Dim wsB As Worksheet Dim i As Long Dim n As Long ' ' -- 40行くらいのDim宣言がつづき... -- ' Set ws1 = Sheets("Sheet1") Set ws2 = Sheets("Sheet2") Set wsB = Sheets("Sheet3") ' ' ' -- ここで100行ぐらいの長い処理 -- ' ' ' ここからはじめてws1, ws2, i, nの変数を使う For i = 1 To 100 ws1.Cells(i, 1) = "main process" Next i For n = 2 To 200 ws2.Cells(n, 2) = "sub process" Next n ' このプロシージャではけっきょくwsBの変数を使ってなかったりする End Sub
' -- いい例 -- Sub process() ' ' ' -- 例として、ここで100行ぐらいの長い処理 -- ' 実際に100行以上あるプロシージャは分割すること ' ' ' 使う直前に変数を宣言する Dim i As Long ' iの変数スコープがここから Dim main_process_sheet As Worksheet Set main_process_sheet = Sheets("Sheet1") For i = 1 To 100 main_process_sheet.Cells(i, 1) = "main process" Next i ' iの変数スコープここまで ' 使う直前に変数を宣言する Dim n As Long ' nの変数スコープがここから Dim sub_process_sheet As Worksheet Set sub_process_sheet = Sheets("Sheet2") For n = 2 To 200 sub_process_sheet.Cells(n, 2) = "sub process" Next n ' nの変数スコープがここまで ' wsB変数は消す End Sub
アドバイス 3: 変数・定数の型をしっかり設定する
型を設定すれば、文字列や数値、はたまた配列なのかパッと見て分かるようになる。
つぎの例を見て、パッと見でわかるコードはどっちだろうか?
' -- 悪い例 -- Dim end_message Dim i
' -- いい例 -- Dim end_message As String Dim i As Long
アドバイス 4: 適切な名前をしっかりつける
変数や定数、引数などには適切な名前をつけること。名前をちゃんとつけないと人でいえば、「おまえ」とか「おい」みたいに言ってるようなもの。
たとえば、つぎのように「ws1」「wsZZ」みたいな変数があったらどうだろう?どんなことに使う変数か分かるだろうか?
' -- 悪い例 -- Sub aa() Dim wsA As Worksheet Dim wsZZ As Worksheet End Sub
下記のコードのほうがどんな変数なのか、分かりやすくイメージしやすい。
' -- いい例 -- Sub converteDataToSheet() Dim print_sheet As Worksheet Dim data_master_sheet As Worksheet End Sub
アドバイス 5: なるべくグローバル変数を使わない
グローバル変数は使わないようにしよう。どこで変数宣言が始まって、どんな型なのか分からなくなりコードがカオスになる。また、変数のスコープと呼ばれるものも広くなるのでおすすめしない。
代わりにプライベート変数を使うか、プロパティとして別モジュールに分けるようにするといい。
下記で悪い例といい例を比べてみよう。
' -- 悪い例 -- Dim data As String ' ' ' -- ここで100行ぐらいの長い処理 -- ' ' Sub converteData() data = ← ここの変数にどんな型データを入れられるか100行以上戻らないと分からない End Sub
' -- いい例 -- ' ' ' -- ここで100行ぐらいの長い処理 -- ' ' Sub converteData() ' プライベート変数にする ' data変数には文字列型のデータを入れられることがすぐにわかる Dim data As String data = End Sub
アドバイス 6: シートオブジェクト名でコードを書く
シート名で書かず、シートオブジェクト名を設定してコードを書くこと。これによって、ユーザー側でシート名を変更してもムダに改修しなくてすむ。
まず悪い例を見てみよう。
' -- 悪い例 -- ' シート名で設定してしまうと、 ' だれかにシート名を変更されたらコードを変更しなければならない Worksheets("Sheet1").Range("A1") = "Some string"
つぎにいい例。可読性も高く変更に強くなる。
' -- いい例 -- ' シートオブジェクト名で設定すれば、 ' シート名が変更されてもコードを書き換えなくていい MainProcessSheet.Range("A1") = "Some string"
ちなみに、シートオブジェクト名の設定の仕方だが、つぎのように変更すればOKだ。
- Excelのエディタを開く
- Ctrl + r キーで左側にプロジェクト表示
- F4 キーで左側にプロパティ表示
- (オブジェクト名)の項目を変更
アドバイス 7: すべての処理を1つのモジュールに書かない。必ず分割する
なるべく1つのプロシージャ、関数で1つの処理を意識してコードを書くこと。いろんな処理を1つのプロシージャ、関数に書かない。長くても30~50行ほどにとどめる。
ちなみに、関数をシンプルにすることでつぎのようなメリットがある。
- テストしやすい
- 処理がシンプルになり可読性、保守性があがる
- 他の人が見てもコードが理解しやすい
アドバイス 8: 他モジュール呼び出しは モジュール.関数 or プロシージャ
改修時、少なからず既存コードを理解する作業がある。既存コードをモジュール名.関数名
または、モジュール名.プロシージャ名
にしていると可読性が高まる。
つぎの例ではMainモジュールから、Settingsモジュールのプロパティを呼び出している。
' -- Settings.bas モジュール -- Property Get exportFileName() As String exportFileName = "output-file-name" End Property
' -- Main.bas モジュール -- Sub csvFileExport() ' モジュール名.関数 or プロシージャ or プロパティ で設定する Settings.exportFileName() End Sub
アドバイス 9: モジュール名をしっかり設定、汎用モジュール名を設定しておく
Module1, Module2などと設定せず、Settingsなど分かりやすいモジュール名にすること。あなたが改修するとき、どこにコードを追加すればいいかすぐに理解できるようになる。
例として、5つの汎用モジュール名を用意したので参考にしてほしい。
- Main ... 最終的な処理を実行する処理を書く
- Libraries ... 共通処理、汎用処理を書く
- Settings ... セルの取得、ファイルの名前設定、プロパティ など設定
- Import ... CSVやAccessなどのインポート処理を書く
- Export ... CSVやxlsx形式などのエクスポート処理を書く
まとめ: 可読性・改修しやすさを追求していこう
今回は、可読性、保守性を中心に9つアドバイスをしてきた。可読性・改修しやすさを追求することで、いままで書いてきたVBAコードの質が格段にアップする。
VBAだけでなく、他のプログラミング言語にも通用するアドバイスだ。ちゃんと実践してくれれば、他の言語にもスムーズに挑戦できるようになるだろう。
ぜひ9つのアドバイスを参考にコーディングしていってほしい。