VBA之正则表达式(8)-- 重复字符分组

实例需求:数据保存在A列中,需要将其中重复字符分拆后保存在后续的列中,为简化示例代码,只考虑小写英文字符。

这个需求也并不复杂,用VBA代码逐个判断字符和其前后的字符对比,就可以区分每组,高手可以写出递归调用过程。用正则处理这种问题会更简单。

Sub RegExpDemo()
    Dim strTxt As String
    Dim objRegEx As Object, objMatch As Object
    Dim objMH As Object, c As Range
    Set objRegEx = CreateObject("vbscript.regexp")
    objRegEx.Global = True
    objRegEx.Pattern = "([a-z])\1*"
    Range("B:AA").ClearContents
    For Each c In Range([A1], Cells(Rows.Count, "A").End(xlUp))
        strTxt = c.Value
        Set objMatch = objRegEx.Execute(strTxt)
        If objMatch.Count > 0 Then
            col = 2
            For Each objMH In objMatch
                Cells(c.Row, col) = objMH.Value
                col = col + 1
            Next
        End If
    Next
    Set objMH = Nothing
    Set objMatch = Nothing
    Set objRegEx = Nothing
End Sub


【代码解析】
第5行代码使用后期绑定创建正则对象。
第6行代码设置为全局搜索模式。
第7行代码指定正则匹配字符串,([a-z])用于匹配单个小写英文字符,并提取为第一组,\1*含义是第一组字符重复0次(也就是只有单个字符的情况)或者多次。
第8和代码清空后续列用于保存结果。
第9行代码第19行代码循环处理工作表中的数据。
第11行执行正则匹配。
如果匹配成功,第14行到第17行代码将匹配结果写入工作表后续列中。
注意第15行代码读取的是objMH.Value,而不是objMH.submatches(0).Value。


似乎这个代码也没有什么神奇的地方,只是匹配模式中使用了匹配组\1

接下来才是今天要讲的重点,上面的正则匹配是通用思路,解决问题时,都是去设法提取匹配的字符串,然后在VBA中加工,这个示例需要写入工作表单元格,那么只要拆分成数组,就可以一次性写入单元格区域了,VBA中拆分数组肯定是用Split函数了。下面的升级版解决方案中用到了正则替换。

Sub RegExpRepDemo()
    Dim strTxt As String, arrRes
    Dim objRegEx As Object, objMatch As Object
    Dim objMH As Object, c As Range
    Set objRegEx = CreateObject("vbscript.regexp")
    objRegEx.Global = True
    objRegEx.Pattern = "([a-z])(?!\1|$)"
    Range("B:AA").ClearContents
    For Each c In Range([A1], Cells(Rows.Count, "A").End(xlUp))
        strTxt = c.Value
        arrRes = Split(objRegEx.Replace(strTxt, "$1 "))
        Cells(c.Row, 2).Resize(1, UBound(arrRes) + 1).Value = arrRes
    Next
    Set objMH = Nothing
    Set objMatch = Nothing
    Set objRegEx = Nothing
End Sub

【代码解析】
与上面代码相同的步骤这里就不再赘述。

匹配模式 含义
([a-z]) 匹配单个小写英文字符,并提取为第一组
?! 零宽度否定顺序环视,不消耗字符,只用于环视判断
\1 第一组匹配字符(一个或者多个)
$ 行的结束标识

aaabbccccdeeee为例看一下正则匹配过程。

游标位置 匹配组 下一个字符 说明
0 a a 下一个字符与匹配组相同,不满足正则模式
1 a a 下一个字符与匹配组相同,不满足正则模式
2 a b 下一个字符与匹配组不同,满足正则模式,将被替换为a+空格
3 b b 下一个字符与匹配组相同,不满足正则模式
4 b c 下一个字符与匹配组不同,满足正则模式,将被替换为b+空格
依次处理每个字符
13 e $ 下一个为字符结束标识,不满足正则模式

正则替换之后的字符串为aaa bb cccc d eeee,注意字符串末尾并不会添加空格,使用Split拆分为数组,可以直接写入一行单元格内,这波操作比第一个代码更简洁。


相关博文链接:
VBA之正则表达式(1)-- 基础篇
VBA之正则表达式(2)-- 批量修改公式
VBA之正则表达式(3)-- 特殊公式计算
VBA之正则表达式(4)-- 提取日期和金额
VBA之正则表达式(5)-- 中文字符
VBA之正则表达式(6)-- 设置音标格式
VBA之正则表达式(7)-- 乾坤大挪移(数据整理)
VBA之正则表达式(8)-- 重复字符分组
VBA之正则表达式(9)-- 添加千分位(1/3)
VBA之正则表达式(10)-- 添加千分位(2/3)
VBA之正则表达式(11)-- 添加千分位(3/3)

发布了107 篇原创文章 · 获赞 49 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/taller_2000/article/details/89735304