I have Excel VBA code that generates an Outlook e-mail with an attachment.
This worked in Windows 8.1 but does not work in Windows 10. I have stepped through the macro, and it gets all the way to the end, generates the e-mail, then fails on the OutMail.Send command. The error is
Runtime error 287 - Application-defined or object-defined error
Here is the code.
Sub batchallocationemail()
'define email & pdf
Dim IsCreated As Boolean
Dim PdfFile As String, Title As String
Dim OutlApp As Object
Dim OutMail As Object
'
' print allocation Macro
'define worksheets
Dim ws As Worksheet
Set ws = Sheets("Caseworkers")
Dim ws2 As Worksheet
Set ws2 = Sheets("Allocation Sheet")
'define range
Dim NameRange As Range
Dim NameRange2 As Range
Dim x As Range
Dim z As Range
Set z = ws2.Range("B1")
Set NameRange = ws.Range("A1:C69")
Set NameRange2 = ws.Range("A2:A69")
Set NameRange3 = ws.Range("C2:C69")
'Selects name from list and pastes into allocation
ws.Select
NameRange.AutoFilter Field:=2, Criteria1:="In"
For Each x In NameRange2.SpecialCells(xlCellTypeVisible)
x.Copy
ws2.Select
Range("B1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
ws2.Select
'CONVERTS ACTIVE SHEET TO PDF AND EMAILS IT
' Define Title
Title = Range("B1").Value
' Define PDF filename
Title = "Allocation Sheet for " & Range("B1").Value
PdfFile = CreateObject("WScript.Shell").SpecialFolders("Desktop") & "\" & Title & ".pdf"
' Export activesheet as PDF
With ActiveSheet
.ExportAsFixedFormat Type:=xlTypePDF, Filename:=PdfFile, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
End With
' Use already open Outlook if possible
On Error Resume Next
Set OutlApp = GetObject(, "Outlook.Application")
If Err Then
Set OutlApp = CreateObject("Outlook.Application")
IsCreated = True
End If
OutlApp.Visible = True
On Error GoTo 0
' Prepare e-mail with PDF attachment
Set OutMail = OutlApp.CreateItem(0)
With OutMail
' Prepare e-mail
OutMail.Subject = Title
OutMail.To = x.Offset(0, 2).Value ' <-- Put email of the recipient here
OutMail.CC = x.Offset(0, 3).Value ' <-- Put email of 'copy to' recipient here
OutMail.Body = "Hello," & vbLf & vbLf _
& "Please see your attached allocation sheet in PDF format." & vbLf & vbLf _
& "Kind Regards," & vbLf _
& Application.UserName & vbLf & vbLf
OutMail.Attachments.Add PdfFile
' Try to send
Application.Visible = True
OutMail.Display
OutMail.Send
End With
' Quit Outlook if it was not already open
If IsCreated Then OutlApp.Quit
' Release the memory of object variable
Set OutMail = Nothing
Set OutlApp = Nothing
Next x
End Sub
sorry about this, i think I have fixed it. I posted this earlier after looking through for hours last night but I seem to have got it. Instead of .Send i used Application.SendKeys "%s" which is a shortcut. This seems to send the e-mail properly.
Related
I have an excel file with a button, which when the user click on it, should be opened an outlook mailbox with specific excel table, several text lines at the beginning of the mail body (before the table), and my default signature (as defined in outlook) should be there too.
When i run my code, only the excel table is appaering on the mail body (the required text before the table and the signature is missing).
Please your help, thanks a lot
here is my code:
Sub SendCA_list()
Dim oApp As Object
Set oApp = CreateObject("Outlook.Application")
Dim oMail As Object
Set oMail = oApp.CreateItem(olMailItem)
'select the table
Range("Table4[[#Headers],[Department]]").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
ActiveWindow.SmallScroll Down:=-129
Selection.Copy
With oMail
.Body = "Hi All," & vbNewLine & "Enclosed below open A/Is list from last ISO Internal Audit. Please review and perform the required corrective actions." & vbNewLine & "Please update status and details in the audit report until next week."
Dim wordDoc As Object
Set wordDoc = oMail.GetInspector.WordEditor
wordDoc.Range.Paste
.Display
End With
u can try like this.
it checks where the inserted text stops and paste the data after.
With OutMail
.Body = "Hi All," & vbNewLine & "Enclosed below open A/Is list from last ISO Internal Audit. Please review and perform the required corrective actions." & vbNewLine & "Please update status and details in the audit report until next week." & vbCrLf
Dim wordDoc As Object
Set wordDoc = OutMail.GetInspector.WordEditor
wordDoc.Application.Selection.Start = Len(.Body)
wordDoc.Application.Selection.End = Len(.Body)
wordDoc.Application.Selection.Paste
Display
End With
The problem was that i used .body instead of .htmlbody.
Here is the correct code:
Sub SendCA_list()
Dim oApp As Object
Set oApp = CreateObject("Outlook.Application")
Dim oMail As Object
Set oMail = oApp.CreateItem(olMailItem)
Range("Table4[[#Headers],[Department]]").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
ActiveWindow.SmallScroll Down:=-129
Selection.Copy 'select and copy the required table
Dim rng As Range
Set rng = Selection.SpecialCells(xlCellTypeVisible) 'range of selected table
With oMail
.HtmlBody = "Hi All," & "<br>" & "Enclosed below open A/Is list from last ISO Internal Audit. Please review and perform the required corrective actions." & "<br>" & "Please update status and details in the audit report until next week."
Dim wordDoc As Object
Set wordDoc = oMail.GetInspector.WordEditor
oMail.HtmlBody = .HtmlBody & "<br>" & RangetoHTML(rng) 'this is a function which paste the selected range to outlook mail in html format
.Display
End With
End Sub
Function for insert the range from excel to html body mail:
Function RangetoHTML(rng As Range)
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteAllUsingSourceTheme, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML1 = ts.ReadAll
ts.Close
RangetoHTML1 = Replace(RangetoHTML1, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
This year I inherited support of about a dozen accdb applications in Office 2010 Win 7 that often manipulate external excel files.
I keep getting the same error scenario. It is in my vba for excel commands,
but only AFTER the first iteration of a loop. It always works fine the first time through. Seems to have something to do with how I am identifying the objects. I've read multiple articles on best practices for working with the objects and the specific error but nothing has translated into a solution. Can someone ELI5 what I am doing wrong?
In the example below it is throwing the error early in the second iteration at the Range("A1").Select command.
Code:
Sub runCleanAndImportUnpre()
Dim strFolder As String
Dim strTableDest As String
strTableDest = "Unpresented_EOD_Import"
strFolder = "C:\Users\lclambe\Projects\Inputs\test2"
Call CleanAndImportUnpresentedInAGivenFolder(strTableDest, strFolder)
End Sub
Function CleanAndImportUnpresentedInAGivenFolder(strTable As String, strFolder As String)
' Function that opens files in a folder, cleans them up and saves them.
Dim myfile
Dim mypath
Dim strPathFileName As String
Dim i As Integer
'Call ClearData(strTable)
'if it needs a backslash on the end, add one
If Right(strFolder, 1) <> "\" Then
strFolder = strFolder & "\"
End If
mypath = strFolder
ChDir (strFolder)
myfile = Dir(mypath)
ChDir (mypath)
myfile = Dir("")
i = 1
Do While myfile <> ""
'Format the excel report
strPathFileName = mypath & myfile
'use for unpresented
Call formatExcelUnPresentedForImport(strPathFileName)
i = i + 1
myfile = Dir()
Loop
End Function
Function formatExcelUnPresentedForImport(filePath As String)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Note:
' Called from CleanAndImportUnpresentedInAGivenFolder when
' importing Unpresented reports
'
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error GoTo formatExcelUnPresentedForImport_Error
Dim strFilePath As String
Dim strReportType As String
Dim i As Integer
Dim iTotal_Row
Dim Lastrow As Long
Dim iCol As Integer
Dim appExcel As excel.Application
Dim wkb As excel.Workbook
Dim sht As Worksheet
Dim rng As Range
strReportType = reportType
strFilePath = filePath
Set appExcel = New excel.Application
appExcel.Visible = False
'Define the worksheet
Set wkb = appExcel.Workbooks.Open(strFilePath, ReadOnly:=False)
'Turn off error msg: "minor loss of fidelity" if you are sure no data will be lost
wkb.CheckCompatibility = False
'Expand Column to avoid scientific notation
appExcel.Columns("A:A").EntireColumn.AutoFit
'Find last row
'FAILS HERE ON SECOND ITERATION OF LOOP:
Range("A1").Select
ActiveCell("A1").Select
Selection.End(xlDown).Select
'Delete the last 3 rows of totals
ActiveCell.offset(-2, 0).Select
Selection.EntireRow.Delete
Selection.EntireRow.Delete
Selection.EntireRow.Delete
'Add a TRIM of Cash Amount Field2 at column L
Range("L2").Select
ActiveCell.FormulaR1C1 = "=TRIM(RC[-9])"
Range("L2").Select
'Copy it to rest of cells to bottom
Selection.Copy
Lastrow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
Selection.AutoFill Destination:=Range("L2:L" & Lastrow), Type:=xlFillDefault
Range("L2:L" & Lastrow).Select
'Delete original unformatted unpresented
Selection.Copy
ActiveSheet.Paste
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
'Delete all the rows except Unpresented
Range("B:B,C:C,D:D,E:E,F:F,G:G,H:H,I:I,J:J,K:K").Select
Range("K1").Activate
Selection.Delete Shift:=xlToLeft
'Add a Header
Range("B1").Select
ActiveCell.FormulaR1C1 = "Unpresented"
wkb.Save
wkb.Close
appExcel.Quit
Set wkb = Nothing
Set appExcel = Nothing
On Error GoTo 0
Exit Function
formatExcelUnPresentedForImport_Error:
Set wkb = Nothing
Set appExcel = Nothing
strMessage = "Error " & err.Number & " (" & err.Description & ") in procedure formatExcelUnPresentedForImport of Module modExternalExcelClean."
strMessage = strMessage & " Application will stop processing now." & vbNewLine
strMessage = strMessage & "Please note or copy this error message and contact application developer for assistance."
MsgBox strMessage, vbCritical + vbOKOnly, "Error"
End
End Function
Just guessing that you are not iterating through an Excel file the second time, thus it throws an error. To debug it in ELI5 style, change your code like this:
Do While myfile <> ""
MsgBox myFile
'Format the excel report
strPathFileName = mypath & myfile
'use for unpresented
Call formatExcelUnPresentedForImport(strPathFileName)
i = i + 1
myfile = Dir()
Loop
and pay attention to the MsgBox every time. Is it showing what you think it should be showing?
I had search all over of this question and still not get the exact codes for it.
I need to copy the color of the pivot table from excel to outlook body. When running the code i got the format but the only problem is the color of the table is turning into black and grey.
Please help me to figure it out how to put the exact color that i need.
This is my codes:
Sub AUTO_MAIL()
Dim rng As Range, rng2 As Range, rng3 As Range, rng4 As Range, sub1 As Range, sub2 As Range, sub3 As Range, sub4 As Range
Dim OutApp As Object
Dim OutMail As Object
Set rng = Nothing
On Error Resume Next
' Only send the visible cells in the selection.
Set rng = Sheets("Data Entry").PivotTables(1).TableRange1
Set rng2 = Sheets("ACN Workflow").PivotTables(1).TableRange1
Set rng3 = Sheets("L'Oreal Workflow").PivotTables(1).TableRange1
Set rng4 = Sheets("MTD Volume").PivotTables(1).TableRange1
Set sub1 = Sheets("Data Entry").Range("A1:E1").SpecialCells(xlCellTypeVisible)
Set sub2 = Sheets("ACN Workflow").Range("A1:G1").SpecialCells(xlCellTypeVisible)
Set sub3 = Sheets("L'Oreal Workflow").Range("A1:G1").SpecialCells(xlCellTypeVisible)
Set sub4 = Sheets("MTD Volume").Range("A1:B1").SpecialCells(xlCellTypeVisible)
If rng Is Nothing Then
MsgBox "The selection is not a range or the sheet is protected. " & _
vbNewLine & "Please correct and try again.", vbOKOnly
Exit Sub
End If
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = ""
.CC = ""
.BCC = ""
.Subject = "Step+ Volume Tracker, Data Entry/Workflow Ageing Report and Rejection Report |"
.HTMLBody = "<b>Dear All,</b><br><br>" & "Please see below summary of invoices and links to the <b>Volume Tracker</b> and <b>Ageing Report</b> (Data Entry and Workflow).<br>" & RangetoHTML(sub4) & vbCrLf & RangetoHTML(rng4) & vbCrLf & RangetoHTML(sub3) & vbCrLf & RangetoHTML(rng3) & vbCrLf & RangetoHTML(sub2) & vbCrLf & RangetoHTML(rng2) & vbCrLf & RangetoHTML(sub1) & vbCrLf & RangetoHTML(rng)
' In place of the following statement, you can use ".Display" to
' display the e-mail message.
.display
End With
On Error GoTo 0
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2013
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "\" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
rng.SpecialCells(xlCellTypeVisible).Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.readall
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
You will have to tweak the code a bit which should look something like this:
Sub due()
Dim ol As Object 'Outlook.Application
Dim olEmail As Object 'Outlook.MailItem
Dim olInsp As Object 'Outlook.Inspector
Dim wd As Object 'Word.Document
Dim rCol As Collection, r As Range, i As Integer
'/* if outlook is running use GO, create otherwise */
Set ol = GetObject(Class:="Outlook.Application")
Set olEmail = ol.CreateItem(0) 'olMailItem
Set rCol = New Collection
With rCol
.Add Sheet1.Range("A1:B6") '/* add your ranges the same sequence */
.Add Sheet2.Range("A1:B6") '/* as you want them added in the body */
End With
With olEmail
.To = ""
'/* bonus basic html */
.HTMLBody = "<html><body style=""font-family:calibri"">" & _
"<p><b>Dear Deer,</b><br><br> She see seas." & _
"</p></body></html>"
Set olInsp = .GetInspector
If olInsp.EditorType = 4 Then 'olEditorWord
Set wd = olInsp.WordEditor
For i = 1 To rCol.Count '/* iterate all ranges */
Set r = rCol.Item(i): r.Copy
wd.Range.InsertParagraphAfter
wd.Paragraphs(wd.Paragraphs.Count).Range.PasteAndFormat 16
'16 - wdFormatOriginalFormatting
Next
End If
wd.Range.InsertParagraphAfter
wd.Paragraphs(wd.Paragraphs.Count).Range.Text = "Regards, Patricia"
wd.Paragraphs.Last.Range.Sentences.Last.Font.Bold = True
.Display
End With
End Sub
In case you want to do more, you will have to read more about Word VBA. This is just a sample on what you can do with Outlook's Word Editor.
The list of sheets is specified in the names range "SaveList", which takes some as worksheets and some as charts (full page ones) but it falls over with
run-time error 13 "type mismatch"
Routine code below
Sub SaveFile()
'Recalc Sheets prior to saving down
A = MsgBox("Do you want to Save the Performance Reports?", vbOKCancel)
If A = 2 Then Exit Sub
Dim SaveSheets As Variant
Dim strFilename As String
Dim sheetListRange As Range
Dim sheetName As Variant
Dim wksheet As Variant
Dim wkbSrc As Workbook
Dim wkbNew As Workbook
Dim wksNew As Worksheet
Dim wksSrc As Worksheet
Dim i As Integer
Dim OutApp As Object
Dim OutMail As Object
Dim v As Variant
Dim Jimmy As Variant
'On Error GoTo ErrorHandler
strFilename = Worksheets("Control").Range("SavePath").Value & "Ergonomie_Consultants_Performance_" & Format$(Now(), "YYYYMMDD") & ""
v = strFilename
Set sheetListRange = Worksheets("Control").Range("SaveList")
Set wkbSrc = ActiveWorkbook
Set wkbNew = Workbooks.Add
i = 0
For Each sheetName In sheetListRange
If sheetName = "" Then GoTo NEXT_SHEET
For Each wksheet In wkbSrc.Sheets
If wksheet.Name = sheetName Then
i = i + 1
wksheet.Copy Before:=wkbNew.Sheets(i)
Set wksNew = ActiveSheet
With wksNew
.Cells.Select
.Cells.Copy
.Cells(1, 1).PasteSpecial Paste:=xlPasteValues
.Cells(1, 1).PasteSpecial Paste:=xlPasteFormats
End With
ActiveWindow.Zoom = 75
GoTo NEXT_SHEET
End If
Next wksheet
NEXT_SHEET:
Next sheetName
Application.DisplayAlerts = False
'dont need the default new sheets created by created a new workbook
wkbNew.Worksheets("Sheet1").Delete
ActiveWorkbook.SaveAs Filename:=v, FileFormat:=xlNormal
If VarType(v) <> vbString Then Exit Sub
If Dir(v) <> "" Then
If MsgBox("File already exists - do you wish to overwrite it?", vbYesNo, "File Exists") = vbNo Then Exit Sub
End If
With ActiveWorkbook
.ExportAsFixedFormat Type:=xlTypePDF, Filename:=v, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, From:=1, To:=3, OpenAfterPublish:=False
End With
' ActiveWorkbook.Close
' EMAIL Attachment File
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.To = "waverley.inc#gmail.com"
' .CC = ""
' .BCC = ""
.Subject = "Report" & Format$(Now(), "_YYYYMMDD")
.Body = "DRAFT PLEASE REVIEW :Consultant Report" & Format$(Now(), "_YYYYMMDD")
.Attachments.Add v & ".pdf"
.Send
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Application.DisplayAlerts = True
ActiveWorkbook.Close
Exit Sub
ErrorHandler:
'If there is an unknown runtime error give the user the error number and associated description
'(Description is already set if the erorr is G_LNG_CRITICAL_ERROR)
If Err.Number <> CRITICAL_ERROR Then Err.Description = "Run-time error " & Err.Number & ": " & Err.Description
Err.Description = "Error saving worksheet as file: " & Err.Description
Err.Source = "Error saving worksheet as file: " & Err.Source
'Raise the error up to the error handler above
Err.Raise Number:=CRITICAL_ERROR
End Sub
Try the section of code below instead of your 2 x For Each loops.
using Application.Match to find if the Sheet.Name is found within sheetListRange array (values read from Named Range "SaveList").
Dim sheetListRange As Variant
' instead of saving the Range, save the values inside the Range in an Array
sheetListRange = Application.Transpose(Worksheets("Control").Range("SaveList"))
Set wkbSrc = ActiveWorkbook
Set wkbNew = Workbooks.Add
i = wkbNew.Sheets.Count
For Each wksheet In wkbSrc.Sheets
' instead of 2 X loops, use Application.Match
If Not IsError(Application.Match(wksheet.Name, sheetListRange, 0)) Then ' worksheet match in "SaveList" Named Range
wksheet.Copy Before:=wkbNew.Sheets(i)
If Not wksheet.CodeName Like "Chart*" Then ' if current sheet is not type Chart
Set wksNew = ActiveSheet
With wksNew
.Cells.Copy
.Cells(1, 1).PasteSpecial Paste:=xlPasteValues
.Cells(1, 1).PasteSpecial Paste:=xlPasteFormats
End With
End If
i = i + 1
ActiveWindow.Zoom = 75
End If
Next wksheet
I am using the code below to create and send an email from excel using IBM Notes.
I have tried and tried to get this email to save into a folder as a PDF or just print it so i can print it as a PDF.
Whatever i try i cannot seem to get this to print/save as PDF. The rest of the code is working fine.
I came close, by using this piece of code (which saves the attachment from each email as it's being created).
Attachment = Range("F" & i).value
Set AttachME = doc.CREATERICHTEXTITEM("attachment")
Set EmbedObj = AttachME.EmbedObject(1454, "", Attachment, "")
EmbedObj .ExtractFile "C:\attach\" & EmbedObj .Name
I even tried changing this to:
Set doc = db.CreateDocument
doc.ExtractFile "C:\attach\" & "SomeFileName.pdf"
But alas this produces a object doesn't support this property or method error.
I am also trying this:
doc.Print True, False
But still no luck.
My full code:
Sub Send()
ActiveSheet.DisplayPageBreaks = False
Dim answer As Integer
answer = MsgBox("Are you sure you want to Send All Announcements?", vbYesNo + vbQuestion, "Notice")
If answer = vbNo Then
Exit Sub
Else
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim Attachment As String
Dim WB3 As Workbook
Dim WB4 As Workbook
Dim Rng As Range
Dim db As Object
Dim doc As Object
Dim body As Object
Dim header As Object
Dim stream As Object
Dim session As Object
Dim i As Long
Dim j As Long
Dim j2 As Long
Dim server, mailfile, user, usersig As String
Dim LastRow As Long, LastRow2 As Long, WS As Worksheet
LastRow = Worksheets(1).Range("F" & Rows.Count).End(xlUp).Row 'Finds the last used row
j = 18
With ThisWorkbook.Worksheets(1)
For i = 18 To LastRow
'Start a session of Lotus Notes
Set session = CreateObject("Notes.NotesSession")
'This line prompts for password of current ID noted in Notes.INI
Set db = session.CurrentDatabase
Set stream = session.CreateStream
' Turn off auto conversion to rtf
session.ConvertMime = False
'Email Code
'Create email to be sent
Set doc = db.CreateDocument
doc.Form = "Memo"
Set body = doc.CreateMIMEEntity
Set header = body.CreateHeader("Promotion Announcement for week " & Range("I8").value & ", " & Range("T8").value & " - Confirmation required")
Call header.SetHeaderVal("HTML message")
'Set From
Call doc.ReplaceItemValue("Principal", "Food Specials <mailto:Food.Specials#Lidl.co.uk>")
Call doc.ReplaceItemValue("ReplyTo", "Food.Specials#Lidl.co.uk")
Call doc.ReplaceItemValue("DisplaySent", "Food.Specials#Lidl.co.uk")
Call doc.ReplaceItemValue("Subject", "Promotion Announcement for week " & Range("I8").value & ", " & Range("T8").value & " - Confirmation required")
'To
Set header = body.CreateHeader("To")
Call header.SetHeaderVal(Range("N" & i).value)
'Email Body
Call stream.WriteText("<HTML>")
Call stream.WriteText("<font size=""3"" color=""black"" face=""Arial"">")
Call stream.WriteText("<p>Good " & Range("A1").value & ",</p>")
Call stream.WriteText("<p>Please see attached an announcement of the spot buy promotion for week " & Range("I8").value & ", " & Range("T8").value & ".<br>Please check, sign and send this back to us within 24 hours in confirmation of this order. Please also inform us of when we can expect the samples.</p>")
Call stream.WriteText("<p>The details are as follows:</p>")
'Insert Range
Set WB3 = Workbooks.Open(Range("F" & i).value)
With WB3.Sheets(1)
.Range("A20:J39").SpecialCells(xlCellTypeVisible).Select
Set Rng = Selection
End With
Call stream.WriteText(RangetoHTML(Rng))
WB3.Close SaveChanges:=False
'Attach file
Attachment = Range("F" & i).value
Set AttachME = doc.CREATERICHTEXTITEM("attachment")
Set EmbedObj = AttachME.EmbedObject(1454, "", Attachment, "")
Call stream.WriteText("<BR><p>Please note the shelf life on delivery should be 75% of the shelf life on production.</p></br>")
'Signature
Call stream.WriteText("<BR><p>Kind regards / Mit freundlichen Grüßen,</p></br>")
Call stream.WriteText("<p><b>Lidl UK Food Specials Team</b></p>")
Call stream.WriteText("<table border=""0"">")
Call stream.WriteText("<tr>")
Call stream.WriteText("<td><img src=""http://www.lidl.co.uk/statics/lidl-uk/ds_img/layout/top_logo2016.jpg"" alt=""Mountain View""></td>")
Call stream.WriteText("<td><img src=""http://www.lidl.co.uk/statics/lidl-uk/ds_img/assets_x_x/BOQLOP_NEW%281%29.jpg"" alt=""Mountain View""></td>")
Call stream.WriteText("</tr>")
Call stream.WriteText("</table>")
Call stream.WriteText("</font>")
Call stream.WriteText("</body>")
Call stream.WriteText("</html>")
Call body.SetContentFromText(stream, "text/HTML;charset=UTF-8", ENC_IDENTITY_7BIT)
doc.Print True, False
doc.Save True, False
Call doc.PutInFolder("TEST")
Call doc.Send(False)
session.ConvertMime = True ' Restore conversion - very important
'Clean Up the Object variables - Recover memory
Set db = Nothing
Set session = Nothing
Set stream = Nothing
Set doc = Nothing
Set body = Nothing
Set header = Nothing
'WB3.Close savechanges:=False
Application.CutCopyMode = False
'Email Code
j = j + 1
Next i
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Success!" & vbNewLine & "Announcements have been sent."
MsgBox doc.GetItemValue("subject")(0)
End If
End Sub
Function RangetoHTML(Rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2010
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
Rng.Copy
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
.Cells(1).PasteSpecial Paste:=8
.Cells(1).PasteSpecial xlPasteValues, , False, False
.Cells(1).PasteSpecial xlPasteFormats, , False, False
.Cells(1).Select
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
fileName:=TempFile, _
Sheet:=TempWB.Sheets(1).name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.ReadAll
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close SaveChanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function
Please can someone show me where I am going wrong?
The Notes APIs don't have the ability to save a message as a PDF.
You can't pass a range to EmbedObject. EmbedObject wants a filename - for a file that you've already saved to disk. You can create a PDF and attach it to an email using EmbedObject. If someone has already created a PDF and attached it to an email, you can save the PDF to disk using ExtractFile - which, as you found through your second attempt is a method of the NotesRichTextItem class, not the NotesDocument class. And as for your final attempt, the NotesDocument class does not have a print method, either.
To the best of my knowledge, the only solutions for saving Notes email messages as PDF files require third-party commercial software. (There are some PDF-related open source projects on the OpenNTF website, but I believe they are all based on Lotus XPages technology, which you cannot access from VBA.)