VBA 正则表达式:使用自定义函数在 Excel 单元格内的字符串之间提取多个字符串
VBA regex: extract multiple strings between strings within Excel cell with custom function
在 Excel 列中,我有如下数据:
“奥迪 (ADI)、梅赛德斯 (modelx) (MEX)、法拉利超快、高 PS (FEH)”
有数百个模型,由名称和括号中三个大写字母的缩写描述。
我只需要提取名称和缩写来分隔单元格。我通过以下模块成功地为缩写做了这个:
Function extrABR(cellRef) As String
Dim RE As Object, MC As Object, M As Object
Dim sTemp As Variant
Const sPat As String = "([A-Z][A-Z][A-Z][A-Z]?)" ' this is my regex to match my string
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = sPat
If .Test(cellRef) Then
Set MC = .Execute(cellRef)
For Each M In MC
sTemp = sTemp & ", " & M.SubMatches(0)
Next M
End If
End With
extrABR = Mid(sTemp, 3)
End Function
但是,我没有设法为名字这样做。我想通过以下正则表达式交换正则表达式:(^(.*?)(?= \([A-Z][A-Z][A-Z])|(?<=, )(.*)(?= \([A-Z][A-Z][A-Z]))
,但 VBA 似乎不允许回顾。
有什么想法吗?
RE.REPLACE --
试试这个函数.. 括号之间的任何内容都将替换为“”,只为您提供模型名称字符串,然后您可以将其拆分为逗号并在需要时获取字符串数组。
Function ModelNames(cellRef) As String
Dim RE As Object, MC As Object, M As Object
Dim sTemp As Variant, sPat As String
sPat = "\([^)]+\)"
'Or you can use your formula pattern "([A-Z][A-Z][A-Z][A-Z]?)" to get (modelx) in the final output.
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = sPat
End With
ModelNames = RE.Replace(cellRef, "")
End Function
正确,不支持后视,但仅当您预期的匹配重叠时才需要它们。这里不是这种情况,你所有的比赛都是不重叠的。所以,你可以再次依赖 capturing:
(?:^|,)\s*(.*?)(?=\s*\([A-Z]{3,}\))
见regex demo。通过 .Submatches(0)
.
访问第 1 组值
详情:
(?:^|,)
- 字符串开头或逗号
\s*
- 零个或多个空白字符
(.*?)
- 捕获第 1 组:除换行字符外的任何零个或多个字符尽可能少
(?=\s*\([A-Z]{3,}\))
- 与紧随其后的位置相匹配的正面前瞻
\s*
- 零个或多个空白字符
\(
- 一个 (
字符
[A-Z]{3,}
- 三个或更多大写字符
\)
- 一个 )
字符。
演示截图:
在 Excel 列中,我有如下数据:
“奥迪 (ADI)、梅赛德斯 (modelx) (MEX)、法拉利超快、高 PS (FEH)”
有数百个模型,由名称和括号中三个大写字母的缩写描述。
我只需要提取名称和缩写来分隔单元格。我通过以下模块成功地为缩写做了这个:
Function extrABR(cellRef) As String
Dim RE As Object, MC As Object, M As Object
Dim sTemp As Variant
Const sPat As String = "([A-Z][A-Z][A-Z][A-Z]?)" ' this is my regex to match my string
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = sPat
If .Test(cellRef) Then
Set MC = .Execute(cellRef)
For Each M In MC
sTemp = sTemp & ", " & M.SubMatches(0)
Next M
End If
End With
extrABR = Mid(sTemp, 3)
End Function
但是,我没有设法为名字这样做。我想通过以下正则表达式交换正则表达式:(^(.*?)(?= \([A-Z][A-Z][A-Z])|(?<=, )(.*)(?= \([A-Z][A-Z][A-Z]))
,但 VBA 似乎不允许回顾。
有什么想法吗?
RE.REPLACE -- 试试这个函数.. 括号之间的任何内容都将替换为“”,只为您提供模型名称字符串,然后您可以将其拆分为逗号并在需要时获取字符串数组。
Function ModelNames(cellRef) As String
Dim RE As Object, MC As Object, M As Object
Dim sTemp As Variant, sPat As String
sPat = "\([^)]+\)"
'Or you can use your formula pattern "([A-Z][A-Z][A-Z][A-Z]?)" to get (modelx) in the final output.
Set RE = CreateObject("vbscript.regexp")
With RE
.Global = True
.MultiLine = True
.Pattern = sPat
End With
ModelNames = RE.Replace(cellRef, "")
End Function
正确,不支持后视,但仅当您预期的匹配重叠时才需要它们。这里不是这种情况,你所有的比赛都是不重叠的。所以,你可以再次依赖 capturing:
(?:^|,)\s*(.*?)(?=\s*\([A-Z]{3,}\))
见regex demo。通过 .Submatches(0)
.
详情:
(?:^|,)
- 字符串开头或逗号\s*
- 零个或多个空白字符(.*?)
- 捕获第 1 组:除换行字符外的任何零个或多个字符尽可能少(?=\s*\([A-Z]{3,}\))
- 与紧随其后的位置相匹配的正面前瞻\s*
- 零个或多个空白字符\(
- 一个(
字符[A-Z]{3,}
- 三个或更多大写字符\)
- 一个)
字符。
演示截图: