根据发件人姓名为附件创建文件夹

Create folders for attachments based on sender name

学生通过电子邮件发送评估答案,我将它们放在与评估编号相关的文件夹中。一个学生在完成评估时可能会收到多封电子邮件,其中包含不同的附件。

我的收件箱下有一个名为 AllNZBAT 的主文件夹。我有评估编号的子文件夹。 112、123、2785 等用于学生的电子邮件。

我需要从多封电子邮件中提取学生的附件,并将它们放在一个文件夹中,该文件夹中的学生姓名(发件人)位于该评估的文件夹中。

所以文件夹“John Smith”保存了他所有的评估 123 的附件。

我正在尝试编写一个执行此操作的宏。它创建文件夹树和带有学生姓名的文件夹。我无法在包含发件人姓名的文件夹中获取附件。

有时我会得到两个同一个学生名字的文件夹,但其中一个文件夹的名字后面也会有(Unicode 编码冲突)。

Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
Dim myNewFolder As Outlook.Folder
Dim currentFolder As Outlook.Folder

'https://www.codeproject.com/Questions/5258321/Outlook-VBA-automatically-create-a-folder-based-on
'https://vbatutorialcode.com/save-all-attachments-from-outlook-into-folder-vba/
'

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

Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Set olFolder = olFolder.Folders("All NZBat")  'set the start folder - replace it with selection

' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")

Dim FoldersArray As Variant
Dim LastFolder As Integer
Dim strParentFolderName As String

'use to create the folders on the drive
Dim fs As Object 'Using late binding to avoid having to include a reference to Microsoft Scripting Runtime
Set fs = CreateObject("Scripting.FileSystemObject")

'C:\Dropbox\NZBAT Resources2FebStudetnResults
' Get the path to your My Documents folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)

On Error Resume Next

