IT系/VBA/基本/判定

Last-modified: 2020-07-19 (日) 21:48:14

目次


概要

判定に関するVBAのTIPS。

判定に使う演算子

比較演算子

  • 比較演算子には、「=」「>」「>」「>=」「 <=」「<>」がある。
    また、Is演算子Like演算子も比較に使用する。
    =   左項と右項の値が等しい
    >   左項の値が右項の値より大きい
    <   左項の値が右項の値より小さい
    >=  左項の値が右項の値以上
    <=  左項の値が右項の値以下
    <>  左項と右項の値が等しくない
    Is  オブジェクトの比較
    Like 文字列のパターン比較

論理演算子

  • And演算子Or演算子Not演算子がよく使用される論理演算子。Xor演算子もある。
    And 左項と右項の両方が真、ならば真
    Or  左項と右項のどちらかが真、ならば真
    Not 論理値反転
    Xor 排他的論理演算
  • Eqv演算子(論理等価), Imp演算子(論理包含)も存在するが、使うことはない*2
  • VB.netのAndAlso演算子、OrElse演算子のような短絡評価(ショートサーキット)をする演算子は存在しない。

判定用のVBA関数

判定用の関数。合致する場合はTrueが返却される。

' 配列かどうかチェック
IsArray(arr)
' 日付型に変換可能かチェック
IsDate("2020/01/01")
' 数値として扱えるかチェック
IsNumeric("999")
' VariantのEmpty値のチェック
IsEmpty("脳みそ")
' Null値が含まれるかチェック
IsNull("ぬる")
' オブジェクトかチェック
IsObject(obj)
' 引数が省略されたかチェック(OptionalのVariant型引数/ParamArray)
IsMissing(opt)

データ型の判定

  • TypeName 関数でデータ型を文字列で取得できる。
    Dim a As String
    Dim b As Boolean
    Dim c As New Collection
    Debug.Print "a : " & TypeName(a)
    Debug.Print "b : " & TypeName(b)
    Debug.Print "c : " & TypeName(c)
    ' 実行結果
    a : String
    b : Boolean
    c : Collection
  • 上記のTypeName関数を利用してデータ型の判定を行うことができる。
    Select Case TypeName(a)
        Case "String"
             Debug.Print "String"
        Case "Boolean"
             Debug.Print "Boolean"
        Case "Collection"
             Debug.Print "Collection"
        Case Else
             Debug.Print "Other"
    End Select
  • VarType 関数でもデータ型の判定を行うことができる。
    こちらは、文字列ではなくオブジェクトの既定のプロパティの種類を示す整数を返す点に違いがある。
  • TypeOfを使用した判定方法もあるが、Object型に限られ(String、Integer等には使用できない)、Implements(インタフェース)を使用したObjectの場合、互換性を確認するので元のクラス(インタフェース)と同一判定される。
    なお、TypeOfはIf...Then...Else ステートメントの条件式の構文として存在するようであり、TypeOf演算子があるわけではない。

オブジェクトが設定されているかどうかを判定する

  • Is演算子でNothingと比較をする。Not演算子をつければ、オブジェクトが設定されていることを判定できる。
    If Not obj Is Nothing Then
        ' Do Something
    End If

文字列の判定

文字列が等しいかどうかを判定する

「=」演算子、「<>」演算子を使用する。*3

Dim str As String: str = "光"
If str = "光" Then
    Debug.Print "光あれ!"
ElseIf str <> "闇" Then
    Debug.Print "あいまいな鈍色なり…"
Else
    Debug.Print "世界は闇に包まれた!"
End If

文字列が含まれているかどうかを判定する

InStr関数を使用する。

Dim str As String: str = "月光"
If InStr(str , "光") > 0 Then
    Debug.Print "光あれ!"
Else
    Debug.Print "世界は闇に包まれた!"
End If

パターンマッチング

Like演算子でパターン比較を行う。
より高度なパターンマッチングは、RegExpオブジェクトを使用した正規表現を使用する。

' ワイルドカード「*」を使用
Dim str As String: str = "東京都葛飾区亀有公園前派出所"
If str  Like "東京都*区*" Then
    Debug.Print "23区内です"
