首页 > 解决方案 > For循环在多列中输出

问题描述

我正在尝试将 Outlook 电子邮件解析为 Excel 电子表格。

所有“vText”都在 B 列而不是 B 到 E 列中输出。

原始电子邮件文本:

Caller: First Last
Phone: 123-456-7890
For: Company Name - Address
City: Metropolis
MSGID: 3068749608

我很好地提取了 Caller、Phone 和 MSGID 字段,但解析公司名称并没有奏效。它会将电话或 MSGID 值随机粘贴到该列中。

Option Explicit
 Private Const xlUp As Long = -4162

Sub CopyAllMessagesToExcel()
 Dim objOL As Outlook.Application
 Dim objItems As Outlook.Items
 Dim objFolder As Outlook.MAPIFolder
 Dim olItem As Outlook.MailItem
 Dim xlApp As Object
 Dim xlWB As Object
 Dim xlSheet As Object
 Dim vText, vText2, vText3, vText4, vText5 As Variant
 Dim sText As String
 Dim rCount As Long
 Dim bXStarted As Boolean
 Dim enviro As String
 Dim strPath As String
 Dim Reg1 As Object
 Dim M1 As Object
 Dim M As Object
 Dim OutlookNamespace As NameSpace
              

enviro = CStr(Environ("USERPROFILE"))
'the path of the workbook
 strPath = enviro & "file path"
     On Error Resume Next
     Set xlApp = GetObject(, "Excel.Application")
     If Err <> 0 Then
         Application.StatusBar = "Please wait while Excel source is opened ... "
         Set xlApp = CreateObject("Excel.Application")
         bXStarted = True
     End If
     On Error GoTo 0
     'Open the workbook to input the data
     Set xlWB = xlApp.Workbooks.Open(strPath)
     Set xlSheet = xlWB.Sheets("Sheet1")

    'Find the next empty line of the worksheet
    'rCount = xlSheet.Range("B" & xlSheet.Rows.Count).End(xlUp).Row 'original code
    rCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(xlUp).Row
     rCount = rCount + 1
     
    Set objOL = Outlook.Application
    Set OutlookNamespace = objOL.GetNamespace("MAPI")
    Set objFolder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("SubFolder").Folders("SubSubFolder")
    Set objItems = objFolder.Items
 
    For Each olItem In objItems
 
      On Error Resume Next

     With olItem
     
     sText = olItem.Body

     Set Reg1 = CreateObject("VBScript.RegExp")
    ' \s* = invisible spaces
    ' \d* = match digits
    ' \w* = match alphanumeric
     
    
    Dim i As Integer
        
    For i = 1 To 4
    
    With Reg1
    '.IgnoreCase = True
    Select Case i   'each Case = one specific string parsed
    Case 1
    'pull everything after Caller (separated by :), and stop at line end \n
        .Pattern = "(Caller[:]([\w-\s]*)\s*)\n"
        
    Case 2
       .Pattern = "(Phone[:]([\d-\s]*)\s*)\n"
       
'#### CASE 3 NOT WORKING
    Case 3
    'pull everything after For (separated by :), and stop at the dash [-]
    .Pattern = "(For[:]([\w-\s]*)\s*)[-]"
     
    Case 4
    'pull everything after MSGID, and stop at the dash [-]
        .Pattern = "(MSGID[:]([\w-\s]*)\s*)[-]"
    End Select
    End With
    
    If Reg1.Test(sText) Then
    
' each "(\w*)" and the "(\s)" are assigned a vText variable
        Set M1 = Reg1.Execute(sText)
        For Each M In M1
           vText = Trim(M.SubMatches(1))
           vText2 = Trim(M.SubMatches(2))
           vText3 = Trim(M.SubMatches(3))
           vText4 = Trim(M.SubMatches(4))
        Next
  
  xlSheet.Range("a" & rCount) = .ReceivedTime
  xlSheet.Range("b" & rCount) = vText
  xlSheet.Range("c" & rCount) = vText2
  xlSheet.Range("d" & rCount) = vText3
  xlSheet.Range("e" & rCount) = vText4
  'xlSheet.Range("D" & rCount) = .Subject
  'xlSheet.Range("f" & rCount) = vText5

'##Checking on output per iteration:
'MsgBox ("inputting data in row #" & rCount)

' next line
 rCount = rCount + 1

    End If
    
Next i
    
      ' do whatever
       Debug.Print .Subject
     
    End With
    
    Next
     'xlWB.Close 1
     'If bXStarted Then
     '    xlApp.Quit
     'End If
     Set M = Nothing
     Set M1 = Nothing
     Set Reg1 = Nothing
     Set xlApp = Nothing
     Set xlWB = Nothing
     Set xlSheet = Nothing
     
    Set objItems = Nothing
    Set objFolder = Nothing
    Set objOL = Nothing

End Sub

标签: excelvbaoutlook

解决方案


我会将正则表达式移动到一个单独的函数中:

Function ExtractText(txt As String, patt As String)
    Static reg As Object
    Dim matches, rv As String  'EDIT: moved from Static line
    If reg Is Nothing Then
        Set reg = CreateObject("VBScript.RegExp")
        'set up IgnoreCase etc here...
    End If
    reg.Pattern = patt
    If reg.Test(txt) Then
        Set matches = reg.Execute(txt)
        rv = matches(0).submatches(1)
    End If
    ExtractText = rv
End Function

然后你的主要代码的核心变成这样:

Set objOL = Outlook.Application
Set OutlookNamespace = objOL.GetNamespace("MAPI")
Set objFolder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("SubFolder").Folders("SubSubFolder")
Set objItems = objFolder.Items
 
For Each olItem In objItems
    sText = olItem.Body
    xlSheet.Range("a" & rCount) = .ReceivedTime
    xlSheet.Range("b" & rCount) = ExtractText(sText, "(Caller[:]([\w-\s]*)\s*)\n")
    xlSheet.Range("c" & rCount) = ExtractText(sText, "(Phone[:]([\d-\s]*)\s*)\n")
    xlSheet.Range("d" & rCount) = ExtractText(sText, "(For[:]([\w-\s]*)\s*)[-]")
    xlSheet.Range("e" & rCount) = ExtractText(sText, "(MSGID:\s?(\d{1,})-)")'<<edit
    'xlSheet.Range("D" & rCount) = .Subject
    'xlSheet.Range("f" & rCount) = vText5
    'MsgBox ("inputting data in row #" & rCount)
    rCount = rCount + 1
Next olItem


推荐阅读