Excel VBAでISODD・ISEVENが使えない時の対処法と奇数・偶数判定のベストプラクティス

ExcelのワークシートではISODD・ISEVENで簡単に奇数・偶数判定ができるのに、いざVBAマクロで同じように書くと「定義されていません」とエラーになってしまう——本記事では、その理由とVBAでの正しい奇数・偶数判定の書き方を、実務でそのまま使えるサンプルコード付きで詳しく解説します。

目次

VBAでISODD・ISEVENが「定義されていません」になる理由

まず押さえておきたいのは、ISODD・ISEVENは「ワークシート関数」であり、「VBAの組み込み関数」ではないという点です。

たとえば、VBAのコードに次のように書くとします。

Sub Sample()
    Dim v As Long
    v = 10

    ' これはエラーになる
    If ISEVEN(v) Then
        MsgBox "偶数です"
    End If
End Sub

このコードを実行すると、「コンパイルエラー: Sub または Function が定義されていません」というエラーになります。理由は簡単で、VBE(VBAの編集画面)から見たときに、ISEVENISODDという名前の関数は存在しないからです。

ところが、Excelのセル上では、

  • =ISEVEN(A1)
  • =ISODD(A1)

のように普通に使えます。これは「ワークシート関数」としてExcel側に用意されているためで、VBAから利用するときには「WorksheetFunction」を経由して呼び出す必要がある、もしくはVBAだけで完結する別の書き方(Mod演算)を使う必要がある、というわけです。

偶数・奇数判定の2つの代表的なアプローチ

VBAで偶数・奇数を判定する方法は大きく分けて次の2つです。

解決アプローチ内容サンプルコード(抜粋)メモ
WorksheetFunction経由で呼び出すApplication.WorksheetFunction.IsEven / IsOdd を使い、ワークシート関数ISODD・ISEVENをVBAから利用するIf WorksheetFunction.IsEven(対象値) Then
    '偶数処理
Else
    '奇数処理
End If
ワークシート関数の動きをそのまま使いたいときに便利
自前で剰余演算を使う値 Mod 2 = 0 なら偶数、値 Mod 2 <> 0 なら奇数と判定するDim isEven As Boolean
isEven = (値 Mod 2 = 0)
Excel関数に依存せず、シンプルかつ高速

どちらを使っても正しく判定できますが、「Excel関数の動きに合わせたい」ならWorksheetFunction、「処理速度とシンプルさを優先」するならMod演算というイメージで使い分けるとスッキリします。

WorksheetFunction.IsEven / IsOdd を使う方法

基本構文

ワークシート関数ISEVEN/ISODD をVBAから使うには、WorksheetFunctionオブジェクトを経由して呼び出します。

If Application.WorksheetFunction.IsEven(値) Then
    ' 偶数のときの処理
Else
    ' 奇数のときの処理
End If

If WorksheetFunction.IsOdd(値) Then
    ' 奇数のときの処理
End If
  • Application.は省略しても動作しますが、明示的に書いておくと可読性が上がるのでおすすめです。
  • WorksheetFunctionを付け忘れてIsEvenとだけ書くと、「定義されていません」というコンパイルエラーになります。

代表的な実装例(行の値を判定して書き出す)

以下は、指定列(ここでは7列目)の値が偶数か奇数かを判定し、結果を9列目に書き出していくサンプルです。質問文にあった例に少しだけ手を入れ、コメントを追加しています。

Sub MacroTest()
    Dim rowIdx As Long
    Dim ans As String

    rowIdx = 2  ' 見出し行を飛ばして2行目から開始

    While rowIdx &lt; 15
        ' 7列目 (G列) の値が偶数かどうかを判定
        If WorksheetFunction.IsEven(Cells(rowIdx, 7).Value) Then
            ans = "偶数"
        Else
            ans = "奇数"
        End If

        ' 判定結果を 9列目 (I列) に出力
        Cells(rowIdx, 9).Value = ans

        rowIdx = rowIdx + 1
    Wend
End Sub

この書き方のポイントは次の通りです。

  • WorksheetFunction.IsEven を使うことで、「セルの数値に対してISEVENを実行した結果」をVBAでそのまま利用できる。
  • セルが空白や文字列でも、ワークシート関数と同じ挙動(エラーやFALSEなど)を期待できる。
  • VBA7 / 64bit環境でも問題なく動作する一般的な書き方です。

WorksheetFunctionを使うときの注意点

WorksheetFunctionを使うときによくあるつまずきと対策をまとめておきます。

