简体   繁体   English

Excel VBA:协助在Excel中编辑Outlook电子邮件解析器

[英]Excel VBA: assistance editing an outlook email parser in excel

I've been trying to create an email parser that has excel go through my outlook emails in a specific, designated folder. 我一直在尝试创建一个具有excel的电子邮件解析器,该解析器在特定的指定文件夹中浏览我的Outlook电子邮件。 The code below works great, i modified it from another forum, except for one issue: in the emails i'm trying to parse, the bottom section can contain multiple items. 下面的代码很好用,我从另一个论坛修改了它,除了一个问题:在我要解析的电子邮件中,底部可能包含多个项目。 I basically need this to repeat these steps for every instance of the word "item," but with the next item and its associated sku, qty, and cost. 我基本上需要这样做,以便对单词“ item”的每个实例重复这些步骤,但要包含下一个项目及其相关的sku,qty和cost。

So, when it's done with an email and moves on to the next, it should look like this in excel: 因此,当处理完电子邮件并转到下一封电子邮件时,它在excel中应如下所示:

fax, date, cust1, cust address1, item1, sku1, qty1, cost1 传真,日期,客户1,客户地址1,项目1,SKU1,数量1,成本1

fax, date, cust1, cust address1, item2, sku2, qty2, cost2 传真,日期,客户1,客户地址1,项目2,sku2,数量2,成本2

fax, date, cust2, cust address2, item1, sku1, qty1, cost1 传真,日期,客户2,客户地址2,项目1,sku1,数量1,成本1

Is there any way to do this? 有什么办法吗?

Below is my current code, but it just shows the first instance of the product, sku, qty, and cost, and then moves on to the next email. 下面是我当前的代码,但仅显示了产品的第一个实例,sku,数量和成本,然后继续处理下一封电子邮件。

        Dim msgText As String
        Dim msgLine() As String
        Dim messageArray() As String

        i = 0

        For Each myOlMailItem In myOlFolder.Items


            i = i + 1                                    ' first parsed message ends up on worksheet one row below headings

            msgText = myOlMailItem.Body

            messageArray = Split(msgText, vbCrLf)        ' split into lines

            For j = 0 To UBound(messageArray)


                msgLine = Split(messageArray(j) & ":", ":")  ' split up line ( add ':' so that blank lines do not error out)

                Select Case Left(msgLine(0), 3)
                    Case "FAX"
                        anchor.Offset(i, 0).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 4)
                    Case "DATE"
                        anchor.Offset(i, 1).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 6)
                    Case "CUSTOM"
                        anchor.Offset(i, 2).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 6)
                    Case "CUSTOM"
                        anchor.Offset(i, 3).Value = messageArray(j + 1) + messageArray(j + 2) + messageArray(j + 3)
                    End Select

                Select Case Left(msgLine(0), 4)
                    Case "ITEM"
                        anchor.Offset(i, 4).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 3)
                    Case "SKU"
                        anchor.Offset(i, 5).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 8)
                    Case "QTY"
                        anchor.Offset(i, 6).Value = msgLine(1)
                    End Select

                Select Case Left(msgLine(0), 4)
                    Case "COST"
                        anchor.Offset(i, 7).Value = msgLine(1)
                    End Select

            Next

                anchor.Offset(i, -1).Value = myOlMailItem.SenderName
                                        ' add row number on left of "Priority" column (make sure that "anchor" is not in first worksheet column)

            Next
    End Sub

The emails look like the below. 电子邮件如下所示。 They can have variable amounts of items ordered. 他们可以订购数量不定的物品。 The below template shows how 3 different items would appear. 以下模板显示了3种不同的项目。

DATE                 : 12/01/2018
------------------------------------------------------------                    
CUSTOMER             : CUSTOMER NAME
                     : ADDRESS
                     : ADDRESS
                     : ADDRESS
PHONE                : PHONE
FAX                  : FAX
------------------------------------------------------------                    
DELIVER TO           : DELIVER TO CUSTOMER
                     : ADDRESS
                     : ADDRESS
                     : ADDRESS
