Forum Discussion

JonnShea's avatar
JonnShea
Copper Contributor
May 31, 2023

VBA - Attaching Files embedded in a worksheet to an email through VBA

Hi everyone, I'm going to start off by saying I'm brand new to VBA coding.  So please bear with me. 

 

I have an excel document that I am using VBA to send out emails based on the data in a worksheet. I have this set up and it works.  The problem I have is when I try to Include 8 attachments. The attachments are always the same and never change.

 

Multiple people use this document and will send emails with the 8 attachments, so I need the files in either a centralized location to store the attachments or somewhere we can all access.  I found a youtube tutorial that helped me, It suggested to store the files in a separate worksheet named "HiddenSheet"  I was able to add a file in cell A1 of the hidden sheet to attach, but I'm having difficulty attaching all 8 files, which are stored in cells A1:A8.  No matter what I've tried, the files are never included as an attachment. 

 

Any help would be great, or any alternate suggestions so that everyone can send an email from the excel.  

 

Below is the code I've made. Again I'm new so I apologize if it's bad.  In the code, I have 3 attachment Tests in there:

 

Test 1 - Using a file path which works but not everyone has access to the same location

Test 2 - Was taking one word document file and embedding it in the HiddenSheet in cell A1 which works but it did not work the same way when trying to do this 8 times.

Test 3 - Taking 8 files, embedding them in the HiddenSheet in cells A1:A8 which does not work. 

 

Sub SaveAsDraft()

 

'Declare variables
Dim objOutlook As Outlook.Application
Dim objMail As Outlook.MailItem
Dim strTo As String
Dim strCC As String
Dim strSubject As String
Dim strBody As String
Dim strSharedMailbox As String
Dim strEmailAddress As String
Dim attachmentCell As Range
Dim hiddenSheet As Worksheet
Set hiddenSheet = ThisWorkbook.Worksheets("HiddenSheet")
Dim fileToAttach As String
Dim fileType As String
Dim i As Integer

 

'Attachments as String TEST 1
'Dim strAttachment1 As String
'Dim strAttachment2 As String
'Dim strAttachment3 As String
'Dim strAttachment4 As String
'Dim strAttachment5 As String
'Dim strAttachment6 As String
'Dim strAttachment7 As String
'Dim strAttachment8 As String

'Set variables
strTo = strEmailAddress
strSharedMailbox = "SharedMailbox@_____.com"
strCC = "Boss@____.com; Me@____.com"
strSubject = "This is the subject of the email"
strBody = "This is the body of the email" & " " & "Signed, ________"


'strAttachmentName = "____.docx" ' Name of the attachment <--- TEST 2

 

'Attachments File paths TEST 1
'strAttachment1 = "C:\___.pdf"
'strAttachment2 = "C:\___.pdf"
'strAttachment3 = "C:\___.pdf"
'strAttachment4 = "C:\___.pdf"
'strAttachment5 = "C:\___.xlsm"
'strAttachment6 = "C:\___.xlsm"
'strAttachment7 = "C:\___.xlsx"
'strAttachment8 = "C:\___.mp4"

 

'Create an instance of Outlook
Set objOutlook = New Outlook.Application

 

'Get the email addresses and check cell color
i = 5
Do While Len(ActiveSheet.Cells(i, 22).Value) > 0 ' Check if cell in column V is not empty
' Check cell color
If ActiveSheet.Cells(i, 22).Interior.Color = RGB(255, 255, 0) Then ' RGB(255, 255, 0) represents yellow color
' Set the email address
strEmailAddress = ActiveSheet.Cells(i, 22).Value

'Create a new email
Set objMail = objOutlook.CreateItem(olMailItem)

 

'Set the email properties
objMail.To = strEmailAddress
objMail.SentOnBehalfOfName = strSharedMailbox
objMail.CC = strCC
objMail.Subject = strSubject
objMail.Body = strBody

 

' Add the attachments - TEST 3
For Each attachmentCell In hiddenSheet.Range("A1:A8")
If attachmentCell.Value <> "" Then
objMail.Attachments.Add attachmentCell.Value, olByValue
End If
Next attachmentCell

 

' Save the attachment data to a temporary file <---- TEST 2
'Dim tempFilePath As String
'tempFilePath = "C:\Temp\" & strAttachmentName
'Open tempFilePath For Binary Access Write As #1
'Put #1, , attachmentData
'Close #1

 

' Add the attachment from the temporary file <---- TEST 2
'objMail.Attachments.Add tempFilePath, olByValue, 1, strAttachmentName

 

'Add the attachments TEST 1
'objMail.Attachments.Add strAttachment1
'objMail.Attachments.Add strAttachment2
'objMail.Attachments.Add strAttachment3
'objMail.Attachments.Add strAttachment4
'objMail.Attachments.Add strAttachment5
'objMail.Attachments.Add strAttachment6
'objMail.Attachments.Add strAttachment7
'objMail.Attachments.Add strAttachment8

 

'Draft email
objMail.Close (olSave)

 

'Close the object
Set objMail = Nothing
End If

 

'Move to the next row
i = i + 1
Loop

 

'Show confirmation message to user
MsgBox "Done", vbInformation

 

End Sub

