2015-10-15 54 views
4

我在Excel VBA中使用Microsoft正则表达式引擎。我对正则表达式很陌生,但我现在有一个模式工作。我需要扩展它,并且遇到麻烦。这是我到目前为止的代码:Excel中的正则表达式VBA

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没有的括号和+

我一直在使用这个作为参考,这真棒,但我仍然有点困惑。 How to use Regular Expressions (Regex) in Microsoft Excel both in-cell and loops

编辑

我遇到了必须匹配上了一些新的情况。

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*) > 

回答

1

您可以使用此Regex模式;

.Pattern = "\<\!ELEMENT\s+(\w+)\s+\((#\w+|(\w+)\+)\)\s+\>" 
  1. 该部分

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

说匹配

#A-Z0-9
一个-Z0-9 +

括号内。

即匹配任一

(#PCDATA)
(DealParty +)

验证整个字符串

  • 然后,子匹配是用于提取DealNumber进行第一次有效匹配,DealParty for theoth呃有效匹配
  • 下面编辑的代码 - 记子匹配现在是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 
    
    +0

    谢谢你的帖子,这是我的问题的确切答案。从那以后,我遇到了一些我需要的比赛。其中之一是多线,我无法获得匹配的模式。我一整天都在regex101网站上工作。我编辑了我的原始文章以包含它们。我想我可能无法在一种模式中完成所有的事情。 –

    +0

    我只是想问一个新的问题的额外比赛。谢谢你的帮助! –

    +0

    嗨布雷特。你可以看看我的新帖子吗?它被埋得很快,因为我觉得非常荒谬的原因而被降级。 [第二次尝试](http://stackoverflow.com/questions/33215467) –

    3

    看着你的模式,你有太多的捕获组。您只想捕获PCDATADealParty。尝试改变你的模式:

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

    这里是存根(stub):Regex101

    +0

    它没有工作。当我运行它时,它会停止在'sExtract = M.SubMatches(1)'上,如果我将光标放在它上面,我会得到'<无效的过程调用或参数>和'.pattern <对象变量或块变量没有设置“我改变的唯一的事情就是模式。 –

    +0

    我刚刚意识到你以为我想提取'PCDATA'而不是这种情况。我已经更新了我的问题。 –

    +0

    您编辑的问题仍然让我感到困惑。你有像'<!ELEMENT x(y)>'这样的行。你想得到什么? 'x','y'还是两者兼而有之? –