VBA高速化の裏ワザ集|重い処理を一瞬に変えるプロのTips

VBA & Excel
スポンサーリンク

朝9時に「このマクロ、すぐ終わるはず」とポチッと実行——。

気がつけば、お昼休憩が終わってもExcelはまだ『実行中』。

モニターを見つめるだけの時間に虚無が広がり、 とうとう私の作業PCが“高級砂時計”と化した日がありました。

原因は…そう、自作のマクロです。 何万行ものデータを1セルずつ丁寧に処理し、無駄に画面をチラチラ更新し、 「君、真面目すぎるんだよ」と言いたくなるようなコードでした。

結果、3万件のデータの処理に6時間もかかり、ドッと疲れた心が残り、 「あぁ…これ、私が書いたんだよな」とちょっと情けなくもなったのを覚えています。

でも、そんな私でも分かりました。

VBAマクロって、ちょっとした書き方で劇的に速くなるって。

この記事では、かつての私のように “遅いマクロに人生の貴重な時間を奪われている人”のために、 初心者でも実践できるVBA高速化の裏ワザをまとめました。

あの6時間、今なら3分で終わらせられます。(…たぶん)

スポンサーリンク
  1. はじめに:そのマクロ、なぜ遅い?
  2. マクロが遅くなる主な原因とは?
    1. その1:Select や Activateを多用している
    2. その2:セルを1つずつ処理している
    3. その3:画面更新や再計算がオンのまま
    4. その4:処理対象の範囲がムダに広い
    5. まとめ:それ、ちょっとしたことで速くなります
  3. 裏ワザ①|画面描画&自動計算を止める
    1. 画面描画:見なくていいのに律儀に更新しようとするExcelさん
    2. 自動再計算:几帳面すぎる数式チェックは一時停止でOK
    3. 実際に使うときのおすすめセット
    4. まとめ
  4. 裏ワザ②|ループは極力やめて配列で一括処理
    1. 1セルずつ処理=“超スロー宅配便”
    2. 配列で一括処理すると世界が変わる
    3. 実際にやってみた(体験談)
    4. ワンポイント:配列の行列インデックスに注意!
    5. まとめ
  5. 裏ワザ③|With構文や変数活用で無駄を省く
    1. With構文でまとめて効率アップ!
    2. WorksheetやRangeを変数に格納するのもおすすめ
    3. おまけ:With構文と変数を組み合わせると最強説
    4. まとめ:小さな書き方の工夫が積もると“大違い”
  6. 裏ワザ④|処理結果を途中で出力・可視化しない
    1. Debug.Printがたくさんあるとどうなる?
    2. MsgBoxの多用はもっと危険
    3. じゃあどうすればいいの?
    4. ちょっと応用:ログの出力先を選べるようにする
    5. まとめ:見せたい気持ちもわかるけど、ほどほどに
  7. ビフォーアフター|どれだけ速くなったか検証!
    1. Before:改善前のマクロ処理時間(実話です)
    2. After:改善後のマクロ処理時間
    3. 計測コードも載せておきます!
  8. よくある質問(Q&A)で疑問も解消
    1. Q1:いろいろ改善したのに、まだ遅いのはなぜ?
      1. A:根本的に“処理対象が大きすぎる”か、“外部アプリ連携”がボトルネックになっている可能性があります。
    2. Q2:配列を使ったら逆にややこしくなったんですが…
      1. A:最初は戸惑いますが、「1回覚えると世界が広がる系」の技術なので大丈夫!
    3. Q3:高速化のために書き方を見直したらバグが増えました…
      1. A:それ、“やりすぎ高速化”かもしれません。丁寧さとスピードは共存できます!
    4. Q4:本番運用では結局ログとか必要じゃないですか?
      1. A:その通り。でも“見せ方”と“タイミング”で高速化は維持できます。
  9. おわりに|“効率化の達人”への第一歩

はじめに:そのマクロ、なぜ遅い?

Excelでマクロを動かすとき、ふと「この処理、なんか遅くない?」と感じたことはありませんか?

実は私もかつて、そんな「遅いマクロ」に人生の貴重な時間を奪われていたひとりでした。

たとえば、月初の請求データを処理するマクロ。

「今月こそはスマートにいける!」とボタンを押したはずが——

結果:Excelがフリーズ。カーソルが砂時計に。気づけば自分もフリーズ。

別ウィンドウで進捗を確認しようにも、「応答なし」の無言の圧。

しょうがなく待っているうちに別の作業を始めたら、戻った頃にはまたエラー。

極めつけは、大量データを処理するマクロが6時間かかって、残業確定になったときの虚無感。

