(1条消息) VBA正则表达式深度解析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
版权

目录

本文章可以学到:

先上代码:

分析:

调式:

细心一点会发现两个问题:

一个一个的来解答


本文章可以学到:

  • VBA正则表达式匹配第N个结果

  • VBA正则表达式剔除匹配包含字符的数字中剔除字符,只保留数字

先上代码:

Function GetStr(ByVal rng As String, str As String, Optional i As Long, Optional s As Boolean)'第一个参数rng    为数据源'第二个参数str    为正则表达式'第三个参数i      为正则表达式成功匹配的结果列表中的第几个,从0开始,默认为0即第1个'第四个参数s      为文本[True]或数字[False],用于剔除数字中的文本内容,默认为数字[False]If IsMissing(i) Then i = 0If IsMissing(s) Then s = FalseDim iRg As ObjectSet iRg = CreateObject("VBscript.regexp")With iRg.Global = True.Pattern = str   '表达式,直接从用户函数的第二个参数中调用If .Execute(rng).Count = 0 Then'如果匹配到结果的量为0则GetStr = ""'返回结果为空值'函数结束ElseIf IsNumeric(.Execute(rng)(i)) Or s Then'如果第一次得到的结果是数字或者函数的第4个参数为True或非0则GetStr = .Execute(rng)(i)'直接返回第一次得到的结果'函数结束ElseGetStr = GetStr(.Execute(rng)(i), "[0-9]+[.]{0,1}[0-9]{0,}")'否则从第一次返回的结果中剔除数字以外的字符'即调用函数本身再传入一个数字的正则表达式"[0-9]+[.]{0,1}[0-9]{0,}"End IfEnd IfEnd WithEnd Function

测试结果:

  B C D E F
2 源文本.1 ss11.11cmcxzas/.'22.22cmwq.,3cmd.,/;eq4.44444cm
3 正则表达式.1 [0-9]+[.]{0,}[0-9]{0,}[cm]
4                 第3参数(i)
第4参数(s)     
0 1 2 3
5
6 0 11.11   =GetStr(C2,C3,C4,B6) 22.22  =GetStr(C2,C3,D4,B6) 3  =GetStr(C2,C3,E4,B6) 4.44444  =GetStr(C2,C3,F4,B6)
7 1 11.11c  =GetStr(C2,C3,C4,B7) 22.22c =GetStr(C2,C3,D4,B7) 3c =GetStr(C2,C3,E4,B7) 4.44444c =GetStr(C2,C3,F4,B7)
8          
9 源文本.2 ss11.11cmcmxzas/.'22.22cmwq.,333333cmd.,/;eq4.44444cm
10 正则表达式.2 [0-9]+[.]{0,}[0-9]{0,}[cm]+
11                 第3参数(i)
第4参数(s)     
0 1 2 3
12
13 0 11.11      =GetStr(C9,C10,C11,B13) 22.22    =GetStr(C9,C10,D11,B13) 333333   =GetStr(C9,C10,E11,B13) 333333cm  =GetStr(C9,C10,E11,B14)
14 1 11.11cmcm  =GetStr(C9,C10,C11,B14) 22.22cm  =GetStr(C9,C10,D11,B14) 333333cm =GetStr(C9,C10,E11,B14) 4.44444cm =GetStr(C9,C10,F11,B14)

分析:

我们从[C6]单元格开始说起

代入目标单元格解析的公式是:

=GetStr("ss11.11cmcxzas/.'22.22cmwq.,3cmd.,/;eq4.44444cm","[0-9]+[.]{0,}[0-9]{0,}[cm]",0,0)

调式:

在第17行代码添加断点,然后在监视窗口中添加监视:

irg.Execute(Rng)

双击[C6]单元格,回车就可以看到如下图所示

可以看到这个 "[0-9]+[.]{0,}[0-9]{0,}[cm]" 正则表达式作用在这段"ss11.11cmcxzas/.'22.22cmwq.,3cmd.,/;eq4.44444cm"文字中,会得到4个结果,那么就可以通过传入第3个参数  i   来选择我们想要的第几个结果。

在[C6]单元格中我们第三个参数是0,也是就返回匹配到的第0个结果,11.11c

细心一点会发现两个问题:

  1. 传入的正则表达式是 "[0-9]+[.]{0,}[0-9]{0,}[cm]",末尾是 cm 为啥只匹配到了c

  2. 【C6】单元格的结果是11.11

一个一个的来解答

第1个问题是因为[cm]默认只匹配中括号中的第一个符号,也就是c,如果想要匹配[cm]有几种方法

  • 笨方法:[c][m]或者[cm]{2}或者[cm]{0,}

  • 好方法:[cm]+或者cm

第2个问题是因为一般匹配的数字的时候,数字后面可能会有一些特定字符比如单位。而匹配的结果会把这些字符一起放进去,这样就不方便使用公式进行计算或者统计总数,需要二次匹配,也就是在得到一个包含字符的数字中剔除字符,只保留数字。

关键就在24-33行代码:

If IsNumeric(.Execute(rng)(i)) Or s Then'如果第一次得到的结果是数字或者函数的第4个参数为True或非0则GetStr = .Execute(rng)(i)'直接返回第一次得到的结果ElseGetStr = GetStr(.Execute(rng)(i), "[0-9]+[.]{0,1}[0-9]{0,}")'否则从第一次返回的结果中剔除数字以外的字符'即调用函数本身再传入一个数字的正则表达式"[0-9]+[.]{0,1}[0-9]{0,}"End If

根据这个思路看测试结果,就很清晰明了了。

(0)

相关推荐