2 Replies

  • SnowMan55's avatar
    SnowMan55
    Bronze Contributor

    JonnShea 

    I do not see an obvious error in your code. I cleaned it up some (see below), and have it working for me, for eight files (of seven different file types).  I did not use the CC feature.  I also added error handling code, as you say this is/will be used by others.


    Are you perhaps using a very old version of Outlook? (My version of Outlook is 2305, referenced by the VBA project via the "Microsoft Outlook 16.0 Object Library").


    Do any of the files exceed your attachment size limit? Or do they in combination exceed the limit?


    You do not mention any error message, so I'll assume there was none.  So in the code below, I capture a reference to each generated Attachment object, and include a Debug.Assert statement immediately after; execution will stop if such an object is not created.

     

    Sub CreateDrafts()
    '   This macro generates draft emails for the recipients in column
    '       V (22), starting from row 5 down until a blank cell is
    '       encountered, but only for cells with email addresses that
    '       are highlighted in (pure) yellow.
    
        'Declare variables
        Dim strActionInProgress As String
        Dim objRecipientSheet   As Worksheet
        Dim objAttachmentSheet  As Worksheet
        Dim objOutlook  As Outlook.Application
        Dim objMail     As Outlook.MailItem
        Dim strTo       As String
        Dim strCC       As String
        Dim strSubject  As String
        Dim strBody     As String
        Dim strSharedMailbox    As String
        Dim strEmailAddress     As String   'for a recipient
        Dim rngAttachmentCell   As Range
        Dim strFileToAttach As String
        Dim objAttachment   As Outlook.Attachment
        Dim in4Row  As Long '[Integer only goes up to 32,767]
        
        '----   Capture a reference to the active worksheet.  (This
        '       avoids problems if the user clicks on a different sheet
        '       while this macro is executing.)
        Set objRecipientSheet = ActiveSheet
        
        '----
        On Error GoTo CreateDraft_ErrHndlr
        strActionInProgress = "gathering info"
        Set objAttachmentSheet = ThisWorkbook.Worksheets("HiddenSheet")
        
        'Set variables
        strTo = strEmailAddress
        strSharedMailbox = "SharedMailbox@_____.com"
        strCC = "Boss@____.com; Me@____.com"
        strSubject = "This is the subject of the email"
        strBody = "This is the body of the email" & " " _
                & vbCrLf & "Signed, ________"
        
        '----   Create an instance of Outlook.
        strActionInProgress = "opening Outlook"
        Set objOutlook = New Outlook.Application
        
        '----   Generate draft emails for cells that qualify.
        in4Row = 5   'the starting row
        ' Check if cell in column V is not empty
        Do While Len(objRecipientSheet.Cells(in4Row, 22).Value) > 0
            ' Check the cell's backgound color.
            If objRecipientSheet.Cells(in4Row, 22).Interior.Color _
                    = RGB(255, 255, 0) Then  '= yellow
                ' Grab the email address.
                strActionInProgress = "getting recipient info"
                strEmailAddress = objRecipientSheet.Cells(in4Row, 22).Value
                
                'Create a new email.
                strActionInProgress = "creating a MailItem object"
                Set objMail = objOutlook.CreateItem(olMailItem)
                
                'Set the MailItem properties.
                strActionInProgress = "populating the Mail object"
                objMail.To = strEmailAddress
                objMail.SentOnBehalfOfName = strSharedMailbox
                objMail.CC = strCC
                objMail.Subject = strSubject
                objMail.Body = strBody
                
                ' Add the attachments - TEST 3
                strActionInProgress = "accessing file list"
                For Each rngAttachmentCell In objAttachmentSheet.Range("A1:A8")
                    strActionInProgress = "accessing file list"
                    strFileToAttach = rngAttachmentCell.Value
                    If strFileToAttach <> "" Then
                        strActionInProgress = "attaching a file"
                        Set objAttachment = objMail.Attachments.Add( _
                                strFileToAttach, olByValue)
                        Debug.Assert (objAttachment Is Nothing) = False
                    End If
                Next rngAttachmentCell
                
                'Draft email
                strActionInProgress = "saving the draft"
                objMail.Close olSave
                
                'Release the object reference.
                Set objMail = Nothing
            End If
            
            'Advance to the next row.
            in4Row = in4Row + 1
        Loop
        
        'Show confirmation message to user
        MsgBox "Done", vbInformation
    CreateDraft_Exit:
        '   Dereference external objects. [less likely important for
        '   internal objects]
        Set objAttachment = Nothing
        Set objMail = Nothing
        Set objOutlook = Nothing
        
        Exit Sub
    
    CreateDraft_ErrHndlr:
        Dim in4ErrorCode    As Long
        Dim strErrorDescr   As String
        Dim strMessage  As String
        Dim in4UserResponse As VbMsgBoxResult
        '  --   Capture information about the error (exception).
        in4ErrorCode = Err.Number
        strErrorDescr = Err.Description
        '  --   Notify the user.
        strMessage = "Error " & CStr(in4ErrorCode) & " occurred while " _
                & strActionInProgress
        If Len(strEmailAddress) > 0 Then
            strMessage = strMessage & " for " & strEmailAddress
        End If
        strMessage = strMessage & ":" & vbCrLf & strErrorDescr _
                & vbCrLf & vbCrLf & strFileToAttach
        in4UserResponse = MsgBox(strMessage, vbExclamation Or vbRetryCancel _
                , "CreateDrafts")
        '  --   Recover from the error.
        If in4UserResponse = vbRetry Then
            Debug.Assert False  '...for debugging only
            Resume
        ElseIf in4UserResponse = vbCancel Then
            Resume CreateDraft_Exit
        End If
    End Sub

     

    • JonnShea's avatar
      JonnShea
      Copper Contributor
      I checked outlook and it says I'm using version 2208, with 16.0 object library, not sure if that's causing the attachments not to attach.

      I also tried your code verbatim and same thing occurs where the emails are saved in outlook without any of the attachments, and no error popup either. Each file is small enough to be used as an attachment, they are all different file types (pdf, xls, xlsm, mp4) I'm able to attach them if they are stored somewhere first, like c:\temp but they wont attach if they are embedded in a hidden sheet in excel. Just to humor myself, I've clicked on each file in the hidden sheet and they all open.

      I really appreciate your help with this. it's truly mindboggling why they will not attach!

Resources