简体   繁体   English

将 Outlook 电子邮件另存为 PDF + 附件

[英]Saving Outlook email as PDF + Attachments

So I am using a macro to save incoming mail (with an inbox rule and VBA code).所以我使用宏来保存传入的邮件(带有收件箱规则和 VBA 代码)。 The problem I am having is that when there are multiple emails with the same name (and also if the attachments have the same name) they will not save.我遇到的问题是,当有多封电子邮件具有相同名称时(以及如果附件具有相同名称),它们将无法保存。 (they overwrite each other). (它们相互覆盖)。

I need both the email and the attachments to loop through 1-10 (there can be up to ten emails and attachments with the same names).我需要电子邮件和附件循环遍历 1-10(最多可以有 10 封具有相同名称的电子邮件和附件)。 Here is the code:这是代码:

Sub SaveAsMsg(MyMail As MailItem)
' requires reference to Microsoft Scripting Runtime
' \Windows\System32\Scrrun.dll
' Also requires reference to Microsoft Word Object Library
Dim fso As FileSystemObject
Dim strSubject As String
Dim strSaveName As String
Dim blnOverwrite As Boolean
Dim strFolderPath As String
Dim looper As Integer
Dim strID As String
Dim olNS As Outlook.NameSpace
Dim oMail As Outlook.MailItem

strID = MyMail.EntryID
Set olNS = Application.GetNamespace("MAPI")
Set oMail = olNS.GetItemFromID(strID)

'Get Sender email domain
sendEmailAddr = oMail.SenderEmailAddress
companyDomain = Right(sendEmailAddr, Len(sendEmailAddr) - InStr(sendEmailAddr, "@"))

' ### USER OPTIONS ###
blnOverwrite = False ' False = don't overwrite, True = do overwrite

'### THIS IS WHERE SAVE LOCATIONS ARE SET ###
'Currently only saves to yPath. Change the yPath variable to mPath in other areas of the script to enable the month folder.
bPath = "C:\email\" 'Defines the base path to save the email
cPath = bPath & companyDomain & "\" 'Adds company domain to base path
yPath = cPath & Format(Now(), "yyyy") & "\" 'Add year subfolder
mPath = yPath & Format(Now(), "MMMM") & "\" 'Add month subfolder

'### Path Validity ###
'Make sure base path exists
If Dir(bPath, vbDirectory) = vbNullString Then
   MkDir bPath
End If
'Make sure company domain path exists
'If Dir(cPath, vbDirectory) = vbNullString Then
   'MkDir cPath
'End If
'Make sure year path exists
'If Dir(yPath, vbDirectory) = vbNullString Then
   'MkDir yPath
'End If
'Make sure month path exists (uncomment below lines to enable)
'If Dir(mPath, vbDirectory) = vbNullString Then
 'MkDir mPath
'End If

'### Get Email subject & set name to be saved as ###
emailSubject = CleanFileName(oMail.Subject)
saveName = Format(oMail.ReceivedTime, "yyyymmdd") & "_" & emailSubject & ".txt"
Set fso = CreateObject("Scripting.FileSystemObject")

'### If don't overwrite is on then ###
If blnOverwrite = False Then
   looper = 0
   Do While fso.FileExists(yPath & saveName)
      looper = looper + 1
      saveName = Format(oMail.ReceivedTime, "yyyymmdd") & "_" & emailSubject & "_" & looper & ".txt"
   Loop
Else '### If don't overwrite is off, delete the file ###
   If fso.FileExists(yPath & saveName) Then
      fso.DeleteFile yPath & saveName
   End If
End If

'### Save MSG File ###
oMail.SaveAs bPath & saveName, olTXT

'### If Mail Attachments: clean file name, save into path ###
If oMail.Attachments.Count > 0 Then
   For Each atmt In oMail.Attachments
      atmtName = CleanFileName(atmt.FileName)
      atmtSave = bPath & Format(oMail.ReceivedTime, "yyyymmdd") & "_" & atmtName
      atmt.SaveAsFile atmtSave
   Next
End If

Set oMail = Nothing
Set olNS = Nothing
Set fso = Nothing
End Sub

Function CleanFileName(strText As String) As String
Dim strStripChars As String
Dim intLen As Integer
Dim i As Integer
strStripChars = "/\[]:=," & Chr(34)
intLen = Len(strStripChars)
strText = Trim(strText)
For i = 1 To intLen
strText = Replace(strText, Mid(strStripChars, i, 1), "")
Next
CleanFileName = strText
End Function