あれは今思い出しても胃が痛い。

そして何より悔しかったのは—— 「これ、自分が書いたんだよな…」というあの切ない自己責任感です。泣ける。

でも、そこで気づいたんです。 遅いマクロには、ちゃんと遅くなる理由がある。

そして、それをちょっと直すだけで劇的に速くなる方法があるということも。

この記事では、そんな私の“やらかし経験”をもとに、 初心者でも実践できるマクロ高速化の基本と裏ワザを紹介していきます。

今マクロを待ちながらこの記事を読んでいるあなた。大丈夫、今日から変われます。

マクロが遅くなる主な原因とは?

さて、あなたのマクロが遅い理由——それは、たいてい「よくあること」が積み重なった結果です。

「えっ、そんなことで?」と思うような些細なことが、処理時間の地雷になっていることはザラにあります。

ここでは、私もかつてやらかした“VBA初心者あるあるな原因”を交えて紹介していきますね。

その1:Select や Activateを多用している

Range("A1").Select
Selection.Value = "こんにちは"

一見何の問題もなさそうに見えるこのコード。

ですが、実はこれは“遠回りな書き方”なんです。

Select や Activate を挟むと、Excelは毎回「よし、画面を切り替えるぞ!」と全力でがんばろうとします。

そのせいで、処理が目に見えて重くなるんですね。特にループ内で使うと地獄絵図に。

その2:セルを1つずつ処理している

For i = 1 To 10000
    Cells(i, 1).Value = Cells(i, 1).Value * 2
Next i

このスタイル、初心者のうちは「まあ普通では?」と思いがち。

でも実はこれ、1行ずつExcelとやり取りしてる状態なんです。

人間にたとえると、毎回ひとこと話すたびに部屋から出て戻ってきてるようなイメージ。

それは疲れるし、時間もかかりますよね…。

その3:画面更新や再計算がオンのまま

VBAを動かすたびに、Excelは律儀に

  • 画面の状態を更新し、
  • 数式を再計算し、
  • “何か変わったかな?”と一生懸命チェックし続けています。

真面目で偉い。でもそれ、今はいらないんです。

作業中は「画面のことは気にせず処理に集中してくれ!」と一声かけるだけで、ぐっと快適になります。

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

そして最後に元に戻すのも忘れずに。

Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic

その4:処理対象の範囲がムダに広い

マクロで UsedRange を使っていたら、目に見えないゴミのようなデータまで含まれていた、なんてことも。

空白だと思っていたセルに、実は1個だけスペースが入ってる…とか、地味〜な罠が潜んでいるので、本当に必要な範囲だけ処理するように意識しましょう。

まとめ:それ、ちょっとしたことで速くなります

遅いマクロには、だいたい理由があります。しかも、その理由は「気をつければ避けられたかも」というものが大半。

この章で紹介したようなポイントを見直すだけで、

  • 「マクロ=待ち時間」だった日々
  • 「Excelが応答しない」とにらめっこする時間 から卒業できます!

次の章では、実際にどんな裏ワザがあるのか、わたし流の“高速化Tips”を紹介していきますよ 。

裏ワザ①|画面描画&自動計算を止める

マクロが遅くなる原因の中でも、真っ先に改善すべき「2大ボトルネック」があります。

それが、画面の更新(ScreenUpdating)と、シートの再計算(Calculation)です。

画面描画:見なくていいのに律儀に更新しようとするExcelさん

VBAが動いている間、Excelはまるで“実況中継”をしているかのように、処理のたびに画面を更新し続けます。

セルに何か書き込むたびに、 > 「A1セルに入力されたぞ〜」 > 「次はB1に移動して〜」 > 「グラフの表示を変更中です〜」

というような裏側の動作が、延々と行われているんですね。

でも……正直、その実況中継、今は要らないんです。

なので、マクロ実行中は画面更新を止めてしまいましょう。

Application.ScreenUpdating = False

これだけで、大幅に処理が軽くなることがあります。

そして忘れちゃいけないのが、最後にTrueへ戻すこと!

Application.ScreenUpdating = True

戻し忘れると、マクロ終了後も画面が更新されないままになって、「あれっ?Excel壊れた?」と慌てる羽目に…。

自動再計算:几帳面すぎる数式チェックは一時停止でOK

Excelはとっても真面目な子です。 セルをひとつ変えるたびに、全シートの数式を再計算してくれます。

えらいけど、それが処理スピードを大きく下げる要因になっていることも…。

そこで、マクロ実行中は一時的に計算モードを「手動」に切り替えておくと快適になります。

Application.Calculation = xlCalculationManual

