Any other method to solve "automation error" - vba

I was able to successfully complete (with so much help from a stack exchange user) a macro to automatically mail merge a word document from excel. But the problem now is, unless the word document is open, I get an automation error.
Right now, I solve it by just opening the word document every time, but I doubt that is the right programming method.
Any suggestions to overcome this error? I am very new to VBA. This is part of my student assignments. Any advise or code changes to help overcome this error? I read the official msdn docs, did not understand a thing. :'(
The error is usually "automation error - with a cross sign" or this one:
http://imgur.com/a/zitah
For both these errors, solution so far was to open the word document first and then run macro.
Update:
I removed "on error..." part and now the error is this:
http://imgur.com/a/epmGR
The program is as follows:
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Sub RunMerge2()
Dim wd As Object, wdocSource As Object
Dim sh As Worksheet
Dim Lrow As Long, i As Long
Dim cdir As String, client As String, newname As String
Dim sSQL As String
cdir = "C:\Users\Kamlesh\Desktop\"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wdocSource = wd.Documents.Open(cdir & "\master\installers.docx")
Set sh = ActiveSheet
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
With sh
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To Lrow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
client = .Cells(i, 1).Value
newname = "Installer Instructions - " & client & ".docx"
wdocSource.MailMerge.MainDocumentType = wdFormLetters
'~~> Sample String
sSQL = "SELECT * FROM `Sheet1$` WHERE [Client Name] = '" & .Range("A" & i).Value & "'"
wdocSource.MailMerge.OpenDataSource Name:=strWorkbookName, _
AddToRecentFiles:=False, Revert:=False, Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:=sSQL
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.ActiveDocument.SaveAs cdir & newname
wd.ActiveDocument.Close SaveChanges:=False
End If
Next i
End With
wdocSource.Close SaveChanges:=False
'wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
End Sub

this line
Set wdocSource = wd.Documents.Open(cdir & "\master\installers.docx")
should be
Set wdocSource = wd.Documents.Open(cdir & "master\installers.docx")
and
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
can be replaced with
strWorkbookName = ThisWorkbook.FullName
To find what part of the code is causing the error, in Tools > Options > Editor tab check everything
(source: windows.net)
and in the General tab check everything and select Break in Class Module
(source: s-msft.com)
.aspx#odc_ac2007_ta_ErrorHandlingAndDebuggingTipsForAccessVBAndVBA_BasicErrorHandling)

Related

Runtime Error '5852' Requested object is not available. Issue with .Destination = wdSendToNewDocument

