2015-03-31 124 views
0

我需要從同一行中提取地址和潛在的郵政編碼作爲單獨的實體。地址行可能包含或不包含郵政編碼,可能包含或不包含其他不需要的字符串。這是由於Web表單中存在一個錯誤,該錯誤是固定的,但已經對一組元素造成了損害。VBA和RegEx與Excel 2010中的任意字符串匹配

可能形式和結果:

  • 地址:有的地址251,99302東西電話:555 6798 8473 - 迴歸 「的一些地址251」 和 「99302東西」 在單獨的字符串。逗號可能會或可能不會被空白尾隨。
  • 地址:部分地址251 - 返回「部分地址251」
  • 地址:部分地址251,99302 - 返回「部分地址251」和「99302」。再次,逗號可能會或可能不會被空白尾隨。

我這如何可以編程在VBA通過遍歷字符串並檢查單個字符和字符串做一個基本的瞭解,但我覺得這將是耗時的,不是很健壯之後。或者如果它強大的話,它會因爲所有可能的變化而變得巨大。

我正在爲如何形成正則表達式和可能的條件以獲得理想的結果而苦苦掙扎。

這是一個較大的項目的一部分,所以我不會粘貼所有的各種代碼,但我從Outlook拉郵件來分析和轉儲相關信息到Excel工作表。我的Outlook和Excel代碼都有效,但提取信息的邏輯有點不妥。

下面是新片段我一直在努力:

Function regexp(str As String, regP As String) 

Dim rExp As Object, rMatch As Object 

Set rExp = CreateObject("vbscript.regexp") 
With rExp 
    .Global = False 
    .MultiLine = False 
    .IgnoreCase = True 
    .Pattern = regP 
End With 

Set rMatch = rExp.Execute(str) 
If rMatch.Count > 0 Then 
    regexp = rMatch(0) 
Else 
    RegEx = vbNullString 
    Debug.Print "No match found!" 
End If 

End Function 


Sub regexpAddress(str As String) 
Dim result As String 
Dim pattern As String 

If InStr(str, "Telephone:") Then pattern = "/.+?(?=Telephone:)/" 
result = regexp(str, pattern) 

End Sub 

我不知道怎麼在這裏形成的正則表達式。一個概述應該拉動正確的信息(1個字符串,而不是2,但這仍然是一個改進) - 但只有當該行包含字符串「電話:」,並且我有很多情況下,它不會包含該信息。

這是當前的,有點缺陷的邏輯,其中由於某種原因不總是產生我想要的結果:

For Each objMail In olFolder.Items 

name = "" 
address = "" 
telephone = "" 
email = "" 

vIterations = vIterations + 1 

arrBody = Split(objMail.body, Chr(10)) ' Split mail body when linebreak is encountered, throwing each line into its own array position 
For i = 0 To UBound(arrBody) 
    arrLine = Split(arrBody(i), ": ") ' For each element (line), make new array, and if text search matches then write the 2nd half of the element to variable 
    If InStr(arrBody(i), "Name:") > 0 Then ' L2 
     name = arrLine(1) ' Reference 2nd column in array after the split 
    ElseIf InStr(arrBody(i), "Address:") > 0 Then 
     address = arrLine(1) 
    ElseIf InStr(arrBody(i), "Telephone:") > 0 Then 
     telephone = CLng(arrLine(1)) 
    ElseIf InStr(arrBody(i), "Email:") > 0 Then 
     email = arrLine(1) 
    End If ' L2 
Next 
Next ' Next/end-for 

該邏輯接受和下述類型的格式輸入:

Name: Joe 
Address: Road 
Telephone: 55555555555555 
Email: [email protected] 

並將joe,road,55555和[email protected]返回給某些定義的Excel單元格。當郵件按預期排序時,此工作正常。

問題:在某些情況下,一個錯誤導致我的webform不能在地址後面插入換行符。該腳本仍然工作的大部分,但的MailItem內容有時會結束這樣看:

Name: Joe 
Address: Road Telephone: 55555555555555 
Email: [email protected] 

地址字段被污染,當它達到Excel文件(「路電話」,而不僅僅是「道」),但沒有信息的損失。這是可以接受的,因爲它很容易去除剩餘的字符串。

