実行時エラー11
「0で除算しました」の原因と対処
割り算の直前だけを確認しても、根本原因が見つからないことがあります。開始番号・終了番号の検索失敗によって分母が0になった例から、確認する順番を整理します。
このエラーを調べることになったのは、PowerShellから複数のExcelマクロを順番に実行している途中で、VBAの実行時エラー11「0で除算しました」が発生したためです。
処理では、開始番号から終了番号までの対象件数を求め、その件数を分母にして割合を計算していました。ところが、指定した番号がデータ内に見つからず、検索結果をもとに計算した分母が0になっていた可能性がありました。
0で割った行は、異常が表面化した場所です。実際の原因は、その前に行った番号検索やデータ取得の失敗にある場合があります。
HIDDEN ERROR
検索失敗を見逃す問題のある例
Findで番号を検索した結果、対象がなければNothingが返ります。そのとき件数を更新しないまま処理を続けると、初期値の0が分母に使われます。
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から開始番号と終了番号を検索します。どちらかが見つからない場合は計算せず、確認対象をメッセージで知らせます。
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 SubApplication.Match見つからない場合はエラー値を返すため、IsErrorで判定できる。
+ 1開始位置と終了位置を両方含めた件数として計算する。
targetCount <= 00だけでなく、開始・終了の順序が逆の場合も計算を止める。
ClearContents計算できないときに、前回の割合を結果欄へ残さない。
シート名、セル位置、検索範囲は例です。実際のブック構成に合わせて変更してください。
ANOTHER CASE
別ファイルの生産数が0になる場合
同じエラーは、不具合率を「不具合件数÷生産数」で求める処理でも発生します。月が替わった直後など、別のExcelファイルから取得する生産数がまだ更新されておらず、セルに数値の0が入っているケースです。
この場合、0を一律に割合0%へ置き換えると、「不具合なし」と「生産数未取得」を区別できなくなります。
未取得または生産実績なしとして、結果欄を空白にします。
データの組合せに矛盾があるため、確認を促して処理を止めます。
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になったのかを残したままでは、誤った集計結果につながります。検索やデータ取得の段階で止める方が、原因を見つけやすく安全です。