エクセルVBAコーディングガイドライン【随時更新】

★気に入ったらシェアをお願いします!


guide-line

photo credit: amsfrank DSC00201 via photopin (license)

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

弊社でお仕事をする場合に、「こういうコーディングルールでやろうね」というのを、自分自身または一緒にお仕事をするパートナーさんにお伝えすべく、エクセルVBAのコーディングガイドラインを作ろうということになりました。

GoogleドキュメントやEvernoteで共有してもいいのですが、拙著「ExcelVBAを実務で使い倒す技術 」にもほとんど書いてある内容ですし、別に企業秘密とするほどのことでもないので、せっかくなら記事にしてしまえ!

ということで、記事として書かせてもらっています。

あくまで、弊社ではこう…というものなので、いろいろとご意見、好み、その他、色々とあるかもしれませんが、一部でも皆様のご参考になれば幸いです。

命名規則

変数、定数、プロシージャなど、名前には意味が伝わる単語を使います。

例えば…

これではどんな役割を持つ変数なのかわかりません…。

なお、VBAにおける名前は短いに越したことはないですが、長くてもメンバー候補が使えますので、それほど気にしなくてもよいです。

【エクセルVBA】初心者にとっても便利なVBEの自動メンバー表示とその使い方
エクセルVBAの業務効率を上げるためのVBEのテクニックについてお伝えしています。今回は、VBEのステキ機能である「自動メンバー表示」とは何か、また自動メンバー表示を使いこなす方法についてです。

意味がわからないよりは、長いほうがマシです。

変数名

変数名はアルファベットのキャメル記法で書きます。

また、データ型に合わせて、以下接頭語で始めるようにしてください。

  • str:String
  • date:Date
  • rng:Range
  • ws:Worksheet
  • wb:Workbook
  • obj:Object

整数型や通貨型の場合はこの限りではないですが、状況に応じて以下接頭語を使うことを推奨します。

  • row:行
  • col:列
  • min:最小
  • max:最大
  • avg:平均

ただし、以下については短くてシンプルな名称でも可読性には影響を与えませんので、使っても問題なしです。

  • i, j, k:イテレータ
  • tmp, buf:一時的な変数
  • obj:一時的なオブジェクト変数

プロシージャ

メインルーチンなどそのマクロ独自のSubプロシージャは日本語名でもOKです。

ただし、他のプロシージャから頻繁に呼び出される可能性があるSubプロシージャ、またはFunctionプロシージャはアルファベットのキャメル記法でお願いします。

というのも、他のマクロに再利用する際を考えると、日本語名でないほうが都合がよい場合が多いからです。

また「~かどうか」を返すBoolean型のFunctionプロシージャに関しては

  • is~
  • has~
  • can~

を使うとわかりやすいですし、かっこいいです。

定数

定数はアルファベットのスネーク記法で命名をします。

列挙体

「e + 単語」のキャメル記法でネーミングします。

Cellsプロパティの引数として列番号などによく使われますので、単語はなるべく短いワードが望ましいです。

また、ワークシートの列数を表す列挙体の場合は、そのオブジェクト名と同じワードを使うのがおすすめです。

例えばワークシートのオブジェクト名が「wsPref」であれば

と命名します。

変数の宣言

まず、前提として、不要な変数は増やさないようにしたいところです。

変数が増えるということは、管理すべき対象が増えるということなので、無駄に増やすと可読性やメンテナンス性を低下させることになります。

変数を使うことが有効なのかどうかの見極めが大事ですね。

変数の宣言は強制する

VBEのオプション設定で変数の宣言を強制するようにします。

以下記事にある通り、VBEの「ツール」→「オプション」(アクセスキー Alt → T → O )の「編集」タブ、「変数の宣言を強制する」にチェックで、常に作用します。