Else
    Debug.Print "23区外です"
End If
Dim nStr As String: nStr = "19"
If nStr Like "[1-5]*" Then
    Debug.Print "範囲内です"
Else
    Debug.Print "範囲外です"
End If

ひらがな/カタカナかどうか判定する

StrConv関数を使用する。
あくまで、変換対象の全角ひらがな/カタカナの部分が一致しているかを判定するため、変換対象とならない英数字記号、漢字、半角カタカナが混じっていても無視される。

Dim str As String: str = "ひらがな"
If str = StrConv(str, vbHiragana) Then
    Debug.Print "ひ、ひらがなでごわす"
Else
    Debug.Print  "チェスト!ひらがなではありもはん!"
End If
Dim str2 As String: str2 = "カタカナ"
If str2 = StrConv(str2 , vbKatakana) Then
    Debug.Print "カタ、カタカナ、カナ"
Else
    Debug.Print  "カタカナではない・・・!"
End If
 

全角ひらがな/カタカナのみを許容するチェックを行うなら、正規表現を使用して以下のように行う方法がある。

' ひらがなチェック
Function IsZenHiragana(pValue) As Boolean
    With CreateObject("VBScript.RegExp")
        .Pattern = "^[ぁ-んー]*$"    ' 空文字をFalseにするなら*を+にする
        .IgnoreCase = False
        .Global = True
        IsZenHiragana = .Test(pValue)
    End With
End Function
' カタカナチェック
Function IsZenKatakana(pValue) As Boolean
    With CreateObject("VBScript.RegExp")
        .Pattern = "^[ァ-ンヴー]*$"    ' 空文字をFalseにするなら*を+にする
        .IgnoreCase = False
        .Global = True
        IsZenKatakana = .Test(pValue)
    End With
End Function

半角/全角かどうか判定する

ひらがな/カタカナと同様、StrConv関数を使用する。
あくまで、変換対象の半角/全角の部分が一致しているかを判定するため、変換対象とならない英数字記号、漢字、全角が混じっていても無視される。

Dim str As String: str = "ぜんかくハンカク"
If str = StrConv(str, vbWide) Then
    Debug.Print "全角だがや"
Else
    Debug.Print  "全角じゃにゃあ!"
End If
 

以下のように、ANSI文字列に変換して長さを比較する方法もある。

Dim str As String: str = "ぜんかくハンカク"
Dim checkValue As String
checkValue = StrConv(str , vbFromUnicode)
If Len(str) <> LenB(checkValue) Then
    Debug.Print "全角だがや"
Else
    Debug.Print  "全角じゃにゃあ!"
End If
 

半角/全角のみを許容するチェックは、ひらがな/カタカナ同様、正規表現を使用してチェックすれば実現できる。

大文字/小文字かどうか判定する

UCase関数を使用する。
注意点はStrConv関数と同じで全角/半角英字以外は変換対象とならないので無視される。

Dim str As String: str = "AAA"
If str = UCase(str) Then
    Debug.Print "大文字オンリー"
Else
    Debug.Print  "小文字混じり"
End If
 

大文字/小文字のみを許容するチェックは、ひらがな/カタカナ同様、正規表現を使用してチェックすれば実現できる。

数値の判定