ポイント内容対策例
空白・文字列の扱い空セルや文字列に対して実行すると、ワークシート関数同様にエラーになる場合があります。IsNumericで事前チェックを入れる。
小数の扱い小数をそのまま渡すと、ExcelのISODD/ISEVENの仕様に従って判定されるため、意図と違う結果になる場合があります。CLngIntで整数化してから渡す。
エラー処理不正な値が混ざっていると実行時エラーで止まってしまう可能性があります。エラーをトラップして、エラー時の処理(スキップ・空欄・固定文字など)を決めておく。

エラーに強い書き方の一例

実務でよくある「数値以外も混ざっているリスト」に対して奇数・偶数を判定する場合の、少し丁寧な書き方を紹介します。

Sub MacroTestSafe()
    Dim rowIdx As Long
    Dim v As Variant
    Dim ans As String

    rowIdx = 2

    While rowIdx &lt; 15
        v = Cells(rowIdx, 7).Value

        If IsNumeric(v) Then
            ' 整数に丸めてから判定(小数が来ても安全)
            If WorksheetFunction.IsEven(CLng(v)) Then
                ans = "偶数"
            Else
                ans = "奇数"
            End If
        ElseIf IsEmpty(v) Then
            ans = ""   ' 空白はそのまま空欄にするなど、ルールを決める
        Else
            ans = "数値以外"
        End If

        Cells(rowIdx, 9).Value = ans
        rowIdx = rowIdx + 1
    Wend
End Sub

こうしておくと、「空白」「文字列」「小数」「整数」が混在していても、マクロが途中で止まらず、判定結果をわかりやすく書き出すことができます。

Mod演算子でシンプルに奇数・偶数判定する方法

Mod演算子での基本判定ロジック

VBAだけで完結させたい場合には、剰余演算子 Mod を使うのがもっともシンプルです。

  • 値 Mod 2 = 0 … 偶数
  • 値 Mod 2 <> 0 … 奇数

たとえば、次のように書けます。

Sub ModSample()
    Dim n As Long
    n = 10

    If n Mod 2 = 0 Then
        MsgBox "偶数です"
    Else
        MsgBox "奇数です"
    End If
End Sub

Mod演算はVBAの組み込み機能なので、Excel関数に依存せず高速に判定できるのが利点です。また、負の整数や0についても問題なく判定できます(0は偶数です)。

汎用的な判定関数として切り出す

同じ判定ロジックを何度も書くのは非効率なので、ユーザー定義関数(UDF)として共通化しておくのがおすすめです。

Public Function IsEvenNumber(ByVal value As Long) As Boolean
    IsEvenNumber = (value Mod 2 = 0)
End Function

Public Function IsOddNumber(ByVal value As Long) As Boolean
    IsOddNumber = (value Mod 2 &lt;&gt; 0)
End Function

これで、VBAのどこからでも次のように呼び出せます。

Sub ModFunctionSample()
    Dim i As Long

    For i = -5 To 5
        If IsEvenNumber(i) Then
            Debug.Print i &amp; " は偶数"
        Else
            Debug.Print i &amp; " は奇数"
        End If
    Next i
End Sub

特にループ処理の中で何度も判定するようなケースでは、Modでの判定はWorksheetFunctionよりも軽量なので、処理速度が気になるマクロではこちらを優先して使うと良いでしょう。

Variantやセルの値を受け取る関数例

実際のマクロでは、「セルの値が整数とは限らない」「空白や文字も来る」といった状況が多いので、Variantを受け取る判定関数にしておくと扱いやすくなります。

Public Function EvenOddLabel(ByVal value As Variant) As String
    ' 数値以外は空文字を返す(ルールは用途に応じて変更)
    If Not IsNumeric(value) Then
        EvenOddLabel = ""
        Exit Function
    End If

    ' 小数が来た場合は整数部分で判定したいなど、方針を決める
    ' ここでは四捨五入してから判定する例
    Dim n As Long
    n = CLng(value)

    If n Mod 2 = 0 Then
        EvenOddLabel = "偶数"
    Else
        EvenOddLabel = "奇数"
    End If
End Function

この関数を使えば、次のようにVBAから利用できます。

Sub UseEvenOddLabel()
    Dim rowIdx As Long

    For rowIdx = 2 To 50
        Cells(rowIdx, 9).Value = EvenOddLabel(Cells(rowIdx, 7).Value)
    Next rowIdx
End Sub

また、標準モジュールに置いておけば、セル上でも=EvenOddLabel(G2)のように関数として利用できるので、「VBAでもワークシートでも同じ関数名で使いたい」ときにも便利です。

WorksheetFunction と Mod の違いを整理

