Like演算子で、[と]を文字として扱い比較したい

このQ&Aのポイント
  • VBA(Excel2003)でフォルダ内のファイルリストを作成する際に、指定したキーワードを含むかどうかを判定する機能を作りたい。
  • VB6ではうまくいったが、VBAではうまくいかないため、正規表現を使う方法を模索している。
  • 参照設定の変更やRegExpとCreateObjectを試したが、解決しなかった。ヒントを教えてほしい。
回答を見る
  • ベストアンサー

Like演算子で、[と]を文字として扱い比較したい

今、フォルダ内のファイルリストを作成するVBA(Excel2003)を作っています。そこで、ファイル(絶対パス:フルパス)に「含まれていい文字」と「含まれない文字」(キーワード)を指定できる機能を作っています。 以前、VB6で類似の機能を作った時は、すんなり行ったのですが、VBAではうまくいきません。正規表現が使えるに越したことはないのですが、「 [ や ] を文字として認識するだけでもいいです。」 リストを作るフォルダには、  [20].txt  テキスト[a]txt  メモ[10] - コピー.txt などのテストファイルとその他ファイルが存在します。 キーワードを指定しないときには、うまく行きます。 指定すると、たとえば [10].txt というファイルがヒットしないように、NGワードを [10] を指定すると、[20].txtまでヒットしません。[a]では全てがヒットしません。 また、OKワードに[10]を指定すると[10]と[20]がヒットします。 ===== NGワードを比較している部分 ==== 引数:in_str が NGワード(スペースで区切って複数指定可能) 引数:target_Str がフルパス Public Function keywords_NG(in_Str As String, target_Str As String) As Boolean   If in_Str = "" Then     keywords_NG = True     Exit Function   End If      Dim wordArray() As String   Erase wordArray()   wordArray() = Split(in_Str, Space(1))     Dim tempFLG As Boolean   tempFLG = True      Dim wordIDX As Long   For wordIDX = 0 To UBound(wordArray) Step 1     If wordArray(wordIDX) <> "" And target_Str <> "" Then       If target_Str Like "*" & wordArray(wordIDX) & "*" = True Then         tempFLG = False       End If     End If   Next   If tempFLG = True Then     keywords_NG = True   Else     keywords_NG = False   End If End Function ===== OKワードを比較している部分 ==== 引数:in_Str が OKワード(スペースで区切って複数指定可能) 引数:target_Str がフルパス Public Function keywords_OK(in_Str As String, target_Str As String) As Boolean   If in_Str = "" Then     keywords_OK = True     Exit Function   End If   Dim wordArray() As String   Erase wordArray()   wordArray() = Split(in_Str, Space(1))      Dim tempFLG As Boolean   tempFLG = False      Dim wordIDX As Long   For wordIDX = 0 To UBound(wordArray) Step 1     If wordArray(wordIDX) <> "" And target_Str <> "" Then       If target_Str Like "*" & wordArray(wordIDX) & "*" = True Then         tempFLG = True       End If     End If   Next      If tempFLG = True Then     keywords_OK = True   Else     keywords_OK = False   End If    End Function ===== [や]を区切り文字ではなくする関数 ==== Public Function keywords_escape_sequence(keywordStr As String) As String      If keywordStr = "" Then     keywords_escape_sequence = ""     Exit Function   End If      Dim myIDX As Currency   Dim str_X As String      str_X = ""        For myIDX = 1 To Len(keywordStr) Step 1     If Mid(keywordStr, myIDX, 1) = "[" Then       str_X = str_X & "[[]"     ElseIf Mid(keywordStr, myIDX, 1) = "]" Then       str_X = str_X & "[]]"     Else       str_X = str_X & Mid(keywordStr, myIDX, 1)     End If   Next      keywords_escape_sequence = str_X End Function =====================================================     If keywords_OK(keywords_OK_Str, フルパス)) = True And _       keywords_NG(keywords_NG_Str, フルパス)) = True Then         'ファイルリスト作成     end if ===================================================== 正規表現を使うためには…というページを見つけ参照設定に以下の項目にチェックを入れてみましたが、結果は変わらす □Microsoft VBScript Regular Expressions 5.5 ===== RegExp と CreateObject ==== 参照設定をできれば変更したくない場合は、RegExp と CreateObject を使えば良いとあるページに書いてありましたが、参照設定でもできなかったので、これだけは試してません。 ヒントだけでもお教えください。