Sub SaveAsPDF(MyMail As MailItem)
' requires reference to Microsoft Scripting Runtime
' \Windows\System32\Scrrun.dll
' Also requires reference to Microsoft Word Object Library
Dim fso As FileSystemObject
Dim strSubject As String
Dim strSaveName As String
Dim blnOverwrite As Boolean
Dim strFolderPath As String
Dim looper As Integer
Dim strID As String
Dim olNS As Outlook.NameSpace
Dim oMail As Outlook.MailItem

strID = MyMail.EntryID
Set olNS = Application.GetNamespace("MAPI")
Set oMail = olNS.GetItemFromID(strID)

'Get Sender email domain
sendEmailAddr = oMail.SenderEmailAddress
companyDomain = Right(sendEmailAddr, Len(sendEmailAddr) - InStr(sendEmailAddr, "@"))

' ### USER OPTIONS ###
blnOverwrite = False ' False = don't overwrite, True = do overwrite

'### THIS IS WHERE SAVE LOCATIONS ARE SET ###
bPath = "C:\email\" 'Defines the base path to save the email
cPath = bPath & companyDomain & "\" 'Adds company domain to base path
yPath = cPath & Format(Now(), "yyyy") & "\" 'Add year subfolder
mPath = yPath & Format(Now(), "MMMM") & "\" 'Add month subfolder

'### Path Validity ###
If Dir(bPath, vbDirectory) = vbNullString Then
    MkDir bPath
End If
'If Dir(cPath, vbDirectory) = vbNullString Then
   ' MkDir cPath
'End If
'If Dir(yPath, vbDirectory) = vbNullString Then
   ' MkDir yPath
'End If

'### Get Email subject & set name to be saved as ###
emailSubject = CleanFileName(oMail.Subject)
saveName = Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & ".mht"
Set fso = CreateObject("Scripting.FileSystemObject")

'### If don't overwrite is on then ###
If blnOverwrite = False Then
    looper = 0
    Do While fso.FileExists(bPath & saveName)
        looper = looper + 1
        saveName = Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & "_" & looper & ".mht"
        pdfSave = Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & "_" & looper & ".pdf"
        Loop
Else '### If don't overwrite is off, delete the file ###
    If fso.FileExists(bPath & saveName) Then
        fso.DeleteFile bPath & saveName
    End If
End If
oMail.SaveAs bPath & saveName, olMHTML
pdfSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & ".pdf"

'### Open Word to convert file to PDF ###
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Set wrdApp = CreateObject("Word.Application")

Set wrdDoc = wrdApp.Documents.Open(FileName:=bPath & saveName, Visible:=True)
wrdApp.ActiveDocument.ExportAsFixedFormat OutputFileName:= _
            pdfSave, ExportFormat:= _
            wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
            wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=0, To:=0, _
            Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
            CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
            BitmapMissingFonts:=True, UseISO19005_1:=False

wrdDoc.Close
wrdApp.Quit

'### Clean up files ###
With New FileSystemObject
    If .FileExists(bPath & saveName) Then
        .DeleteFile bPath & saveName
    End If
End With

'### If Mail Attachments: clean file name, save into path ###
If oMail.Attachments.Count > 0 Then
    For Each atmt In oMail.Attachments
        atmtName = CleanFileName(atmt.FileName)
        atmtSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & atmtName
        atmt.SaveAsFile atmtSave
    Next
End If

Set oMail = Nothing
Set olNS = Nothing
Set fso = Nothing
End Sub

If anyone has any idea, help would be greatly appreciated.如果有人有任何想法,将不胜感激。

This works really well once you delete the if statements that delete the file.一旦删除了删除文件的if语句,这会非常有效。 Thank you for the foundation.谢谢你的基础。

I've modified the PDF portion of your code (for the better, I hope) and fixed an issue that the pdf filename would not increment if it existed already.我已经修改了您代码的 PDF 部分(希望更好)并修复了 pdf 文件名如果已经存在则不会增加的问题。 I had to write a separate loop for the PDF because you basically stopped the loop with this line: pdfSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & ".pdf" but I can't seem to get rid of that line without producing an error so made a new loop.我不得不为 PDF 编写一个单独的循环,因为你基本上用这一行停止了循环: pdfSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & ".pdf"但我似乎无法在不产生错误的情况下摆脱该行,因此创建了一个新循环。 Maybe someone can simplify that part for me.也许有人可以为我简化那部分。

I've also added a line to delete the .mht file only used to create the PDF and modified the filenames a bit:我还添加了一行来删除仅用于创建 PDF 的.mht文件并稍微修改了文件名:

Function CleanFileName(strText As String) As String
Dim strStripChars As String
Dim intLen As Integer
Dim i As Integer
strStripChars = "/\[]:=," & Chr(34)
intLen = Len(strStripChars)
strText = Trim(strText)
For i = 1 To intLen
strText = Replace(strText, Mid(strStripChars, i, 1), "")
Next
CleanFileName = strText
End Function



