如何在单元格和循环中使用Microsoft Excel中的正则表达式(正则表达式)

Por*_*ner 548 regex excel vba

如何在Excel中使用正则表达式并利用Excel强大的网格设置进行数据操作?

  • 单元格函数返回匹配的模式或替换字符串中的值.
  • Sub循环遍历一列数据并提取匹配到相邻单元格.
  • 需要什么设置?
  • Excel的正则表达式的特殊字符是什么?

我的理解正则表达式是不理想的许多情况下(使用或不使用正则表达式?),因为Excel可以使用Left,Mid,Right,Instr类型相似的操作命令.

Por*_*ner 894

正则表达式用于模式匹配.

要在Excel中使用,请执行以下步骤:

步骤1:将VBA引用添加到"Microsoft VBScript Regular Expressions 5.5"

  • 选择"开发人员"标签(我没有此标签,我该怎么办?)
  • 从"代码"功能区部分中选择"Visual Basic"图标
  • 在"Microsoft Visual Basic for Applications"窗口中,从顶部菜单中选择"工具".
  • 选择"参考"
  • 选中"Microsoft VBScript Regular Expressions 5.5"旁边的框以包含在您的工作簿中.
  • 点击"确定"

第2步:定义您的模式

基本定义:

- 范围.

  • 例如a-z匹配从a到z的小写字母
  • 例如0-5匹配0到5之间的任何数字

[] 恰好匹配这些括号内的一个对象.

  • 例如[a]匹配字母a
  • 例如,[abc]匹配单个字母,可以是a,b或c
  • 例如[a-z]匹配字母表中的任何单个小写字母.

()为返回目的分组不同的匹配.见下面的例子.

{} 用于在其之前定义的模式的重复副本的乘数.

  • 例如,[a]{2}匹配两个连续的小写字母a:aa
  • [a]{1,3}匹配至少一个和三个小写字母a,aa,aaa

+ 匹配至少一个或多个之前定义的模式.

  • 例如,a+将匹配一个连续的a,aa,aaa,等

? 匹配零或之前定义的模式之一.

  • 例如,模式可能存在也可能不存在,但只能匹配一次.
  • 例如,[a-z]?匹配空字符串或任何单个小写字母.

* 匹配在其之前定义的模式的零个或多个. - 例如,可能存在或不存在的模式的通配符.- 例如[a-z]*匹配空字符串或小写字母串.

. 匹配除换行符之外的任何字符 \n

  • 例如,a.匹配以a开头并以除外的任何内容结尾的两个字符串\n

| OR运算符

  • 例如a|b意味着要么ab可以被匹配.
  • 例如,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         |
Run Code Online (Sandbox Code Playgroud)

预定义字符缩写:

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
Run Code Online (Sandbox Code Playgroud)

示例1:以宏的形式运行

以下示例宏查看单元格中的值,A1以查看前1个或2个字符是否为数字.如果是这样,它们将被删除,并显示其余字符串.如果没有,则会出现一个框,告诉您没有找到匹配项.细胞A1的值12abc将返回abc,价值1abc将返回abc的值abc123将返回"不匹配",因为数字是不是在字符串的开头.

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
Run Code Online (Sandbox Code Playgroud)

示例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
Run Code Online (Sandbox Code Playgroud)

将字符串("12abc")放入单元格中A1.=simpleCellRegex(A1)在单元格中输入此公式,B1结果将为"abc".

在此输入图像描述


示例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
Run Code Online (Sandbox Code Playgroud)

示例4:拆分不同的模式

此示例循环遍历范围(A1,A2&A3)并查找以三位数字开头的字符串,后跟单个字母字符,然后是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
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述


附加模式示例

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
Run Code Online (Sandbox Code Playgroud)

  • 你不应该忘记`设置regEx = Nothing`.当Sub经常执行时,您将获得Out Of Memory异常. (20认同)
  • 后期绑定行:`设置regEx = CreateObject("VBScript.RegExp")` (9认同)
  • 不真实...像Notepad ++这样的简单独立工具在其查找和替换中具有“正则表达式”选项...但是在像Excel这样的世界级工具中,您必须是一名程序员才能做到这一点,并且以最晦涩和最复杂的方式.. (6认同)
  • @PortlandRunner 在“项目资源管理器”(?)中,这个 excel 文件缺少“模块”子文件夹,尽管另一个文件显示了一个。右键单击该文件并选择“插入模块”,然后双击“模块 1”并粘贴代码。已保存。返回工作簿并再次键入该功能 - 它起作用了。对于像我这样没有经验的人来说,答案中可能值得注意吗?谢谢您的帮助。 (3认同)
  • 好的,我很确定这是因为代码在`ThisWorkbook`中。尝试将代码移至单独的“模块”。 (2认同)