数字であるか判定する

  • IsNumeric 関数を使用する。
    IsNumeric 関数に数値とみなされるもの(符号付、16進数表記、全角数字等)はTrueになるため、想定したチェック結果にならない場合がある。
    Dim var
    var = "53"
    Debug.Print IsNumeric(var)    ' True
    var = "- 123"
    Debug.Print IsNumeric(var)    ' True
    var = "123+"
    Debug.Print IsNumeric(var)    ' True
    var = "1.95"
    Debug.Print IsNumeric(var)    ' True
    var = ".95"
    Debug.Print IsNumeric(var)    ' True
    var = "001.95"
    Debug.Print IsNumeric(var)    ' True
    var = "4.5"
    Debug.Print IsNumeric(var)    ' True
    var = "10e8"
    Debug.Print IsNumeric(var)    ' True
    var = "&O123"
    Debug.Print IsNumeric(var)    ' True
    var = "&H123"
    Debug.Print IsNumeric(var)    ' True
    var = "\123,456.789"
    Debug.Print IsNumeric(var)    ' True
    var = "One"
    Debug.Print IsNumeric(var)    ' False
    var = "四"
    Debug.Print IsNumeric(var)    ' False
    var = "001.95."
    Debug.Print IsNumeric(var)    ' False
  • 整数のみの数字であるかを判定したいなら、以下のようなFunctionを作成して判定する。
    Function IsIntegralNumber(pValue) As Boolean
        Dim i As Long
        If Len(pValue) > 0 Then    ' 未入力はTrue
            For i = 1 To Len(pValue)
                If Not Mid(pValue, i, 1) Like "[0-9]" Then
                    IsIntegralNumber = False
                    Exit Function
                End If
            Next
        End If
        IsIntegralNumber = True
    End Function
  • 上記をRegExpオブジェクトを使って正規表現でチェックを行うなら、以下のような感じ。
    Function IsIntegralNumber(pValue) As Boolean
        With CreateObject("VBScript.RegExp")
            .Pattern = "^[0-9]*$"
            .IgnoreCase = False
            .Global = True
            IsHalfAlphaNumericSymbol = .Test(pValue)
        End With
    End Function

奇数・偶数を判定する

  • Mod 2 の余りが1なら奇数、そうでなければ偶数。
    Dim i As Long: i = 11
    If  i Mod 2 = 0 Then
        Debug.Print "ぐぅ"
    Else
        Debug.Print "きぃぃ!"
    End If
  • WorksheetFunctionオブジェクトのIsEvenIsOddメソッドで判定することも可能。まあ、Mod使えばよいと思う。
    Dim var: var = "11"
    If  Application.WorksheetFunction.IsEven(var) Then
        Debug.Print "ぐぅ"
    Else
        Debug.Print "きぃぃ!"
    End If

年月日の判定

日付として妥当か判定する

IsDate 関数は、Date型に変換可能な文字列であるかをチェックする。
ただ、特定の形式「yyyy/mm/dd」にマッチするかどうかといった用途では、許容範囲が広すぎる。
正規表現で判定するか、以下のようにロジックで「半角数字4文字 + / + 半角数字2文字 + / + 半角数字2文字」の形式であることをチェックしてから、IsDate 関数でチェックする。

Function IsDate4y2m2d(pValue As String) As Boolean
    Dim i As Long, tmp As String, tmpDate As String
    If Len(pValue) > 0 Then
        For i = 1 To Len(pValue)
            tmp = Mid(pValue, i, 1)
            If i <> 5 And i <> 8 And (tmp Like "[0-9]") Then
                tmpDate = tmpDate & tmp
            ElseIf (i = 5 Or i = 8) And (tmp <> "/") Then
                IsDate4y2m2d = False
                Exit Function
            End If
        Next
        If Len(tmpDate) <> 8 Then
            IsDate4y2m2d = False
            Exit Function
        End If
        tmpDate = Format(tmpDate, "####/##/##")
        IsDate4y2m2d = VBA.IsDate(tmpDate)
        Exit Function
    End If
    IsDate4y2m2d = True
End Function

閏年の判定

閏(うるう)年は、西暦年が4で割り切れる年。
ただし、100で割り切れる年は、その年がさらに400で割り切れる場合のみ、閏年となる。
このロジックで実装する方法と、「(Month(DateSerial(年, 2, 28) + 1)) = 2」のようにVBA関数を使って2/29が存在する場合をチェックする方法がある。
以下は、ロジック実装した場合。

Function IsLeapYear(yearValue As Integer) As Boolean
    If ((yearValue Mod 4) = 0 And (yearValue Mod 100) <> 0 Or (yearValue Mod 400) = 0) Then
        IsLeapYear= True
        Exit Function
    End If
    IsLeapYear = False
End Function

休日・祝日の判定

VBA関数で土日を休日として判定する。祝日は予めDictionaryに登録しておき判定を行う。

