🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Calculation — 計算を手動にして高速化する(そして切ったまま忘れる静かな罠)

|

Excel VBA の Calculation — 計算を手動にして高速化する(そして切ったまま忘れる静かな罠)

TL;DRApplication.Calculation = xlCalculationManual は、書き込みのたびに再計算するのを やめて、すべての再計算を一度のパスにまとめるよう Excel に指示します。数式の多いブックでは、 これこそがマクロを本当に速くするスイッチで — 画面更新よりはるかに効きます。ただし VBA で もっとも危険なレバーでもあります。誤って手動のまま放置すると、数式はただ更新を止め、何の 見た目の合図もなく、ブックは古くて間違った数字を表示します。状態を保存し、エラーハンドラーの 中で戻し、運任せには決してしないでください。

Sub FastCalc()
    Dim savedCalc As XlCalculation
    savedCalc = Application.Calculation          ' 元が何だったかを覚えておく
    Application.Calculation = xlCalculationManual ' 書き込みごとの再計算を止める
    On Error GoTo CleanExit
    ' ... 何千もの書き込み、その間の再計算はゼロ ...
    Application.Calculate                         ' 結果が必要になったら一度だけ再計算を強制
CleanExit:
    Application.Calculation = savedCalc           ' Automatic を決め打ちせず、保存した状態に戻す
End Sub

マクロがセルへ書き込むたびに、Excel はそのセルが供給する依存関係の連鎖を丸ごと再計算します。数式の 重いブックでは、その再計算こそが — 画面ではなく — 本当のボトルネックです。手動モードは、まず何千も の書き込みを着地させ、再計算を一度だけ行います。本記事は 1 つの考えを軸にしています — Calculation は速度を買うスイッチであり、そして失敗が目に見えないがゆえに、決して切ったまま残す 余裕のないスイッチである。 この非対称性を掴めば、必要なだけの敬意をもってこれを扱えるように なります。

この記事で学べること

  • 考え方の軸 — 書き込みのたびに完全な再計算が走る。手動はそれを一度のパスに先送りする
  • 数式の多いブックで本当の速度の勝ちになる理由(そして ScreenUpdating がそうではない理由)
  • 最も大事なルール — 手動状態が残ると、警告なしに古い数字が表示される
  • 後の処理が結果を必要とするとき、Application.Calculate でマクロの途中で再計算を強制する
  • xlCalculationAutomatic を決め打ちせず、保存した状態に戻す
  • ブックが開いていないときに Calculation を設定すると出る error 1004

考え方の軸:書き込みのたびに再計算が走る

Excel の既定は xlCalculationAutomatic です。どれかのセルが変わった瞬間に、Excel はそれに依存する すべての数式を、連鎖的に再計算します。手作業では、まさにそれが望みどおりです — 数字を打てば合計が 更新される。けれど 10,000 セルへ書き込むマクロの中では、Excel は完全な依存関係の再計算を最大 10,000 回走らせ、実際のモデルでは一回のパスが何千もの数式に触れることがあります。

Application.Calculation = xlCalculationManual は、その結びつきを断ちます。書き込みはセルへ着地 しますが、あなたが指示する(またはユーザーが F9 を押す)まで Excel は再計算しません。書き込みを すべて安く済ませてから、最後に一度の再計算を起こします。

Application.Calculation = xlCalculationManual
Range("A1:A10000").Value = someArray   ' 10,000 個の値を投入、再計算はゼロ
Application.Calculate                    ' 再計算は一度きり

状態は 3 つ、xlCalculationAutomaticxlCalculationManual、そして xlCalculationSemiautomatic (データテーブルを除いて自動)です。マクロで気にかけるのは最初の 2 つです。

これが本当の速度の勝ちになる理由

マクロの速度スイッチには序列があり、人はそれを間違った順で手に取ります。 ScreenUpdating は有名なほうですが、取り除くのは画面の再描画だけ です。VLOOKUPSUMIFS、あるいは OFFSETINDIRECT のような揮発性関数だらけのブックでは、 再描画は再計算の隣ではごくささいなものです。ScreenUpdating だけを切っても、計算に縛られたマクロは ほとんど速くなりません。Calculation を切れば、数分が数秒になりえます。数式の多いブックでスイッチ を一つだけ設定するなら、これにしましょう。この 2 つを合わせ — さらにセル単位でループする代わりに 配列を丸ごと書き込むこと — が、標準的な高速マクロのレシピです。

最も大事なルール:手動状態が残ると静かに壊れる

Calculation が危険なスイッチである理由がこれです。ScreenUpdating が切れたままなら、見えます — 画面がフリーズしています。Calculation が手動のまま残ると、何も 見えません。ブックはまったく正常に見えます。けれど、あらゆる数式は最後に計算された値で凍りついて います。誰かが入力を編集しても合計は変わらず、その人はずっと後で気づくか — もっと悪いことに — 気づかず、古い数字の上に作ったレポートを送ってしまいます。

これは VBA で最も損害の大きい残留状態です。まさに、誰かが間違った数字を信じるまで症状が出ない からです。だから、見た目のスイッチよりも規律は厳しくなります。必ず戻し、そしてエラーハンドラーの 中で戻す — マクロ途中のクラッシュが、ブックを手動のまま置き去りにできないように。

' 脆い書き方 - ループがエラーになると、計算は手動のまま置き去りにされ、
' ブック内のあらゆる数式が静かに更新を止める:
Application.Calculation = xlCalculationManual
DoRiskyWork
Application.Calculation = xlCalculationAutomatic   ' エラー時には決して到達しない