ここまでの内容を踏まえて、WorksheetFunction.IsEven/IsOddModを使った判定の違いを表にまとめます。

項目WorksheetFunction.IsEven / IsOddMod演算(値 Mod 2)
依存関係Excelのワークシート関数に依存VBAのみで完結
書き方のシンプルさWorksheetFunctionの指定が必要1行の式で判定可能
処理速度関数呼び出し分のオーバーヘッドあり比較的高速(大量ループに向く)
Excelと同じ仕様を使いたい場合◎(セルでの結果と揃えやすい)×(自分で仕様を決めて実装する)
学習コストWorksheetFunctionの使い方を覚える必要ありMod演算の意味さえ分かればOK
おすすめ用途「セルのISEVEN/ISODDと同じ判定がしたい」場合高速処理・シンプルさ重視の業務マクロ

用途別・どちらを使うべきかの目安

実務でありがちなシチュエーションごとに、どちらの方法を選ぶとよいかの目安を挙げておきます。

シチュエーション推奨方法コメント
既にセルでISEVEN/ISODDを使っており、VBAでも同じ結果に揃えたいWorksheetFunction.IsEven / IsOddセルの動作と完全一致させたい場合はWorksheetFunction一択。
数万〜数十万行をループして判定する重い処理Mod演算処理速度を考えるとModの方が有利。UDF化しておくと再利用性も高い。
ロジックをVBAと他言語(Pythonなど)で共通化したいMod演算どの言語でも「n % 2」のような剰余演算は共通。移植性を考えると◎。
VBA初心者向けの教育用サンプルMod演算「2で割って余りが0なら偶数」という説明は直感的で理解しやすい。

奇数・偶数判定の実務的な活用例

行番号の偶数行・奇数行で処理を分ける(縞模様・色分け)

もっともよく使うパターンは、「行番号が偶数か奇数かで処理を変える」ケースです。たとえば、一覧表の偶数行にだけ背景色を塗る「ゼブラ行」をVBAで実装する例です。

Sub ColorAlternateRows()
    Dim lastRow As Long
    Dim r As Long

    lastRow = Cells(Rows.Count, 1).End(xlUp).Row

    For r = 2 To lastRow
        If r Mod 2 = 0 Then
            ' 偶数行だけ薄いグレーを塗る
            Rows(r).Interior.ColorIndex = 15
        Else
            ' 奇数行は塗りつぶしなしに戻す
            Rows(r).Interior.ColorIndex = xlNone
        End If
    Next r
End Sub

このように、行番号と組み合わせる場合は、WorksheetFunctionを使わずにModだけで十分です。

明細番号・伝票番号のルールチェック

業務システムによっては、「奇数番号が売上、偶数番号が返品」のような運用ルールが決まっていることがあります。その場合、入力された伝票番号の奇数・偶数をチェックして、誤入力を防ぐことができます。

Function IsValidSlipNo(ByVal slipNo As Variant, ByVal isReturn As Boolean) As Boolean
    If Not IsNumeric(slipNo) Then
        IsValidSlipNo = False
        Exit Function
    End If

    Dim n As Long
    n = CLng(slipNo)

    If isReturn Then
        ' 返品なら偶数番号であること
        IsValidSlipNo = (n Mod 2 = 0)
    Else
        ' 通常売上なら奇数番号であること
        IsValidSlipNo = (n Mod 2 &lt;&gt; 0)
    End If
End Function

フォームの「登録」ボタンにこの関数を組み合わせれば、番号ルールの自動チェックが簡単に実装できます。

偶数月・奇数月だけ処理する

奇数月のみ、偶数月のみ処理を行いたい場合にも、Month関数とModを組み合わせればシンプルに書けます。

Sub ProcessOddMonths()
    Dim targetDate As Date
    Dim m As Long

    targetDate = Date  ' 今日の日付
    m = Month(targetDate)

    If m Mod 2 &lt;&gt; 0 Then
        MsgBox "奇数月なので処理を実行します。"
        ' ここに処理を書く
    Else
        MsgBox "偶数月なので今回はスキップします。"
    End If
End Sub

年月を扱う処理は一見複雑になりがちですが、月番号は1〜12の整数なので、Mod 2でサクッと奇数月・偶数月を判定できます。

よくあるつまずきポイントと対処法

IsEven/IsOddをそのまま書いてコンパイルエラー

もっともありがちなミスは、次のようにIsEvenだけ書いてしまうパターンです。

' コンパイルエラーになる例
If IsEven(Cells(2, 1).Value) Then
    ' ...
End If

