マクロの処理速度に関するお話です。
今回のテーマは「錯覚しやすいForステートメントの処理速度」です。
For文をたくさん分割しても処理は遅くならない
↓のようなマクロがあったとします。
For R = 1 To 10000 処理A : 10行くらい 処理B : 10行くらい 処理C : 10行くらい 処理D : 10行くらい Next
それぞれの処理は、
Cells(R, ○)を計算に使うような処理だと思ってください。
全部で40行くらいの、「For文による行ごとのデータ処理」ですね。
また、それぞれの処理の関係は、
- 処理Bは処理Aの後でやる必要がある
- 処理Cと処理Dは一緒にやる必要がある
だったとしましょう。
この時、
For R = 1 To 10000 処理A Next For R = 1 To 10000 処理B Next For R = 1 To 10000 処理C 処理D Next
↑こういう風にマクロを書き換えたとします。
なんか無駄なことしてて遅そう…。
ですが、よーく考えてみてください。
For文1個の書き方と、For文3個の書き方は、
なんと「Rに1を足す×20000回」しか処理の内容に差がありません。
足し算20000回とか、処理時間を計測できませんので、差は0です。
なんか人間の感覚だと、1から10000まで行ったり来たりしてて
すごい2度手間で、処理が遅くなる気がしてしまいますが、
錯覚なんです。
スピード面では、両者は誤差どころかほぼ0なので、
For文をまとめるのに速度的な意味がないことは、まずは知っておきましょう。
For文を分けたほうが変更に強い
For R = 1 To 10000 処理A Next For R = 1 To 10000 処理B Next For R = 1 To 10000 処理C 処理D Next
この書き方は、実はかなりいい書き方です。
どの処理とどの処理に関連があるのかが、見ただけで分かるからです。
「処理D」を書き換える必要が発生したとしましょう。
「処理AとBは見なくてOK。処理Cはしっかり見ること。」というのが明示されていますね。
ループ文の中身は、複雑なことも多々あります。
特に「処理の順番が大事」だったりすると、
改修時にループ全体を見渡す必要が出てしまいます。
それを軽減しているのですね。
独立したコードは、独立しているとわかるように書くと、
ロジックの掴みやすい、読みやすいコードを書くことができます。
理想はプロシージャ分割
せっかく「独立したコード」が書けたので、
さらにいい書き方をしましょう。
Call データの全行を処理Aする Call データの全行を処理Bする Call データの全行を処理Cと処理Dする
と、プロシージャに分けるのです。
処理A,B,C,Dは実際は10行の処理なので、
全体で40行になっており、処理Aからは処理Dが見えません。
プロシージャに分けると、A,B,C,Dの処理順が一望できるので、
処理の流れが格段につかみやすくなります。
また、各プロシージャの中で、それぞれ専用のFor文がループするため、
Sub データの全行を処理Aする For R = 1 To 10000 If is処理の中断条件を満たす Then Exit ○○ ' ←これをSubにするかForにするか選べる End If Next 処理Aの最後の処理 ' Exit For なら実行される。Exit Subなら実行されない。 End Sub
このように「Exit For」や「Exit Sub」を、処理A専用で使うことができます。
分岐の処理や処理の中断判定を、かなりキレイに書く道具になります。
「ループ部分を丸ごと関数化」は、
とても大事な関数分けポイントなので意識しておきましょう。
おまけ:本当に足し算分しか差は出ないのか?
本当に足し算だけの差なのでしょうか?
何とかして早くできないかな。
実は、「ループが1つ」なのを利用した高速化はあります。
処理Aの段階で、よく使う値を変数に入れておき、
それを処理B,C,Dでも使う方法です。
頻出の値を、
現ループの売上 = Cells(R, 2)
と変数に入れておいて、
セル値ではなく、変数「現ループの売上」を処理B,C,Dでも使えば、
「ワークシートのR行目を参照」
⇩
「変数を参照」
に、処理の内容を変えることができます。
参照先がオブジェクトからメモリに代わるので、
実際、少しですが早くはなります。(ほんの少しね)
ただし!
これは高速化の手法としては最低最悪です。
本来独立であるはず処理を、互いに影響が出るように、結合してしまっているからです。
たとえば、「処理Aで求める値が(税込)に仕様変更」されたとしましょう。
現ループの売上 = Cells(R, 2) * 1.1
無意味な結合に気づかず、↑こんな風にコード書き換えてしまうと、
処理B,C,Dが全滅します。
こういうことを繰り返した結果、
「どこを変えるとどこをに影響があるかわからなくなってしまった」コードを、
からまってしまったコード、俗にスパゲティコードと呼ぶのです。
独立した処理は、ちゃんと独立を保ちましょう。
パスタはペンネもおいしいですよ。