直し方は TL;DR の CleanExit パターンです。On Error GoTo CleanExit、そしてラベルの中で戻す。 詳しくは VBA On Error を参照してください。

Automatic を決め打ちせず、保存した状態に戻す

ほとんどのチュートリアルは、マクロを Application.Calculation = xlCalculationAutomatic で締めくくり ます。それは化けたバグです。ユーザーは意図的にブックを手動モードにしていたかもしれません — 重いモデルは、キー入力のたびに再計算しないよう手動のままにされることが多いのです。あなたのマクロが 走り、いまや相手のブックを黙って自動に切り替えてしまい、まさに相手が避けていた遅い再計算を 引き起こします。

正しいパターンは、見つけたものを保存し、それを戻すことです。

Dim savedCalc As XlCalculation
savedCalc = Application.Calculation       ' 手動かもしれないし、自動かもしれない
Application.Calculation = xlCalculationManual
' ... 処理 ...
Application.Calculation = savedCalc       ' 見つけたときのままブックを残す

マクロは、勝手に思い込んだ状態ではなく、借りた状態のまま環境を残すべきです。これは、 ScreenUpdating の入れ子呼び出しのちらつきを遠ざけるのと同じ「保存 して復元する」習慣です。

後の処理が結果を必要とするときに再計算を強制する

手動モードには、復元とはまったく関係のない第二の罠があります。マクロが数式を書き、そのあとそれらの 数式が生む結果を読むと、読み取りは古いままです — 数式がまだ再計算されていないからです。

Application.Calculation = xlCalculationManual
Range("B1").Formula = "=SUM(A1:A100)"
Debug.Print Range("B1").Value    ' 古い - B1 はまだ再計算されていない
Application.Calculate            ' いま再計算する
Debug.Print Range("B1").Value    ' 正しい

後の処理が、前の書き込みが計算したはずの値に依存するときはいつでも、先に Application.Calculate (アプリケーション全体)、ActiveSheet.Calculate(1 枚のシート)、または Range.Calculate(1 つの 範囲)を呼びましょう。手動モードでは、結果は最後の Calculate 呼び出しと同じ新しさしか持ちません。

ブックが開いていないときの error 1004

最後の落とし穴:Application.Calculation は、ブックが開いているときにしか設定できません。ブックが 一つも存在しない状態で、アドインやスタートアップルーチンから設定すると 実行時エラー 1004 が発生 します。コードが Excel のライフサイクルの早い段階で走るなら、プロパティに触れる前に If Workbooks.Count > 0 Then でガードしましょう。

ExcelMaster の活用

Calculation は 3 つのスイッチの中で最大の高速化をもたらし、最大のリスクを背負います。正しく使う ということは、前の状態を保存し、後の処理が数式の結果を読むときに再計算を強制し、保存した状態を エラーハンドラーの中で戻し、そしてブックが開いていないと 1004 を投げうると知っていることを意味 します。どれか一つでも外せば、クラッシュか、もっと悪いことに、静かに古い数字だらけのブックが手に 入ります。

ExcelMaster は、その一連の パターンを丸ごと引き受けます。仕事を述べれば — 「前提を更新したあと、このモデルを再計算して」 — 手動モードに設定し、書き込みを行い、結果が必要なところぴったりで Application.Calculate を呼び、 開始時の計算状態を CleanExit ハンドラーの中で戻します。ブックはユーザーが残したそのままで、ただ 速く、返ってきます。

よくある質問

Application.Calculation = xlCalculationManual は何をしますか?

変更のたびに Excel が数式を自動で再計算するのを止めます。書き込みは相変わらずセルへ着地しますが、 Application.Calculate を呼ぶかユーザーが F9 を押すまで、どの数式も再計算されません。数式の多い ブックでは、これはマクロに使える単一の高速化として最大のもので、何千もの再計算を一度に置き換える からです。

マクロを走らせたあと数式が更新されなくなったのはなぜですか?

ほぼ間違いなく、マクロが Application.Calculation = xlCalculationManual を設定して戻さなかったの です — たいていは戻す行の手前でエラーになったせいです。ブックはいま手動モードで、数式は見た目の 合図なしに最後に計算した値を保ちます。Application.Calculation = xlCalculationAutomatic に設定する (または F9 を押す)とともに、コードではエラーハンドラーの中で設定を戻し、二度と置き去りにされない ようにしましょう。

Calculation は Automatic に戻すべきですか、それとも元の状態に戻すべきですか?

元の状態に戻しましょう。まず値を保存し(savedCalc = Application.Calculation)、最後に savedCalc へ戻します。xlCalculationAutomatic を決め打ちすると、重いモデルを意図的に手動のまま にしているユーザーを黙って上書きし、相手が避けていた遅い再計算を強いてしまいます。

手動モードのとき、VBA で再計算を強制するには?

すべてを再計算するには Application.Calculate、1 枚のシートには ActiveSheet.Calculate、1 つの 範囲には SomeRange.Calculate を呼びます。後の処理が、前の数式の書き込みが生んだはずの値を読む ときは、つねにこれが必要です — 手動モードでは、計算するまでそれらのセルは古いままです。

Application.Calculation を設定すると error 1004 になるのはなぜですか?

Application.Calculation は、ブックが開いているときにしか設定できないからです。コードがスタート アップ時に、あるいはブックが一つも存在する前にアドインから走ると、その代入は実行時エラー 1004 を 発生させます。プロパティを設定する前に If Workbooks.Count > 0 Then でガードしましょう。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-17。

関連ガイド: VBA ScreenUpdating · VBA EnableEvents · VBA On Error · VBA Range · VBA WorksheetFunction