和風スパゲティのレシピ

日本語でコーディングするExcelVBA

マクロの速度は、それを追求すべき場所でだけ追求する

マクロの高速化に関する考え方です。


マクロの処理速度はどこまで気にするべきか。
というテーマです。


プログラミングに限らず、訓練とか練習って

  1. 最初は量をこなすので精一杯
  2. だんだん慣れてきて、質にこだわれるようになる
  3. 今度は質を気にしすぎて、量がこなせなくなる
  4. 量と質のバランスが取れるようになる

という成長を遂げる気がします。

この3で感じるスランプ感から、
4へ抜け出す手助けになればいいなと思って書いていきますね。

注:ある程度の基本はおさえた前提の話です


最初に注意事項です。

Application.ScreenUpdating = False

で画面の描画を止めるとか、

Range("A1").Select
Selection = ○○

↑このSelectをやめるとかは、高速化ではなく基礎です。


今回題材にしてるのは、

  • このループ処理は参照が重複しちゃってるな~
  • Ifの組み方が無駄な判定をしてそうだな~
  • 違うメソッドを使った方が早いのかな~

などの、ロジック的なお話です。


「Selectしない」っていうのは、

  1. 最初は量をこなすので精一杯
  2. だんだん慣れてきて、質にこだわれるようになる
  3. 今度は質を気にしすぎて、量がこなせなくなる
  4. 量と質のバランスが取れるようになる

↑この話でいうところの「1から2の話」です。
速度を追及されない場面でも、Selectはしてはいけません。


まだ1の段階の方は、何でもかんでも高速化して、経験を積んだ方がいいです。
量をこなしていないのに、「効率よく高速化」なんてできませんからね。

1⇒2の訓練をサボる口実に、この記事を利用しませんように。
この記事の対象者は、3の方ですよ。


と保険をかけてから、本文に入ります。

マクロの速度には限界が(キリが)ない

まず大前提として、マクロを「理論上最速」にするのは不可能です。

ただのコードの精査ですら、高速にしようと思ったらいくらでも高速になりますし、
Excelを2つ立ち上げてマルチコアで処理みたいな、
とんでもマクロを見たこともあります。(私は作れません)


ひとまず、最速を目指すことは不可能なので、

「どうやって早くするか」よりも、「どこまで早くするか」を先に考えることが大事

というのをまずは意識しましょう。

まず一番は「なんのために」

どこまで早くするか を考えるには、
まず「どうして早くするのか」を考えましょう。


「そんなもん早くした方がいいからにきまってるだろ!」


と言わないでください。
例えば↓の高速化が出来そうだとします。

  • A:4時間 ⇒ 2時間
  • B:10分 ⇒ 5分
  • C:2秒 ⇒ 1秒

どれをやるべきでしょうか?


これだけだとまだイメージしずらいですね。

もっと詳しく書くと、

  • A:月1回の業務。実行して帰宅して、次の日の朝終わっていればいいマクロ
  • B:毎週月曜日の朝に実行しなければいけないマクロ
  • C:ツールバーにボタンを登録していて、ポチポチ使える汎用マクロ

こうだとします。


これで答えは出ましたね。

まっさきにCをやりましょう。

ツールバーのマクロが早いと快適で、仕事が捗ります。
逆にポチポチ押せるボタンの反応が悪いと、ストレスマッハですからね。

この1秒は重要な1秒です。


次いでBですが、まあやる必要が生じたらやりましょう。

休み明けの10分なんて、給湯室にいる間に過ぎ去りますし、
週初めのミーティングとかあるならその裏で実行すればいいです。


やってはいけないのはAです。
PCがスクリーンセーバーでお休みするまでの時間しか変わっていません。

Aのマクロに求められるのは、絶対に止まらない頑強性です。
Aのマクロが万が一転んでも、あなたはその時お風呂にいるのです。

華麗な高速化は、得てしてトリッキーだったりします。
そんなリスクを冒す場面ではありません。


こんな感じで、マクロにはマクロの目的があるので、
どれくらい短くできるかよりも、短くなったとき何がうれしいかの方が、
高速化には重要だったりします。

また、高速化には難読化も付きまとうので、
メンテがどれくらい発生するか = コードが読みやすいか
ともバランスをとる必要があります。


早くなったらうれしいかどうかを考えて、
嬉しい物だけを高速化しましょう。

次に「どこをはやくするか」

晴れて「早くした方がうれしいマクロ」は決まりました。


次にどうやって早くするかですが、その前に。


プログラムの性質として、

「すべての処理を早くするよりも、最も遅い処理を超早くした方が、
 全体の処理速度は早くなる」

という性質があることは知っておきましょう。


なので、まずは「一番遅い処理がどこか」を考えなければいけません。


なんですが、その処理を見分けるには、経験がものを言います。
なかなか「遅い処理はこれ!」というのは難しいです。

Debug.Print "○○の処理まで終了:" & Time

をコード内にちりばめておけば、
おおよそどの辺が遅いかは見当がつきますので、
後はどの処理が重くなっているか、がんばって調べましょう。


ということで、「どこをはやくするか」の見極めは訓練しかないのですが、
訓練しなくてもすぐに効果が出るものがあります。


それは「どこをはやくしても意味がないか」を意識することです。

これは何となくイメージできるんじゃないでしょうか?
一瞬で終わりそうな箇所には手を入れなくていいということです。

  • Integer より Longがはやい
  • Worksheets("シート名") より Worksheets(1) がはやい
  • Range("A1")よりCells(1, 1)がはやい

あたりの、うんちく好きが語るどうでもいい部分も、片っ端から無視していいです。


この判断が出来るようになるだけでも、

「速度を気にしてキリがない」状態を脱する、
ひとつのきっかけになると思います。

最後に「どう早くするか」

いよいよ高速化です。

どうやったら早くなるかを考えましょう。


当たり前ですが、「こうやれば早くなります」なんてありませんので、頑張って考えてください。

いままでの過程を経て「早くする意味あるかな?」とか、
余計なことで気が散らない頭になっているはずです。

集中して考える土台は整っていますので、
思う存分高速化してください。

まとめ

今回は「マクロの速度は、それを追求すべき箇所でだけ追求する」ということで、

  1. まずは「なんのために早くするのか」考える
  2. 次に「どこをはやくするのか」考える
  3. 最後に「どうやって早くするのか」考える

というお話でした。


マクロの早さが気になって、キリがないよ~に陥っていた人は、
早くする意味のないマクロ
早くしても無駄な処理
を意識するようにしてみましょう。

おまけ:やりたくなるけどやってはいけない高速化

早くする意味があまりなく
難読化するデメリットが大きい高速化が↓このあたりです。

1個のFor文で、なるべく多くのことを済ませようとする

www.limecode.jp

Elseを使って、Ifが同じ判定を何度もしないようにする

www.limecode.jp


「早くする意味なし!」と直感気付きにくいので、
意外とやってしまっている方は多いかもしれません。

やっちまっていた方は、
これを機にこれらの処理を「読みやすさ重視」にシフトしましょう。