処理が終わったら、自動モードに戻しておくのも忘れずに!

Application.Calculation = xlCalculationAutomatic

こうすることで、必要なときだけ再計算され、無駄がなくなります。

実際に使うときのおすすめセット

処理の最初と最後に、下記のようなテンプレを入れておくと安心です:

Sub 高速処理マクロ()
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    ' ここに本処理を書く
    ' ...

    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub

まとめ

この2つの設定だけでも、体感速度はまるで別物! いわば「Excelにちょっと休んでてもらう」イメージですね。

次の章では、「1セルずつ真面目にループする」問題にメスを入れていきます。 マクロが“秒速”になる魔法のワザ、まだまだ続きますよ。

裏ワザ②|ループは極力やめて配列で一括処理

VBAでよくある書き方に、こんなコードがあります:

For i = 1 To 10000
    Cells(i, 1).Value = Cells(i, 1).Value * 2
Next i

このコード、いかにも「がんばってる感」はあるのですが……処理速度という面では残念ながら赤点です。

1セルずつ処理=“超スロー宅配便”

この書き方は、ExcelとVBAの間で毎回データをやり取りしています。

人間にたとえるなら、「1行のデータを処理するたびに、隣の部屋に移動して報告→また戻って次の行」という作業を1万回繰り返しているようなもの。

そりゃ時間もかかりますよね…。

配列で一括処理すると世界が変わる

ここで登場するのが配列(Array)を使った処理です。

1万行をまとめて読み込んで、まとめて書き戻すだけで、処理速度が劇的に変わります。

例:配列で処理するコード

Sub 一括処理デモ()
    Dim data As Variant
    Dim i As Long

    ' 一括読み込み
    data = Range("A1:A10000").Value

    ' 配列内で処理(ここでは×2してみる)
    For i = 1 To UBound(data, 1)
        data(i, 1) = data(i, 1) * 2
    Next i

    ' 一括書き戻し
    Range("A1:A10000").Value = data
End Sub

これだけのことで、処理時間が数十秒→1秒未満になることもあります。

実際にやってみた(体験談)

私のケースでは、1万5,000件の売上データをループで計算していたとき、約40秒かかっていた処理が、配列を使ったら1.6秒に!

最初は「え?もう終わったの?」とExcelを疑いました(笑)

ワンポイント:配列の行列インデックスに注意!

VBAでRangeを読み込んだ配列は、1から始まる二次元配列になります。 たとえば Range(“B2:C4”) を読み込んだ場合:

data(1,1) → B2 の値  
data(2,2) → C3 の値

ここを勘違いすると「変なとこ書き換えちゃった!」ってなりやすいので、最初は単列 or 小さめの範囲で試して慣れていくのがおすすめです。

まとめ

マクロの処理を速くしたいなら、「ループ処理が重い」という常識をまず疑うのが第一歩。

配列による一括処理は、まさに「根本的に早くなる考え方」です。

次の章では、地味だけど大事な「With構文や変数の活用」で、さらに処理をスリムにしていきますよ。

VBAの書き方改革は続きます!

裏ワザ③|With構文や変数活用で無駄を省く

VBAが遅くなる原因のひとつに、「同じ場所を何度も指定している」問題があります。

たとえばこんなコード、見覚えありませんか?

Worksheets("月次報告").Range("B2").Value = "売上"
Worksheets("月次報告").Range("B3").Value = "利益"
Worksheets("月次報告").Range("B4").Value = "成長率"

一見問題なさそうですが、実は毎回”Worksheets(“月次報告”)”を呼び出していることで、処理が無駄に重くなっている可能性があります。

With構文でまとめて効率アップ!

そんなときは With 構文の出番です。

With Worksheets("月次報告")
    .Range("B2").Value = "売上"
    .Range("B3").Value = "利益"
    .Range("B4").Value = "成長率"
End With

こうすると、対象のオブジェクトを1回だけ指定して、その中身をまとめて操作できるようになります。

地味に見えて、実はめちゃくちゃ効果的。

可読性もアップして、修正もしやすくなる一石三鳥。

WorksheetやRangeを変数に格納するのもおすすめ

さらに効率的にするなら、よく使うワークシートやセル範囲を変数に格納してしまいましょう。

Dim ws As Worksheet
Set ws = Worksheets("月次報告")

ws.Range("B2").Value = "売上"
ws.Range("B3").Value = "利益"

このようにしておくと、コードの見通しがぐっとよくなります。

変数名も wsMonthly など意味が分かりやすいものにすれば、数か月後に見返しても「何やってるか」が分かりやすくなりますよ。

おまけ:With構文と変数を組み合わせると最強説

