1
votes

I am trying to loop through a set of worksheets, save each of them as a separate workbook, and then send them as attachment by mail.

However when running the below code, I end up with error 287 triggered by .Send. I have outlook open, so that is not the problem. If I change .Send to .Display, the mails are generated as drafts as displayed properly with the correct sheet attached.

Sub SendWorksheetsByMail()
    Dim wb As Workbook
    Dim destinationWb As Workbook
    Dim OutApp As Outlook.Application
    Dim OutMail As Outlook.MailItem

    Set wb = Workbooks("Test.xlsm")

    Application.EnableEvents = False
    Application.ScreenUpdating = False

    For Each ws In wb.Worksheets
        'Ignore Summary and Config
        If ws.Name <> "Summary" And ws.Name <> "Config" Then
            'On Error Resume Next
            Set OutApp = CreateObject("Outlook.Application")
            Set OutMail = OutApp.CreateItem(olMailItem)

            ws.Copy
            Set destinationWb = ActiveWorkbook
            destinationWb.SaveAs "C:\****************\" & ws.Name & ".xlsx", FileFormat:=51
            With OutMail
                .To = "*******************"
                .Subject = "Test"
                .Body = "Test"
                .Attachments.Add destinationWb.FullName
                .Send
            End With

            Set OutMail = Nothing
            Set OutApp = Nothing
        End If
    Next ws

    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub

Edit: "It also fails even without an attachment. Essentially generating a message containing only the subject and text "test"."

Any suggestions for how to solve this? It would save a lot of time to not have to click Send for each individual mail, as the number of mails to send could potentially become quite large.

4
Have you tried .Save before .Send? Just a thought.David Zemens
Just curious, why include OutMail at the line OutMail.Attachments.Add destinationWb.FullName when it's in With OutMail?BruceWayne
Typo, had written it without with to begin with, and thought it was the attachement causing problems at first, so took that part out. And then just pasted it without changing it. Works both wazs though. But will update code above.johankr
See here -- there may be a lag while Outlook is attaching the file, and you may need to control for that lag. Or see here: Outlook security settings may prevent sending mail via automation.David Zemens
@DavidZemens allready tried the first method, and it still fails when I step through with F8. It also fails even without an attachment. Essentially generating a message containing only the subject and text "test". I also think it is likely to be a security issue. The question is how to get around it. Since I need to send attachements, the first solution will not work, and for the second, I am unsure I will get the permission to install Redemption.johankr

4 Answers

0
votes

This is what I used to send a mail with attachment to multiple addresses, listed in column H while the name of the receiver is listed in another column

Sub Mail()
'####################################
'###    Save the file as pdf   ######
'####################################
Dim FSO As Object
Dim s(1) As String
Dim sNewFilePath As String

Set FSO = CreateObject("Scripting.FileSystemObject")
s(0) = ThisWorkbook.FullName

If FSO.FileExists(s(0)) Then
    '//Change Excel Extension to PDF extension in FilePath
    s(1) = FSO.GetExtensionName(s(0))
    If s(1) <> "" Then
        s(1) = "." & s(1)
        sNewFilePath = Replace(s(0), s(1), ".pdf")

        '//Export to PDF with new File Path
        ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=sNewFilePath, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
    End If
Else
    '//Error: file path not found
    MsgBox "Error: this workbook may be unsaved.  Please save and try again."
End If

Set FSO = Nothing
'##########################################
'###    Attach the file and mail it  ######
'##########################################
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim cell As Range
Dim FileCell As Range
Dim rng As Range

With Application
    .EnableEvents = False
    .ScreenUpdating = False
End With

Set sh = Sheets("sheet")

Set OutApp = CreateObject("Outlook.Application")
For Each cell In sh.Columns("H").Cells.SpecialCells(xlCellTypeConstants)

    If cell.Value Like "?*@?*.?*" Then
        Set OutMail = OutApp.CreateItem(0)

        With OutMail
            .to = cell.Value
            .Subject = "file delivery "
            .Body = "Hi " & cell.Offset(0, -3).Value & " here is my file"
            .Attachments.Add sNewFilePath


            .Send  'Or use .Display
        End With

        Set OutMail = Nothing
    End If
Next cell

Set OutApp = Nothing
With Application
    .EnableEvents = True
    .ScreenUpdating = True
End With
End Sub
0
votes

Try .GetInspector before .Send. It would be like .Display without displaying.

0
votes

I found a two step soultion. By changing .Send to .Display in the code above, the messages will be created as drafts in outlook and Displayed. If you do not want an extra window per e-mail, changing .Display to .Save will just put them in the draft folder.

Then I can use a macro written in Outlook to send all drafts. Code based on solution found at the mrexcel forums.

I also discovered after reading this answer on SO that the drafts folder can not be selected when running the macro.

Hope this helps others running into the same problem.

Public Sub SendDrafts()

    Dim lDraftItem As Long
    Dim myOutlook As Outlook.Application
    Dim myNameSpace As Outlook.NameSpace
    Dim myFolders As Outlook.Folders
    Dim myDraftsFolder As Outlook.MAPIFolder

    'Send all items in the "Drafts" folder that have a "To" address filled in.

    'Setup Outlook
    Set myOutlook = Outlook.Application
    Set myNameSpace = myOutlook.GetNamespace("MAPI")
    Set myFolders = myNameSpace.Folders

    'Set Draft Folder.
    Set myDraftsFolder = myFolders("*******@****.com").Folders("Drafts")

    'Loop through all Draft Items
    For lDraftItem = myDraftsFolder.Items.Count To 1 Step -1
        'Check for "To" address and only send if "To" is filled in.
        If Len(Trim(myDraftsFolder.Items.Item(lDraftItem).To)) > 0 Then
            'Send Item
            myDraftsFolder.Items.Item(lDraftItem).Send
        End If
    Next lDraftItem

    'Clean-up
    Set myDraftsFolder = Nothing
    Set myNameSpace = Nothing
    Set myOutlook = Nothing

End Sub

Might be a good idea to add code that differntiates the messages you are trying to send from other drafts that may already be in the folder.

Would still prefere a one step solution, so I will wait with marking this as a solution.

0
votes

I finally found the answer googling a lot.

The problem is not with the .send method, but rather the session object.

Replace Set myOutlook = Outlook.Application with Set objOutlook = ThisOutlookSession

This ensures that your macro is using the same outlook session that is open. Atleast it did the trick for me