So I have been trying to use a the below macro to split a mail-merged document into individual documents. When I run the macro, I receive "Runtime Error '5852' Requested object is not available." The issue is highlighted as .Destination = wdSendToNewDocumentwhen using the debug action.
I though that perhaps the issue was with the file being located on my OneDrive but after moving the files to a local drive, I recieved the same issue. Any insight into how to resolve this error would be helpful.
If more info is necessary, please let me know and I would be happy to answer as best I could.
Code for reference:
Sub MailMergeToDoc()
'
' MailMergeToDoc Macro
' Collects the results of the mail merge in a document
'
' Sourced from: https://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html
Application.ScreenUpdating = False
Dim StrFolder As String, StrName As String, MainDoc As Document, i As Long, j As Long
Const StrNoChr As String = """*./\:?|"
Set MainDoc = ActiveDocument
With MainDoc
StrFolder = .Path & "\"
With .MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
On Error Resume Next
For i = 1 To .DataSource.RecordCount
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
If Trim(.DataFields("Last_Name")) = "" Then Exit For
'StrFolder = .DataFields("Folder") & "\"
StrName = .DataFields("Last_Name") & "_" & .DataFields("First_Name")
End With
On Error GoTo NextRecord
.Execute Pause:=False
For j = 1 To Len(StrNoChr)
StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
Next
StrName = Trim(StrName)
With ActiveDocument
'Add the name to the footer
'.Sections(1).Footers(wdHeaderFooterPrimary).Range.InsertBefore StrName
.SaveAs FileName:=StrFolder & StrName & ".docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
' and/or:
.SaveAs2 FileName:=StrFolder & StrName & ".pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
NextRecord:
Next i
End With
End With
Application.ScreenUpdating = True
End Sub
This is pretty basic troubleshooting. You can't just copy code without understanding what it's doing.
Your MailMerge object does not exist when you're trying to run the mail merge.
You need to create a Mail Merge first in your Word doc - just use the Wizard - and that object will be magically filled. Then you'll have to progress to your next error.

Why are my MergeField names the only data pulling through to a PDF via MailMerge in Excel?

I am currently trying to use the code below in VBA to bring data in a table into a mailmerge word document which then saves the individual merges as a pdf. The code almost does this but when I run the macro on my excel sheet the pdf's saved only bring through the mergefield names from the word document and not the data itself.
Any ideas on where I can go from here? I am currently using Office 2016.
Sub RunMailMerge()
Dim objWord
Dim objDoc
Dim StrFolder As String, StrName As String, i As Long, j As Long
Dim strWorkbookName As String: strWorkbookName = ThisWorkbook.FullName
Const StrNoChr As String = """*./\:?|": StrName = "Easy.docx"
StrFolder = ThisWorkbook.Path & Application.PathSeparator
If Dir(StrFolder & strDocNm) = "" Then Exit Sub
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
With objWord
'Disable alerts to prevent an SQL prompt
.DisplayAlerts = wdAlertsNone
'Display Word - change this to False once the code is running correctly
.Visible = False
'Open the mailmerge main document - set Visible:=True for testing
Set objWord = .Documents.Open(Filename:=StrFolder & StrName, ReadOnly:=True,
AddToRecentFiles:=False, Visible:=False)
With objWord
With .MailMerge
'Define the mailmerge type
.MainDocumentType = wdFormLetters
'Define the output
.Destination = wdSendToNewDocument
.SuppressBlankLines = False
'Connect to the data source
.OpenDataSource Name:=strWorkbookName, _
ReadOnly:=True, _
LinkToSource:=False, _
AddToRecentFiles:=False, _
Format:=wdOpenFormatAuto, _
Connection:="User ID=Admin;DataSource=strWorkbookName;" & _
"Mode=Read;Extended Properties=""HDR=YES;IMEX=1"";", _
SQLStatement:="SELECT * FROM `Sheet1 SQLStatement:=", _
SubType:=wdMergeSubTypeAccess
'Process all eligible records
For i = 1 To .DataSource.RecordCount
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
'Exit if the field to be used for the filename is empty
If Trim(.DataFields("Tenant")) = "" Then Exit For
'StrFolder = .DataFields("Folder") & Application.PathSeparator
StrName = .DataFields("Tenant")
End With
.Execute Pause:=True
'Clean up the filename
For j = 1 To Len(StrNoChr)
StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
Next
StrName = "Letter - " & Trim(StrName)
'Save as a PDF
objWord.SaveAs Filename:=StrFolder & StrName & ".pdf", _
FileFormat:=wdFormatPDF, AddToRecentFiles:=False
Next i
'Disconnect from the data source
.MainDocumentType = wdNotAMergeDocument
End With
'Close the mailmerge main document
.Close False
End With
Call CloseAll
Set wdDoc = Nothing: Set wdApp = Nothing
End With
End Sub
Sub CloseAll()
Dim objWord
Dim objDoc
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
objWord.ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
End Sub
That code is essentially a copy of code I've posted elsewhere (e.g. https://www.mrexcel.com/forum/general-excel-discussion-other-questions/713478-word-2007-2010-mail-merge-save-individual-pdf-files-post4796480.html#post4796480), but why you'd add your call to CloseAll is a mystery.
Nonetheless, it's also clear you've also partially modified the code for use with late binding, by replacing:
Dim wdApp As New Word.Application, wdDoc As Word.Document
with:
Dim objWord
Dim objDoc
...
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
Had you stuck with early binding throughout, the code would work. Right now, though, your modified code employs a mix of late binding with named Word constants, which are really only applicable to early binding. You need to fully adapt the code to late binding or revert to code that is entirely early binding.
Why are you trying to drive a mail merge via VBA code? You should be able to A) set up the data in Excel or Access, B) set up the template in Word & connect it to the data source, C) run the mail merge. Unless you're doing something really, really fancy, there should be no need for VBA.
Since it seems some sadist has forced you to do things the hard way, it looks like your error is most likely here:
Connection:="User ID=Admin;DataSource=strWorkbookName;" & _
"Mode=Read;Extended Properties=""HDR=YES;IMEX=1"";", _
SQLStatement:="SELECT * FROM `Sheet1
SQLStatement:=", _
SubType:=wdMergeSubTypeAccess
First of all:
Connection:="User ID=Admin;DataSource=strWorkbookName;" & _
should be
Connection:="User ID=Admin;DataSource=" & strWorkbookName & ";" & _
Second, your SQLStatement parameter is unterminated, and I'm pretty sure that "Sheet1" (not sure why you have an extra backtick in there) isn't the way to reference the "table" (i.e. worksheet) when selecting from an Excel workbook. IIRC, it should be "WorkBook$WorkSheet", so this:
SQLStatement:="SELECT * FROM `Sheet1
should be something like:
SQLStatement:="SELECT * FROM " & strWorkbookName & "$Sheet1", _
That line is followed by the end of the string
SQLStatement:=", _
which was part of the actual SQL string being sent to the database engine in Excel. That ain't gonna work.
The way I read it, that line should be:
Connection:="User ID=Admin;DataSource=" & strWorkbookName & ";" & _
"Mode=Read;Extended Properties=""HDR=YES;IMEX=1"";", _
SQLStatement:="SELECT * FROM " & strWorkbookName & "$Sheet1", _
SubType:=wdMergeSubTypeAccess
You may have to tweak it a bit, but I think that'll get you on the right track.

