目次
概要
判定に関するVBAのTIPS。
判定に使う演算子
比較演算子
- 比較演算子には、「=」「>」「>」「>=」「 <=」「<>」がある。
また、Is演算子、Like演算子も比較に使用する。= 左項と右項の値が等しい > 左項の値が右項の値より大きい < 左項の値が右項の値より小さい >= 左項の値が右項の値以上 <= 左項の値が右項の値以下 <> 左項と右項の値が等しくない Is オブジェクトの比較 Like 文字列のパターン比較
- 比較演算子の優先順位はすべて同じであり、左から右に評価される*1。
- Like 演算子の動作は、Option Compare ステートメントに依存する。 各モジュールの既定の文字列比較方法は Option Compare Binary。
- Is演算子については、/IT系/VBA/基本/オブジェクト#ef5d7a45も参照。
論理演算子
- 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オブジェクトのIsEven、IsOddメソッドで判定することも可能。まあ、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/基本/判定/' には、下位層のページがありません。
リンク集
重複を恐れないリンク集。
比較演算子・論理演算子
- 比較演算子 | Microsoft Docs
- 演算子の優先順位 | Microsoft Docs
- 演算子 - 基本文法 - Excel VBA入門
- VBA 演算子 - TipsFound
- Like演算子とワイルドカード|VBA入門
判定用VBA関数
- IsArray 関数 (Visual Basic for Applications) | Microsoft Docs
- IsDate 関数 (Visual Basic for Applications) | Microsoft Docs
- IsEmpty 関数 (Visual Basic for Applications)| Microsoft Docs
- IsError 関数 (Visual Basic for Applications)| Microsoft Docs
- IsMissing 関数 (Visual Basic for Applications) | Microsoft Docs
- IsNull 関数 (Visual Basic for Applications) | Microsoft Docs
- IsNumeric 関数 (Visual Basic for Applications) | Microsoft Docs
- IsObject 関数 (Visual Basic for Applications) | Microsoft Docs
- TypeName 関数 (Visual Basic for Applications) | Microsoft Docs
- VarType 関数 (Visual Basic for Applications) | Microsoft Docs
- 【VBA】引数のタイプを判定するIs...関数のまとめ | あじゅWeb
- Excel VBA を学ぶなら moug モーグ | 即効テクニック | 変数に関する情報を取得(TypeName関数、VarType関数)
文字列の判定
- 文字列の比較:Excel VBA|即効テクニック|Excel VBAを学ぶならmoug
- Office TANAKA - Excel VBA Tips[文字種を判定する]
- VBAで文字列かどうかを判定する-VarType関数:エクセルマクロ・Excel VBAの使い方/VBA関数
- Excel VBA を学ぶなら moug モーグ | 即効テクニック | 文字列が半角、全角、混在かを判断する
数値の判定
年月日の判定
- 6.説明1-5 VBAでの年月の判定
- Microsoft Excel VBA - 閏年を判定する関数
- 日付か時刻かの判別: やむえむのExcel VBAメモ
- VBAのIsDateが「True」になる「妥当な日付文字列」とは? | 志木駅前のパソコン教室・キュリオステーション志木店のブログ
- VBAで休日・祝日を判定する | かずさプログラマーの雑記帳
セルの判定
- 空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説
- 空白セルを正しく判定する方法2|VBA技術解説
- [Excel VBA]セルが数式かどうか調べるには? | 日経クロステック(xTECH)
- VBAでセルのエラーの種類を判定する(CVErr + XlCVError 列挙型) - Qiita
その他判定
- SGソフトウェア開発ブログ: [VBA] 動的配列の初期化判定
- Variant型の動的配列で初期化済みかどうかを判定する方法 | プログラミングテクニック集キヤミー
- VBA高速化検証:Empty値の判定方法 - Excel Tips for Teachers
- オブジェクトが空(Nothing)であるかを調べる方法[エクセルVBA] : バヤシタ
- VBA IsError 関数 - Tipsfound
- VBAで#N/Aエラーを判定する-CVErr関数:エクセルマクロ・Excel VBAの使い方/VBA関数
- 【エクセルVBA】FileSystemオブジェクトでファイルやフォルダが存在するかを判定する
- VBAでファイルの文字コード判定を行う | ぽぽづれ。
- 64ビット環境かどうかを判別するVBAマクロ | 初心者備忘録
- シートが保護されているか確認(ProtectContents プロパティ) | ExcelWork.info
- Excel vba 全角判定、数字判定!! | 長瀬高秋のIT日記
- 複数条件判定を行う時のコツ|VBA技術解説
動画
- (チュートリアル道場) Excel VBA入門 レッスン10 比較演算子 - YouTube
- (チュートリアル道場) Excel VBA入門 レッスン11 論理演算子 - YouTube
- (IT係長) 【Excel|VBA】算術演算子・比較演算子★ - YouTube
- (伊川直助) 【Excel VBA】SCHOOL OF VBA 第四回目 条件判定 - YouTube
- (伊川直助) 【ACCESS VBA】Boolean型で真偽判定 - YouTube