'get all the folders under the All NZBat
For Each Folder In olFolder.Folders
  ' Debug.Print Folder.FolderPath    '\*****@*****.ac.nz\Inbox\All NZBat2
   
 Set currentFolder = Folder
     FoldersArray = Split(Folder.FolderPath, "\")
     LastFolder = UBound(FoldersArray)
     
     'Debug.Print FoldersArray(LastFolder) '112
     'get the last folder in the path string = 112 so we can make a new folder with its name
    strParentFolderName = FoldersArray(LastFolder)
    
'Next

'need to get all the emails in the folder

' Set the Attachment folder with the name of the sender.
strFolderpath = "C:\Dropbox\EmailedAssessments\" & strParentFolderName & "\"  ' & objMsg.SenderName & " \ "
 'Debug.Print strFolderpath  'C:\Dropbox\NZBAT Resources2\
   '  strFolderpath = Replace(strFolderpath, " ", "_")
  'make the folder
    
    If Not fs.folderexists(strFolderpath) Then
        fs.createfolder (strFolderpath)
    End If



' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection

'Set currentFolder = 'Application.ActiveExplorer.currentFolder

' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In currentFolder.Items  'objSelection

'Debug.Print objMsg.Subject
strFolderpathFull = strFolderpath & objMsg.SenderName & " \ "
 ' strFolderpathFull = Replace(strFolderpathFull, " ", "_")
 
 'Debug.Print strFolderpathFull  'C:\Dropbox\NZBAT Resources2\Kathryn Tonks \
 
 ' Dim fs As Object 'Using late binding to avoid having to include a reference to Microsoft Scripting Runtime
  '  Set fs = CreateObject("Scripting.FileSystemObject")
    
    'make the subfolder
    If Not fs.folderexists(strFolderpathFull) Then
        fs.createfolder (strFolderpathFull)
    End If

    ' This code only strips attachments from mail items.
    ' If objMsg.class=olMail Then
    ' Get the Attachments collection of the item.
    Set objAttachments = objMsg.Attachments
    lngCount = objAttachments.Count
    strDeletedFiles = ""

    If lngCount > 0 Then

        ' We need to use a count down loop for removing items
        ' from a collection. Otherwise, the loop counter gets
        ' confused and only every other item is removed.

        For i = lngCount To 1 Step -1

            ' Save attachment before deleting from item.
            ' Get the file name.
            strFile = objAttachments.Item(i).FileName

            ' Combine with the path to the Temp folder.& StudentFolder
            strFile = strFolderpathFull & strFile
       '    strFile = Replace(strFile, "_\_", "\")
         
 
            ' Save the attachment as a file.
            objAttachments.Item(i).SaveAsFile strFile
           Debug.Print strFile & " Saved attachment"


            'write the save as path to a string to add to the message
            'check for html and use html tags in link
            If objMsg.BodyFormat <> olFormatHTML Then
                strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
            Else
                strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
                strFile & "'>" & strFile & "</a>"
            End If

            'Use the MsgBox command to troubleshoot. Remove it from the final code.
            'MsgBox strDeletedFiles

        Next i

        ' Adds the filename string to the message body and save it
        ' Check for HTML body
        If objMsg.BodyFormat <> olFormatHTML Then
            objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
        Else
            objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
        End If
      
        
        g.Save
    End If
Next
Next
End Sub

你的代码真的很接近工作(顺便说一句,它不会以它被复制到问题中的形式编译)......但是我没有完全调试它,而是采取了清理它直到它工作的方法;有很多多余的代码。

下面的代码读取 all assignment folders/student 文件夹和电子邮件...并创建作业子目录,以及其中的学生目录,并保存assignment/student 目录中的附件。它使用对已保存附件的引用更新电子邮件正文。

如果您希望它仅适用于选定的文件夹,您需要稍微调整以下代码。

我怀疑重复目录名称的问题可能是由于将学生电子邮件地址中的不兼容字符放入学生的目录路径名称中...所以我包含了一个非常原始的清理功能(我没有测试太多)希望避免这种情况;它可能需要调整。

顺便说一句,我使用早期绑定,因此如果您还没有 MS 脚本运行时,则需要添加对它的引用。

Option Explicit

Public Sub SaveAttachments()

    Const ParentDirectory = "C:\Dropbox\EmailedAssessments\"
    
    Dim fs As New FileSystemObject                          ' File system object
    Dim MAPINamspace As Outlook.NameSpace                   ' MAPI namespace
    Dim InboxFolder As folder                               ' Inbox
    Dim ParentFolder As folder                              ' Parent folder ... e.g. "ALL NZBAT"
    Dim AssignmentSubFolder As folder                       ' Assignment folders in Parent Folder
    Dim OutlookMessage As MailItem                          ' Outlook message
    Dim AssignmentDirectory As String                       ' Assignment Directory
    Dim StudentDirectory As String                          ' Student Directory (within Assignment Directory)
    Dim AttachmentPathFileName As String                    ' Attachment Path and File Name
    Dim DeletedAttachments As String                        ' A record of all deleted attachments to append to Outlook message
    Dim OutlookAttachment As Attachment                     ' Outlook attachment
    
    Set MAPINamspace = Outlook.Application.GetNamespace("MAPI")
    Set InboxFolder = MAPINamspace.GetDefaultFolder(olFolderInbox)
    Set ParentFolder = InboxFolder.Folders("ALL NZBAT")
    
    ' Get all the Outlook subfolders in the Parent Folder "ALL NZBAT"
    For Each AssignmentSubFolder In ParentFolder.Folders
        
        ' Setup the directory where each assignment's data will be saved
        AssignmentDirectory = ParentDirectory & AssignmentSubFolder.Name & "\"
        If Not fs.folderexists(AssignmentDirectory) Then
            fs.createfolder (AssignmentDirectory)
        End If
        
        ' Check each selected item for attachments. 
        For Each OutlookMessage In AssignmentSubFolder.Items
        
            ' Setup the directory where each student's attachments will be saved, cleaning (in a primitive way) the SenderName
            StudentDirectory = AssignmentDirectory & CleanName(OutlookMessage.SenderName) & "\"
            If Not fs.folderexists(StudentDirectory) Then
                fs.createfolder (StudentDirectory)
            End If
        
            ' Save all the attachments from the message
            DeletedAttachments = ""
            For Each OutlookAttachment In OutlookMessage.Attachments
                
                ' Save the attachment
                AttachmentPathFileName = StudentDirectory & OutlookAttachment.FileName
                OutlookAttachment.SaveAsFile AttachmentPathFileName
                
                ' Keep a record of the all the saved attachments.
                If OutlookMessage.BodyFormat <> olFormatHTML Then
                    DeletedAttachments = DeletedAttachments & vbCrLf & "<file://" & AttachmentPathFileName & ">"
                Else
                    DeletedAttachments = DeletedAttachments & "<br>" & "<a href='file://" & AttachmentPathFileName & "'>" & AttachmentPathFileName & "</a>"
                End If

            Next
        
            ' Append a record of all of the saved attachments to the start of the outlook message
            If DeletedAttachments <> "" Then
                If OutlookMessage.BodyFormat <> olFormatHTML Then
                    OutlookMessage.Body = vbCrLf & "The file(s) were saved to " & DeletedAttachments & vbCrLf & OutlookMessage.Body
                Else
                    OutlookMessage.HTMLBody = "<p>" & "The file(s) were saved to " & DeletedAttachments & "</p>" & OutlookMessage.HTMLBody
                End If
                OutlookMessage.Save
            End If
            
        Next
        
    Next
End Sub

Public Function CleanName(InputName As String) As String

    Dim Counter As Long
    Dim WorkChar As String
    
    ' A primitive file name cleaner
    For Counter = 1 To Len(InputName)
        WorkChar = Mid(InputName, Counter, 1)
        If Asc(WorkChar) <= 31 Or InStr(1, "<>:""/|?*", WorkChar) > 0 Then
            CleanName = CleanName & "_"
        Else
            CleanName = CleanName & WorkChar
        End If
    Next
    
End Function