Consulting

Results 1 to 4 of 4

Thread: Merge email message and attachements into one pdf file

  1. #1

    Merge email message and attachements into one pdf file

    Hi guys,

    I got the following code which merges email messages and the attachments into one pdf file of the selected email and save it down on the shared folder. I want to do the following things :

    1. At the moment when it merges email message and attachments into pdf then in the pdf file attachments appear first and then at the bottom email message appear . I want it done the other way so email message on the top and then attachments at the bottom.

    2. The code ignores any pdf attachments or JPEG attachments in the email .

    3. My clients won't receive any excel attachments so I want to tidy up the code so it won't look for excel attachments.
    Public Sub MergeMailAndAttachsToPDF_New(MortANo As String)
        Dim xSelMails As MailItem
        Dim xFSysObj As FileSystemObject
        Dim xOverwriteBln As Boolean
        Dim xLooper As Integer
        Dim xEntryID As String
        Dim xNameSpace As Outlook.NameSpace
        Dim xMail As Outlook.MailItem
        Dim xExt As String
        Dim xSendEmailAddr, xCompanyDomain As String
        Dim xWdApp As Word.Application
        Dim xDoc, xNewDoc As Word.Document
        Dim I As Integer
        Dim xPDFSavePath As String
        Dim xPath As String
        Dim xFileArr() As String
        ' Dim xExcel As Excel.Application
        Dim xWb As Workbook
        Dim xWs As Worksheet
        Dim xTempDoc As Word.Document
        Dim strFileName As String
        On Error Resume Next
        If (Outlook.ActiveExplorer.Selection.Count > 1) Or (Outlook.ActiveExplorer.Selection.Count = 0) Then
             MsgBox "Please Select a email.", vbInformation + vbOKOnly
             Exit Sub
        End If
        Set xSelMails = Outlook.ActiveExplorer.Selection.Item(1)
        xEntryID = xSelMails.EntryID
        Set xNameSpace = Application.GetNamespace("MAPI")
        Set xMail = xNameSpace.GetItemFromID(xEntryID)
        xSendEmailAddr = xMail.SenderEmailAddress
        xCompanyDomain = Right(xSendEmailAddr, Len(xSendEmailAddr) - InStr(xSendEmailAddr, "@"))
        xOverwriteBln = False
        Set xExcel = New Excel.Application
        xExcel.Visible = False
        Set xWdApp = New Word.Application
        xExcel.DisplayAlerts = False
        strSaveFldr = GetPrivateProfileString32("U:\test.ini", "SaveFolder", "FolderName")
        strFileName = MortANo & "-" & DocType_Col1 & "-" & email & "-" & Environ("Username")
        xPDFSavePath = strSaveFldr & strFileName & ".pdf"
        If xPDFSavePath = "False" Then
            xExcel.DisplayAlerts = True
            xExcel.Quit
            xWdApp.Quit
            Exit Sub
        End If
        xPath = Left(xPDFSavePath, InStrRev(xPDFSavePath, ""))
        cPath = xPath & xCompanyDomain & ""
        yPath = cPath & Format(Now(), "yyyy") & ""
        mPath = yPath & Format(Now(), "MMMM") & ""
        If Dir(xPath, vbDirectory) = vbNullString Then
            MkDir xPath
        End If
        EmailSubject = CleanFileName(xMail.Subject)
        xSaveName = Format(xMail.ReceivedTime, "yyyymmdd") & "_" & EmailSubject & ".doc"
        Set xFSysObj = CreateObject("Scripting.FileSystemObject")
        If xOverwriteBln = False Then
            xLooper = 0
           Do While xFSysObj.FileExists(yPath & xSaveName)
               xLooper = xLooper + 1
               xSaveName = Format(xMail.ReceivedTime, "yyyymmdd") & "_" & EmailSubject & "_" & xLooper & ".doc"
            Loop
        Else
            If xFSysObj.FileExists(yPath & xSaveName) Then
                xFSysObj.DeleteFile yPath & xSaveName
            End If
        End If
        xMail.SaveAs xPath & xSaveName, olDoc
        If xMail.Attachments.Count > 0 Then
            For Each Atmt In xMail.Attachments
                xExt = SplitPath(Atmt.FileName, 2)
                If (xExt = ".docx") Or (xExt = ".doc") Or (xExt = ".docm") Or (xExt = ".dot") Or (xExt = ".dotm") Or (xExt = ".dotx") _
                Or (xExt = ".xlsx") Or (xExt = ".xls") Or (xExt = ".xlsm") Or (xExt = ".xlt") Or (xExt = ".xltm") Or (xExt = ".xltx") Then
                    atmtName = CleanFileName(Atmt.FileName)
                    atmtSave = strSaveFldr & Format(xMail.ReceivedTime, "yyyymmdd") & "_" & atmtName
                    Atmt.SaveAsFile atmtSave
                End If
            Next
        End If
        Set xNewDoc = xWdApp.Documents.Add("Normal", False, wdNewBlankDocument, False)
        Set xFilesFld = xFSysObj.GetFolder(xPath)
        xFileArr() = GetFiles(strSaveFldr)
        For I = 0 To UBound(xFileArr()) - 1
             xExt = SplitPath(xFileArr(I), 2)
             If (xExt = ".xlsx") Or (xExt = ".xls") Or (xExt = ".xlsm") Or (xExt = ".xlt") Or _
                 (xExt = ".xltm") Or (xExt = ".xltx") Then  'conver excel to word
                 Set xWb = xExcel.Workbooks.Open(xPath & xFileArr(I))
                 Set xTempDoc = xWdApp.Documents.Add("Normal", False, wdNewBlankDocument, False)
                 Set xWs = xWb.ActiveSheet
                 xWs.UsedRange.Copy
                 xTempDoc.Content.PasteAndFormat wdFormatOriginalFormatting
                 xTempDoc.SaveAs2 xPath & xWs.Name + ".docx", wdFormatXMLDocument
                 xWb.Close False
                 Kill xPath & xFileArr(I)
                 xTempDoc.Close wdDoNotSaveChanges, wdOriginalDocumentFormat, False
             End If
        Next
        xExcel.DisplayAlerts = True
        xExcel.Quit
        xFileArr() = GetFiles(xPath)
        ' Merge Documents
        For I = 0 To UBound(xFileArr()) - 1
             xExt = SplitPath(xFileArr(I), 2)
             If (xExt = ".docx") Or (xExt = ".doc") Or (xExt = ".docm") Or (xExt = ".dot") Or (xExt = ".dotm") Or (xExt = ".dotx") Then
                 MergeDoc xWdApp, xPath & xFileArr(I), xNewDoc
                 Kill xPath & xFileArr(I)
             End If
        Next
        xNewDoc.Sections.Item(1).Range.Delete wdCharacter, 1
        xNewDoc.SaveAs2 xPDFSavePath, wdFormatPDF
        xNewDoc.Close wdDoNotSaveChanges, wdOriginalDocumentFormat, False
        xWdApp.Quit
        Set xMail = Nothing
        Set xNameSpace = Nothing
        Set xFSysObj = Nothing
        MsgBox "Merged successfully", vbInformation + vbOKOnly
    End Sub
     
    Public Function SplitPath(FullPath As String, ResultFlag As Integer) As String
        Dim SplitPos As Integer, DotPos As Integer
        SplitPos = InStrRev(FullPath, "/")
        DotPos = InStrRev(FullPath, ".")
        Select Case ResultFlag
        Case 0
            SplitPath = Left(FullPath, SplitPos - 1)
        Case 1
            If DotPos = 0 Then DotPos = Len(FullPath) + 1
            SplitPath = Mid(FullPath, SplitPos + 1, DotPos - SplitPos - 1)
        Case 2
            If DotPos = 0 Then DotPos = Len(FullPath)
            SplitPath = Mid(FullPath, DotPos)
        Case Else
            Err.Raise vbObjectError + 1, "SplitPath Function", "Invalid Parameter!"
        End Select
    End Function
       
    Function CleanFileName(StrText As String) As String
        Dim xStripChars As String
        Dim xLen As Integer
        Dim I As Integer
        xStripChars = "/\[]:=," & Chr(34)
        xLen = Len(xStripChars)
        StrText = Trim(StrText)
        For I = 1 To xLen
            StrText = Replace(StrText, Mid(xStripChars, I, 1), "")
        Next
        CleanFileName = StrText
    End Function
     
    Function GetFiles(xFldPath As String) As String()
        On Error Resume Next
        Dim xFile As String
        Dim xFileArr() As String
        Dim xArr() As String
        Dim I, x As Integer
        x = 0
        ReDim xFileArr(1)
        xFileArr(1) = xFldPath '& ""
        xFile = Dir(xFileArr(1) & "*.*")
        Do Until xFile = ""
             x = x + 1
             xFile = Dir
        Loop
        ReDim xArr(0 To x)
        x = 0
        xFile = Dir(xFileArr(1) & "*.*")
        Do Until xFile = ""
             xArr(x) = xFile
             x = x + 1
             xFile = Dir
        Loop
        GetFiles = xArr()
    End Function
     
    Sub MergeDoc(WdApp As Word.Application, xFileName As String, Doc As Document)
        Dim xNewDoc As Document
        Dim xSec As Section
        Set xNewDoc = WdApp.Documents.Open(FileName:=xFileName, Visible:=False)
        Set xSec = Doc.Sections.Add
        xNewDoc.Content.Copy
        xSec.PageSetup = xNewDoc.PageSetup
        xSec.Range.PasteAndFormat wdFormatOriginalFormatting
        xNewDoc.Close
    End Sub
    Any help will be much appreciated . Thanks

  2. #2
    Can anyone please help me in this? Thanks

  3. #3

    hi. Have you managed to fix thee code?

    Quote Originally Posted by RajOberoi View Post
    Hi guys,

    I got the following code which merges email messages and the attachments into one pdf file of the selected email and save it down on the shared folder. I want to do the folloiwng things :

    1. At the moment when it merges email message and attachments into pdf then in the pdf file attachments appear first and then at the bottom email message appear . I want it done the other way so email message on the top and then attacments at the bottom.

    2. The code ignores any pdf attachments or JPEG attachments in the email .

    3. My clients won't receive any excel attachments so I want to tidy up the code so it won't look for excel attachments.
    Public Sub MergeMailAndAttachsToPDF_New(MortANo As String)
        Dim xSelMails As MailItem
        Dim xFSysObj As FileSystemObject
        Dim xOverwriteBln As Boolean
        Dim xLooper As Integer
        Dim xEntryID As String
        Dim xNameSpace As Outlook.NameSpace
        Dim xMail As Outlook.MailItem
        Dim xExt As String
        Dim xSendEmailAddr, xCompanyDomain As String
        Dim xWdApp As Word.Application
        Dim xDoc, xNewDoc As Word.Document
        Dim I As Integer
        Dim xPDFSavePath As String
        Dim xPath As String
        Dim xFileArr() As String
        ' Dim xExcel As Excel.Application
        Dim xWb As Workbook
        Dim xWs As Worksheet
        Dim xTempDoc As Word.Document
        Dim strFileName As String
        On Error Resume Next
        If (Outlook.ActiveExplorer.Selection.Count > 1) Or (Outlook.ActiveExplorer.Selection.Count = 0) Then
             MsgBox "Please Select a email.", vbInformation + vbOKOnly
             Exit Sub
        End If
        Set xSelMails = Outlook.ActiveExplorer.Selection.Item(1)
        xEntryID = xSelMails.EntryID
        Set xNameSpace = Application.GetNamespace("MAPI")
        Set xMail = xNameSpace.GetItemFromID(xEntryID)
        xSendEmailAddr = xMail.SenderEmailAddress
        xCompanyDomain = Right(xSendEmailAddr, Len(xSendEmailAddr) - InStr(xSendEmailAddr, "@"))
        xOverwriteBln = False
        Set xExcel = New Excel.Application
        xExcel.Visible = False
        Set xWdApp = New Word.Application
        xExcel.DisplayAlerts = False
        strSaveFldr = GetPrivateProfileString32("U:\test.ini", "SaveFolder", "FolderName")
        strFileName = MortANo & "-" & DocType_Col1 & "-" & email & "-" & Environ("Username")
        xPDFSavePath = strSaveFldr & strFileName & ".pdf"
        If xPDFSavePath = "False" Then
            xExcel.DisplayAlerts = True
            xExcel.Quit
            xWdApp.Quit
            Exit Sub
        End If
        xPath = Left(xPDFSavePath, InStrRev(xPDFSavePath, ""))
        cPath = xPath & xCompanyDomain & ""
        yPath = cPath & Format(Now(), "yyyy") & ""
        mPath = yPath & Format(Now(), "MMMM") & ""
        If Dir(xPath, vbDirectory) = vbNullString Then
            MkDir xPath
        End If
        EmailSubject = CleanFileName(xMail.Subject)
        xSaveName = Format(xMail.ReceivedTime, "yyyymmdd") & "_" & EmailSubject & ".doc"
        Set xFSysObj = CreateObject("Scripting.FileSystemObject")
        If xOverwriteBln = False Then
            xLooper = 0
            Do While xFSysObj.FileExists(yPath & xSaveName)
                xLooper = xLooper + 1
                xSaveName = Format(xMail.ReceivedTime, "yyyymmdd") & "_" & EmailSubject & "_" & xLooper & ".doc"
            Loop
        Else
            If xFSysObj.FileExists(yPath & xSaveName) Then
                xFSysObj.DeleteFile yPath & xSaveName
            End If
        End If
        xMail.SaveAs xPath & xSaveName, olDoc
        If xMail.Attachments.Count > 0 Then
            For Each Atmt In xMail.Attachments
                xExt = SplitPath(Atmt.FileName, 2)
               If (xExt = ".docx") Or (xExt = ".doc") Or (xExt = ".docm") Or (xExt = ".dot") Or (xExt = ".dotm") Or (xExt = ".dotx") _
               Or (xExt = ".xlsx") Or (xExt = ".xls") Or (xExt = ".xlsm") Or (xExt = ".xlt") Or (xExt = ".xltm") Or (xExt = ".xltx") Then
                   atmtName = CleanFileName(Atmt.FileName)
                   atmtSave = strSaveFldr & Format(xMail.ReceivedTime, "yyyymmdd") & "_" & atmtName
                   Atmt.SaveAsFile atmtSave
               End If
            Next
        End If
        Set xNewDoc = xWdApp.Documents.Add("Normal", False, wdNewBlankDocument, False)
        Set xFilesFld = xFSysObj.GetFolder(xPath)
        xFileArr() = GetFiles(strSaveFldr)
        For I = 0 To UBound(xFileArr()) - 1
             xExt = SplitPath(xFileArr(I), 2)
             If (xExt = ".xlsx") Or (xExt = ".xls") Or (xExt = ".xlsm") Or (xExt = ".xlt") Or _
                (xExt = ".xltm") Or (xExt = ".xltx") Then  ' conver excel to word
                Set xWb = xExcel.Workbooks.Open(xPath & xFileArr(I))
                Set xTempDoc = xWdApp.Documents.Add("Normal", False, wdNewBlankDocument, False)
                Set xWs = xWb.ActiveSheet
                xWs.UsedRange.Copy
                xTempDoc.Content.PasteAndFormat wdFormatOriginalFormatting
                xTempDoc.SaveAs2 xPath & xWs.Name + ".docx", wdFormatXMLDocument
                xWb.Close False
                Kill xPath & xFileArr(I)
                xTempDoc.Close wdDoNotSaveChanges, wdOriginalDocumentFormat, False
             End If
        Next
        xExcel.DisplayAlerts = True
        xExcel.Quit
        xFileArr() = GetFiles(xPath)
        ' Merge Documents
        For I = 0 To UBound(xFileArr()) - 1
             xExt = SplitPath(xFileArr(I), 2)
             If (xExt = ".docx") Or (xExt = ".doc") Or (xExt = ".docm") Or (xExt = ".dot") Or (xExt = ".dotm") Or (xExt = ".dotx") Then
                 MergeDoc xWdApp, xPath & xFileArr(I), xNewDoc
                 Kill xPath & xFileArr(I)
             End If
        Next
        xNewDoc.Sections.Item(1).Range.Delete wdCharacter, 1
        xNewDoc.SaveAs2 xPDFSavePath, wdFormatPDF
        xNewDoc.Close wdDoNotSaveChanges, wdOriginalDocumentFormat, False
        xWdApp.Quit
        Set xMail = Nothing
        Set xNameSpace = Nothing
        Set xFSysObj = Nothing
        MsgBox "Merged successfully", vbInformation + vbOKOnly
    End Sub
     
    Public Function SplitPath(FullPath As String, ResultFlag As Integer) As String
        Dim SplitPos As Integer, DotPos As Integer
        SplitPos = InStrRev(FullPath, "/")
        DotPos = InStrRev(FullPath, ".")
        Select Case ResultFlag
        Case 0
            SplitPath = Left(FullPath, SplitPos - 1)
        Case 1
            If DotPos = 0 Then DotPos = Len(FullPath) + 1
            SplitPath = Mid(FullPath, SplitPos + 1, DotPos - SplitPos - 1)
        Case 2
            If DotPos = 0 Then DotPos = Len(FullPath)
            SplitPath = Mid(FullPath, DotPos)
        Case Else
            Err.Raise vbObjectError + 1, "SplitPath Function", "Invalid Parameter!"
        End Select
    End Function
       
    Function CleanFileName(StrText As String) As String
        Dim xStripChars As String
        Dim xLen As Integer
        Dim I As Integer
        xStripChars = "/\[]:=," & Chr(34)
        xLen = Len(xStripChars)
        StrText = Trim(StrText)
        For I = 1 To xLen
            StrText = Replace(StrText, Mid(xStripChars, I, 1), "")
        Next
        CleanFileName = StrText
    End Function
     
    Function GetFiles(xFldPath As String) As String()
        On Error Resume Next
        Dim xFile As String
        Dim xFileArr() As String
        Dim xArr() As String
        Dim I, x As Integer
        x = 0
        ReDim xFileArr(1)
        xFileArr(1) = xFldPath '& ""
        xFile = Dir(xFileArr(1) & "*.*")
        Do Until xFile = ""
             x = x + 1
             xFile = Dir
        Loop
        ReDim xArr(0 To x)
        x = 0
        xFile = Dir(xFileArr(1) & "*.*")
        Do Until xFile = ""
             xArr(x) = xFile
             x = x + 1
             xFile = Dir
        Loop
        GetFiles = xArr()
    End Function
     
    Sub MergeDoc(WdApp As Word.Application, xFileName As String, Doc As Document)
        Dim xNewDoc As Document
        Dim xSec As Section
        Set xNewDoc = WdApp.Documents.Open(FileName:=xFileName, Visible:=False)
        Set xSec = Doc.Sections.Add
        xNewDoc.Content.Copy
        xSec.PageSetup = xNewDoc.PageSetup
        xSec.Range.PasteAndFormat wdFormatOriginalFormatting
        xNewDoc.Close
    End Sub
    Any help will be much appreciated . Thanks

  4. #4
    Site Admin VBAX Wizard Aussiebear's Avatar
    Joined
    Dec 2005
    Location
    Queensland
    Posts
    5,495
    Location
    Maybe try this:

    Sub MergeEmailsAndAttachmentsToPDF()
        ' Configuration (Customize these)
        Dim sharedFolderPath As String
        sharedFolderPath = "\\your\shared\folder\path\" 
        ' Replace with your shared folder path
        Dim pdfFileName As String
        pdfFileName = "MergedEmail.pdf" 
        ' You can make this dynamic if needed
        Dim outlookApp As Object, outlookMail As Object
        Dim fso As Object, pdfFilePath As String
        Dim i As Long, attachment As Object
        Dim wordApp As Object, wordDoc As Object
        Dim tempFilePath As String
        ' Create necessary objects
       Set outlookApp = Application
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set wordApp = CreateObject("Word.Application")
       wordApp.Visible = False 
        ' Keep Word hidden
        ' Get the selected email (you can adapt this to loop through multiple emails)
        If outlookApp.Selection.Count = 0 Then
            MsgBox "No email selected.", vbExclamation
            Exit Sub
        End If
        Set outlookMail = outlookApp.Selection(1)
        ' Create a temporary Word document
        tempFilePath = Environ("TEMP") & "\temp_email.docx" 
        ' Use a temporary file
        Set wordDoc = wordApp.Documents.Add
        wordDoc.SaveAs2 tempFilePath, 16 
        ' Save as .docx
        ' Add email body to Word document
        With wordDoc.Content
            .InsertAfter outlookMail.Subject & vbCrLf & vbCrLf 
            ' Add subject
            .InsertAfter "From: " & outlookMail.SenderEmailAddress & vbCrLf
            .InsertAfter "Sent: " & outlookMail.SentOn & vbCrLf & vbCrLf
            .InsertAfter outlookMail.Body & vbCrLf & vbCrLf 
            ' Add body    .InsertBreak wdPageBreak 
            ' Page break for attachments section
            .InsertAfter "Attachments:" & vbCrLf & vbCrLf
        End With
        ' Add attachments to Word document
        For Each attachment In outlookMail.Attachments
            attachment.SaveAsFile Environ("TEMP") & "\" & attachment.FileName 
            ' Save attachment temporarily
            wordDoc.Content.InsertAfter attachment.FileName & vbCrLf 
            ' List attachment names
        Next attachment
        ' Convert Word document to PDF
        pdfFilePath = sharedFolderPath & pdfFileName
        wordDoc.ExportAsFixedFormat pdfFilePath, wdExportFormatPDF 
        ' Convert to PDF
        ' Clean up temporary files (Word doc and attachments)
        wordDoc.Close 
        wdSaveOptions.wdDoNotSaveChanges
        fso.DeleteFile tempFilePath, True 
        ' Delete the temporary Word file
        For Each attachment In outlookMail.Attachments
            fso.DeleteFile Environ("TEMP") & "\" & attachment.FileName, True 
            ' Delete temporary attachments
        Next attachment
        ' Close Word application
        wordApp.Quit
        ' Release objects (important for memory management)
        Set outlookMail = Nothing
        Set outlookApp = Nothing
        Set fso = Nothing
        Set wordDoc = Nothing
        Set wordApp = Nothing
        Set attachment = Nothing
        MsgBox "Email and attachments merged to PDF and saved to: " & pdfFilePath, vbInformation
    End Sub
    Remember To Do the Following....
    Use [Code].... [/Code] tags when posting code to the thread.
    Mark your thread as Solved if satisfied by using the Thread Tools options.
    If posting the same issue to another forum please show the link

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •