忍者ブログ
VBAによる実用アプリケーションの構築、およびGAS(Google Apps Script)やOffice Scriptへのモダンな移行パスを検証・解説するテックブログ。現場で即戦力となるコードモジュールや再利用可能な実用部品を継続的に提供します。

【VBA】配列から最大値を求める方法:WorksheetFunctionとループ処理の使い分け・エラー対策

VBAには、配列から最大値を直接求める組み込み関数(標準関数)は存在しません。しかし、Excel VBAであれば、ワークシート関数の Max を呼び出すことで簡単に最大値を取得できます。

この記事では、WorksheetFunction.Max を使う際のデータ型に関する注意点(仕様)と、予期せぬエラーを防ぐためのエラー処理、さらに安全に最大値を求めるループ処理の実装コードを解説します。

1. WorksheetFunction.Max を使う際の注意点(仕様の解説)

WorksheetFunction.Max は非常に便利ですが、「何を引数に渡すか」によって、数値以外のデータ(文字列や論理値など)が含まれていた場合の挙動が変わります。特に「セル範囲」を渡す場合と、「VBAの配列」を直接渡す場合で違いがあるため注意が必要です。

【比較対象となるデータ型の挙動まとめ】

  • 数値:セル範囲=計算される / VBA配列=計算される
  • 日付 (Date):セル範囲=計算される(シリアル値) / VBA配列=計算される(シリアル値)
  • 論理値 (Boolean):セル範囲=無視される / VBA配列=計算される(True=1, False=0)
  • 数値化できる文字列 (例: "100"):セル範囲=無視される / VBA配列=計算される(自動で数値化)
  • 数値化できない文字列 (例: "abc"):セル範囲=無視される / VBA配列=エラーになる(実行時エラー1004等)

このように、VBAの配列を直接 WorksheetFunction.Max に渡すと、数値に変換できない文字列が混ざっていた瞬間にエラーで処理が止まってしまいます。そのため、実務で使用する際はエラー処理(エラートラップ)が必須となります。

2. 実践コード①:WorksheetFunctionを使ったコード(エラー処理付き)

配列内に計算不ような文字列("abc"など)が混ざっていた場合に備え、On Error GoTo ステートメントを使ってエラーを検知するコードです。

Sub GetMaxWithWorksheetFunction()
    Dim numbers As Variant
    Dim maxVal As Double
    
    ' テスト用配列 (わざとエラーになる文字列 "abc" を混ぜています)
    numbers = Array(10, 45, 23, "100", "abc", 5)
    
    ' --- エラー監視を開始 ---
    On Error GoTo ErrorHandler
    
    ' WorksheetFunction.Maxで最大値を取得
    ' ("100"は数値化されますが、"abc"があるためここでエラーが発生します)
    maxVal = WorksheetFunction.Max(numbers)
    
    ' 正常に取得できた場合
    MsgBox "最大値は: " & maxVal
    
    ' エラー処理ブロックに行かないように終了
    Exit Sub
    
ErrorHandler:
    ' エラーが発生した場合の処理
    MsgBox "最大値の取得に失敗しました。" & vbCrLf & _
           "配列に数値として評価できないデータが含まれています。", _
           vbCritical, "エラー"
End Sub

【ポイント】
コードをシンプルに保ちたい場合におすすめです。ただし、エラーになった場合は「最大値が分からない」状態で処理が終わってしまうという弱点があります。

3. 実践コード②:ループ処理を使ったコード(安全・汎用型)

配列内に文字列が混ざっていてもエラーで止めず、「数値として扱えるものだけを拾って最大値を見つける」という柔軟な処理をしたい場合は、ループ処理(For ~ Next)と IsNumeric 関数を組み合わせるのがベストです。Excel以外の環境(AccessやWordのVBA)でも動作します。

Sub GetMaxWithLoopSafe()
    Dim numbers As Variant
    Dim maxVal As Double
    Dim i As Long
    Dim isFirstNumeric As Boolean
    
    ' テスト用配列 (文字列や空白が混ざっているケース)
    numbers = Array("テスト", 10, 45, "abc", 89, Empty, 5)
    
    ' 配列が初期化されているか(空でないか)の簡易チェック
    If IsEmpty(numbers) Then
        MsgBox "配列が空です。", vbExclamation
        Exit Sub
    End If
    
    isFirstNumeric = False
    
    ' 配列の最初から最後までループ
    For i = LBound(numbers) To UBound(numbers)
        
        ' 要素が数値として評価できる場合のみ処理 (IsNumeric)
        If IsNumeric(numbers(i)) And Not IsEmpty(numbers(i)) Then
            
            If Not isFirstNumeric Then
                ' 最初の有効な数値を見つけた時、それを暫定の最大値とする
                maxVal = CDbl(numbers(i))
                isFirstNumeric = True
            Else
                ' 2つ目以降の数値と比較し、大きければ上書きする
                If CDbl(numbers(i)) > maxVal Then
                    maxVal = CDbl(numbers(i))
                End If
            End If
            
        End If
    Next i
    
    ' 結果の判定
    If isFirstNumeric Then
        MsgBox "最大値は: " & maxVal ' 結果: 89 ("テスト"や"abc"は無視される)
    Else
        MsgBox "配列内に有効な数値が見つかりませんでした。", vbExclamation
    End If
    
End Sub

【ポイント】
IsNumeric 関数を使うことで、実行時エラーを未然に防ぎながら安全に比較を行います。業務システムなど、予期せぬデータが混入する可能性がある配列を処理する場合に非常に強力です。

4. まとめ

  • 手軽に書きたい・配列に数値しか入らないと確信できる場合
    ⇒ WorksheetFunction.Max + 念のためのエラー処理(On Error)
  • 文字列などが混ざる可能性があり、安全に数値だけを比較したい場合
    ⇒ ループ処理 + IsNumeric 関数での判定

用途とデータの性質に合わせて使い分けてみてください!


PR