Function IsHoliday(day As Date, dic As Dictionary) As Boolean
    If dic.Exists(day) Or Weekday(day) = 1 Or Weekday(day) = 7 Then
        IsHoliday= True
    Else
        IsHoliday= False
    End If
End Function

日付か時刻かの判定

Dim MyValue As Variant
MyValue = InputBox("日付か時刻かを判別します。")
If IsDate(MyValue) Then
    If CDate(MyValue) = Int(CDate(MyValue)) Then
        MsgBox ("日付のみ")
    ElseIf CDate(MyValue) < 1 Then
        MsgBox ("時刻のみ")
    Else
        MsgBox ("日付のみ、時刻のみの値ではありません。")
    End If
Else
    MsgBox ("日時ではありません。")
End If

その他判定

配列の初期化判定

以下のようにNot Notで判定できるようだが、仕組みが不明瞭。

Dim arr() As String
ReDim arr(0)
If Not Not arr Then
    Debug.Print "arr is ReDim."
End If
 

エラーが発生するかどうかで確認するのが、無難とされる。

Function IsRedim(ByRef arr As Variant) As Boolean
    On Error Resume Next
    Err.Clear
    IsRedim = CBool(UBound(arr))
    IsRedim = (Err.Number = 0)
End Function

64bit環境判定

PC環境が64bit*4であるかどうかを判定する方法。WMIを使って判定する。

Public Function Isx64() As Boolean
    Dim colItems As Object
    Dim itm As Object
    Dim ret As Boolean
    ret = False '初期化
    Set colItems = CreateObject("WbemScripting.SWbemLocator").ConnectServer.ExecQuery("Select * From Win32_OperatingSystem")
    For Each itm In colItems
        If InStr(itm.OSArchitecture, "64") Then
            ret = True
            Exit For
        End If
    Next
    Isx64 = ret
End Function

ワークシート保護判定

ProtectContents プロパティで判定する。

If ActiveSheet.ProtectContents = True Then
    Debug.Print "ワークシートは保護されています。"
Else
     Debug.Print "ワークシートは保護されていません。"
End If

文字コード判定