Pat*_*ker 192

要直接在Excel公式中使用正则表达式,以下UDF(用户定义的函数)可能会有所帮助.它或多或少直接将正则表达式功能公开为excel函数.

这个怎么运作

它需要2-3个参数.

  1. 要使用正则表达式的文本.
  2. 正则表达式.
  3. 格式字符串,指定结果的外观.它可以包含$0,$1,$2,等等.$0是整个匹配,$1并且up对应于正则表达式中的相应匹配组.默认为$0.

一些例子

提取电子邮件地址:

=regex("Peter Gordon: some@email.com, 47", "\w+@\w+\.\w+")
=regex("Peter Gordon: some@email.com, 47", "\w+@\w+\.\w+", "$0")
Run Code Online (Sandbox Code Playgroud)

结果是: some@email.com

提取几个子串:

=regex("Peter Gordon: some@email.com, 47", "^(.+): (.+), (\d+)$", "E-Mail: $2, Name: $1")
Run Code Online (Sandbox Code Playgroud)

结果是: E-Mail: some@email.com, Name: Peter Gordon

将单个单元格中的组合字符串拆分为多个单元格中的组件:

=regex("Peter Gordon: some@email.com, 47", "^(.+): (.+), (\d+)$", "$" & 1)
=regex("Peter Gordon: some@email.com, 47", "^(.+): (.+), (\d+)$", "$" & 2)
Run Code Online (Sandbox Code Playgroud)

结果:Peter Gordon some@email.com...

如何使用

