2014-02-12 47 views
3

我試圖複製谷歌日曆的方法從敘述創建約會。我想輸入5pm Happy Hour for 1 hour並將其解析爲最終的Outlook AppointmentItem。VBScript正則表達式填充甚至不匹配時需要匹配

我覺得我的問題是我最後有一大塊可選的文本。並且因爲它是可選的,所以正則表達式通過,但是不匹配子匹配,因爲它不是匹配所必需的。我希望它填充,因爲我想使用submatches作爲我的解析引擎。

我在列A中有一堆測試用例(在Excel中工作,然後移動到Outlook),我的代碼列出了右側的子匹配。這是潛在的輸入

1. 5pmCST Happy Hour for 1 hour 
2. 5pm CST Happy Hour for 1 hour 
3. 5pm Happy Hour for 1 hour 
4. 5 pm Happy Hour for 1 hour 
5. 5 pm CST Happy Hour for 1 hour 
6. 5 Happy Hour for 1 hour 
7. 5 Happy Hour 
8. 5pmCST Happy Hour 
9. 5pm CST Happy Hour 
10. 5pm Happy Hour 
11. 5:00CST Happy Hour for 1 hour 
12. 5:00 CST Happy Hour for 1 hour 

的代表性樣品下面是運行測試

Sub testest() 

    Dim RegEx As VBScript_RegExp_55.RegExp 
    Dim Matches As VBScript_RegExp_55.MatchCollection 
    Dim Match As VBScript_RegExp_55.Match 
    Dim rCell As Range 
    Dim SubMatch As Variant 
    Dim lCnt As Long 
    Dim aPattern(1 To 8) As String 

    Set RegEx = New VBScript_RegExp_55.RegExp 
    aPattern(1) = "(1?[0-9](:[0-5][0-9])?)" 'time 
    aPattern(2) = "(?)" 'optional space 
    aPattern(3) = "([ap]m)?" 'optional ampm 
    aPattern(4) = "(?)" 'optional space 
    aPattern(5) = "([ECMP][DS]T)?" 'optional time zone 
    aPattern(6) = "(?)" 'optional space 
    aPattern(7) = "(.+?)" 'event description 
    aPattern(8) = "((for)([1-2]?[0-9](.[0-9]?[0-9])?)(hours?))?" 'optional duration 

    RegEx.Pattern = Join(aPattern, vbNullString) 
    Debug.Print RegEx.Pattern 

    Sheet1.Range("C1").Resize(1000, 100).ClearContents 

    For Each rCell In Sheet1.Range("A1").CurrentRegion.Columns(1).Cells 
     lCnt = 0 
     rCell.Offset(0, 2).Value = RegEx.test(rCell.Text) 
     If RegEx.test(rCell.Text) Then 
      Set Matches = RegEx.Execute(rCell.Text) 

      For Each Match In Matches 
       For Each SubMatch In Match.SubMatches 
        lCnt = lCnt + 1 
        rCell.Offset(0, 2 + lCnt).Value = SubMatch 
       Next SubMatch 
      Next Match 
     End If 
    Next rCell 

End Sub 

圖案代碼

(1?[0-9](:[0-5][0-9])?)(?)([ap]m)?(?)([ECMP][DS]T)?(?)(.+?)((for)([1-2]?[0-9](.[0-9]?[0-9])?)(hours?))? 

爲#1的子匹配是

1  2   3  4  5  6  7 
5     pm    CST    H 

它停止馬因爲所有以「for」開頭的內容都是可選的,所以在「歡樂時光」的「H」處進行調整。如果我刪除可選部分,我的模式變成

(1?[0-9](:[0-5][0-9])?)(?)([ap]m)?(?)([ECMP][DS]T)?(?)(.+?)(for)([1-2]?[0-9](.[0-9]?[0-9])?)(hours?) 

但是#7-#10不通過,因爲它們沒有持續時間。 #1的submmatches給我什麼,我想雖然

1  2  3  4  5  6  7    8  9  10  11 
5   pm   CST   Happy Hour  for 1   hour 

我想每一個可能的子匹配,以填補即使VBScript不需要它來使正則表達式通。我擔心這只是它的工作原理,而我正試圖讓正則表達式來爲我做解析工作。我考慮通過越來越多的限制性模式來運行它,直到它沒有通過,然後使用最後通過的模式,但這似乎很糟糕。

是否有可能得到正則表達式來填補這些子匹配?

+0

雖然您可以用regexp解決這個問題,但我認爲正則表達式不是複製Google日曆行爲的解決方案。如果你想這樣做,你必須將字符串拆分成一個原子列表,獲得每個原子的「組」類型並獲得這些原子組合的上下文。使用正則表達式的方法,您將很難用其他格式,例如從17到1800_的_Happy Hour。 – AutomatedChaos

+0

這是我的第一個方法,它看起來像很多代碼。我用正則表達式不是很強大,並認爲它可能會簡化代碼。感謝您的反饋。 –

回答

2

我假設每一行都是單個單元格中的所有內容。所以我能夠使用錨點。 我也不認爲你需要儘可能多的捕捉組。在A2

Group 1  Time 
Group 2  am/pm 
Group 3  Time Zone 
Group 4  Description 
Group 5  Hours (and fractions of hours) 

與您的數據:我成立了以正則表達式的,下面的程序解析數據到相鄰列。 Submatch是否「未填充」並不重要。你也可以填充數組中的元素,或者任何你想做的事情。如果您想要更多的子匹配,您可以隨時爲可選空格添加捕獲組,或者將相關的非捕獲組更改爲捕獲組。

另外,由於「for」是可選的,我選擇使用前視來確定「description」的結束。描述將以\ s + for \ s +序列結束;或與「行尾」。因爲我假設每個單元格只有一個條目和一行,所以多行和全局屬性是不相關的。

必須在「for」之前和之後包含空格,以避免在描述中包含該序列時出現問題。

Option Explicit 
'set Reference to Microsoft VBScript Regular Expressions 5.5 
Sub ParseAppt() 
    Dim R As Range, C As Range 
    Dim RE As RegExp, MC As MatchCollection 
    Dim I As Long 
Set R = Range("a2", Cells(Rows.Count, "A").End(xlUp)) 
Set RE = New RegExp 
With RE 
    .Pattern = "((?:1[0-2]|0?[1-9])(?::[0-5]\d)?)\s*([ap]m)?\s*([ECMT][DS]T)?\s*(.*?(?=\s+for\s+|$))(?:\s+for\s+(\d+(?:\.\d+)?)\s*hour)?" 
    .IgnoreCase = True 
    For Each C In R 
     If .Test(C.Text) = True Then 
      Set MC = .Execute(C.Text) 
      For I = 0 To 4 
       C.Offset(0, I + 1) = MC(0).SubMatches(I) 
      Next I 
     End If 
    Next C 
End With 
End Sub 
+0

謝謝羅恩。這並不是抓住「12點午餐1小時」的全部時間 - 而是隻抓住時間1。我會研究模式的含義,並可能在過程中學到一些東西。我正在創建所有這些捕獲以確保我可以預測子集中的可預測信息,但是你已經這樣做了,所以希望一旦我瞭解了模式,我就能得到它。 –

+0

@DickKusleika你是對的。解決方法是顛倒交替順序,以便正則表達式首先查找10-12小時,然後使用可選的前導零查找較早的小時。我會在我的答案中改變它。 –

+0

美麗。我現在正在通過正則表達式並學習很多東西。由於某種原因'a | pm'匹配a或pm而不是a或p然後m。我在你的回答中編輯過,所以請檢查我的編輯。 –