但在以下情況下(不輸入電子郵件),電話號碼不僅丟失,而且實際上由其他任意mailitem的電話號碼取代,我無法找到我的生活1)爲什麼它不會得到正確的號碼,(2)爲什麼跳轉到一個新的郵件項目,找到電話號碼或(3)如何選擇這個其他的MailItem:

Name: Joe 
Address: Road Telephone: 5555555555555 
Email: 

在Excel:

Name: Joe 
Address: Road Telephone 
Telephone: 8877445511 
Email: 

因此,TL; DR:我的選擇邏輯是有缺陷的,因爲它被如此匆匆砍死r,更不用說它是如何產生虛假信息的,我無法弄清楚如何以及爲什麼,我想用一些其他解決方案(如regexp?)來做更好的操作,而不是更強大的代碼。

回答

0

我不知道這是愚蠢的運氣還是如果我真的設法學習一些正則表達式,但這些模式完全是我所需要的。

' regex patterns - use flag /i 
adrPattern = "([a-z ]{2,}\s{0,1}\d{0,3})" ' Select from a-z or space, case insensitive and at least 2 characters long, followed by optional space, ending with 0-3 digits 
adrZipcode = "\b(\d{4})\b" ' Exactly 4 digits surrounded on both sides by either space, text or non-word character like comma 

編輯:「固定」電話問題。花了2個小時試圖用正則表達式寫出來,並且悲慘地失敗之後,我發現解決問題的過程是錯誤創建數組的問題,比將它作爲計算問題來處理要容易得多。它是:

mailHolder = Replace(objMail.body, "Telephone:", Chr(10) + "Telephone:") 
arrBody = Split(mailHolder, Chr(10)) 
0

不久前,我有一個類似的問題。 代碼可能不是非常專業,但它可以幫助:) 你能檢查這段代碼是否能正確地爲你工作嗎?

Function regexp(str As String, regP As String) 

Dim rExp As Object, rMatch As Object 

Set rExp = CreateObject("vbscript.regexp") 
With rExp 
    .Global = False 
    .MultiLine = False 
    .IgnoreCase = True 
    .pattern = regP 
End With 

Set rMatch = rExp.Execute(str) 
If rMatch.Count > 0 Then 
    regexp = rMatch(0) 
Else 
    RegEx = vbNullString 
    Debug.Print "No match found!" 
End If 

End Function 

Function for_vsoraas() 

For Each objMail In olFolder.Items 

vIterations = vIterations + 1 

objMail_ = Replace(objMail.body, Chr(10), " ")  
Dim StringToSearch(3) As String 
StringToSearch(0) = "Name:" 
StringToSearch(1) = "Address:" 
StringToSearch(2) = "Telephone:" 
StringToSearch(3) = "Email:" 

Dim ArrResults(4) As String 'name,address,telephone,email, zipcode 

For i = 0 To UBound(StringToSearch) 
    ResultString = "" 
    StartString = InStr(objMail_, StringToSearch(i)) 
    If StartString > 0 Then 
     If i = UBound(StringToSearch) Then 'last string to search, dont search EndString 
     ResultString = Right(objMail_, Len(objMail_) + Len(StringToSearch(i))) 
     Else 
     EndString = 0 
     j = i 
     While (EndString = 0) 'prevent case no existing EndString 
     EndString = InStr(objMail_, StringToSearch(j + 1)) 
     j = j + 1 
      If j = UBound(StringToSearch) And EndString = 0 Then 
      EndString = Len(objMail_) + 1 
      End If 
     Wend 
     ResultString = Mid(objMail_, StartString + Len(StringToSearch(i)) + 1, EndString - 1 - StartString - Len(StringToSearch(i))) 

     End If 
    ArrResults(i) = ResultString 
    End If 
Next i 

'search zipcode and address 
ArrResults(4) = regexp(ArrResults(1), "\b(\d{5})\b") 
ArrResults(1) = regexp(ArrResults(1), "([a-z ]{2,}\s{0,1}\d{0,3})") 

'your varabile 
Name = ArrResults(0) 
Address = ArrResults(1) 
Telephone = ArrResults(2) 
Email = ArrResults(3) 
ZipCode = ArrResults(4) 

Next ' Next/end-for 
End Function