------------------------------------------------------------                                                                                                                                                                  
ITEM NAME            : ITEM NAME
SKU                  : SKU
QTY                  : QTY #
COST                 : COST $
------------------------------------------------------------                    
ITEM NAME            : ITEM NAME
SKU                  : SKU
QTY                  : QTY #
COST                 : COST $
------------------------------------------------------------                   
ITEM NAME            : ITEM NAME
SKU                  : SKU
QTY                  : QTY #
COST                 : COST $
------------------------------------------------------------                    

This should get you close: 这应该使您接近:

Dim keyValuePairs() As String       ' Fields extracted from the e-mail
Dim messageLines() As String        ' Individual Lines in the e-mail
Dim itemList() As String            ' List of Item information in a single e-mail
                                    ' (0, n) = Item Name of Item n
                                    ' (1, n) = SKU of Item n
                                    ' (2, n) = Quantity of Item n
                                    ' (3, n) = Cost of Item n

Dim currentItem As Integer          ' Index for looping through customer item list
Dim customerName As String          ' Customer Name
Dim customerAddress As String       ' Customer Address
Dim customerPhone As String         ' Customer Phone Number - Currently Ignored
Dim customerFax As String           ' Customer Fax Number
Dim deliveryName As String          ' Delivery Customer Name - Currently Ignored
Dim deliveryAddress As String       ' Delivery Address - Currently Ignored
Dim messageLine As Integer          ' Index for walking through message lines
Dim orderDate As String             ' Date of Order
Dim parseState As String            ' Manages which address is being parsed
Dim targetExcelRow As Integer       ' Excel row on which to place data
Dim itemCount As Integer            ' Number of items in a single e-mail
Dim itemValue As String              ' Trimmed value

targetExcelRow = 1          ' Start placing items on the first row below headings

' Loop through e-mails
For Each myOlMailItem In myOlFolder.Items

    ' Set up for a New Message
    messageLines = Split(myOlMailItem.Body, vbCrLf)  ' Split the message body into lines
    itemCount = -1                                   ' Reset the item count
    ReDim itemList(3, 0)                             ' Reset the item list
    customerName = ""                                ' Reset all static values
    customerAddress = ""
    customerFax = ""
    customerPhone = ""
    orderDate = ""
    deliveryName = ""
    deliveryAddress = ""

    ' Loop through the lines in the e-mail
    For messageLine = 0 To UBound(messageLines)

        ' Array is expected to have only two values per line.
        ' Position 0 is the Key. Position 1 is the Value.
        keyValuePairs = Split(messageLines(messageLine), ":")

        If UBound(keyValuePairs) > 0 Then   ' This ignores blank lines and dividers
            itemValue = Trim$(keyValuePairs(1))
            Select Case Trim$(keyValuePairs(0))
                Case "DATE"
                    orderDate = itemValue
                    parseState = ""
                Case "CUSTOMER"
                    customerName = itemValue
                    parseState = "CUSTADDR"
                Case "FAX"
                    customerFax = itemValue
                Case "DELIVER TO"
                    deliveryName = itemValue
                    parseState = "DELIVADDR"
                Case "ITEM NAME"
                    itemCount = itemCount + 1
                    ReDim Preserve itemList(3, itemCount)
                    itemList(0, itemCount) = itemValue
                Case "SKU"
                    itemList(1, itemCount) = itemValue
                Case "QTY"
                    itemList(2, itemCount) = itemValue
                Case "COST"
                    itemList(3, itemCount) = itemValue
                Case "PHONE"
                    customerPhone = itemValue
                Case ""    ' Handle blank field names
                    Select Case parseState
                        Case "CUSTADDR"
                            customerAddress = customerAddress + itemValue
                        Case "DELIVADDR"
                            deliveryAddress = deliveryAddress + itemValue
                        Case Else   ' Error: Unhandled State
                            'Debug.Print "Unhandled blank field encountered at message line " & Trim$(CStr(j + 1)) & "."
                            Err.Raise Number:=vbObjectError, _
                                      source:="E-Mail Parse Function", _
                                      Description:="Unhandled blank field encountered at message line " & Trim$(CStr(j + 1)) & "."
                    End Select

                Case Else
                    'Debug.Print "Unhandled keyword encountered at message line " & Trim$(CStr(j + 1)) & "."
                    Err.Raise Number:=vbObjectError, _
                              source:="E-Mail Parse Function", _
                              Description:="Unhandled keyword encountered at message line " & Trim$(CStr(j + 1)) & "."
            End Select

        End If

    Next messageLine

    ' Now write the data to the Excel Sheet

    For currentItem = 0 To itemCount
        With anchor
            .Offset(targetExcelRow, -1).Value = myOlMailItem.SenderName ' SenderName of Priority Column
            .Offset(targetExcelRow, 0).Value = customerFax              ' Fax Number
            .Offset(targetExcelRow, 1).Value = orderDate                ' Order Date
            .Offset(targetExcelRow, 2).Value = customerName             ' Customer Name
            .Offset(targetExcelRow, 3).Value = customerAddress          ' Customer Address
            .Offset(targetExcelRow, 4).Value = itemList(0, currentItem) ' Item Name
            .Offset(targetExcelRow, 5).Value = itemList(1, currentItem) ' SKU
            .Offset(targetExcelRow, 6).Value = itemList(2, currentItem) ' Quantity
            .Offset(targetExcelRow, 7).Value = itemList(3, currentItem) ' Cost
        End With
        targetExcelRow = targetExcelRow + 1
    Next currentItem