Selecting only one row from a excel sheet (as part of mail merge)

I am totally new to VBA and I am writing a code to mail merge data from each row in an excel sheet to a certain word document and save that document with name corresponding to the first cell value from each row.
Each row contains the information of a client. That is why I have to mailmerge each row info seperately.
So far the code works fine, but two problems I need to solve:
1) SQLStatement:="SELECT * FROMSheet1$" ends up mail merging info from all the rows in sheet during each iteration of the for loop (the loop iterates through each row). So what happens is that, each client's document includes data of other clients (excel rows) as well.
2) The usual automation error unless I keep the source word document open.
So can someone please tell me how to select the info from only the row where the iteration has reached.
I triedSQLStatement:="SELECT rw.row* FROMSheet1$" But it does not work
Any help would be good.
The full code is:
Sub RunMerge()
'booking document begins here
Dim wd As Object
Dim wdocSource As Object
Dim activedoc
Dim strWorkbookName As String
Dim x As Integer
Dim cdir As String
Dim client As String
Dim sh As Worksheet
Dim rw As Range
Dim rowcount As Integer
Set sh = ActiveSheet
For Each rw In sh.Rows
If sh.Cells(rw.Row, 1).Value = "" Then
Exit For
End If
cdir = "C:\Users\Kamlesh\Desktop\"
client = Sheets("Sheet1").Cells(rw.Row + 1, 1).Value
Dim newname As String
newname = "Offer Letter - " & client & ".docx"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Set wdocSource = wd.Documents.Open("C:\Users\Kamlesh\Desktop\master\Regen-booking.docx")
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdocSource.MailMerge.MainDocumentType = wdFormLetters
wdocSource.MailMerge.OpenDataSource _
Name:=strWorkbookName, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet1$`"
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.Visible = True
wd.ActiveDocument.SaveAs cdir + newname
'wdocSource.Close SaveChanges:=False
'wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
Next rw
End Sub
My Excel Sheet looks like this
Try this. Obviously this is untested as I do not know your header names and values
SQLStatement:="SELECT * FROM `Sheet1$` WHERE SomeField = 'SomeUniqueValue'"
Something like
SQLStatement:="SELECT * FROM `Sheet1$` WHERE Client = " & Range("A" & rw + 1).Value & "'"
Replace "A" by the actual column
Replace "Client" by the actual header of the column
Also like I mentioned in the comment below the question, why are you creating and destroying objects in the loop? You can instantiate the Word Application out of the For loop. And you can destroy it out of the For Loop.
Is this what you are trying? (UNTESTED)
Change sSQL = "SELECT * FROMSheet1$WHERE [Client Name] = '" & .Range("A" & i).Value & "'" in the below code as per your requirements.
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Sub RunMerge()
Dim wd As Object, wdocSource As Object
Dim sh As Worksheet
Dim Lrow As Long, i As Long
Dim cdir As String, client As String, newname As String
Dim sSQL As String
cdir = "C:\Users\Kamlesh\Desktop\"
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error GoTo 0
Set wdocSource = wd.Documents.Open(cdir & "\master\Regen-booking.docx")
Set sh = ActiveSheet
strWorkbookName = ThisWorkbook.Path & "\" & ThisWorkbook.Name
With sh
Lrow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 2 To Lrow
If Len(Trim(.Range("A" & i).Value)) <> 0 Then
client = .Cells(i, 1).Value
newname = "Offer Letter - " & client & ".docx"
wdocSource.MailMerge.MainDocumentType = wdFormLetters
'~~> Sample String
sSQL = "SELECT * FROM `Sheet1$` WHERE [Client Name] = '" & .Range("A" & i).Value & "'"
wdocSource.MailMerge.OpenDataSource Name:=strWorkbookName, _
AddToRecentFiles:=False, Revert:=False, Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWorkbookName & ";Mode=Read", _
SQLStatement:=sSQL
With wdocSource.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.ActiveDocument.SaveAs cdir & newname
wd.ActiveDocument.Close SaveChanges:=False
End If
Next i
End With
wdocSource.Close SaveChanges:=False
wd.Quit
Set wdocSource = Nothing
Set wd = Nothing
End Sub

Run-time Error 91 : Object variable or With block variable not set

I have 2 separate word documents with Mail Merge lists. And I have an excel workbook with 2 sheets. Based on the worksheet name & if the sheet is not empty, I need to send the mailmerge to that respective word document(s).
When I try to execute this code, it runs upto the first document and at the second document, it stops with an error Run-time Error 91 : Object variable or With block variable not set
I'm not sure what's causing this error (if it's the Dim variable or With block). Would greatly appreciate if someone could kindly help me rectify this error.
Sub Generate_Certificate()
Dim wd As Object
Dim wdoc_reg As Object
Dim wdoc_occ As Object
Dim strWbName_reg As String
Dim strWbName_occ As String
Const wdFormLetters = 0, wdOpenFormatAuto = 0
Const wdFormLetters1 = 0, wdOpenFormatAuto1 = 0
Const wdSendToNewDocument = 0, wdDefaultFirstRecord = 1, wdDefaultLastRecord = -16
Const wdSendToNewDocument1 = 0, wdDefaultFirstRecord1 = 1, wdDefaultLastRecord1 = -16
On Error Resume Next
Set wd = GetObject(, "Word.Application")
If wd Is Nothing Then
Set wd = CreateObject("Word.Application")
End If
On Error Goto 0
For Each Sheet In ActiveWorkbook.Sheets
'Generate report using "Mailmerge" if any data available for Mailmerge1
If Sheet.Name Like "Sheet1" And IsEmpty(ThisWorkbook.Sheets("Sheet1").Range("A2").Value) = False Then
Set wdoc_reg = wd.Documents.Open("C:\Mailmerge1.docx")
strWbName_reg = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdoc_reg.MailMerge.MainDocumentType = wdFormLetters
wdoc_reg.MailMerge.OpenDataSource _
Name:=strWbName_reg, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto, _
Connection:="Data Source=" & strWbName_reg & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet1$`"
With wdoc_reg.MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord
.LastRecord = wdDefaultLastRecord
End With
.Execute Pause:=False
End With
wd.Visible = True
wdoc_reg.Close SaveChanges:=False
Set wdoc_reg = Nothing
Set wd = Nothing
End If
'Generate report using "Mailmerge" if any data available for Mailmerge2
If Sheet.Name Like "Sheet2" And IsEmpty(ThisWorkbook.Sheets("Sheet2").Range("A2").Value) = False Then
Set wdoc_occ = wd.Documents.Open("C:\Mailmerge2.docx")
strWbName_occ = ThisWorkbook.Path & "\" & ThisWorkbook.Name
wdoc_occ.MailMerge.MainDocumentType = wdFormLetters1
wdoc_occ.MailMerge.OpenDataSource _
Name:=strWbName_Occ, _
AddToRecentFiles:=False, _
Revert:=False, _
Format:=wdOpenFormatAuto1, _
Connection:="Data Source=" & strWbName_occ & ";Mode=Read", _
SQLStatement:="SELECT * FROM `Sheet2$`"
With wdoc_occ.MailMerge
.Destination = wdSendToNewDocument1
.SuppressBlankLines = True
With .DataSource
.FirstRecord = wdDefaultFirstRecord1
.LastRecord = wdDefaultLastRecord1
End With
.Execute Pause:=False
End With
wd.Visible = True
wdoc_occ.Close SaveChanges:=False
Set wdoc_Occ = Nothing
Set wd = Nothing
End If
Next
End Sub
As stated by Tim Williams in the question's comments.
You have Set wd = Nothing inside your loop, which will clear your reference to Word after the first sheet. Move that to just before the End Sub