エクセルVBA超入門!たった10分でスタート地点に立つための方法
エクセルVBA…まず何をしたら良いかわからない…!という声をよく耳にします。今回はVBAプログラミングをいざ書き始める直前の状態を目標に、エクセルVBAの最低限のセッティングの仕方についてお伝えします。

モジュールの宣言セクションに以下記載がある状態であれば、変数の宣言が必須となります。

宣言を強制することで

  • 変数名のスペルミスの防止
  • 変数の型を明確にする

などのメリットがあります。

暗黙の型は使わない

型指定をしないとVariant型になりますが、変数の役割が見えづらくなりますので、特に理由がない限りは型を指定をすべきです。

また、以下のような書き方をすると、変数xがVariant型になってしまうので注意が必要です。

このように記述するのが正しい書き方です。

また、オブジェクト変数でいうとObject型も便利ではありますが、同様の理由から、できるだけ型指定は詳細にするのが良いです。

スコープはできる限り小さく

原則、変数・定数はプロシージャレベルで宣言をすることで、可読性と安全性が高まります。理由もなくモジュールレベルやパブリックにはしないように…。

また、宣言をするのは、使用する直前での宣言が望ましいです。

プロシージャ冒頭にプロシージャ内で使用するすべての変数を宣言するというしきたりがあったりなかったりしますが、近くにあるほうが

  • 型は何か
  • 宣言時のコメント

といった情報がスクロールなしで得られるようになります。

ただし、定数の場合は、プロシージャの冒頭または宣言セクションでまとめて宣言をしておくのもよいでしょう。後で値を変更するときに、わかりやすい位置にあると便利です。

Integer型は使わない

整数はLong型で統一で問題ありません。

Integer型はメモリ領域をセーブできるというメリットも無きにしも非ずのように見えるかもなのですが、公式にこのように発言されています。

しかし、最近のバージョンでは、Integer型として宣言されていても、VBAはすべての整数値をLong型に変換します。したがって、Integer変数を使用することによるパフォーマンス上の利点はなくなりました。実際、Long変数はVBAで変換する必要がないため、少し速くなる可能性があります。

Currency型を使う

小数点を取り扱う金額はCurrency型(通貨型、固定小数点)を使います。

コンピュータはそもそも小数付の計算が苦手で、SingleやDoubleの計算では誤差が発生する場合があるのですが、Currencyなら安心して使えます。

Currencyは小数点以下4桁までを取り扱うことができ、計算時は1万倍して整数にしてから、計算後に1万で割って戻すという処理をしているので、小数付の計算による誤差が出ないのです。

ただし、小数点以下5桁以下は丸められてしまいますので、その点は知っておく必要があります。

コードのフォルム

ネストとインデント

ネストであれば必ずその深さの分のインデントを加えてください。理想としては深さは3つまでがいいですね。

Withステートメントの活用

Withステートメントを使うとネストは増えてしまいますが、同じオブジェクトを何度も書かなくて済みますし、可読性も上がる場合が多く、コードを書くための強力な武器になります。

縦に揃える

一行が長いときには、アンダースコアによる行連結シーケンスによる改行が有効ですが、縦に揃えることを意識すると可読性が高まります。

長いメッセージを記述するときや

引数の多い命令を記述するときに有効です。 

コメント

コードを見てわかるコメントは不要

一般的にコードを見ればわかるような内容についてのコメントは不要です。

例えば以下のようなパターン。

コメント入れなくてもわかりますから…情報密度が薄くなっちゃいます。

プロシージャの説明

頻繁に呼び出されることのあるプロシージャであるなら、役割、引数、返り値などについてコメントを入れておきます。

例えば、以下のようなコメントです。

役割や使い方がぱっとわかりますし、再利用もしやすくなります。

マジックナンバーは禁止

マジックナンバーは使用禁止です。メンテナンス性を著しく犠牲にします。マジックナンバー、絶対ダメ!

