歴3年がおしえるVBAコードを書くための9つのアドバイス
コードの可読性が高く改修しやすいだけでムダな時間が減る

今回のアドバイスは「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だ。

  1. Excelのエディタを開く
  2. Ctrl + r キーで左側にプロジェクト表示
  3. F4 キーで左側にプロパティ表示
  4. (オブジェクト名)の項目を変更

アドバイス 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つのアドバイスを参考にコーディングしていってほしい。

事務作業を自動化してもっと"ラク"しませんか?

あなたの会社の事務作業...効率化してラクに。もっと重要な業務に集中できるようになります。

日々増えるルーティンの事務作業...
「この作業めんどくさい...」
「事務作業に時間をとられて他に集中できない...」

あなたの代わりにVBAを使ってパソコン業務を自動化。あなたはもっと価値のあることに時間を使うことができるため売上UP、ムダなコストの削減が期待できます。

また、作って終わりではなくつぎの3つのことを約束します。

  • しっかりドキュメント作成
  • きれいな見やすいコードでムダな工数カット
  • できるだけボタン1つポチッと押すだけで業務が完了

どんなにささいなめんどくさい事務作業でも相談してください。相談は無料です。
3年の業務効率化実績があるため、力になれるかもしれません。

※件名には「業務効率化の相談」と記載ください。できるだけ24時間以内に返信します。