将发件人的邮件移动到发件人文件夹名称

5
我想将发件人的邮件移动到我为其创建的文件夹中。
发件人名称显示为“Doe,John(美国)”,我的文件夹将是“Doe,John”。
我需要怎样才能将SenderName与在"Inbox"下两个级别的子文件夹名称进行比较?即Inbox→Folder1→"Doe, John"。
Public Sub MoveToFolder()
Dim objOutlook As Outlook.Application
Dim objNameSpace As Outlook.NameSpace
Dim objDestFolder As Outlook.MAPIFolder
Dim objSourceFolder As Outlook.Folder
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim obj As Object

Dim objSubfolder As Outlook.Folder
Dim olsubFolder As Outlook.Folder

Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim Msg As Outlook.MailItem

Dim objVariant As Variant
Dim lngMovedItems As Long
Dim intCount As Integer

Set objOutlook = Application
Set objNameSpace = objOutlook.GetNamespace("MAPI")
Set currentExplorer = objOutlook.ActiveExplorer
Set Selection = currentExplorer.Selection
Set objSourceFolder = currentExplorer.CurrentFolder
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")

Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Set olFolder = olFolder.Folders("Inbox")
Set colFolders = objParentFolder.Folders

For Each obj In Selection
    Set objVariant = obj

    Dim sfName As Object
    Set sfName = Left(objVariant.senderName, Len(objVariant.senderName) - 5)

    If objVariant.Class = olMail Then

        On Error Resume Next
        ' Use These lines if the destination folder
        '  is not a subfolder of the current folder
        For Each objSubfolder In colFolders
            For Each olsubFolder In objSubfolder
                If olsubFolder.Name = sfName Then
                    Set objDestFolder = objSubfolder
                    MsgBox "Ductus Exemplo"
                    'objVariant.Move objDestFolder
                    'count the # of items moved
                    lngMovedItems = lngMovedItems + 1
                     'Display the number of items that were moved.
                    MsgBox "Moved " & lngMovedItems & " messages(s) from  " & _
                    sfName & "to " & objDestFolder
                Else
                    If objDestFolder Is Nothing Then
                        MsgBox "No Folder Found for " & sfName
                        'Set objDestFolder = objSourceFolder.Folders.Add(sfName)
                        Exit Sub
                    End If

            Next
        Next
    Next
End If
End Sub

对于赏金猎人们,现在我已在此发表评论,如果你想引起我的注意,可以使用 @Tyop。 - user5942421
这个问题不太清楚(至少对我来说是这样的 :))。在我看来,你想要类似于规则的东西。规则与问题的目标有何不同? - Daniel Dušek
1
@dee 我的理解是“Doe, John (US)”是格式的一个例子。有许多发件人的发件人名称后面都添加了“(US)”,数量未知。这就是为什么OP将Set sfName = Left(objVariant.senderName, Len(objVariant.senderName) - 5)包含在内,以删除后缀,而不是通过规则将邮件移动到“Doe, John”文件夹中。即使OP创建了包括“(US)”的文件夹,仍然会有多个发件人需要分类到相应的子文件夹中。 - user5942421
1
OP的代码表明邮件将被选中。邮件不应该在到达时立即处理。 - user5942421
我将我的Outlook收件箱按子文件夹(组)进行了组织;在这些子文件夹中,每个人都有一个单独的文件夹。文件夹名称的结构与他们的Outlook名称相同。即,姓,名,中间首字母,国家代码(我的文件夹中不使用中间首字母和国家代码)。 建议的代码创建了一个具有正确子文件夹格式(姓,名)的文件夹(Folder1),并将邮件项目移动到该文件夹,但我需要将其移动到具有该发件人名称的现有文件夹中。 - Adavid02
因此,在收件箱下的第一级是“组名称”,然后第二级是“发件人姓名”,邮件将被移动到该级别。假设所有发件人姓名都是唯一的,这样做是否正确?也就是说,假设您的圈子中没有人具有相同的名字和姓氏? - PatricK
3个回答

2
目标似乎是在调用时根据发件人姓名组织选定的邮件项目。
当没有选择移动任何项目时(即仅选择会议项目),可以将项目移动到所选文件夹内。
在选择要处理项目的文件夹时,该文件夹不能是主子文件夹或其子文件夹。
Option Explicit

Private Const SUB_FDR As String = "Folder1" ' The name of main sub-folder under Inbox to move mails to

