TL;DR —
Modは整数除算のあとの 余り を返します。7 Mod 3は1です。これは関数ではなく 演算子 なので、a Mod bと括弧なしで書きます。人が驚くのは二点です。VBA は まず 両方のオペラ ンドを整数に丸めること(6.7 Mod 3は7 Mod 3と同じように振る舞う)、そして結果は 被除数の符号 — 左側の数 — を取ること。だから-7 Mod 3は-1で、ワークシートの2ではありません。
Sub RemaindersAndTheSignTrap()
Debug.Print 7 Mod 3 ' 1 - 7 / 3 の余り
Debug.Print 10 Mod 2 ' 0 - 割り切れる、つまり「10 は偶数か?」-> True
Debug.Print -7 Mod 3 ' -1 - 符号は除数ではなく被除数 (-7) に従う
Debug.Print 6.7 Mod 3 ' 1 - 6.7 は先に 7 へ丸められ、その後 7 Mod 3
End Sub
Mod、Round、Rnd は、ワークシートの親戚のような関数に見
えて、実は静かに違う挙動をする三つの計算ツールです。なかでも Mod は、人がセルの数式をそのままマクロへ
移し、そのあと負の数がなぜ間違って出たのか分からなくなる、まさにそれです。
この記事で学べること
- 考え方の軸 —
Modは 整数除算のあとの余り であり、演算子である - VBA が割り算の前にオペランドを整数へ丸める理由
- 第一の罠 —
-7 Mod 3は VBA では-1、ワークシートでは2。符号の規則が違うから - 日常のイディオム — 偶数判定、N 行おき、リストを循環させる
- 常に正の結果を強制する方法、そして
x Mod 0が実行時エラーを起こす理由
考え方の軸:整数除算のあとの余り
割り算は二つのものを与えます — ある数が別の数に何回収まるか、そして何が残るか、です。Mod はその 残り
を渡します。17 Mod 5 は 2 です。5 は 17 に 3 回収まって 2 が余るからです。これがすべての考え方であ
り、Mod がパターンの繰り返されるあらゆる場所に現れる理由でもあります。余りが 0 なら「割り切れる」と
いう意味で、これが これは偶数か、これは N 行目か、グループが一つ埋まったか を判定する方法になるの
です。
二つの性質が、VBA の Mod を独自のものにしています。第一に、これは + や * と同じ 演算子 であっ
て関数ではありません — a Mod b と書き、Mod(a, b) とは決して書きません。第二に、整数 に対して働
きます。小数を渡すと、VBA は余りを取る 前に 各オペランドを整数へ丸めます。
Debug.Print 6.7 Mod 3 ' 1 - 6.7 は 7 へ丸められ、その後 7 Mod 3 = 1(0.7 ではない)
Debug.Print 5.4 Mod 2 ' 1 - 5.4 は 5 へ丸められ、その後 5 Mod 2 = 1
本当に 小数の 余りが必要なら、Mod はそれを与えてくれません — a - Int(a / b) * b で自分で計算しま
しょう。ですが十中八九、Mod こそがまさに望むものです。整数の個数を扱うからこそなのです。
第一の罠:負の数で符号が変わる
これはフォーラムを埋め尽くすものです。シートで動く数式があり、同じ計算を VBA に貼り付けると、負の数が間 違った符号で出てくるのです。
Debug.Print -7 Mod 3 ' VBA: -1
' シート上の =MOD(-7, 3) は 2 を返す
どちらも「正しい」のです — それぞれ別の、文書化された規則に従っています。VBA の Mod は被除数(左の
オペランド)の符号を取ります。-7 Mod 3 は -1、7 Mod -3 は 1 です。ワークシートの MOD は除
数の符号を取ります。MOD(-7, 3) は 2 です。ですから、セルで信頼していた数式が、マクロへ移した瞬間
に静かに別の数字を出すことがあり、何も警告してくれません。
本当に望むのが 決して負にならない 結果 — リストのまわりでインデックスを回すときによくある — なら、符 号の規則と戦うのではなく、それを打ち消しましょう。
' a の符号がどうであれ、常に 0 .. b-1 に収まる
result = ((a Mod b) + b) Mod b
Debug.Print ((-7 Mod 3) + 3) Mod 3 ' 2 - 意図してワークシートの答えにする
教訓は「VBA が間違っている」ではありません。負の数が現れうるときは、望む符号を自分で決めて組み立てる
— VBA の Mod が、コピー元のセルと一致すると思い込まない。 ということです。
覚えておく価値のあるイディオム
Mod の実際の用途のほとんどは、ひと握りのパターンのどれかです。これらを覚えれば、あらゆる場所でそれと
分かるようになります。
If n Mod 2 = 0 Then ... ' n は偶数か?(奇数なら 1)
If i Mod 3 = 0 Then ... ' 3 個おき(行の色分け、バッチ処理)
colour = palette(i Mod paletteCount) ' 固定リストを、端まで来たら先頭へ戻りながら循環する
行の色分けは、Mod が ループ の中でその真価を発揮する場面です。3 行ごとに色を
付ける、10 レコードごとに区切りを挿入する、i Mod 2 で色を交互に変える。どれも結局は「余りは 0 か?」で
あり、同じ判定が違う服を着ているだけです。
エラーになる境界:ゼロ除算
一つだけ、静かには失敗しないケースがあります — マクロを止めるのです。x Mod 0 は、x / 0 と同じく
実行時エラー 11「Division by zero(ゼロで除算しました)」 を発生させます。割る相手がなければ余りは定
義できないからです。除数が 0 になりうるなら(空かもしれない件数、ユーザーが指定するステップ幅など)、先
に守りましょう。
If groupSize > 0 Then
If i Mod groupSize = 0 Then InsertSeparator i
End If
関連する境界がサイズです。Mod は VBA の整数型の範囲で働くので、Integer や Long として型付けした極
端に大きなオペランドはオーバーフローすることがあります。約 20 億を超える値を扱うなら、LongLong(64
ビット版 VBA)か Double として型付けし、VBA に整数へ丸めさせましょう。
ExcelMaster の活用
Mod は VBA でいちばん単純な演算子に見えて、どれも警告なしに失敗する三つの罠を隠しています。負の被除数
は、数式をコピーしてきたワークシートとは逆の符号にひっくり返り、小数のオペランドは割り算の前に静かに丸め
られ、うっかり 0 になった除数はエラー 11 でマクロ全体を止めます。
ExcelMaster には、パターンをそのまま説
明できます — 「12 行ごとに小計を挿入して」や「奇数番号の請求書に印を付けて」 — すると、余りの判定を正し
い形で書きます。非負の結果が必要なときは ((a Mod b) + b) Mod b で包み、オペランドを意図的に整数のまま
にし、空のグループが実行を決してクラッシュさせないよう除数を守ります。ブックとコードはあなたの手元に残り
ます。
よくある質問
-7 Mod 3 はなぜ VBA では -1、ワークシートでは 2 になるのですか?
二つが別の符号規則を使うからです。VBA の Mod 演算子は 被除数(左のオペランド)の符号を取るので
-7 Mod 3 は -1 です。ワークシートの MOD 関数は 除数 の符号を取るので MOD(-7, 3) は 2 で
す。ワークシートと同じ常に正の答えを VBA で得るには、((a Mod b) + b) Mod b と書きます。
VBA で Mod は関数ですか、演算子ですか?
演算子です。+ や * と同じです。a Mod b と書き、Mod(a, b) とは書きません — 括弧もカンマもありませ
ん。式の中に置かれ、a を b で整数除算した余りを返します。
VBA の Mod は小数で使えますか?
直接には使えません — VBA は余りを取る前に両方のオペランドを整数へ丸めるので、6.7 Mod 3 は 7 Mod 3
のように振る舞い、1 を返します。本物の小数の余りが必要なら、a - Int(a / b) * b で自分で計算しましょ
う。
VBA で数が偶数か奇数かを調べるには?
2 に対する余りを使います。If n Mod 2 = 0 は偶数で真、奇数では偽(余りは 1)になります。同じパターン
i Mod k = 0 は、任意の k について「k 個ごと」を判定します — 3 行ごと、10 レコードごと、などです。
Mod をゼロで使うとどうなりますか?
x Mod 0 は実行時エラー 11「Division by zero(ゼロで除算しました)」を発生させます。除数がなければ余り
が定義できないからです。除数が 0 になりうるなら — 空の件数やユーザー指定のステップ幅など — Mod を使う
前に If divisor > 0 Then で確認しましょう。
検証環境
動作確認: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-18.
関連ガイド: VBA Round · VBA Rnd · VBA For ループ · VBA If Then Else · VBA WorksheetFunction