マジックナンバーになりやすいポイントとしては

  • 行数、列数
  • 係数
  • セルのアドレス
  • 配列やオブジェクトの要素数
  • 引数
  • ファイル名、パス名
  • パスワード
  • URLやメールアドレス

などがあります。

定数や列挙型を使うことで、マジックナンバーを避けましょう。

ユーザーの干渉・省略

テーブルの走査

テーブルの走査にはDo While~Loop文を使います。

繰り返し回数の指定を変更することなく、テーブルのレコード追加や削除に対応できます。

コレクションの走査

コレクションの走査にはFor Each~Next文を使います。

コレクションのCountプロパティを使えば、For~Next文でも対応はできますが、For Each~Next文のほうがループ内でのオブジェクトの指定が簡潔になります。

ワークシートの指定はオブジェクト名で

シートの指定はできる限りオブジェクト名を使います。

  • どのモジュールからでも同名でアクセスできる
  • 可読性が確保できる
  • シート名の変更の影響を受けない
  • 宣言が不要

など大量のメリットがあります。

宣言もセットも不要!エクセルVBAでワークシートをオブジェクト名で取り扱う方法
エクセルVBAで頻繁に取り扱うワークシート。実はオブジェクト変数を使わずに「オブジェクト名」を使って操作する方法があります。プロジェクト全体で定数のように使うことができ便利ですので、その使い方をお伝えします。

特に、インデックス番号による指定は、シートの並び順に依存するので危なっかしいです。

シート名を省略した場合は、暗黙的にActiveSheetへの処理となります。しかし、ActiveSheetはユーザーの操作によって想定しないシートが対象になることもあるので注意です。

ワークシートの新規作成をした直後であれば、戻り値を使ってオブジェクト変数にすぐさま格納するのが良いでしょう。

ワークブックを明示する

以下のように親オブジェクトであるワークブックを省略することも避けるほうが良いです。

この場合は、ActiveWorkbookが親オブジェクトとして認識されますが、ユーザーの操作によって想定しないオブジェクトが指定されたりします。

基本的にThisWorkbookを使うか、オブジェクト変数で特定をしましょう。

またActiveSheetと同様なのですが、ワークブックを新規作成をした直後には、戻り値を使ってオブジェクト変数に格納しちゃいましょう。

コピー&ペースト

Selectメソッドは使わない

コピペ動作をマクロ記録すると

などといったコードが出力されますが、コピペにSelectメソッドは不要です。

Selectをするたびにアプリケーションの動作が入り、実行速度が犠牲になりますし、クリップボードを使うのはユーザーの干渉を受ける可能性があり危険です。

以下のよいうに、Copyメソッド一文でOKです。

セル範囲で処理できるなら一発で

Copyメソッドは範囲でも機能します。

単なるコピペであれば、繰り返しを使って1セルずつコピペをするのではなく、範囲で一気にコピペすることを優先しましょう。

実行速度に圧倒的な差が生まれます。

高速化

特に理由がない限り、シートの処理をするのであれば、以下アプリケーションオブジェクトに関するプロパティ群を設定して、高速化を図ります。

遅い…重い…そんなエクセルVBAプログラムの処理速度を劇的に改善する方法
エクセルVBAの実行速度が遅い・重いって時ありませんか?そんな時にエクセルVBAのプログラムの処理速度を速くするテクニックを紹介します。プログラムの実行時間を測定する方法も合わせてお伝えします。

日付リテラル

エクセルVBAにおいて日付の指定はダブルクォーテーション囲みでも許されていますが、「日付リテラル」つまりシャープ記号囲みがおすすめです。

というのも、日付リテラルを使うことで、日付として受け付けられない文字列をはじくこともできますし、入力後に規定のフォーマットに変換されるので、想定外の値が入力されることも防ぐことができます。

まとめ

以上、エクセルVBAのコーディングガイドラインでした!

どうぞご活用くださいませ。

良いガイドライン見つけたら、随時更新していきますね。