web-dev-qa-db-ja.com

Microsoft Excelでセル内とループの両方で正規表現(Regex)を使用する方法

Excelで正規表現を使用して、データ操作の設定などのExcelの強力なグリッドを利用するにはどうすればよいですか。

  • 一致したパターンまたは置換後の値を文字列で返すためのセル内関数。
  • データの列をループして隣接するセルとの一致を抽出するためのSub。
  • どのような設定が必要ですか?
  • 正規表現に対するExcelの特殊文字は何ですか?

Regexは、ExcelがLeftMidRightInstr型のコマンドを同様の操作に使用できるため、多くの状況( 正規表現を使用するかしないか? )には理想的ではないことがわかります。

491
Portland Runner

正規表現 はパターンマッチングに使用されます。

Excelで使用するには、次の手順に従います。

ステップ1 : "Microsoft VBScript正規表現5.5"へのVBA参照の追加

  • [開発者]タブを選択します( このタブが表示されません。
  • [コード]リボンセクションから[Visual Basic]アイコンを選択します。
  • 「Microsoft Visual Basic for Applications」ウィンドウで、トップメニューから「ツール」を選択します。
  • 「参照」を選択してください
  • ブックに含めるには、 "Microsoft VBScriptの正規表現5.5"の横のチェックボックスをオンにします。
  • 「OK」をクリック

ステップ2 :あなたのパターンを定義する

基本定義:

-範囲。

  • 例えば。 a-zはaからzまでの小文字に一致します
  • 例えば。 0-5は、0から5までの任意の数に一致します

[]これらの角かっこ内のオブジェクトの1つと正確に一致します。

  • 例えば。 [a]は文字aと一致します
  • 例えば。 [abc]は、a、b、cのいずれかの文字に一致します。
  • 例えば。 [a-z]は、アルファベットの小文字1文字に一致します。

()返品を目的として、さまざまな一致をグループ化します。以下の例を参照してください。

{}前に定義されたパターンの繰り返しコピーの乗数。

  • 例えば。 [a]{2}は、2つの連続した小文字のaに一致します。aa
  • 例えば。 [a]{1,3}は、最低1文字から最大3文字の小文字のaaaaaaに一致します

+前に定義されたパターンの少なくとも1つ以上に一致します。

  • 例えば。 a+は、連続するaのaaaaaaなどに一致します。

?その前に定義されているパターンの0個または1個に一致します。

  • 例えば。パターンは存在してもしなくてもよいが、一度だけ一致させることができる。
  • 例えば。 [a-z]?は、空の文字列または任意の1文字の小文字に一致します。

*直前に定義された0個以上のパターンに一致します。 - 例存在してもしなくてもよいパターンのワイルドカード。 - 例[a-z]*は、空の文字列または小文字の文字列と一致します。

.改行以外の任意の文字と一致します\n

  • 例えば。 a.で始まり\n以外のもので終わる2文字の文字列に一致します。

| OR演算子

  • 例えば。 a|bは、aまたはbのいずれかを一致させることができることを意味します。
  • 例えば。 red|white|orangeは正確にいずれかの色に一致します。

^ NOT演算子

  • 例えば。 [^0-9]文字に数字を含めることはできません
  • 例えば。 [^aA]文字は小文字のaまたは大文字のAにはできません

\後に続く特殊文字をエスケープします(上記の振る舞いをオーバーライドします)

  • 例えば。 \.\\\(\?\$\^

アンカーパターン:

^文字列の先頭で一致する必要があります

  • 例えば。 ^a最初の文字は小文字でなければなりませんa
  • 例えば。 ^[0-9]最初の文字は数字でなければなりません。

$文字列の末尾で一致する必要があります

  • 例えば。 a$最後の文字は小文字でなければなりませんa

優先順位表:

Order  Name                Representation
1      Parentheses         ( )
2      Multipliers         ? + * {m,n} {m, n}?
3      Sequence & Anchors  abc ^ $
4      Alternation         |

定義済みの文字の省略形:

abr    same as       meaning
\d     [0-9]         Any single digit
\D     [^0-9]        Any single character that's not a digit
\w     [a-zA-Z0-9_]  Any Word character
\W     [^a-zA-Z0-9_] Any non-Word character
\s     [ \r\t\n\f]   Any space character
\S     [^ \r\t\n\f]  Any non-space character
\n     [\n]          New line

例1 マクロとして実行

次の例のマクロは、セルA1の値を調べて、最初の1文字か2文字が数字かどうかを調べます。そうであれば、それらは削除され、残りの文字列が表示されます。そうでない場合は、一致が見つからないことを知らせるボックスが表示されます。 A1のセル12abc値はabcを返し、1abcの値はabcを返し、abc123の値は文字列の先頭にないため、 "Not Matched"を返します。

Private Sub simpleRegex()
    Dim strPattern As String: strPattern = "^[0-9]{1,2}"
    Dim strReplace As String: strReplace = ""
    Dim regEx As New RegExp
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1")

    If strPattern <> "" Then
        strInput = Myrange.Value

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.Test(strInput) Then
            MsgBox (regEx.Replace(strInput, strReplace))
        Else
            MsgBox ("Not matched")
        End If
    End If
End Sub

例2 セル内関数として実行

この例は例1と同じですが、セル内関数として実行するように設定されています。使用するには、コードをこれに変更します。

Function simpleCellRegex(Myrange As Range) As String
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim strReplace As String
    Dim strOutput As String


    strPattern = "^[0-9]{1,3}"

    If strPattern <> "" Then
        strInput = Myrange.Value
        strReplace = ""

        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = strPattern
        End With

        If regEx.test(strInput) Then
            simpleCellRegex = regEx.Replace(strInput, strReplace)
        Else
            simpleCellRegex = "Not matched"
        End If
    End If
End Function

文字列( "12abc")をセルA1に配置します。セルB1にこの式=simpleCellRegex(A1)を入力すると、結果は "abc"になります。

enter image description here


例3 ループスルー範囲

この例は例1と同じですが、セル範囲をループします。

Private Sub simpleRegex()
    Dim strPattern As String: strPattern = "^[0-9]{1,2}"
    Dim strReplace As String: strReplace = ""
    Dim regEx As New RegExp
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1:A5")

    For Each cell In Myrange
        If strPattern <> "" Then
            strInput = cell.Value

            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = False
                .Pattern = strPattern
            End With

            If regEx.Test(strInput) Then
                MsgBox (regEx.Replace(strInput, strReplace))
            Else
                MsgBox ("Not matched")
            End If
        End If
    Next
End Sub

例4 :異なるパターンに分割する

この例では、範囲(A1A2A3)をループ処理し、3桁の数字で始まり、その後に単一の英字が続き、次に4桁の数字が続くストリングを探します。 ()を使用することで、出力はパターンマッチを隣接するセルに分割します。 $1は、()の最初のセット内で一致した最初のパターンを表します。

Private Sub splitUpRegexPattern()
    Dim regEx As New RegExp
    Dim strPattern As String
    Dim strInput As String
    Dim Myrange As Range

    Set Myrange = ActiveSheet.Range("A1:A3")

    For Each C In Myrange
        strPattern = "(^[0-9]{3})([a-zA-Z])([0-9]{4})"

        If strPattern <> "" Then
            strInput = C.Value

            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = False
                .Pattern = strPattern
            End With

            If regEx.test(strInput) Then
                C.Offset(0, 1) = regEx.Replace(strInput, "$1")
                C.Offset(0, 2) = regEx.Replace(strInput, "$2")
                C.Offset(0, 3) = regEx.Replace(strInput, "$3")
            Else
                C.Offset(0, 1) = "(Not matched)"
            End If
        End If
    Next
End Sub

結果:

enter image description here


追加のパターン例

String   Regex Pattern                  Explanation
a1aaa    [a-zA-Z][0-9][a-zA-Z]{3}       Single alpha, single digit, three alpha characters
a1aaa    [a-zA-Z]?[0-9][a-zA-Z]{3}      May or may not have preceeding alpha character
a1aaa    [a-zA-Z][0-9][a-zA-Z]{0,3}     Single alpha, single digit, 0 to 3 alpha characters
a1aaa    [a-zA-Z][0-9][a-zA-Z]*         Single alpha, single digit, followed by any number of alpha characters

</i8>    \<\/[a-zA-Z][0-9]\>            Exact non-Word character except any single alpha followed by any single digit
830
Portland Runner

Excelの数式で直接正規表現を使用するには、次のUDF(ユーザー定義関数)が役立ちます。多かれ少なかれ、Excel関数として正規表現機能を直接公開します。

使い方

2〜3個のパラメーターが必要です。

  1. 正規表現を使用するテキスト。
  2. 正規表現。
  3. 結果の外観を指定するフォーマット文字列。 $0$1$2などを含めることができます。 $0は一致全体であり、$1以上は正規表現の各一致グループに対応します。デフォルトは$0です。

いくつかの例

メールアドレスの抽出:

=regex("Peter Gordon: [email protected], 47", "\[email protected]\w+\.\w+")
=regex("Peter Gordon: [email protected], 47", "\[email protected]\w+\.\w+", "$0")

結果:[email protected]

いくつかの部分文字列の抽出:

=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "E-Mail: $2, Name: $1")

結果:E-Mail: [email protected], Name: Peter Gordon

単一のセルの結合文字列を複数のセルのコンポーネントに分解するには:

=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "$" & 1)
=regex("Peter Gordon: [email protected], 47", "^(.+): (.+), (\d+)$", "$" & 2)

