在Excel VBA中的正则表达式

5

我正在使用Excel VBA中的Microsoft正则表达式引擎。虽然我目前有一个可以工作的模式,但我对正则表达式很陌生,我需要扩展它,但我遇到了困难。以下是我的代码:

Sub ImportFromDTD()

Dim sDTDFile As Variant
Dim ffile As Long
Dim sLines() As String
Dim i As Long
Dim Reg1 As RegExp
Dim M1 As MatchCollection
Dim M As Match
Dim myRange As Range

Set Reg1 = New RegExp

ffile = FreeFile

sDTDFile = Application.GetOpenFilename("DTD Files,*.XML", , _
"Browse for file to be imported")

If sDTDFile = False Then Exit Sub '(user cancelled import file browser)


Open sDTDFile For Input Access Read As #ffile
  Lines = Split(Input$(LOF(ffile), #ffile), vbNewLine)
Close #ffile

Cells(1, 2) = "From DTD"
J = 2

For i = 0 To UBound(Lines)

  'Debug.Print "Line"; i; "="; Lines(i)

  With Reg1
      '.Pattern = "(\<\!ELEMENT\s)(\w*)(\s*\(\#\w*\)\s*\>)"
      .Pattern = "(\<\!ELEMENT\s)(\w*)(\s*\(\#\w*\)\s*\>)"

      .Global = True
      .MultiLine = True
      .IgnoreCase = False
  End With

  If Reg1.Test(Lines(i)) Then
    Set M1 = Reg1.Execute(Lines(i))
    For Each M In M1
      sExtract = M.SubMatches(1)
      sExtract = Replace(sExtract, Chr(13), "")
      Cells(J, 2) = sExtract
      J = J + 1
      'Debug.Print sExtract
    Next M
  End If
Next i

Set Reg1 = Nothing

End Sub

目前,我正在对这样一组数据进行匹配:

 <!ELEMENT DealNumber  (#PCDATA) >

我需要提取Dealnumber,但现在,我需要在数据中添加另一个匹配项,就像这样:

<!ELEMENT DealParties  (DealParty+) >

提取Dealparty,但不包括圆括号和加号。

我一直在使用这个作为参考,它非常棒,但我还是有点困惑。如何在Microsoft Excel中使用正则表达式(Regex)在单元格和循环中

编辑

我遇到了几种新的情况需要匹配。

 Extract Deal
 <!ELEMENT Deal  (DealNumber,DealType,DealParties) >

 Extract DealParty the ?,CR are throwing me off
 <!ELEMENT DealParty  (PartyType,CustomerID,CustomerName,CentralCustomerID?,
           LiabilityPercent,AgentInd,FacilityNo?,PartyReferenceNo?,
           PartyAddlReferenceNo?,PartyEffectiveDate?,FeeRate?,ChargeType?) >

 Extract Deals
 <!ELEMENT Deals  (Deal*) >
2个回答

3

从您的模式来看,您有太多的捕获组。您只想捕获PCDATADealParty。尝试将您的模式更改为以下内容:

  With Reg1
      .Pattern = "\<!ELEMENT\s+\w+\s+\(\W*(\w+)\W*\)"

      .Global = True
      .MultiLine = True
      .IgnoreCase = False
  End With

这是代码桩:Regex101

它没起作用。当我运行它时,它停在sExtract = M.SubMatches(1)处,如果我将光标悬停在上面,我会得到<无效的过程调用或参数>.pattern是<object variable or with block variable not set>,我改变的唯一一件事就是模式。 - Matt Williamson
我刚意识到你误以为我想提取PCDATA,但事实并非如此。我已经更新了我的问题。 - Matt Williamson
您编辑后的问题仍然让我感到困惑。您有这样的行:<!ELEMENT x (y)>。您想得到什么?xy还是两者都要? - Code Different
如果没有加号,我想得到x;如果有加号,我想得到y,但不包括加号。 - Matt Williamson

1
您可以使用此正则表达式模式:Regex
  .Pattern = "\<\!ELEMENT\s+(\w+)\s+\((#\w+|(\w+)\+)\)\s+\>"
  1. 这一部分

(#\w+|(\w+)\+)

表示匹配括号内的内容,包括:

#a-z0-9
a-z0-9+

即匹配以下任意内容:

(#PCDATA)
(DealParty+)

用于验证整个字符串

  1. 然后使用子匹配来提取第一个有效匹配的DealNumber和其他有效匹配的DealParty

编辑后代码如下 - 请注意,子匹配现在是M.submatches(0)

    Sub ImportFromDTD()

Dim sDTDFile As Variant
Dim ffile As Long
Dim sLines() As String
Dim i As Long
Dim Reg1 As RegExp
Dim M1 As MatchCollection
Dim M As Match
Dim myRange As Range

Set Reg1 = New RegExp
J = 1

strIn = "<!ELEMENT Deal12Number  (#PCDATA) > <!ELEMENT DealParties  (DealParty+) >"

With Reg1
      .Pattern = "\<\!ELEMENT\s+(\w+)\s+\((#\w+|(\w+)\+)\)\s+\>"
      .Global = True
      .MultiLine = True
      .IgnoreCase = False
End With

If Reg1.Test(strIn) Then
    Set M1 = Reg1.Execute(strIn)
    For Each M In M1
      sExtract = M.SubMatches(2)
      If Len(sExtract) = 0 Then sExtract = M.SubMatches(0)
      sExtract = Replace(sExtract, Chr(13), "")
      Cells(J, 2) = sExtract
      J = J + 1
    Next M
End If

Set Reg1 = Nothing

End Sub

感谢您的帖子,它正是我问题的确切答案。自那以后,我遇到了更多需要匹配的情况。其中之一是多行匹配,我在尝试让模式匹配时遇到了麻烦。我已经在regex101网站上工作了一整天。我已经编辑了我的原始帖子以包括它们。我想我可能无法在一个模式中完成所有操作。 - Matt Williamson
我将为额外的匹配提出一个新问题。谢谢你的帮助! - Matt Williamson
嗨,布雷特。你能帮我看一下我的新帖子吗?它很快就被淹没了,并且因为我觉得非常荒谬的原因而被降级了。第二次尝试 - Matt Williamson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接