要使用此UDF,请执行以下操作(大致基于此Microsoft页面.它们有一些很好的附加信息!):

  1. 在启用宏的文件('.xlsm')中的Excel中,按下ALT+F11以打开Microsoft Visual Basic for Applications Editor.
  2. 将VBA引用添加到Regular Expressions库(从Portland Runners ++回复中无耻地复制):
    1. 点击工具 - > 参考文献(请原谅德语截图) 工具 - >参考
    2. 在列表中找到Microsoft VBScript Regular Expressions 5.5并勾选旁边的复选框.
    3. 单击确定.
  3. 单击" 插入模块".如果你给你的模块不同的名称,确保该模块具有相同的名称,下面的UDF(如命名的模块Regex和功能regex导致#NAME!错误).

    图标行中的第二个图标 - >模块

  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
    
    Run Code Online (Sandbox Code Playgroud)
  5. 保存并关闭Microsoft Visual Basic for Applications Editor窗口.

  • 这个答案结合[这里](http://stackoverflow.com/a/2633992/1698058)创建加载项的步骤,一直非常有帮助.谢谢.确保不要给你的模块和功能提供相同的名称! (6认同)
  • 请重申Chris Hunt的上述评论.不要将您的模块"正则表达式"称为.我以为我已经疯了一段时间,因为#NAME错误导致函数无效 (2认同)
  • @Vijay:同样在 https://github.com/malcolmp/excel-regular-expressions (2认同)

SAm*_*SAm 55

扩大patszim对那些匆忙的人的回答.

  1. 打开Excel工作簿.
  2. Alt+ F11打开VBA/Macros窗口.
  3. 工具然后引用下添加对正则表达式的引用
    ![Excel VBA表单添加引用
  4. 并选择Microsoft VBScript Regular Expression 5.5
    ![Excel VBA添加正则表达式引用
  5. 插入一个新模块(代码需要驻留在模块中,否则它不起作用).
    ![Excel VBA插入代码模块
  6. 在新插入的模块中,
    ![Excel VBA将代码插入模块
  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
    
    Run Code Online (Sandbox Code Playgroud)
  8. 正则表达式模式放在其中一个单元格中,并在其上使用绝对引用. ![Excel正则表达式函数in-cell用法 函数将与其创建的工作簿绑定.
    如果需要在不同的工作簿中使用它,请将该函数存储在Personal.XLSB中

  • 感谢您提到它需要在 Personal.xlsb 中才能在您处理的所有 Excel 文档中可用。大多数(?)其他答案并没有说清楚。Personal.XLSB 将进入文件夹(可能需要创建文件夹)C:\Users\user name\AppData\Local\Microsoft\Excel\XLStart 文件夹 (2认同)

Vik*_*tam 25

这是我的尝试:

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
Run Code Online (Sandbox Code Playgroud)


小智 14

这不是一个直接的答案,但可能会提供一个更有效的替代方案供您考虑。也就是 Google Sheets 有几个内置的Regex 函数,这些函数非常方便,有助于绕过 Excel 中的一些技术程序。显然,在您的 PC 上使用 Excel 有一些优势,但对于绝大多数用户而言,Google 表格将提供相同的体验,并可能在可移植性和文档共享方面提供一些好处。

他们提供

REGEXEXTRACT:根据正则表达式提取匹配的子字符串。

REGEXREPLACE:使用正则表达式用不同的文本字符串替换文本字符串的一部分。

SUBSTITUTE:用字符串中的新文本替换现有文本。

REPLACE:用不同的文本字符串替换文本字符串的一部分。

你可以像这样直接将这些输入到一个单元格中,并会产生你想要的任何东西

=REGEXMATCH(A2, "[0-9]+")
Run Code Online (Sandbox Code Playgroud)

它们与其他函数(例如IF语句)结合使用时也能很好地工作,如下所示:

=IF(REGEXMATCH(E8,"MiB"),REGEXEXTRACT(E8,"\d*\.\d*|\d*")/1000,IF(REGEXMATCH(E8,"GiB"),REGEXEXTRACT(E8,"\d*\.\d*|\d*"),"")
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

希望这为那些被 Excel 的 VBS 组件嘲笑的用户提供了一个简单的解决方法。

  • 感谢分享亚历克斯。这对于那些寻找 Google 版本的人很有用。您可能会考虑编写并回答另一个特定于 Google Sheets Regex 的问题,因为它有自己的命名法,并且对其他人非常有用。无论如何,你有我的支持! (2认同)

Jvd*_*vdV 9

为了增加有价值的内容,我想创建一个关于为什么有时 VBA 中的 RegEx 并不理想的提醒。并非所有表达式都受支持,而是可能会抛出一个Error 5017并可能让作者猜测(我是自己的受害者)。

虽然我们可以找到一些资源什么支持的,这将是有益的知道哪些元字符等的支持。更深入的解释可以在这里找到。在这个来源中提到:

“虽然”VBScript 的正则表达式... 5.5 版实现了许多基本的正则表达式功能,而这些功能在以前的 VBScript 版本中是缺失的。... JavaScript 和 VBScript 实现 Perl 风格的正则表达式。但是,它们缺乏 Perl 和其他现代正则表达式风格中可用的许多高级功能:”


所以,支持的是:

  • 字符串 ancor 的开头\A,或者使用^插入符号匹配字符串中第一个字符之前的位置
  • 字符串结尾 ancor \Z,或者使用$美元符号匹配字符串中最后一个字符之后的位置
  • 正回顾后,如:(?<=a)b(同时阳性预读支持)
  • 负回顾后,如:(?<!a)b(同时排除模式支持)
  • 原子分组
  • 所有格量词
  • Unicode 例如: \{uFFFF}
  • 命名捕获组。或者使用编号捕获组
  • 内联修饰符,例如:(/i区分大小写)或/g(全局)等。通过RegExp对象属性 >RegExp.Global = True以及RegExp.IgnoreCase = True如果可用进行设置。
  • 条件句
  • 正则表达式注释'在脚本中使用常规注释添加这些

我已经不止一次在 VBA 中使用正则表达式了。通常使用LookBehind但有时我什至忘记了修饰符。我自己没有经历过上述所有这些背景,但我想我会尝试广泛参考一些更深入的信息。随意评论/更正/添加。对regular-expressions.info的大量信息大喊大叫。

PS您提到了常规的 VBA 方法和函数,我可以确认它们(至少对我自己而言)在 RegEx 失败的情况下以自己的方式有所帮助。

  • 急需补充 + (2认同)

Dee*_*ews 6

我需要将其用作单元函数(如SUMVLOOKUP),发现很容易:

  1. 确保您在启用宏的Excel文件中(另存为xlsm)。
  2. 打开开发人员工具Alt+F11
  3. 在其他答案中添加Microsoft VBScript正则表达式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
    
    Run Code Online (Sandbox Code Playgroud)
  5. 然后,您可以在单元格中使用=REGPLACE(B1, "(\w) (\d+)", "$1$2")(例如:“ A 243”至“ A243”)


jgr*_*eve 6

Here is a regex_subst() function. Examples:

=regex_subst("watermellon", "[aeiou]", "")
---> wtrmlln
=regex_subst("watermellon", "[^aeiou]", "")
---> aeeo
Run Code Online (Sandbox Code Playgroud)

Here is the simplified code (simpler for me, anyway). I couldn't figure out how to build a suitable output pattern using the above to work like my examples:

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
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

819131 次

最近记录:

5 年,11 月 前