計算モード変更
数式が多いブックでは、再計算が処理速度のボトルネックになりがちです。計算モードを一時的に切り替えて「必要なときだけ再計算」するだけで、体感速度が劇的に向上します。初心者でも使い回せるテンプレートと、狙い撃ちの再計算パターンをまとめました。
計算モードの種類と使い分け
- 自動(xlCalculationAutomatic):
すべての変更に応じて即再計算。通常運用に最適だが、大量書き込み中は遅くなる。 - 手動(xlCalculationManual):
計算は明示的にトリガーするまで止まる。大量の貼り付けや値更新の「処理中だけ」使うのが定石。 - 準自動(xlCalculationSemiautomatic):
依存関係の一部だけ再計算(テーブルやデータテーブルの再計算を抑えたいときに選択肢になる)。 - 再計算コマンド(代表例):
- Application.Calculate(ブック全体)
- Worksheet.Calculate(シート単位)
- Range.Calculate(範囲単位)
- Application.CalculateFull / CalculateFullRebuild(依存解決の全面再構築)
安全テンプレート:元の設定を復元する
Sub CalcMode_SafeWrap()
Dim origCalc As XlCalculation: origCalc = Application.Calculation
Dim origScr As Boolean: origScr = Application.ScreenUpdating
Dim origEvt As Boolean: origEvt = Application.EnableEvents
On Error GoTo Cleanup
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'==== 本処理:大量の値書き込みなど ====
Range("C2:D50000").Value = Range("A2:B50000").Value
'=====================================
'必要なタイミングで再計算
Application.Calculate
Cleanup:
Application.EnableEvents = origEvt
Application.ScreenUpdating = origScr
Application.Calculation = origCalc
End Sub
VB- ポイント:
- 元の状態を保持: 実行前の設定を記憶し、必ず復元。
- エラー時も復元: Cleanupへ確実に流れる構造にする。
狙い撃ち再計算の定番パターン
'1) シートだけ再計算(全ブックを回したくない)
Sub Recalc_SheetOnly()
Application.Calculation = xlCalculationManual
Worksheets("明細").Calculate
Application.Calculation = xlCalculationAutomatic
End Sub
'2) 範囲だけ再計算(計算の重い列に限定)
Sub Recalc_RangeOnly()
Application.Calculation = xlCalculationManual
Range("E2:E100000").Calculate
Application.Calculation = xlCalculationAutomatic
End Sub
'3) 完全再計算(依存関係が乱れた疑いがある場合)
Sub Recalc_FullRebuild()
Application.Calculation = xlCalculationManual
Application.CalculateFullRebuild
Application.Calculation = xlCalculationAutomatic
End Sub
VB- ポイント:
- 範囲・シート単位: 不要な再計算を避けて時間短縮。
- FullRebuild: 名前定義や外部リンクで依存が乱れた場合の切り札。
実務テンプレ:計算と高速化の合わせ技
'大量行の計算列を一括更新→最後に1回だけ全体再計算
Sub FastUpdate_ThenRecalcOnce()
Dim origCalc As XlCalculation: origCalc = Application.Calculation
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'例:数量×単価→金額(配列で高速に計算)
Dim rg As Range: Set rg = Range("A2:D500000")
Dim v As Variant: v = rg.Value
Dim r As Long
For r = 1 To UBound(v, 1)
If IsNumeric(v(r, 3)) And IsNumeric(v(r, 4)) Then
v(r, 2) = v(r, 3) * v(r, 4)
Else
v(r, 2) = ""
End If
Next r
rg.Value = v
'必要なだけ再計算(全体)
Application.Calculate
Application.Calculation = origCalc
Application.ScreenUpdating = True
End Sub
VB- ポイント:
- 配列×手動計算: 無駄な再計算を抑え、書き戻し後に1回だけ再計算。
- 戻し忘れ防止: 終了時に必ず元へ。
例題で練習
'例題1:ピボット更新前後だけ再計算(安定運用)
Sub Example_RecalcAroundPivot()
Application.Calculation = xlCalculationManual
'ピボット更新やデータ整備
ActiveSheet.PivotTables(1).PivotCache.Refresh
'更新後に再計算
Application.Calculate
Application.Calculation = xlCalculationAutomatic
End Sub
'例題2:見えている行の集計だけ計算→最後に全体再計算
Sub Example_VisibleOnly_CalcThenFull()
Application.Calculation = xlCalculationManual
Dim area As Range: Set area = Range("A1").CurrentRegion
area.AutoFilter Field:=2, Criteria1:="営業A"
Dim vis As Range
On Error Resume Next
Set vis = area.Offset(1).Resize(area.Rows.Count - 1).Columns(1).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If Not vis Is Nothing Then
Dim c As Range
For Each c In vis
Cells(c.Row, "H").Value = Cells(c.Row, "C").Value * Cells(c.Row, "D").Value
Next c
End If
Application.Calculate
Application.Calculation = xlCalculationAutomatic
End Sub
'例題3:超重いブックで「準自動」に切り替えて負荷を軽減
Sub Example_Semiauto_Mode()
Dim orig As XlCalculation: orig = Application.Calculation
Application.Calculation = xlCalculationSemiautomatic
'重い更新作業…
Range("E2:E300000").Value = 0
'必要に応じて手動再計算
Application.Calculate
Application.Calculation = orig
End Sub
VB落とし穴とチェックリスト
- 元に戻し忘れ:
- 対策: かならず「元設定の退避+Cleanup」で復帰する。
- イベントの暴発・停止しっぱなし:
- 対策: EnableEvents を False→True に戻す。変更イベント多いブックでは必須。
- 再計算の嵐で遅い:
- 対策: 処理中は xlCalculationManual、終わりに1回だけ Application.Calculate。
- 範囲が広すぎる完全再計算:
- 対策: 可能なら Range/Worksheet 単位に絞る。FullRebuildは最終手段。
- テーブル/データテーブルの負荷:
- 対策: 準自動(xlCalculationSemiautomatic)も検討。重いテーブル計算を抑えやすい。
- 外部リンク・名前定義が複雑:
- 対策: 依存関係がおかしいと感じたら CalculateFull → それでもダメなら CalculateFullRebuild。
