VBAでマクロ開発した処理の速度を高速化する方法を紹介します。
まずは処理時間・速度が遅くなる原因について考えます。
処理が遅くなる原因はほとんどの場合は以下の4つのいずれかに当てはまるかと思います。
それぞれについて詳しく解説します。
・Excelシートへの参照や書き込みが多い
処理の中でセルを参照している回数や書き込む回数が多いと処理時間がかかります。
その理由は、毎回セルに確認する必要があるからです。
例えば、セルA1からA3に「あ」という文字を入力してみます。
Range("A1").Value = "あ"
Range("A2").Value = "あ"
Range("A3").Value = "あ"
このように処理をすると、3回の出力命令を行っていることになります。
次のように記述することもできます。
Range("A1:A3").Value = "あ"
このように処理をすると、1回の出力命令で完了します。
要するに、なるべく少ない出力にした方が処理時間が早くなります。
他にも、セルの情報には背景色や枠線など多くの情報があります。
そのため、①のようにセルの情報を毎回参照するのではなく、②のように変数に入れてから設定するの方が処理速度が早くなります。
1回だけの処理の場合は大きく変わりませんが、繰り返し処理などで数万回と処理するとなると影響してきます。
そのため、複数のセルを操作する場合は、配列に格納して処理を行うことで処理速度を改善できます。
※配列についての説明は割愛します。
・ネストが深い(入れ子になっている)
「IF文の中にIF文、さらにその中にIF文」や「For文の中にFor文、さらにその中にFor文」などネストが深いと処理時間がかかります。
その理由は、単純に確認などの処理が増えてしまうためです。
IF文で例えると、①の場合だと、a~dすべてが0の場合、4回も確認作業をする必要があります。
それに対し、②の場合は1回の確認作業になります。※厳密には違います
これも、基本は「a=0」になる可能性が低い処理ならば、③のようにしても良いのですが、不規則の場合は②の方が良くなります。
※「a=0」が少ない場合は、初めのIF文のみで「ほとんどの場合にb、c、dの比較処理をしなくて済むためです
For文で例えると以下のような処理があるとします。
100回繰り返す処理の中に100回繰り返す処理があると、10000回の処理を行うことになります。
内側のFor文の数字が100から1000になれば、処理回数は900回増えるだけではなく、実際は90000回増えてしまいます。
処理の回数が増えれば増えるだけ処理に時間がかかるので、本当に必要な繰り返しなのかを考える必要があります。
次の①は無駄な処理になっています。
For文の中の、更にFor文の中のIF文に関して、本当にそこに必要なのでしょうか?
この場合は、i行目のA列に空白がなくても10000回繰り返されます。
それに対し②の場合は、内側のFor文を繰り返す前にIF文で絞っています。
この場合、i行目のA列に空白がなければ、繰り返しは100回しか行われません。
このような無駄な繰り返しを減らすことが処理の高速化のポイントになります。
・自動計算になっている ←ポイント
計算方法が自動(数式が自動で計算される)になっている場合は処理時間がかかります。
その理由は、セルを操作する度に数式の更新が行われるためになります。
セル上の数式の実行結果を使用したい場合にはできませんが、数式の実行結果の反映を処理後にしてよい場合は、手動にすることで処理速度を上げられます。
ただ、プログラムを実行する度に数式を手動に変換するのは大変です。
そんな時は、以下の内容を処理の前後に記述することで解決します。
「Application.Calculation = xlCalculationManual」で計算方法の設定を手動にしています。
処理が終了した後に「Application.Calculation = xlCalculationAutomatic」で自動に戻しています。
これだけで劇的に改善されることがあります。
・処理の度にシートを更新している ←ポイント
処理の内容をリアルタイムでExcelに反映していると処理時間がかかります。
その理由は、Excelに表示させるという動作が増えるためです。
長い処理などで途中経過を表示したいこともあるかと思いますが、基本的には処理が完了するまでExcelに反映する必要はないかと思います。
そんな時は、以下の内容を処理の前後に記述することで処理中の反映を止めることができます。
「Application.ScreenUpdating = False」で反映を止めて、「Application.ScreenUpdating = True」で戻しています。
次の処理だと動作のイメージしやすいです。
こちらはA1に「あ」と表示させた後に約5秒間停止して処理を終了するという内容です。
このコードの場合は、「Range(“A1”).Value = “あ”」が実行された時点でA1に「あ」と表示されます。
それに対し次のように書き換えると、5秒後の処理が終わるまで「あ」が表示されなくなります。
以上が処理速度を早くする方法です。
以下の4つを紹介しました。
前半の2つは、いきなりはハードルが高いかもですが、後半の2つだけでも処理時間がかなり短縮されることがあるので、ぜひ試してみてください。
※後半の2つを同時に使用する例は以下になります