質問者が選んだベストアンサー

  • ベストアンサー
  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.1

Sub try() Dim RegExp As Object Dim v(1 To 3) As String Dim KeyWord As String Dim i As Integer Set RegExp = CreateObject("VBScript.RegExp") v(1) = "[20].txt" v(2) = "テキスト[a]txt" v(3) = "メモ [10] - コピー.txt" KeyWord = "10" 'キーワードは[]の中の数字のみ RegExp.Pattern = "\[" & KeyWord & "\]" For i = 1 To 3 If RegExp.Test(v(i)) Then 'キーワードに一致でOK MsgBox v(i) End If Next MsgBox "チェンジ" For i = 1 To 3 If Not RegExp.Test(v(i)) Then 'キーワードに不一致でOK MsgBox v(i) End If Next Set RegExp = Nothing Erase v End Sub 勘違いでしたらスル~して下さい。

psychang
質問者

お礼

メタ文字すべてをエスケープ(?)してみました。 キーワードをセットするボタンに、エラー処理を作りましたが、文字制限のあるので、載せていません。 Public Function keywords_escape_sequence(keywordStr As String) As String    If keywordStr = "" Then   keywords_escape_sequence = ""   Exit Function  End If  'メタ文字のエスケープはReplace関数を使ったほうがスマートだとは思いますが、自作しました。  If frmKeywords.cbMetaCharMode.Value = False Then 'メタ文字を単なる文字として扱うモード     Dim MetaTagChars As String      MetaTagChars = "^$?*+.|{}\[]()" 'メタ文字の一覧 http://codezine.jp/article/detail/1655     Dim myIDX As Long     Dim str_X As String   str_X = ""       For myIDX = 1 To Len(keywordStr) Step 1    Dim tagIDX As Long      Dim tagFlg As Boolean        tagFlg = False        For tagIDX = 1 To Len(MetaTagChars) Step 1          If Mid(keywordStr, myIDX, 1) = Mid(MetaTagChars, tagIDX, 1) Then      tagFlg = True     End If          If Mid(keywordStr, myIDX, 1) = Mid(MetaTagChars, tagIDX, 1) Then      str_X = str_X & "\" & Mid(MetaTagChars, tagIDX, 1)     End If    Next tagIDX        If tagFlg = False Then     str_X = str_X & Mid(keywordStr, myIDX, 1)    End If   Next myIDX      keywords_escape_sequence = str_X  Else 'メタ文字を自分で記述するモード   keywords_escape_sequence = keywordStr  End If End Function ありがとうございました。m(_ _)m

psychang
質問者

補足