Function fncGetCharset(FileName As String) As String
    Dim i                   As Long
    Dim hdlFile             As Long
    Dim lngFileLen          As Long
    Dim bytFile()           As Byte
    Dim b1                  As Byte
    Dim b2                  As Byte
    Dim b3                  As Byte
    Dim b4                  As Byte
    Dim lngSJIS             As Long
    Dim lngUTF8             As Long
    Dim lngEUC              As Long
    On Error Resume Next
    'ファイル読み込み
    lngFileLen = FileLen(FileName)
    ReDim bytFile(lngFileLen)
    If (Err.Number <> 0) Then
        Exit Function
    End If
    '
    hdlFile = FreeFile()
    Open FileName For Binary As #hdlFile
    Get #hdlFile, , bytFile
    Close #hdlFile
    If (Err.Number <> 0) Then
        Exit Function
    End If
    '
    'BOMによる判断
    If (bytFile(0) = &HEF And bytFile(1) = &HBB And bytFile(2) = &HBF) Then
        fncGetCharset = "UTF-8 BOM"
        Exit Function
    ElseIf (bytFile(0) = &HFF And bytFile(1) = &HFE) Then
        fncGetCharset = "UTF-16 LE BOM"
        Exit Function
    ElseIf (bytFile(0) = &HFE And bytFile(1) = &HFF) Then
        fncGetCharset = "UTF-16 BE BOM"
        Exit Function
    End If
    '
    'BINARY
    For i = 0 To lngFileLen - 1
        b1 = bytFile(i)
        If (b1 >= &H0 And b1 <= &H8) Or (b1 >= &HA And b1 <= &H9) Or  _
           (b1 >= &HB And b1 <= &HC) Or (b1 >= &HE And b1 <= &H19) Or _
           (b1 >= &H1C And b1 <= &H1F) Or (b1 = &H7F) Then
            fncGetCharset = "BINARY"
            Exit Function
        End If
    Next i
    '
    'SJIS
    For i = 0 To lngFileLen - 1
        b1 = bytFile(i)
        If (b1 = &H9) Or (b1 = &HA) Or (b1 = &HD) Or (b1 >= &H20 And b1 <= &H7E) Or (b1 >= &HB0 And b1 <= &HDF) Then
            lngSJIS = lngSJIS + 1
        Else
            If (i < lngFileLen - 2) Then
                b2 = bytFile(i + 1)
                If ((b1 >= &H81 And b1 <= &H9F) Or (b1 >= &HE0 And b1 <= &HFC)) And _
                   ((b2 >= &H40 And b2 <= &H7E) Or (b2 >= &H80 And b2 <= &HFC)) Then
                   lngSJIS = lngSJIS + 2
                   i = i + 1
                End If
            End If
        End If
    Next i
    '
    'UTF-8
    For i = 0 To lngFileLen - 1
        b1 = bytFile(i)
        If (b1 = &H9) Or (b1 = &HA) Or (b1 = &HD) Or (b1 >= &H20 And b1 <= &H7E) Then
            lngUTF8 = lngUTF8 + 1
        Else
            If (i < lngFileLen - 2) Then
                b2 = bytFile(i + 1)
                If (b1 >= &HC2 And b1 <= &HDF) And (b2 >= &H80 And b2 <= &HBF) Then
                   lngUTF8 = lngUTF8 + 2
                   i = i + 1
                Else
                    If (i < lngFileLen - 3) Then
                        b3 = bytFile(i + 2)
                        If (b1 >= &HE0 And b1 <= &HEF) And (b2 >= &H80 And b2 <= &HBF) And (b3 >= &H80 And b3 <= &HBF) Then
                            lngUTF8 = lngUTF8 + 3
                            i = i + 2
                        Else
                            If (i < lngFileLen - 4) Then
                                b4 = bytFile(i + 3)
                                If (b1 >= &HF0 And b1 <= &HF7) And (b2 >= &H80 And b2 <= &HBF) And (b3 >= &H80 And b3 <= &HBF) And (b4 >= &H80 And b3 <= &HBF) Then
                                    lngUTF8 = lngUTF8 + 4
                                    i = i + 3
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    Next i
    '
    'EUC-JP
    For i = 0 To lngFileLen - 1
        b1 = bytFile(i)
        If (b1 = &H7) Or (b1 = 10) Or (b1 = 13) Or (b1 >= &H20 And b1 <= &H7E) Then
            lngEUC = lngEUC + 1
        Else
            If (i < lngFileLen - 2) Then
                b2 = bytFile(i + 1)
                If ((b1 >= &HA1 And b1 <= &HFE) And _
                   (b2 >= &HA1 And b2 <= &HFE)) Or _
                   ((b1 = &H8E) And (b2 >= &HA1 And b2 <= &HDF)) Then
                   lngEUC = lngEUC + 2
                   i = i + 1
                End If
            End If
        End If
    Next i
    '
    '文字コード出現順位による判断
    If (lngSJIS <= lngUTF8) And (lngEUC <= lngUTF8) Then
        fncGetCharset = "UTF-8"
        Exit Function
    End If
    If (lngUTF8 <= lngSJIS) And (lngEUC <= lngSJIS) Then
        fncGetCharset = "Shift_JIS"
        Exit Function
    End If
    If (lngUTF8 <= lngEUC) And (lngSJIS <= lngEUC) Then
        fncGetCharset = "EUC-JP"
        Exit Function
    End If
    fncGetCharset = ""
End Function

TIPS

別ページの一覧を入れる。

'IT系/VBA/基本/判定/' には、下位層のページがありません。

リンク集

重複を恐れないリンク集。

比較演算子・論理演算子

判定用VBA関数

文字列の判定

数値の判定

年月日の判定

セルの判定

その他判定

動画

その他メモ



*1 もちろん、かっこを使用すると、優先順位をオーバーライドして、式のある部分を他の部分より先に評価させることができる
*2 VB.netではなくなっている。(参考
*3 Javaのようなequalsメソッドでの判定は不要。
*4 Officeが64bitではなく。