Dim ws As Worksheet
Set ws = Worksheets("月次報告")

With ws
    .Range("B2").Value = "売上"
    .Range("B3").Value = "利益"
End With

こうすれば、無駄なオブジェクト参照を削減しつつ、可読性も最高レベルに。

VBA初心者の頃は「With?なんか難しそう」と敬遠しがちですが、慣れたらもう戻れません。

まとめ:小さな書き方の工夫が積もると“大違い”

この章のポイントは、「Excelに何度も同じことを言わない」こと。

オブジェクト参照を何度も繰り返すのは、まるで上司に「会議の時間って何時でしたっけ?」と5回も聞いてるようなもの。

そりゃ効率落ちますよね…。

With構文と変数をうまく使えば、処理もスマートに、読みやすさも抜群になります。

次の章では、処理中の余計な出力(ログやポップアップ)がパフォーマンスに与える影響を見ていきましょう。

マクロ高速化への道はまだまだ続きますよ!

裏ワザ④|処理結果を途中で出力・可視化しない

「ちゃんと動いてるか不安だから、処理の途中でログ出してみよう」

「毎回メッセージボックスで中間結果を見て確認してる」

——その気持ち、すごくわかります。私も以前、マクロを動かすたびに「Debug.Print」と「MsgBox」を量産していました。

でも、実はそれ、処理のスピードをじわじわと遅くする見えない罠なんです。

Debug.Printがたくさんあるとどうなる?

Debug.Print は、イミディエイトウィンドウにログを出力するだけなので「軽い処理」と思われがち。

しかし、大量に実行されると 処理速度に影響を与える原因 になることがあります。

特に、1万件をループして Debug.Print を呼び出していると、思っている以上に遅延を生んでいることも。

「この値ちゃんと入ってるかな?」

「あれ?ここって何件処理された?」

→ それ、あとでまとめて出力した方が速いです。

MsgBoxの多用はもっと危険

そしてさらに問題なのが MsgBox。

処理の途中で止まって「OKボタンをクリックしないと進まない」という仕様が、バッチ処理では完全に足かせになります。

処理が止まりまくる → 確認しすぎて進まない → 本来の業務が終わらない

…と、せっかくのVBA自動化も「人間が立ち会ってないとダメ」なものに逆戻りしてしまいます。

じゃあどうすればいいの?

処理中に様子を見たいときは、ログを一時的に文字列に貯めて、最後に一括で出力するのがおすすめです:

Dim logText As String

For i = 1 To 10000
    ' 何かの処理
    logText = logText & "処理行: " & i & vbCrLf
Next i

Debug.Print logText

もしくは、処理結果をワークシートに一気に書き出すという方法も、実行スピードへの影響が少なくておすすめです。

ちょっと応用:ログの出力先を選べるようにする

後々の拡張性も考えるなら、下記のように「ログ出力先を選べる仕組み」を用意するのも便利です:

Enum LogMode
    ToDebug
    ToSheet
    ToNone
End Enum

Sub 処理ログ出力(Optional mode As LogMode = ToDebug)
    ' ログ出力処理
End Sub

こうしておけば、開発中はログ多め/本番用マクロでは出力なしという切り替えが柔軟にできますよ!

まとめ:見せたい気持ちもわかるけど、ほどほどに

「ちゃんと動いてるかな?」と心配になるのは、VBA初心者のころあるあるです。

でもマクロを速くしたいなら、処理中の出力は“最低限”にするのがベスト。

ログはあとからまとめて見る or 必要なときだけ。

それだけでも、あなたのマクロはスイスイ動き始めます。

次の章では、いよいよビフォーアフターで処理速度がどれだけ変わるかを実例つきでお見せします!

ビフォーアフター|どれだけ速くなったか検証!

「VBA高速化のテクニック、いろいろ教えてくれたけど…で、実際どれくらい速くなるの?」 と思った方、はい、わかります。私もそうでした。

なので、今回はちゃんと“ビフォーアフター”をご用意しました。

VBAマクロも“ダイエット後の姿”を見せないと信頼されませんからね。

Before:改善前のマクロ処理時間(実話です)

以前、私はこんなマクロを書いていました:

  • 1万行のデータをループで1件ずつ処理
  • .Select 付き
  • 画面更新も計算もオンのまま
  • Debug.Print 全開

実行ボタンを押してから、結果が出るまでに約42秒。

途中で「おやつ取りに行けるかも」と離席できるレベルでした。

いや、できれば席を立ちたくないのが理想なんですが…。

After:改善後のマクロ処理時間