アドバイスありがとうございます。 どうやら、[ → [[] 、[ → []] に置換する部分で、置換前データで上書きしていいたようです。自己解決で、すみません。 でも、せっかく教えて頂いたので、RegExp(正規表現というのですか?)でもできるように、今作っていますυ Like演算子でも正規表現は使えると思うのですが、モドキなんでしょうか? やはりRegExpというのでプログラムを組んだほうが、何かと応用が利くのでしょうか?

その他の回答 (1)

  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.2

n-junです。 >Like演算子でも正規表現は使えると思うのですが、モドキなんでしょうか? >やはりRegExpというのでプログラムを組んだほうが、何かと応用が利くのでしょうか? 私的にはLike演算子と正規表現は違う物と認識してます。(実際はわかりませんよ) ただ正規表現自体は、覚えておくと入力チェックなどにも応用できますし、 結構重宝していますのでお薦めしたいですね。

psychang
質問者

お礼

言葉足らずの中、回答頂きありがとうございました。 RegExpの方を使って、プログラミングを続けようと思います。 今日の夜、締め切ります。

psychang
質問者

補足

出来たので、一応載せておきます。 keywords_OK_Str = keywords_escape_sequence(frmKeywords.OK_BOX.Text) keywords_NG_Str = keywords_escape_sequence(frmKeywords.NG_BOX.Text) If keywords_OK(keywords_OK_Str, フルパス)) = True And _   keywords_NG(keywords_NG_Str, フルパス)) = True Then         'ファイルリスト作成 End if ※Microsoft VBScript Regular Expressions 5.5 にチェックを入れなくてもできました。 Public Function keywords_escape_sequence(keywordStr As String) As String          If keywordStr = "" Then         keywords_escape_sequence = ""         Exit Function     End If          Dim myIDX As Currency     Dim str_X As String          str_X = ""              For myIDX = 1 To Len(keywordStr) Step 1         If Mid(keywordStr, myIDX, 1) = "[" Then             str_X = str_X & "\["         ElseIf Mid(keywordStr, myIDX, 1) = "]" Then             str_X = str_X & "\]"         Else             str_X = str_X & Mid(keywordStr, myIDX, 1)         End If     Next          'メタ文字の一覧   http://codezine.jp/article/detail/1655          keywords_escape_sequence = str_X End Function Public Function keywords_NG(in_Str As String, target_Str As String) As Boolean     If in_Str = "" Then         keywords_NG = True         Exit Function     End If          Dim wordArray() As String          Erase wordArray()          wordArray() = Split(in_Str, Space(1)) '(スペースで区切ったキーワードを一個一個取り出し)               Dim tempFLG As Boolean          tempFLG = True          Dim wordIDX As Long          For wordIDX = 0 To UBound(wordArray) Step 1         If wordArray(wordIDX) <> "" Then             Dim RegExp As Object                          Set RegExp = CreateObject("VBScript.RegExp")                          RegExp.Pattern = wordArray(wordIDX)                          If RegExp.Test(target_Str) Then                 tempFLG = False '一個でも一致した場合、NG             End If                          Set RegExp = Nothing         End If     Next          If tempFLG = True Then         keywords_NG = True     Else         keywords_NG = False     End If End Function Public Function keywords_OK(in_Str As String, target_Str As String) As Boolean     If in_Str = "" Then         keywords_OK = True         Exit Function     End If     Dim wordArray() As String          Erase wordArray()          wordArray() = Split(in_Str, Space(1))  '(スペースで区切ったキーワードを一個一個取り出し)          Dim tempFLG As Boolean          tempFLG = False          Dim wordIDX As Long          For wordIDX = 0 To UBound(wordArray) Step 1         If wordArray(wordIDX) <> "" Then             Dim RegExp As Object                          Set RegExp = CreateObject("VBScript.RegExp")                          RegExp.Pattern = wordArray(wordIDX)                          If RegExp.Test(target_Str) Then 'キーワードに一致でOK                 tempFLG = True '一個でも一致した場合、OK             End If                          Set RegExp = Nothing         End If     Next          If tempFLG = True Then         keywords_OK = True     Else         keywords_OK = False     End If     End Function

