VBA実行時エラー

実行時エラー11
「0で除算しました」の原因と対処

割り算の直前だけを確認しても、根本原因が見つからないことがあります。開始番号・終了番号の検索失敗によって分母が0になった例から、確認する順番を整理します。

このエラーを調べることになったのは、PowerShellから複数のExcelマクロを順番に実行している途中で、VBAの実行時エラー11「0で除算しました」が発生したためです。

処理では、開始番号から終了番号までの対象件数を求め、その件数を分母にして割合を計算していました。ところが、指定した番号がデータ内に見つからず、検索結果をもとに計算した分母が0になっていた可能性がありました。

エラーが出た割り算の行だけが原因とは限らない

0で割った行は、異常が表面化した場所です。実際の原因は、その前に行った番号検索やデータ取得の失敗にある場合があります。

BEFORE DIVISION

分母が0になるまでを遡って確認する

MicrosoftのVBAリファレンスでも、実行時エラー11は除数が0のときに発生し、割り算より前に行った変数の処理も確認するよう案内されています。

  1. 01
    開始番号を検索見つからない場合、開始位置を取得できない。
  2. 02
    終了番号を検索検索失敗を確認せず、そのまま処理が進む。
  3. 03
    対象件数を計算不正な検索結果から、分母になる件数が0になる。
  4. 04
    割合を計算この段階で初めて「0で除算しました」と表示される。

割り算を直すのではなく、分母を作った検索処理まで戻って確認する。

HIDDEN ERROR

検索失敗を見逃す問題のある例

Findで番号を検索した結果、対象がなければNothingが返ります。そのとき件数を更新しないまま処理を続けると、初期値の0が分母に使われます。

VBA / 問題のある例実行注意
Dim startCell As Range
Dim endCell As Range
Dim targetCount As Long
Dim defectRate As Double

Set startCell = targetRange.Find(What:=startNumber, LookAt:=xlWhole)
Set endCell = targetRange.Find(What:=endNumber, LookAt:=xlWhole)

If Not startCell Is Nothing And Not endCell Is Nothing Then
    targetCount = endCell.Row - startCell.Row + 1
End If

'targetCountが0なら実行時エラー11になる
defectRate = defectCount / targetCount

この例では、開始番号と終了番号のどちらかが見つからないとtargetCountが更新されず、初期値の0のままです。問題は割り算ではなく、検索できなかった時点で処理を終了しなかったことです。

VALIDATE FIRST

検索結果を確認してから計算する

次の例では、A7~A10000から開始番号と終了番号を検索します。どちらかが見つからない場合は計算せず、確認対象をメッセージで知らせます。

VBA / 安全な例
Option Explicit

Sub CalculateDefectRate()

    Dim ws As Worksheet
    Dim targetRange As Range
    Dim startPosition As Variant
    Dim endPosition As Variant
    Dim targetCount As Long
    Dim defectCount As Double

    Set ws = ThisWorkbook.Worksheets("集計")
    Set targetRange = ws.Range("A7:A10000")

    startPosition = Application.Match( _
                        ws.Range("B2").Value, targetRange, 0)
    endPosition = Application.Match( _
                        ws.Range("B3").Value, targetRange, 0)

    If IsError(startPosition) Or IsError(endPosition) Then
        ws.Range("B5").ClearContents
        MsgBox "開始番号または終了番号が見つかりません。", _
               vbExclamation
        Exit Sub
    End If

    targetCount = CLng(endPosition) _
                  - CLng(startPosition) + 1

    If targetCount <= 0 Then
        ws.Range("B5").ClearContents
        MsgBox "開始番号と終了番号の順序を確認してください。", _
               vbExclamation
        Exit Sub
    End If

    defectCount = CDbl(ws.Range("B4").Value)
    ws.Range("B5").Value = defectCount / targetCount

End Sub
Application.Match

見つからない場合はエラー値を返すため、IsErrorで判定できる。

+ 1

開始位置と終了位置を両方含めた件数として計算する。

targetCount <= 0

0だけでなく、開始・終了の順序が逆の場合も計算を止める。

ClearContents

計算できないときに、前回の割合を結果欄へ残さない。

i

シート名、セル位置、検索範囲は例です。実際のブック構成に合わせて変更してください。

ANOTHER CASE

別ファイルの生産数が0になる場合

同じエラーは、不具合率を「不具合件数÷生産数」で求める処理でも発生します。月が替わった直後など、別のExcelファイルから取得する生産数がまだ更新されておらず、セルに数値の0が入っているケースです。

この場合、0を一律に割合0%へ置き換えると、「不具合なし」と「生産数未取得」を区別できなくなります。

生産数 0 / 不具合 0計算しない

未取得または生産実績なしとして、結果欄を空白にします。

生産数 0 / 不具合あり異常として停止

データの組合せに矛盾があるため、確認を促して処理を止めます。

VBA / 生産数を確認する例
If productionCount = 0 Then

    resultCell.ClearContents

    If defectCount > 0 Then
        MsgBox "生産数が0ですが、不具合件数があります。", _
               vbExclamation
        Exit Sub
    End If

    '生産数が取得できるまで計算しない
    Exit Sub

End If

resultCell.Value = defectCount / productionCount

可能であれば、取得元ファイルの存在、対象月、更新日時も確認します。数値の0だけでは「本当に0」なのか「まだデータがない」のか判断できないためです。

SUMMARY

割る前に、分母が作られた過程を確認する

  • 実行時エラー11は、分母が0の状態で割り算をしたときに発生する
  • 開始番号・終了番号の検索失敗が、後の0除算として表面化することがある
  • 検索結果がNothingやエラー値でないか確認してから計算へ進む
  • 検索結果、順序、件数を確認してから割合を計算する
  • 業務データの0は、「未取得」「本当に0」「データ不整合」を分けて扱う

割り算の直前にIf 分母 <> 0を追加するだけでもエラーは避けられます。しかし、なぜ0になったのかを残したままでは、誤った集計結果につながります。検索やデータ取得の段階で止める方が、原因を見つけやすく安全です。

Microsoft Learn:Division by zero(Error 11)

VBA・Excel自動化の記事