改善したマクロはこうです:

  • 画面更新&自動計算オフ
  • Rangeを配列で一括処理
  • With構文&Worksheetの変数活用
  • Debugログは最小限で後出し式に

結果:処理時間はなんと「約1.8秒」。

もう笑うしかないレベルの爆速です。

Before:42秒  
After :1.8秒(約96%短縮)

Excelから「もう終わったよ」って言われて、 「嘘でしょ、まだ途中でしょ?」と信じられなかったのが最初の感想です(笑)

計測コードも載せておきます!

処理時間を測るときは、こんなコードが便利です:

Sub 計測付きマクロ()
    Dim startTime As Double
    startTime = Timer

    ' マクロ処理を書く
    Call 実行処理

    MsgBox "処理時間: " & Round(Timer - startTime, 2) & "秒"
End Sub

Timer関数は「0時からの秒数」を返すので、処理前後の差分をとるだけで簡単に計測できます。

よくある質問(Q&A)で疑問も解消

ここまで読み進めてくださったあなた、ありがとうございます!

「ちょっとマクロ高速化できそうかも…!」とワクワクしてきた反面、きっとこんな疑問もあるはずです。

この章では、私がVBA初心者だった頃に感じていた「モヤモヤ」や、実際に読者からよく聞かれる質問をまとめてお答えしていきます。

Q1:いろいろ改善したのに、まだ遅いのはなぜ?

A:根本的に“処理対象が大きすぎる”か、“外部アプリ連携”がボトルネックになっている可能性があります。

たとえば…

  • 処理対象が数十万行のレコード
  • AccessやOutlookと連携している
  • ネットワーク上のファイルを逐次処理している

こういったケースでは、そもそも「Excelだけで高速化できる限界」を超えていることも。処理を分割したり、一部を別のツールに任せる(VBA+PowerQueryなど)という選択肢もアリです!

Q2:配列を使ったら逆にややこしくなったんですが…

A:最初は戸惑いますが、「1回覚えると世界が広がる系」の技術なので大丈夫!

私も初めて2次元配列を使ったときは、「え、行と列どっちがどっち!?」となりました(笑)

でも慣れてくると、高速化・コードの整理・自由度すべてが段違いになります。

※もしややこしくなってきたら、まずは1列だけのデータから始めるのが安心です。

Q3:高速化のために書き方を見直したらバグが増えました…

A:それ、“やりすぎ高速化”かもしれません。丁寧さとスピードは共存できます!

たとえば、

  • 可読性を犠牲にして一行に詰め込む
  • ロジックをいじりすぎて仕様からズレる
  • セル参照がズレても気づけなくなった

など、高速化に夢中になりすぎて“何してるか分かりにくいコード”になってしまうこともあります。

「読みやすさ」と「スピード」のバランスを意識すること、それが真の高速化です!

Q4:本番運用では結局ログとか必要じゃないですか?

A:その通り。でも“見せ方”と“タイミング”で高速化は維持できます。

記事でも紹介したように、

  • ログは後からまとめて出す
  • メッセージ表示は開発中だけ
  • 処理件数だけを軽く表示する など

運用目的に応じて“出力の仕組みを切り替えられるコード”を用意しておくと、安定&高速なマクロ運用ができますよ。

おわりに|“効率化の達人”への第一歩

かつて私は、自作マクロの処理が終わるのを黙って待ちながら、 「Excelが止まってる間に、私の仕事も止まってる…」 なんてことを何度も繰り返してきました。

大量のデータ処理に6時間、 応答なしの画面とにらめっこしながら、 「自分で作ったのになんでこんなに使いにくいんだろう」と情けなさを感じたり。

でもそこから、“処理速度”という視点を持って、 ほんの少しマクロの書き方を変えただけで、驚くほどスムーズに動くことを体感できました。

  • Application.ScreenUpdating = False と書くだけで画面がサクサクになる
  • ループではなく配列を使うだけで数十倍速くなる
  • 「読みやすく、速く、かっこいい」コードを書くのが少し楽しくなる

そうして分かったのは、マクロの高速化は、特別な人だけの技術ではないということ。

ちょっと書き方を工夫すれば、 誰でも“効率化の達人”になれるということです。

decopon
decopon

もし今、「自分が書いたマクロが遅くて困っている」という人がいれば、 この記事が“次の一歩”を踏み出すヒントになれたら嬉しいです。

そして願わくば、これからあなたが「速くて快適なマクロ」を作っていく中で、 自分だけでなく、周囲の誰かの時間も救えるようになりますように。

そのとき、今回ご紹介したTipsたちが、あなたの“秘密兵器”になってくれたら幸いです。

コメント

タイトルとURLをコピーしました