使用 RegEx 匹配 Excel/VBA 中的五个字符,第一个字符取决于单元格值
Posted
技术标签:
【中文标题】使用 RegEx 匹配 Excel/VBA 中的五个字符,第一个字符取决于单元格值【英文标题】:Matching five characters in Excel/VBA using RegEx, with first character being dependant on cell value 【发布时间】:2017-06-16 07:59:22 【问题描述】:我需要你的帮助!我想在 Excel/VBA 环境中使用 RegEx。我确实有办法,但我有点达到了我的极限......
我需要在很多行字符串中匹配 5 个字符(字符串在我的 Excel 表的 B 列中,A 稍后出现)。这 5 个字符可以是 5 位数字或“K”后跟 4 位数字(例如 12345
、98765
、K2345
)。这将被 (\d5|K\d4)
覆盖。
它们五个可以在字母或特殊字符之前或之后,但不能是数字。这意味着不允许使用前导零,并且数字不应仅在更长的数字内匹配。这就是我卡住的地方。
如果字符串中有多个可能的匹配项,我需要将它们全部匹配。如果同一行中已经匹配了相同的数字,我希望它不再匹配。对于这两个要求,我已经有了一种解决方案,它作为本文末尾的 VBA 代码的一部分工作:(\d5|K\d4)(?!.*?\1.*$)
此外,我在 A 列中确实有一个特定的单个数字(或“K”)。我需要五个字符以该特定字符开头,否则不匹配。
字符串示例(编号)。 A、B两列用“|”隔开为了更好的可读性
(1) | 1 | 2018/ID11298 00000012345 PersonNR: 889899 普利司通 BNPN (2) | 3 | Kompo 32280EP ###Baukasten### 3789936690 ID PFK Carbon0 (3) | 2 | 20613、20614、Mietop Antragsnummer C300Coup IVS 33221 ABF (4) | 2 | Q21009 中国本土产品衍生 f/Radverbund 991222 VV (5) | 6 | ID:61953 F-Pace Enfantillages (Machine arriere) VvSKPMG Lyon09 (6) | 2 | 2017/22222 22222 21895 Einzelkostenprob。 28932 ZürichMP KOS (7) | ķ | ID:K1245 Panamera Nitsche Radlager Derivativ Bayreumion PwC (8) | 7 | LaunchSupport QBremsen BBG BFG BBD 70142,70119 KK 70142
我在这里寻找的结果是:
(1) | 11298 | ............................. [但不匹配 12345,因为不允许使用前面的数字] (2) | 32280 | ............................. [但不匹配 37899 内的 3789936690] (3) | 20613 | 20614 | ................ [匹配以 2 开头的,不匹配以 3 开头的] (4) | 21009 | ................................ [前面有一个字母,非常好 (5) | 61953 | .............................[随机示例] (6) | 22222 | 21895 | 28932 | ... [全部匹配,但不重复] (7) | K1245 | ............................. [带有“K”的特殊情况] (8) | 70142 | 70119 | ............. [忽略第二个 70142]
到目前为止,我整理的 RegEx/VBA 代码是:
Sub RegEx()
Dim varOut() As Variant
Dim objRegEx As Object
Dim lngColumn As Long
Dim objRegA As Object
Dim varArr As Variant
Dim lngUArr As Long
Dim lngTMP As Long
On Error GoTo Fin
With Worksheets("Sheet1")
varArr = .Range("B2:B50")
Set objRegEx = CreateObject("VBScript.Regexp")
With objRegEx
.Pattern = "(\d5|K\d4)(?!.*?\1.*$)" 'this is where the magic happens
.Global = True
For lngUArr = 1 To UBound(varArr)
Set objRegA = .Execute(varArr(lngUArr, 1))
If objRegA.Count >= lngColumn Then
lngColumn = objRegA.Count
End If
Set objRegA = Nothing
Next lngUArr
If lngColumn = 0 Then Exit Sub
ReDim varOut(1 To UBound(varArr), 1 To lngColumn)
For lngUArr = 1 To UBound(varArr)
Set objRegA = .Execute(varArr(lngUArr, 1))
For lngTMP = 1 To objRegA.Count
varOut(lngUArr, lngTMP) = objRegA(lngTMP - 1)
Next lngTMP
Set objRegA = Nothing
Next lngUArr
End With
.Cells(2, 3).Resize(UBound(varOut), UBound(varOut, 2)) = varOut
End With
Fin:
Set objRegA = Nothing
Set objRegEx = Nothing
If Err.Number <> 0 Then MsgBox "Error: " & Err.Number & " " & Err.Description
End Sub
此代码正在检查 B 列中的字符串,并在 C、D、E 等列中提供其匹配项。它不匹配重复项。然而,它在更大的数字中匹配数字,这是一个问题。例如\b
对我不起作用,因为我仍然想在EP12345
中匹配12345
。
另外,我不知道如何将 A 列中的字符实现为第一个字符。
我已经在这里上传了我的 excel 文件:mollmell.de/RegEx.xlsm
非常感谢您的建议 斯蒂芬
【问题讨论】:
【参考方案1】:要对过长的数字进行排序,可以使用与前后数字不匹配的负后瞻和前瞻:
(?x) (?<!\d) (\d5 | K\d4) (?!\d)
https://regex101.com/r/RBnoMo/1
仅将数字与第 2 列中的键匹配是相当困难的。也许您匹配键或数字,然后执行逻辑:
(?x)
\|[ ](?<key>.)[ ]\| |
(?<!\d) (?<number>\d5 | K\d4) (?!\d)
https://regex101.com/r/60d0yT/2
【讨论】:
感谢您的帮助!虽然(?x)(?<!\d)(\d5|K\d4)(?!\d)
在 regex101 上工作得很好,但不知何故它并不是我的 VBA 代码的一部分。 .Pattern = "(?x)(?<!\d)(\d5|K\d4)(?!\d)"
只是传递一个错误。您碰巧有解决方案吗?
如果我只包含前瞻断言.Pattern = "(\d5|K\d4)(?!\d)"
,则不会有任何错误。当包含后向断言(?x)(?<!\d)(\d5|K\d4)(?!\d)
时会出现错误。
好吧,我刚刚发现 RegEx 的 VBA 适配不支持后视断言(只是前瞻断言)以上是关于使用 RegEx 匹配 Excel/VBA 中的五个字符,第一个字符取决于单元格值的主要内容,如果未能解决你的问题,请参考以下文章