結果:Peter Gordon[email protected] ...

使い方

このUDFを使用するには、次の手順を実行します(おおよそ このMicrosoftページ に基づいています。追加情報があります!)。

  1. Excelのマクロ対応ファイル( '.xlsm')でALT+F11を押して、Microsoft Visual Basic for Applicationsエディターを開きます。
  2. 正規表現ライブラリにVBA参照を追加します( Portland Runners ++ answer )から恥知らずにコピーされます:
    1. Tools->Referencesをクリックします(ドイツ語のスクリーンショットはご容赦ください) Tools -> References
    2. リストでMicrosoft VBScript Regular Expressions 5.5を見つけ、その横のチェックボックスをオンにします。
    3. OKをクリックします。
  3. モジュールの挿入をクリックします。モジュールに別の名前を付ける場合は、モジュールがnot以下のUDFと同じ名前を持っていることを確認してください(たとえば、モジュールRegex関数regexは、#NAME!エラーを引き起こします)。

    Second icon in the icon row -> Module

  4. 中央の大きなテキストウィンドウに次を挿入します。

    Function regex(strInput As String, matchPattern As String, Optional ByVal outputPattern As String = "$0") As Variant
        Dim inputRegexObj As New VBScript_RegExp_55.RegExp, outputRegexObj As New VBScript_RegExp_55.RegExp, outReplaceRegexObj As New VBScript_RegExp_55.RegExp
        Dim inputMatches As Object, replaceMatches As Object, replaceMatch As Object
        Dim replaceNumber As Integer
    
        With inputRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = matchPattern
        End With
        With outputRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = "\$(\d+)"
        End With
        With outReplaceRegexObj
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
        End With
    
        Set inputMatches = inputRegexObj.Execute(strInput)
        If inputMatches.Count = 0 Then
            regex = False
        Else
            Set replaceMatches = outputRegexObj.Execute(outputPattern)
            For Each replaceMatch In replaceMatches
                replaceNumber = replaceMatch.SubMatches(0)
                outReplaceRegexObj.Pattern = "\$" & replaceNumber
    
                If replaceNumber = 0 Then
                    outputPattern = outReplaceRegexObj.Replace(outputPattern, inputMatches(0).Value)
                Else
                    If replaceNumber > inputMatches(0).SubMatches.Count Then
                        'regex = "A to high $ tag found. Largest allowed is $" & inputMatches(0).SubMatches.Count & "."
                        regex = CVErr(xlErrValue)
                        Exit Function
                    Else
                        outputPattern = outReplaceRegexObj.Replace(outputPattern, inputMatches(0).SubMatches(replaceNumber - 1))
                    End If
                End If
            Next
            regex = outputPattern
        End If
    End Function
    
  5. Microsoft Visual Basic for ApplicationsEditorウィンドウを保存して閉じます。

186
Patrick Böker

patszim 's answer を拡張してRushにいる人たち。

  1. Excelブックを開きます。
  2. Alt+F11 VBA/Macrosウィンドウを開く。
  3. ツールに正規表現への参照を追加し、参照
    ![Excel VBA Form add references
  4. そしてMicrosoft VBScript Regular Expression 5.5を選択します
    ![Excel VBA add regex reference
  5. 新しいモジュールを挿入します(コードはモジュール内に存在する必要があります。そうしないと機能しません)。
    ![Excel VBA insert code module
  6. 新しく挿入されたモジュールでは、
    ![Excel VBA insert code into module
  7. 次のコードを追加してください。

    Function RegxFunc(strInput As String, regexPattern As String) As String
        Dim regEx As New RegExp
        With regEx
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .pattern = regexPattern
        End With
    
        If regEx.Test(strInput) Then
            Set matches = regEx.Execute(strInput)
            RegxFunc = matches(0).Value
        Else
            RegxFunc = "not matched"
        End If
    End Function
    
  8. 正規表現パターンはセルの1つに配置され、絶対参照が使用されます。 ![Excel regex function in-cell usage 関数はそれが作成したワークブックに結び付けられます。
    異なるワークブックで使用する必要がある場合は、関数をPersonal.XLSBに保存してください。

48
SAm

これが私の試みです。

Function RegParse(ByVal pattern As String, ByVal html As String)
    Dim regex   As RegExp
    Set regex = New RegExp

    With regex
        .IgnoreCase = True  'ignoring cases while regex engine performs the search.
        .pattern = pattern  'declaring regex pattern.
        .Global = False     'restricting regex to find only first match.

        If .Test(html) Then         'Testing if the pattern matches or not
            mStr = .Execute(html)(0)        '.Execute(html)(0) will provide the String which matches with Regex
            RegParse = .Replace(mStr, "$1") '.Replace function will replace the String with whatever is in the first set of braces - $1.
        Else
            RegParse = "#N/A"
        End If

    End With
End Function
21
Vikas Gautam

これをセル関数(SUMVLOOKUPなど)として使用する必要があり、それが簡単であることがわかりました。

  1. マクロ対応のExcelファイル(xlsmとして保存)に入っていることを確認してください。
  2. オープン開発者ツール Alt + F11
  3. 他の回答と同様にMicrosoft VBScript Regular Expressions 5.5を追加
  4. ワークブックまたは独自のモジュールのいずれかで次の関数を作成します。

    Function REGPLACE(myRange As Range, matchPattern As String, outputPattern As String) As Variant
        Dim regex As New VBScript_RegExp_55.RegExp
        Dim strInput As String
    
        strInput = myRange.Value
    
        With regex
            .Global = True
            .MultiLine = True
            .IgnoreCase = False
            .Pattern = matchPattern
        End With
    
        REGPLACE = regex.Replace(strInput, outputPattern)
    
    End Function
    
  5. それから=REGPLACE(B1, "(\w) (\d+)", "$1$2")を使ってセル内で使うことができます(例: "A 243"から "A243")。

4
DeezCashews

これがregex_subst()関数です。例:

=regex_subst("watermellon", "[aeiou]", "")
---> wtrmlln
=regex_subst("watermellon", "[^aeiou]", "")
---> aeeo

これが単純化されたコードです(とにかく私にとってはもっと単純です)。上の例を使用して適切な出力パターンを作成し、私の例のように機能させる方法はわかりませんでした。

Function regex_subst( _
     strInput As String _
   , matchPattern As String _
   , Optional ByVal replacePattern As String = "" _
) As Variant
    Dim inputRegexObj As New VBScript_RegExp_55.RegExp

    With inputRegexObj
        .Global = True
        .MultiLine = True
        .IgnoreCase = False
        .Pattern = matchPattern
    End With

    regex_subst = inputRegexObj.Replace(strInput, replacePattern)
End Function
1
jgreve

スクリプトを移植可能にする必要があるため、参照ライブラリを有効にする必要はありません。 Dim foo As New VBScript_RegExp_55.RegExp行はUser Defined Type Not Definedエラーを引き起こしました、しかし私は私のために働いた解決策を見つけました。

あなたがしたいことはセルA1に例の文字列を入れて、そしてあなたのstrPatternをテストすることです。それがうまくいったら、次にrngを調整します。

Public Sub RegExSearch()
'https://stackoverflow.com/questions/22542834/how-to-use-regular-expressions-regex-in-Microsoft-Excel-both-in-cell-and-loops
'https://wellsr.com/vba/2018/Excel/vba-regex-regular-expressions-guide/
'https://www.vitoshacademy.com/vba-regex-in-Excel/
    Dim regexp As Object
    'Dim regex As New VBScript_RegExp_55.regexp 'Caused "User Defined Type Not Defined" Error
    Dim rng As Range, rcell As Range
    Dim strInput As String, strPattern As String

    Set regexp = CreateObject("vbscript.regexp")
    Set rng = ActiveSheet.Range("A1:A1")

    For Each rcell In rng.Cells

        strPattern = "([a-z]{2})([0-9]{8})"
        'Search for 2 ## then 8 Digits Eg: XY12345678 = Matched

        If strPattern <> "" Then
            strInput = rcell.Value

            With regexp
                .Global = False
                .MultiLine = False
                .ignoreCase = True
                .Pattern = strPattern
            End With

            If regexp.test(strInput) Then
                MsgBox rcell & " Matched in Cell " & rcell.Address
            Else
                MsgBox "No Matches!"
            End If
        End If
    Next
End Sub
0