Next myOlMailItem

If you prefer the system prints unhandled stuff to the immediate window, uncomment the Debug.Print lines and comment the Err.Raise lines. 如果您希望系统将未处理的内容打印到立即窗口,请取消注释Debug.Print行并注释Err.Raise行。 I have tested this code for one loop using only the sample data you provided. 我仅使用您提供的示例数据对该代码进行了一个循环的测试。 It should work fine for any number of e-mails. 它适用于任何数量的电子邮件。

Notes: 笔记:

  • Your original code invoked a separate Select Case statement for each case. 您的原始代码为每种情况调用了一个单独的Select Case语句。 that was completely unnecessary. 那是完全没有必要的。 I have consolidated them. 我已经巩固了他们。
  • This would be cleaner if implemented using a class for item information and a class for customer information. 如果使用用于项目信息的类和用于客户信息的类来实现,这将更加干净。 I leave that to you as an exercise. 我把它留给你作为练习。
  • I did not do full testing on this, only partial. 我没有对此进行全面测试,只是部分测试。 You may need to do some edge condition testing or special case testing. 您可能需要进行一些边缘条件测试或特殊情况测试。
  • The main idea to take from this is that you can collect all your information first, then write it to the spreadsheet. 从中获得的主要思想是,您可以先收集所有信息,然后将其写入电子表格。
  • In my trials, I passed anchor as a parameter. 在试验中,我通过了anchor作为参数。 The code assumes that anchor has been defined and set. 该代码假定已定义并设置了锚点。
  • This code retrieves the delivery information and the customer phone number even though they are not used. 即使不使用此代码,也可以检索交货信息和客户电话号码。 I figured, Why not? 我想, 为什么不呢?
  • The parseState is used for managing cases when there are no field names on the line to identify the data. 当行中没有用于标识数据的字段名称时, parseState用于管理案例。 The Case "" statement handles any of those cases. Case ""语句处理任何这些情况。 The parseState variable tells that case what to do with the blank line. parseState变量告诉该情况空白行如何处理。 So, when you encounter the CUSTOMER field, it sets the parseState to "CUSTADDR" to let the blank field case know that it is parsing the customer address. 因此,当您遇到CUSTOMER字段时,它将parseState设置为“ CUSTADDR”,以使空白字段的情况知道它正在解析客户地址。

Good Luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM