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

Excel VBA の Mod — 剰余演算子、負の数、そして符号の罠

|

Excel VBA の Mod — 剰余演算子、負の数、そして符号の罠

TL;DRMod は整数除算のあとの 余り を返します。7 Mod 31 です。これは関数ではなく 演算子 なので、a Mod b と括弧なしで書きます。人が驚くのは二点です。VBA は まず 両方のオペラ ンドを整数に丸めること(6.7 Mod 37 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

ModRoundRnd は、ワークシートの親戚のような関数に見 えて、実は静かに違う挙動をする三つの計算ツールです。なかでも Mod は、人がセルの数式をそのままマクロへ 移し、そのあと負の数がなぜ間違って出たのか分からなくなる、まさにそれです。

この記事で学べること

  • 考え方の軸 — Mod整数除算のあとの余り であり、演算子である
  • VBA が割り算の前にオペランドを整数へ丸める理由
  • 第一の罠 — -7 Mod 3 は VBA では -1、ワークシートでは 2。符号の規則が違うから
  • 日常のイディオム — 偶数判定、N 行おき、リストを循環させる
  • 常に正の結果を強制する方法、そして x Mod 0 が実行時エラーを起こす理由

考え方の軸:整数除算のあとの余り

割り算は二つのものを与えます — ある数が別の数に何回収まるか、そして何が残るか、です。Mod はその 残り を渡します。17 Mod 52 です。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-17 Mod -31 です。ワークシートの 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 の整数型の範囲で働くので、IntegerLong として型付けした極 端に大きなオペランドはオーバーフローすることがあります。約 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) とは書きません — 括弧もカンマもありませ ん。式の中に置かれ、ab で整数除算した余りを返します。

VBA の Mod は小数で使えますか?

直接には使えません — VBA は余りを取る前に両方のオペランドを整数へ丸めるので、6.7 Mod 37 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