Export from Excel to Outlook

My workbook has 5 different sheets and I need to copy the five sheets and paste it into 5 different mails. Preferably as HTML.
The below written code only attaches the different sheets to outlook. I need the HTML below the body of the email. Please note that my range in the sheets varies from workbook to workbook but the sheet names remain the same.
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
'Function purpose: To Browser for a user selected folder.
'If the "OpenAt" path is provided, open the browser at that directory
'NOTE: If invalid, it will open at the Desktop level
'BrowseForFolder was a code originally written by Ron De Bruin, I love this function!
Dim ShellApp As Object
'Create a file browser window at the default folder
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
'Set the folder to that selected. (On error in case cancelled)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
'Destroy the Shell Application
Set ShellApp = Nothing
'Check for invalid or non-entries and send to the Invalid error
'handler if found
'Valid selections can begin L: (where L is a letter) or
'\\ (as in \\servername\sharename. All others are invalid
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
'If it was determined that the selection was invalid, set to False
BrowseForFolder = False
End Function
Sub SaveWorksheets()
'saves each worksheet as a separate file in a specific folder.
Dim ThisFolder As String
Dim NameOfFile As String
Dim Period As String
Dim RecipName As String
ThisFolder = BrowseForFolder()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim wsName As String
For Each ws In ActiveWorkbook.Worksheets
wsName = ws.Name
If wsName <> "Data" Then
Period = ws.Cells(4, 1).Value 'put the row and column numbers of the report date here.
RecipName = ws.Cells(1, 29).Value 'put the row and column numbers of the email address here
NameOfFile = ThisFolder & "\" & "Termination Report " & wsName & " " & Period & ".xlsx"
ws.Select
ws.Copy
ActiveWorkbook.SaveAs Filename:= _
NameOfFile, FileFormat:= _
xlOpenXMLWorkbook, CreateBackup:=False
ActiveWindow.Close
Call EmailWorkbooks(RecipName, NameOfFile)
End If
Next ws
End Sub
Sub EmailWorkbooks(RecipName, NameOfFile)
Dim OutApp As Object
Dim OutMail As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.createItem(0)
Msg = "Attached is the xyz report for your review. Please let me know if you have any questions" & vbCrLf & vbCrLf _
& "Thanks," & vbCrLf & vbCrLf _
& "Your Name Here" & vbCrLf _
& "Your Title" & vbCrLf _
& "Your contact info"
Subj = "XYZ Report" & " " & Period
On Error Resume Next
With OutMail
.To = RecipName
'.CC =
.Subject = Subj
.Body = Msg
.Attachments.Add (NameOfFile)
.Save
End With
On Error GoTo 0
End Sub
U can use Add method of PublishObjects collection, short example:
Sub InsertSheetContent()
Dim onePublishObject As PublishObject
Dim oneSheet As Worksheet
Dim scriptingObject As Object
Dim outlookApplication As Object
Dim outlookMail As Object
Dim htmlBody As String
Dim htmlFile As String
Dim textStream
Set scriptingObject = CreateObject("Scripting.FileSystemObject")
Set outlookApplication = CreateObject("Outlook.Application")
For Each oneSheet In ThisWorkbook.Worksheets
htmlFile = ThisWorkbook.Path & "\" & ThisWorkbook.Name & "_" & oneSheet.Name & ".html"
Set onePublishObject = ThisWorkbook.PublishObjects.Add(SourceType:=xlSourceRange, _
Filename:=htmlFile, _
Sheet:=oneSheet.Name, _
Source:=oneSheet.UsedRange.Address, _
HtmlType:=xlHtmlStatic, _
DivID:=oneSheet.Name)
onePublishObject.Publish Create:=True
Set textStream = scriptingObject.OpenTextFile(htmlFile)
htmlBody = textStream.ReadAll
Set outlookMail = outlookApplication.CreateItem(0)
With outlookMail
.htmlBody = htmlBody
.Display
End With
Next oneSheet
End Sub