Sub MoveSenderToFolder()
    Dim oNS As NameSpace, oMainFDR As Folder, oSubFDR As Folder
    Dim oItem As Variant, iMoved As Long
    On Error Resume Next
    Set oNS = Application.GetNamespace("MAPI")
    On Error GoTo 0
    If oNS Is Nothing Then
        MsgBox "Cannot get MAPI namespace from Outlook! Abortting!", vbCritical + vbOKOnly, "MoveSenderToFolder()"
    Else
        ' Proceed to Set Folders
        Set oMainFDR = oNS.GetDefaultFolder(olFolderInbox)
        ' Get the sub folder "SUB_FDR" under Inbox
        If Not oMainFDR Is Nothing Then Set oSubFDR = GetSubFolder(oMainFDR, SUB_FDR)
        If oSubFDR Is Nothing Then
            MsgBox "Cannot get the main sub folder """ & SUB_FDR & """ under """ & oMainFDR.Name & """"
        Else
            iMoved = 0
            ' [1] Process the Selected items
            For Each oItem In ActiveExplorer.Selection
                MoveItemToFolder oItem, oSubFDR, iMoved
            Next
            ' [2] Ask to process a Folder if no MailItems are moved from Selection
            If iMoved = 0 Then
                If vbYes = MsgBox("Would you like to select a folder to move mail items?", vbQuestion + vbYesNo, "MoveSenderToFolder()") Then
                    Set oMainFDR = oNS.PickFolder ' Reuse oMainFDR object to the selected folder
                    ' Only proceed if it's a folder not within Main Sub folder.
                    If Len(Replace(oMainFDR.FolderPath, oSubFDR.FolderPath, "")) = Len(oMainFDR.FolderPath) Then
                        For Each oItem In oMainFDR.Items
                            MoveItemToFolder oItem, oSubFDR, iMoved
                        Next
                    Else
                        MsgBox "Will not process folder/subfolders of the main folder """ & SUB_FDR & """", vbInformation + vbOKOnly, "MoveSenderToFolder()"
                    End If
                End If
            End If
            Set oSubFDR = Nothing
            Set oMainFDR = Nothing
        End If
        Set oNS = Nothing
        MsgBox iMoved & " item(s) are moved.", vbInformation + vbOKOnly, "MoveSenderToFolder()"
    End If
End Sub

' Move input item to a sub folder and increment counter
Private Sub MoveItemToFolder(ByRef oItem As Variant, ByRef oSubFDR As Folder, ByRef iMoved As Long)
    Dim oMail As MailItem, sName As String, oTargetFDR As Folder
    If TypeName(oItem) = "MailItem" Then
        Set oMail = oItem
        sName = GetSenderName(oMail)
        Set oTargetFDR = GetSubFolder(oSubFDR, sName)
        If oTargetFDR Is Nothing Then
            MsgBox "Cannot get Target folder """ & oSubFDR.FolderPath & "\" & sName & """"
        Else
            oMail.Move oTargetFDR
            iMoved = iMoved + 1
        End If
        Set oMail = Nothing
    End If
End Sub

' Extract the Sender Name before any brackets
Private Function GetSenderName(ByRef oItem As MailItem) As String
    Dim sName As String
    sName = oItem.SenderName
    If InStr(1, sName, "(", vbTextCompare) > 1 Then sName = Split(sName, "(")(0)
    If InStr(1, sName, "<", vbTextCompare) > 1 Then sName = Split(sName, "<")(0)
    If InStr(1, sName, "[", vbTextCompare) > 1 Then sName = Split(sName, "[")(0)
    If InStr(1, sName, "{", vbTextCompare) > 1 Then sName = Split(sName, "{")(0)
    GetSenderName = Trim(sName)
End Function

' Given a name, get the sub-folder object from a main folder (create if required)
Private Function GetSubFolder(ByRef oParentFDR As Folder, ByVal sName As String) As Folder
    On Error Resume Next
    Dim oFDR As Folder
    Set oFDR = oParentFDR.Folders(sName)
    If oFDR Is Nothing Then Set oFDR = oParentFDR.Folders.Add(sName)
    Set GetSubFolder = oFDR
End Function


根据评论更新代码

在收件箱中搜索发件人姓名的所有子文件夹。如果找不到,则提示从文件夹选择器创建。

Option Explicit

Private oNS As NameSpace

Sub MoveSenderToFolder()
    Dim oMainFDR As Folder, oSubFDR As Folder
    Dim oItem As Variant, iMoved As Long
    On Error Resume Next
    Set oNS = Application.GetNamespace("MAPI")
    On Error GoTo 0
    If oNS Is Nothing Then
        MsgBox "Cannot get MAPI namespace from Outlook! Abortting!", vbCritical + vbOKOnly, "MoveSenderToFolder()"
    Else
        ' Proceed to Set Folders
        Set oMainFDR = oNS.GetDefaultFolder(olFolderInbox)
        If Not oMainFDR Is Nothing Then
            iMoved = 0
            ' [1] Process the Selected items
            For Each oItem In ActiveExplorer.Selection
                MoveItemToFolder oItem, oMainFDR, iMoved
            Next
            ' [2] Ask to process a Folder if no MailItems are moved from Selection
            If iMoved = 0 Then
                If vbYes = MsgBox("Would you like to select a folder to move mail items?", vbQuestion + vbYesNo, "MoveSenderToFolder()") Then
                    Set oSubFDR = oNS.PickFolder ' Reuse oMainFDR object to the selected folder
                    For Each oItem In oSubFDR.Items
                        MoveItemToFolder oItem, oMainFDR, iMoved
                    Next
                    Set oSubFDR = Nothing
                End If
            End If
            Set oSubFDR = Nothing
            Set oMainFDR = Nothing
        End If
        Set oNS = Nothing
        MsgBox iMoved & " item(s) are moved.", vbInformation + vbOKOnly, "MoveSenderToFolder()"
    End If
End Sub

' Get Folder object based on a Name and a root folder
Private Function GetSenderFolder(ByRef oRootFDR As Folder, ByVal sName As String) As Folder
    Dim oFDR As Folder, oFDR2 As Folder
    For Each oFDR In oRootFDR.Folders
        If oFDR.Name = sName Then
            Set oFDR2 = oFDR
            Exit For
        End If
    Next
    If oFDR Is Nothing Then
        For Each oFDR In oRootFDR.Folders
            Set oFDR2 = GetSenderFolder(oFDR, sName)
            If Not oFDR2 Is Nothing Then Exit For
        Next
    End If
    Set GetSenderFolder = oFDR2
End Function

' Move input item (Mail Items only) to a sub folder and increment counter
Private Sub MoveItemToFolder(ByRef oItem As Variant, ByRef oRootFDR As Folder, ByRef iMoved As Long)
    Dim oMail As MailItem, sName As String, oTargetFDR As Folder
    If TypeName(oItem) = "MailItem" Then
        Set oMail = oItem
        sName = GetSenderName(oMail)
        Set oTargetFDR = GetSenderFolder(oRootFDR, sName)
        If oTargetFDR Is Nothing Then
            If vbYes = MsgBox("Cannot get Target folder """ & oRootFDR.FolderPath & "\" & sName & """" & vbLf & _
                "Would you like to create the folder from folder of your choice?", vbQuestion + vbYesNo) Then
                Set oTargetFDR = CreateSubFolder(sName)
            End If
        End If
        If Not oTargetFDR Is Nothing Then
            oMail.Move oTargetFDR
            iMoved = iMoved + 1
        End If
        Set oMail = Nothing
    End If
End Sub

' Extract the Sender Name before any brackets
Private Function GetSenderName(ByRef oItem As MailItem) As String
    Dim sName As String
    sName = oItem.SenderName
    If InStr(1, sName, "(", vbTextCompare) > 1 Then sName = Split(sName, "(")(0)
    If InStr(1, sName, "<", vbTextCompare) > 1 Then sName = Split(sName, "<")(0)
    If InStr(1, sName, "[", vbTextCompare) > 1 Then sName = Split(sName, "[")(0)
    If InStr(1, sName, "{", vbTextCompare) > 1 Then sName = Split(sName, "{")(0)
    GetSenderName = Trim(sName)
End Function

' Given a name, Create the sub-folder object from Folder Picker
Private Function CreateSubFolder(ByVal sName As String) As Folder
    On Error Resume Next
    Dim oFDR As Folder
    Set oFDR = oNS.PickFolder
    If Not oFDR Is Nothing Then Set oFDR = oFDR.Folders.Add(sName)
    Set CreateSubFolder = oFDR
End Function

很棒的解决方案 - 我喜欢添加一个功能,如果不存在,则在用户指定的位置创建文件夹。 - Nick Peranzi
感谢@NickPeranzi。我总是将自己置于相同的情况中,并考虑可能出现的进一步帮助。您也可能希望在GetSenderFolder中为文件夹名称比较添加LCase()If LCase(oFDR.Name) = LCase(sName) Then - PatricK

2

假设

  • 发件人的子文件夹将位于收件箱下两个级别,但不是单个父文件夹下的(例如,“Doe,John”可以出现在Folder1下,“Doe,Jane”在Folder2下)
  • 在执行宏之前应选择所有应由宏处理的电子邮件
  • 代码不应为缺失发送者创建子文件夹 - 因为存在多个可能的“父”文件夹 - 但应输出包含缺失发送者文件夹列表的消息

触发发送者名称结束的条件:

  • 空格后面或前面的连字符(即“Doe,John-US”=“Doe,John”,“Huntington-Whiteley,Rosie-CAN”=Huntington-Whiteley,Rosie“)
  • 逗号的第二个实例(即“Doe,John,CPA”=“Doe,John”)
  • 空格的第二个实例(即“Doe,John Q”=“Doe,John”)
  • 空格的前面或后面的撇号(即“O'Leary,John”=“O'Leary,John”,但是“Doe,John'US'”=“Doe,John”)
  • 任何其他非字母字符(即“Doe,John:US”=“Doe,John”)

建议的解决方案

此代码将满足上述所有条件,并在末尾输出单个消息,表示无法找到文件夹的任何发件人(而不是每个电子邮件的单独消息)。 它已在Outlook 2013 / Windows 10上进行了测试。

Public Sub MoveToFolder()

Dim objSelection As Selection
Set objSelection = Application.ActiveExplorer.Selection

Dim iSelected As Integer, iMoved As Integer
iSelected = objSelection.Count 'Get a total for output message

Dim StrOutput As String, StrUnmoved As String, StrName As String
StrUnmoved = "Unmoved Item Count by Sender" & vbNewLine & "============================"

Dim objNS As NameSpace
Dim objParentFolder As Folder, objSubFolder As Folder, objDestFolder As Folder
Dim BFound As Boolean, iLoc As Integer
Set objNS = Application.GetNamespace("MAPI")
Set objParentFolder = objNS.GetDefaultFolder(olFolderInbox)

'Only execute code if the parent folder has subfolders
If objParentFolder.Folders.Count > 0 Then
    'Loop through all selected items
    For Each Item In objSelection
        If Item.Class = 43 Then
            'This is an email.
            BFound = False
            StrName = GetSenderName(Item.SenderName)
            For Each objSubFolder In objParentFolder.Folders
                If objSubFolder.Folders.Count > 0 Then
                    On Error Resume Next
                    Set objDestFolder = Nothing
                    Set objDestFolder = objSubFolder.Folders(StrName)
                    On Error GoTo 0
                    If Not objDestFolder Is Nothing Then
                        'Folder found.
                        Item.Move objDestFolder
                        iMoved = iMoved + 1
                        BFound = True
                        Exit For
                    End If
                End If
            Next
            If Not BFound Then
                'Sender folder not found. Check if we have already logged this sender.
                iLoc = 0
                iLoc = InStr(1, StrUnmoved, StrName)
                If iLoc > 0 Then
                    'Existing sender name. Increment current total.
                    StrUnmoved = Left(StrUnmoved, iLoc + Len(StrName) + 1) & _
                    Format(CInt(Mid(StrUnmoved, iLoc + Len(StrName) + 2, 5)) + 1, "00000") & Right(StrUnmoved, Len(StrUnmoved) - iLoc - Len(StrName) - 6)
                Else
                    'New sender name.
                    StrUnmoved = StrUnmoved & vbNewLine & StrName & ": 00001"
                End If
            End If
        End If
    Next

    If iMoved = iSelected Then
        StrOutput = "All " & iSelected & " items moved to appropriate subfolders."
    Else
        'Remove extraneous zeroes
        StrUnmoved = Replace(StrUnmoved, ": 000", ": ")
        StrUnmoved = Replace(StrUnmoved, ": 00", ": ")
        StrUnmoved = Replace(StrUnmoved, ": 0", ": ")
        StrOutput = iMoved & "/" & iSelected & " items moved to appropriate subfolders; see below for unmoved details." & vbNewLine & vbNewLine & StrUnmoved
    End If
    MsgBox StrOutput
Else
    MsgBox "There are no subfolders to the default inbox. Script will now exit."
End If

End Sub

Function GetSenderName(StrFullSender As String) As String

'Only take action if a non-null string is passed
If Len(StrFullSender) > 1 Then
    StrFullSender = Trim(StrFullSender) 'Trim extraneous spaces
    Dim StrOutput As String
    'Find first case of the end of the name
    Dim iChar As Integer
    Dim iCommaCount As Integer
    Dim iSpaceCount As Integer
    For iChar = 1 To Len(StrFullSender)
        Select Case Asc(Mid(StrFullSender, iChar, 1))
            Case 65 To 90, 97 To 122 '192 to 246, 248 to 255 'Include 192-246 and 248-255 if you will receive emails from senders with accents or other symbols in their names
                'No action necessary - this is a letter
            Case 45, 151 'Hyphen or EM Dash - could be a hyphenated name
                If Mid(StrFullSender, IIf(iChar = 1, 1, iChar - 1), IIf(Len(StrFullSender) - iChar > 1, 3, Len(StrFullSender) - iChar + 1)) <> _
                    Trim(Mid(StrFullSender, IIf(iChar = 1, 1, iChar - 1), IIf(Len(StrFullSender) - iChar > 1, 3, Len(StrFullSender) - iChar + 1))) Then Exit For
                    'There is a space on one or both sides of the hyphen. This is a valid stop.
            Case 44
                iCommaCount = iCommaCount + 1
                If iCommaCount > 1 Then Exit For
            Case 32
                iSpaceCount = iSpaceCount + 1
                If iSpaceCount > 1 Then Exit For
            Case 39
                If Mid(StrFullSender, IIf(iChar = 1, 1, iChar - 1), IIf(Len(StrFullSender) - iChar > 1, 3, Len(StrFullSender) - iChar + 1)) <> _
                    Trim(Mid(StrFullSender, IIf(iChar = 1, 1, iChar - 1), IIf(Len(StrFullSender) - iChar > 1, 3, Len(StrFullSender) - iChar + 1))) Then Exit For
                    'There is a space on one or both sides of the apostrophe. This is a valid stop.
            Case Else
                Exit For
        End Select
    Next

    StrOutput = Trim(Left(StrFullSender, iChar - 1))

    GetSenderName = StrOutput
End If

End Function

已在Outlook 2010和Windows 7中进行了测试,运行非常顺畅。 - Adavid02
我发现如果发送者名称是"Smith, W L",代码将不能将消息移动到文件夹中,因为文件夹名称中有第二个名字的首字母。即文件夹名称必须从"Smith, W L"更改为"Smith, W"以便移动消息。 - Adavid02
1
啊,这是在第二个空格之后修剪发件人姓名的副作用,旨在删除中间名字母。可以通过添加额外的逻辑来检查第二个空格仅在前一个单词长度大于一个字符时才结束已清理的发件人姓名,但这取决于此功能对您有多重要。 - Nick Peranzi

0

更新文件夹名称 Folders("Folder1")

Option Explicit
Sub File_olItems()
    Dim olNameSpace As Outlook.NameSpace
    Dim olSourceFolder As Outlook.Folder
    Dim olDestFolder As Outlook.Folder
    Dim currentExplorer As Explorer
    Dim Selection As Selection
    Dim olItem As MailItem
    Dim vItem As Variant
    Dim NameSender As String
    Dim i As Long

    Set olNameSpace = Application.GetNamespace("MAPI")
    Set currentExplorer = Application.ActiveExplorer
    Set Selection = currentExplorer.Selection
    Set olSourceFolder = olNameSpace.GetDefaultFolder(olFolderInbox).Folders("Folder1")

    For Each olItem In Selection
        Set vItem = olItem

        If vItem.Class = olMail Then
            Debug.Print vItem.SentOnBehalfOfName
            NameSender = vItem.SentOnBehalfOfName

            If NameSender = ";" Then
                NameSender = vItem.SenderName
            End If

            If InStr(1, NameSender, "(", vbTextCompare) > 1 Then
                NameSender = Split(NameSender, "(")(0)
                Debug.Print NameSender
            End If

            On Error Resume Next
            Set olDestFolder = olSourceFolder.Folders(NameSender)

            If olDestFolder Is Nothing Then
                Set olDestFolder = olSourceFolder.Folders.Add(NameSender)
            End If

            vItem.Move olDestFolder
'           // count items moved
            i = i + 1
            Set olDestFolder = Nothing
        End If
    Next olItem

'   // Display the number of items that were moved.
    MsgBox "Moved " & i & " Mail Items."

    Set currentExplorer = Nothing
    Set olItem = Nothing
    Set Selection = Nothing
    Set olNameSpace = Nothing
    Set olSourceFolder = Nothing
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接