Sub SaveAsPDF(MyMail As MailItem)
' ### Requires reference to Microsoft Scripting Runtime ###
' ### Requires reference to Microsoft Word Object Library ###
' --- In VBE click TOOLS > REFERENCES and check the boxes for both of the above ---
Dim fso As FileSystemObject
Dim strSubject As String
Dim strSaveName As String
Dim blnOverwrite As Boolean
Dim strFolderPath As String
Dim sendEmailAddr As String
Dim senderName As String
Dim looper As Integer
Dim plooper As Integer
Dim strID As String
Dim olNS As Outlook.NameSpace
Dim oMail As Outlook.MailItem

strID = MyMail.EntryID
Set olNS = Application.GetNamespace("MAPI")
Set oMail = olNS.GetItemFromID(strID)

' ### Get username portion of sender email address ###
sendEmailAddr = oMail.SenderEmailAddress
senderName = Left(sendEmailAddr, InStr(sendEmailAddr, "@") - 1)

' ### USER OPTIONS ###
blnOverwrite = False ' False = don't overwrite, True = do overwrite

' ### Path to save directory ###
bPath = "Z:\email\"

' ### Create Directory if it doesnt exist ###
If Dir(bPath, vbDirectory) = vbNullString Then
    MkDir bPath
End If

' ### Get Email subject & set name to be saved as ###
emailSubject = CleanFileName(oMail.Subject)
saveName = Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & emailSubject & ".mht"
Set fso = CreateObject("Scripting.FileSystemObject")

' ### Increment filename if it already exists ###
If blnOverwrite = False Then
    looper = 0
    Do While fso.FileExists(bPath & saveName)
        looper = looper + 1
        saveName = Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & senderName & "_" & emailSubject & "_" & looper & ".mht"
        Loop
Else
End If

' ### Save .mht file to create pdf from Word ###
oMail.SaveAs bPath & saveName, olMHTML
pdfSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & senderName & "_" & emailSubject & ".pdf"

If fso.FileExists(pdfSave) Then
    plooper = 0
    Do While fso.FileExists(pdfSave)
    plooper = plooper + 1
    pdfSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & senderName & "_" & emailSubject & "_" & plooper & ".pdf"
    Loop
Else
End If


' ### Open Word to convert .mht file to PDF ###
Dim wrdApp As Word.Application
Dim wrdDoc As Word.Document
Set wrdApp = CreateObject("Word.Application")

' ### Open .mht file we just saved and export as PDF ###
Set wrdDoc = wrdApp.Documents.Open(FileName:=bPath & saveName, Visible:=True)
wrdApp.ActiveDocument.ExportAsFixedFormat OutputFileName:= _
            pdfSave, ExportFormat:= _
            wdExportFormatPDF, OpenAfterExport:=False, OptimizeFor:= _
            wdExportOptimizeForPrint, Range:=wdExportAllDocument, From:=0, To:=0, _
            Item:=wdExportDocumentContent, IncludeDocProps:=True, KeepIRM:=True, _
            CreateBookmarks:=wdExportCreateNoBookmarks, DocStructureTags:=True, _
            BitmapMissingFonts:=True, UseISO19005_1:=False

wrdDoc.Close
wrdApp.Quit

' ### Delete .mht file ###
Kill bPath & saveName

' ### Uncomment this section to save attachments ###
'If oMail.Attachments.Count > 0 Then
'    For Each atmt In oMail.Attachments
'        atmtName = CleanFileName(atmt.FileName)
'        atmtSave = bPath & Format(oMail.ReceivedTime, "yyyy-mm-dd-hhmm") & "_" & atmtName
'        atmt.SaveAsFile atmtSave
'    Next
'End If

Set oMail = Nothing
Set olNS = Nothing
Set fso = Nothing
End Sub

I have noticed the following lines of code:我注意到以下几行代码:

strID = MyMail.EntryID
Set olNS = Application.GetNamespace("MAPI")
Set oMail = olNS.GetItemFromID(strID)

There is no need to get a new instance of the MailItem class.无需获取 MailItem 类的新实例。 You can use the instance passed as a parameter.您可以使用作为参数传递的实例。

 If fso.FileExists(bPath & saveName) Then
    fso.DeleteFile bPath & saveName

It looks like you delete existing files instead of saving a new ones with different names.看起来您删除了现有文件而不是保存具有不同名称的新文件。

You may consider using the datetime (not only the date) marker when saving emails/attachments.在保存电子邮件/附件时,您可以考虑使用日期时间(不仅是日期)标记。 Or you may check out whether such file exists on the disk already.或者您可以检查磁盘上是否已经存在此类文件。

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

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