関連するQ&A

  • 2010 excel マクロ 記号の変化

    エラー発生で強制終了になってしまいます。2007年のexcelで作成したものですが、2010だと強制終了になってしまいます。 内容は□をダブルクリックすると■になるように作っています。 記述は2003年からのマクロ記述なので、変化が必要なのでしょうか? Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) 'Private Sub Worksheet_SelectionChange(ByVal Target As Range) 'セルをダブルクリックすると、・→○→△→×→・と変更する。 Dim S1 As String Dim S2 As String Dim S01 As String Dim S02 As String Dim S03 As String Dim S04 As String S1 = "□" S2 = "■" S01 = "・" S02 = "○" S03 = "△" S04 = "×" On Error GoTo ERR_12 sCheckXY S1, S2 sCheckX1234 S01, S02, S03, S04 sChangeXY S1, S2 Exit Sub ERR_12: End End Sub Sub sChangeXY(X As String, Y As String) '選択セルに□があれば■に変える Dim Str0 As String 'str1の左端 Dim Str1 As String 'strの右側更新 Dim Str2 As String 'strの左側更新 Dim Str20 As String 'strの左側一部保存 Dim L As Long Dim M As Long Dim N As Long Str1 = ActiveCell.Text L = Len(Str1) Debug.Print L If L = 0 Then End End If For N = 1 To L Debug.Print Str2 Str0 = Left(Str1, 1) If Str0 = X Or N = L Then If Str20 <> "" Then If N = L Then Str20 = Str20 + Str0 End If If MsgBox(Str20 & "  はチェックしますか?", vbYesNo, "選択肢") = vbYes Then Str2 = Str2 + Replace(Str20, X, Y) Str20 = Str0 Else Str2 = Str2 + Replace(Str20, Y, X) Str20 = Str0 End If Else Str20 = Str0 End If Else Str20 = Str20 + Str0 End If Str1 = Right(Str1, L - N) Next N ActiveCell.Value = Str2 End Sub Sub sCheckXY(X As String, Y As String) '選択セルがXならY,YならXにチェックをかえる If ActiveCell.Text = X Then ActiveCell.Value = Y End ElseIf ActiveCell.Text = Y Then ActiveCell.Value = X End End If End Sub Sub sCheckX1234(X1 As String, X2 As String, X3 As String, X4 As String) '選択セルがXならY,YならXにチェックをかえる If ActiveCell.Text = X1 Then ActiveCell.Value = X2 End ElseIf ActiveCell.Text = X2 Then ActiveCell.Value = X3 End ElseIf ActiveCell.Text = X3 Then ActiveCell.Value = X4 End ElseIf ActiveCell.Text = X4 Then ActiveCell.Value = X1 End End If End Sub

  • またまた エクセルのユーザー定義で

    前回以下のようなコードを教えていただきましたが、この変換を複数列で使えるようにするにはどうしたらいいのでしょうか? D,G,N,Q,X,AA,の列に効かせたいのですが。 Private Sub worksheet_change(ByVal Target As Range) If Intersect(Target, Columns(1)) Is Nothing Or Selection.Count <> 1 Then Exit Sub Dim str As String str = Target Application.EnableEvents = False If Target <> "" Then If Len(str) = 7 Then Target = Left(str, 5) & "A" & Mid(str, 6, 1) & "-" & Right(str, 1) Else Target = Left(str, 5) & "A" & Mid(str, 6, 2) & "-" & Right(str, 1) End If End If Application.EnableEvents = True End Sub

  • 文字列で渡された式

    質問です。 タイトルのままですが文字列で渡された式で 処理を決定させることはできるのでしょうか? たとえば ============================ dim str as string = "10 > 5" if strの文字列判定 then msgbox("TRUE") else msgbox("FALSE") end if ============================

  • like演算子で大カッコがあるか判断するには

    Sub test() Dim R As String R = "あ[あ]あ" If R Like "[" Then MsgBox "文字の中に大カッコがあります" End If End Sub を実行すると、 実行時エラーでパターン文字列が不正です。 になります。 If R Like "(" Then なら、問題なく動きます。 どうすればいいでしょうか?ご回答よろしくお願いします。

  • 文字列の比較をしたい

    String str1 = "北海道" String str2 = "北海道" str1とstr2が同じ場合にある処理をしたい場合、比較のところの記述はどのように書けばよいのでしょうか。 単純に If str1 = str2 Then ~~~~~ Else   ~~~~ End If でよいのでしょうか。 環境はVB.NETです。

  • EXCELで作ったマクロを別のファイルのEXCELでも使えるようにしたいです。

    (1)EXCELファイルでマクロを作成しました。 (実際はここである人の知恵をお借りして作ったものですが…) しかし、(2)EXCELファイルで(1)EXCEL作成マクロが実行できません。 どのような処理をすれば、どのPCでも、どのファイルでも実行できるようなマクロに出来るのでしょうか?? 以下にそのマクロを示します。 ↓↓↓ Sub 文字置換() '半角カタカナを全角に、全角英数を半角にするマクロ (Excel編) Dim rng As Range Dim Re As Object Dim myPat As String Dim c As Range Dim Matches As Object Dim Match As Object Dim Str1 As String Dim Str2 As String Dim buf As String Dim t As Long On Error Resume Next Set rng = ActiveSheet.UsedRange.SpecialCells _ (xlCellTypeConstants, xlTextValues) On Error GoTo 0 If rng Is Nothing Then MsgBox "変換する対象が見当たりません。", 48 Exit Sub End If '全角側 --- 半角側 (!-/ を加えれば記号も半角) myPat = "([\uFF66-\uFF9F]*)([!-}]*)" '正規表現のパターン Set Re = CreateObject("VBScript.RegExp") Application.ScreenUpdating = False With Re .Global = True .IgnoreCase = True .Pattern = myPat For Each c In rng.Cells Set Matches = .Execute(c.Value) If Matches.Count > 0 Then buf = c.Value For Each Match In Matches If Len(Match.Value) > 0 Then Str1 = StrConv(Match.SubMatches(0), vbWide) If Str1 <> "" Then '0 =vbBinaryCompare buf = Replace(buf, Match.SubMatches(0), Str1, , , 0) End If Str2 = StrConv(Match.SubMatches(1), vbNarrow) If Str2 <> "" Then buf = Replace(buf, Match.SubMatches(1), Str2, , , 0) End If End If Str1 = "": Str2 = "" Next Match If buf <> c.Value Then c.Value = buf t = t + 1 End If End If Next c End With Set Re = Nothing Application.ScreenUpdating = True If t > 0 Then MsgBox t & "個のセルを変換しました。", 64 End If End Sub 出来れば、置換した文字数をメッセージBOXに表示したいです。

  • VB2008で構造体を引数とした時にエラー

    VB2008の勉強を始めて数週間の初心者です。 勉強用にいろいろとプログラムを作っているのですが、 構造体(Structure)を引数で渡して戻り値を取得する Functionを作成してみました。 同一クラス内のPrivate Function の場合は問題ないのですいが、 追加した別クラスに Function を作成したところ 「 型 'TEST_A.Form1.str_IN' の値を 'TEST_A.Class1.str_IN' に変換できません。」 のエラーが表示されてしまいます。 別クラスのFunctionを使用する時、引数には構造体は指定できないのでしょうか? なにか文法上の誤りがあるのでしょうか? 初心者なので変な質問してたらスイマセン。 詳しい方がいらっしゃいましたらよろしくお願いします。 ------------------------------------------------------ Public Class Form1  Public Structure str_IN   Public in_aaa As String  End Structure  Private Sub Button1_Click(ByVal sender As System.Object,  ByVal e As System.EventArgs) ~   Dim stin As New str_IN   '------------------------------------   stin.in_aaa = "aaa"   Label1.Text = Test_Sub(stin) '<------- これはok   '-------------------------------------   Dim cls = New Class1   stin.in_aaa = "aaa"   Label1.Text = cls.CFnk(stin) '<----- エラーになる  End Sub  Private Function Test_Sub(ByVal prm_in As str_IN) As String   Dim stin As New str_IN   Dim sout As String   sout = "test_aaa"   Return sout  End Function End Class ------------------------------------------------------------ Public Class Class1 '新たに作成したクラス  Public Structure str_IN   Public in_aaa As String  End Structure  Public Function CFnk(ByVal prm_in As str_IN) As String   Dim stin As New str_IN   Dim sout As String   sout = "test_aaa"   Return sout  End Function End Class

  • Excel2010 VBA 条件色付け

    Sub sample() Dim r As Range For Each r In Range("q6:q30") If myIsNumeric(r) Then r.Offset(0, 1).Value = "数字" Else r.Offset(0, 1).Value = "文字" End If Next End Sub Function myIsNumeric(Target As Range) Dim r As Range Dim buf, tmp Dim flg As Boolean Dim i As Integer buf = Target For i = 1 To Len(buf) tmp = Mid(buf, i, 1) If IsNumeric(tmp) Then flg = True Exit For End If Next myIsNumeric = flg End Function を数字が入ってたら塗りつぶさないで、 数字が入ってなかったら塗りつぶすように直したいです。 あああ→塗る あああ1-1→塗らない 住所→塗る 住所12→塗らない

  • IFステートメントで半角でも全角でもtrueとさせ

    IFステートメントで半角でも全角でもtrueとさせるには? Sub test1() Dim str As String str = "ABC"’←全角のA If str Like "*A*" Then ’←半角のA MsgBox "Aがあります" End If End Sub これで、半角Aもメッセージを表示させたいのですが、 マッチバイトみたいなのってありますか?

  • VBAの処理が止まる原因と対策を知りたい

    現在以下のとおりのVBAを動かしいますが、途中でフリーズしてしまうため、 原因が特定できずに困っています。 その原因と対策もしくは、原因を突き止める方法をご教授いただければと思います。 ・サーバ上にあるブックを4つ開く(BookA、BookB、BookC、BookD) ・BookAに記載している文字列を配列に入れる ・BookB上にて、前述の文字列を検索し、そのアドレスを取得(後述の関数B) ・BookB上にて、前述のアドレスから別の文字列を取得(後述の関数A) となります。なお「Application.ScreenUpdatingの停止」と「Application.Calculationを手動」は実施しましたが、改善しませんでした。 以下環境、状況、VBAの記述になります。 環境 OS:Windows7 64bit CPU:i3 メモリ:8GB EXCEL:2010 状況 ・関数Aから関数Bを呼んだ後にフリーズしている模様です(関数Bを呼ぶところまでは、確認できますが、その後フリーズをするため、関数Aに戻っているかは不明です)。 ・フリーズ時のEXCEL.EXEのCPU使用率は25%で固定です。 関数A Function Test1(WS1 As Worksheet, Str1() As String, Str2() As String) Dim i As Integer Dim Row As Integer, Co As Integer Dim Temp_Range As Range Dim Temp_Str As String For i = 1 To UBound(Str2) ReDim Preserve Str1(i) Temp_Str = Test2(WS1, Str2(i - 1)) If Temp_Str <> "ない" And Temp_Str <> "重複" Then Set Temp_Range = WS1.Range(Temp_Str) If Temp_Range.MergeCells Then Co = Temp_Range.Column + Temp_Range.MergeArea.Count - 1 Else Co = Temp_Range.Column End If   Row = Temp_Range.Row Str1(i - 1) = WS1.Cells(Row, Co).Offset(0, 1).Value End If Next i End Function 関数B Function Test2(WS1 As Worksheet, Str1 As String) As String Dim temp As Range Dim a, b As Boolean Dim r As String Dim i, j As Integer Set temp = WS1.UsedRange For i = 1 To temp.Rows(temp.Rows.Count).Row For j = 1 To temp.Columns(temp.Columns.Count).Column If Replace(WS1.Cells(i, j).Value, vbLf, "") = Replace(Str1, vbLf, "") Then If a = False Then r = WS1.Cells(i, j).Address a = True Else r = "重複" b = True Exit For End If End If Next If b = True Then Exit For Next If r = "" Then r = "ない" Test2 = r End Function