〖ExcelVBA〗InStrで「見つからない(0)」原因と対処法まとめ|大文字小文字・空白・改行・見えない文字

ExcelVBA

「VBA InStr 見つからない」で検索してここに来た方の多くは、
本当は文字が含まれているはずなのに、InStrが0を返す状態に困っているはずです。

まず結論から言うと、InStrは見つからない場合は0を返します。

つまり、コードが間違っているというより「データ側になにか不備がある」ことがほとんどです。
この記事では、よくある原因と解決方法を、コピペOKのコード付きでまとめます。


スポンサーリンク
スポンサーリンク

まず確認:InStrは「何を返す関数」?

InStrは、文字列の中から指定した文字が最初に出てくる位置を返します。見つからなければ0です。

pos = InStr(文字列A, 探す文字)
If pos > 0 Then
    ' 含まれている
Else
    ' 見つからない(0)
End If

原因1:大文字/小文字が違う(デフォルトは区別されやすい)

InStrは比較方法を指定できます。
大文字小文字を区別しないで探したいなら、vbTextCompare を付けるのが定番です。

' 大文字小文字を区別しない(おすすめ)
If InStr(1, "ABC", "abc", vbTextCompare) > 0 Then
    MsgBox "見つかった"
End If

また、モジュールの先頭に Option Compare Text を書く方法もあります(モジュール全体に影響します)

Option Compare Text

原因2:前後の空白(スペース)が混ざっている

セルの値に、前後の空白が入っていると「見つからない」原因になります。
まずは Trim で前後の空白を落としてから探すのが基本です。

Dim s As String
s = Trim(CStr(Range("A1").Value))

If InStr(1, s, "東京", vbTextCompare) > 0 Then
    MsgBox "見つかった"
End If

原因3:改行コードが混ざっている(Alt+Enterなど)

セル内改行(Alt+Enter)などで、文字の間に改行が入っていると、見た目は同じでも一致しないことがあります。
改行には複数種類(CR/LF/CRLF)があるため注意が必要です。

対策:改行をスペースに置換してから探す。

Dim s As String
s = CStr(Range("A1").Value)

s = Replace(s, vbCrLf, " ")
s = Replace(s, vbCr, " ")
s = Replace(s, vbLf, " ")

If InStr(1, s, "東京", vbTextCompare) > 0 Then
    MsgBox "見つかった"
End If

原因4:見えない空白(nbsp:ノンブレークスペース)が混ざっている


この空白は見た目では分かりにくく、Trimでも消えないことがあり、InStrが0になる原因になります。

対策:ChrW(160) を通常の半角スペースに置換します。

Dim s As String
s = CStr(Range("A1").Value)

' nbsp(ChrW(160)) を普通のスペースへ
s = Replace(s, ChrW(160), " ")

s = Trim(s)

If InStr(1, s, "東京", vbTextCompare) > 0 Then
    MsgBox "見つかった"
End If

原因5:数値/日付/エラー値など「文字列ではない」ものを渡している

セルの値が数値や日付でも、VBA的には「文字列として扱えていない」ケースがあります。
基本は CStr で文字列に変換してからInStrするのが安全です。

Dim s As String
s = CStr(Range("A1").Value)

If InStr(1, s, "123", vbTextCompare) > 0 Then
    MsgBox "見つかった"
End If

※セルがエラー値(#N/Aなど)の場合は、先にエラー判定してください。

If IsError(Range("A1").Value) Then Exit Sub

困ったらこれ:InStr用の「正規化(整える)関数」テンプレ

実務では、探す前に文字列を「整える」だけで解決することが多いです。
以下は、空白・改行・nbspをまとめて整えるテンプレです(コピペOK)。

Option Explicit

Private Function NormalizeText(ByVal v As Variant) As String
    Dim s As String

    If IsError(v) Then
        NormalizeText = ""
        Exit Function
    End If

    s = CStr(v)

    ' nbsp(ChrW(160)) を普通のスペースへ
    s = Replace(s, ChrW(160), " ")

    ' 改行をスペースへ
    s = Replace(s, vbCrLf, " ")
    s = Replace(s, vbCr, " ")
    s = Replace(s, vbLf, " ")

    ' 前後の空白を削除
    s = Trim(s)

    NormalizeText = s
End Function

Public Function ContainsText(ByVal v As Variant, ByVal keyword As String) As Boolean
    Dim s As String
    s = NormalizeText(v)

    ContainsText = (InStr(1, s, keyword, vbTextCompare) > 0)
End Function

使い方:

Sub TestContains()

    If ContainsText(Range("A1").Value, "東京") Then
        MsgBox "含まれています"
    Else
        MsgBox "見つかりません"
    End If

End Sub

それでも見つからないときの最終手段:文字コードを調べる

「見た目は同じなのに一致しない」場合、文字コードが違うことがあります。
次のマクロで、文字ごとのコードをイミディエイトウィンドウに出せます(原因特定に強いです)。

Sub DumpCharCodes()

    Dim s As String, i As Long
    s = CStr(Range("A1").Value)

    For i = 1 To Len(s)
        Debug.Print i, Mid$(s, i, 1), AscW(Mid$(s, i, 1))
    Next i

End Sub

まとめ:「InStrが0」はデータのクセを疑うのが近道

  • InStrは見つからないと0を返す
  • 大文字小文字の違いは vbTextCompare / Option Compare Text で対策
  • 空白・改行・nbsp(ChrW(160))など「見えない文字」を整えると解決しやすい
  • 困ったら正規化関数を作って、探す前に整える

このテンプレを入れておけば、「VBA InStr 見つからない」問題はかなりの確率で解決できます。

スポンサーリンク
スポンサーリンク
ExcelVBA
いがぴをフォローする

コメント

タイトルとURLをコピーしました