May 11, 2018

Excel VBA の高速化のポイント



 転職してから業務の様々な場面でExcel VBAを用いることが増えました。世間でもRPA等といった初歩的な自動化/効率化は非常に注目を集めていますが、そんな大仰なものを用いなくてもVBAでやりたいことの多くは実現できます。

 このVBA、言語仕様はもはや古いというレベルではないですし、実行速度も極めて遅いです。しかし、わざわざ開発環境を自分で整える必要もなく、何よりも多くの方に馴染み深いアプリケーションでプログラミングをたやすく実現できるという強みがあります。何でもかんでもExcelで実装し、Accessで処理すべきデータの管理/処理まで無理やりExcelにやらせている人が多かったりするのは否めませんが、マクロ付きファイルを頒布する際等にはやはり「Excelのファイルである」ということは有利です(すべての頒布先がAccessを利用している状況は稀でしょう。しかし、Excelにその心配がいるでしょうか?)。また、マクロの記録機能を用いれば初学者でも何となく動かしてみることはできますよね。さらに、記述した内容を簡単に視認できるというのは、修養のための環境としてはもってこいだったりするのです。
 それでもいつも付きまとうのは「実行速度の遅さ」。特に、数十万レコードといった大量のデータをExcelで処理しなければならないときなど特に、適切でないコーディングが処理時間を大幅に膨らませてしまう恐れがあります。
 網羅的な記述は目指せませんが、思いつく限りのポイントを挙げてみました。ご指摘やご意見頂戴できると幸いです。



  1. 参照を渡してプロシージャ内からオブジェクトにアクセスするのと、グローバルオブジェクトへアクセスするのとの間で速度差はほとんどない
  2. Boolean型変数の判定は「=True」「=False」よりも「」「Not」の方が早い
  3. 文字列型変数A、Bの比較は「A=B」「A<>B」よりも「A Like B」「Not(A Like B)」の方が早い
  4. String型変数の空判定は「=””」「=vbNullString」よりも「Len()=0」の方が早い
  5. 文字列数が定まっている場合、固定長文字列型を用いるべきだ(「As String *」)
  6. Variant型はメモリを食い過ぎるため使用しない。変数型を明示的に宣言させるために「Option Explicit」は習慣づける
  7. オブジェクト変数の生成は「Dim foo as bar = New bar」が簡素だが、この書式で記述するとコンストラクタがコールされない。面倒だが「Dim foo As bar:    Set foo = New bar」と記述する
  8. 文字列型操作に特化した関数を積極的に用いる(「Left$()」等)
  9. VBAはショートサーキットしない。可読性を損なわない範囲で「And」は「If」の入れ子で、「Or」はラベルへの「GoTo」を用いる
  10. 「Application.ScreenUpdating」の切替え
  11. 「Application.Calculation」の切替え
  12. 「データの入力規則」をマクロで設定すると、シートのXMLエラーが頻発する事象が確認されている(Excel2010等)
  13. 「IIf」は遅いので使用を避ける
  14. 不要な初期化は省くべきである(「Dim foo as Boolean:    foo = False」、「Dim bar as Integer:    bar = 0」等)

 変数の取扱いや条件文の記法について、C等の他言語でプログラミングを経験している方は当たり前に意識するものですが、VBAしか知らない方はそうではないことが多いと思います。軽微な処理であればここまで気を配る必要はないでしょうが、処理量が嵩む場合はぜひコードを見直してみましょう。
 一方で、上でも述べましたがメンテナンス性等の観点で周囲の方にも理解しやすいようなコードを書くことも重要です。あげた例でいうと特に「ラベルの多用」は可読性を著しく損ねかねないので注意が必要です。