この場合の対処法は2つだけです。

  • ワークシート関数を使いたいWorksheetFunction.IsEven と書く
  • VBAだけで判定したいCells(2, 1).Value Mod 2 = 0 のように書く

混乱する原因は、「セル上の関数名」と「VBAの関数名」が同じに見えることです。VBAからワークシート関数を使う場合は必ずWorksheetFunctionを経由するというルールだけ覚えておくと、かなりスッキリします。

Double型や小数の扱いで意図しない結果になる

計算結果などを直接渡すと、Double型(小数)になっていることがよくあります。小数をどう扱うかは業務ロジック次第なので、「判定前に整数化する方針」を決めておくと安全です。

よく使うパターンとしては次のようなものがあります。

  • 小数切り捨てで判定したい → Int(value) または Fix(value)
  • 四捨五入で判定したい → CLng(value)

たとえば、「小数点以下は四捨五入してから偶数・奇数を判定する」というルールなら、次のように書けます。

Dim v As Double
v = 10.6

If CLng(v) Mod 2 = 0 Then
    Debug.Print "偶数として扱う"
Else
    Debug.Print "奇数として扱う"
End If

WorksheetFunctionを使う場合でも、渡す前に一度整数化してしまえば、「小数をどう扱うか」を自分でコントロールできます。

負の数の扱いが不安なとき

VBAのModは負の数も扱えます。偶数・奇数判定をするときは、「余りが0かどうか」だけ見ればよいので、負の数でも問題ありません。

  • -4 Mod 2 = 0 → 偶数
  • -3 Mod 2 = -1 → 0ではないので奇数

つまり、判定ロジックは正の数とまったく同じでOKです。負の値を扱う可能性がある処理でも、n Mod 2 = 0という書き方でそのまま使えます。

ISODD・ISEVENをVBAで使いこなすための実践的テクニック

共通モジュールに「判定ラッパー関数」を用意する

プロジェクト全体で何度も奇数・偶数判定を使う場合は、「内部ではModを使うけれど、見た目はIsEven/IsOdd的」なラッパー関数を作っておくと便利です。

Public Function IsEvenValue(ByVal value As Variant) As Boolean
    If Not IsNumeric(value) Then
        IsEvenValue = False
        Exit Function
    End If
    IsEvenValue = (CLng(value) Mod 2 = 0)
End Function

Public Function IsOddValue(ByVal value As Variant) As Boolean
    If Not IsNumeric(value) Then
        IsOddValue = False
        Exit Function
    End If
    IsOddValue = (CLng(value) Mod 2 &lt;&gt; 0)
End Function

こうしておけば、各所のコードは次のようにスッキリ書けます。

If IsEvenValue(Cells(i, 1).Value) Then
    ' 偶数のときの処理
End If

内部の実装(Modで判定するのか、WorksheetFunctionを使うのか)はあとから差し替えられるので、運用フェーズで仕様を変えたくなったときにも柔軟に対応できます。

WorksheetFunctionバージョンとの切り替えも可能

もし「セルのISODD/ISEVENと完全に揃えたい」場合は、先ほどのラッパー関数の中身だけ、WorksheetFunctionを使うように差し替えればOKです。

Public Function IsEvenValue(ByVal value As Variant) As Boolean
    On Error GoTo ErrHandler
    IsEvenValue = Application.WorksheetFunction.IsEven(value)
    Exit Function

ErrHandler:
    ' エラー時の扱いはルールに応じて決める
    IsEvenValue = False
End Function

このように、外から見ると同じ関数名・同じ引数にしておくと、「Mod版」⇔「WorksheetFunction版」を切り替えても、呼び出し側のコードをいじる必要がありません。

まとめ:VBAでの奇数・偶数判定は2パターン覚えれば十分

本記事では、Excelのワークシート関数ISODD・ISEVENがVBAでそのまま使えない理由と、VBAで偶数・奇数を判定する2つの代表的な方法を解説しました。

  • WorksheetFunction.IsEven / IsOdd
    → ワークシート関数の挙動をそのまま使いたいときに最適。
    WorksheetFunctionプレフィックスを忘れないことが重要。
  • Mod演算(値 Mod 2)
    → Excel関数に依存せず、シンプルかつ高速。
    → 共通の判定関数としてUDF化しておくと大規模マクロでも使いやすい。

実務では、「セルの関数と結果を揃えたいか」「処理速度やシンプルさを優先したいか」という観点で使い分けると、迷うことが少なくなります。どちらの書き方も一度手を動かしてサンプルを作っておくと、次に同じような要件が出てきたときにすぐ流用でき、日々のExcel作業の自動化がさらに効率的になります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次