AWE_Email handles the complexity of creating and reading MS Outlook Emails. This includes creating emails with Excel Charts, PivotTables, Ranges, and attachments. Easily create complex search criteria that finds and reads email. Interface with MS Exchange and Outlook to lookup contacts. All source code is included and it's FREE.
Implementation
Add the below AWE_Email class to your workbook (see How to Create a Class for more information). Function definitions, parameters and examples are documented in the comments before each function (see below).
'******************************************************************************************************************
'******************************************************************************************************************
'* AWE_Email: AWE_Email allows for easy automation of Microsoft Outlook emails. Read and respond to emails **
'* based on criteria and information stored in your spreadsheet. Send formatted PivotTables, **
'* Charts/Graphs, reports, ranges or data, workbooks, with data extracted from excel. ** **
'* Author: Mike Libby **
'* Website: AutomationWithExcel.com **
'******************************************************************************************************************
'******************************************************************************************************************
OptionExplicit'==================================================================================================================
'== PRIVATE VARIABLES =============================================================================================
'==================================================================================================================
EnumOutlookFolders:olFolderInbox=6:olFolderSentMail=5:Default=0:EndEnumEnumOutlookItemType:olMailItem=0:EndEnumEnumOutlookBodyFormat:olFormatHTML=2:EndEnumEnumOlMailRecipientType:oloriginator=0:olTo=1:olCC=2:olBCC=3:All=4:EndEnumEnumSchemaTyp:ActualFrom:FromEmail:FromName:DisplayTo:DisplayCC:LastModDt:DateReceived:DateSent:_HasAttach:Subject:body:EndEnumEnumOperatorTyp:EQ:LT:LTE:GT:GTE:BEGINSWITH:CONTAINS:USERDEFINED:EndEnum'==================================================================================================================
'== Find\Read EMAILS ==============================================================================================
'==================================================================================================================
'------------------------------------------------------------------------------------------------------------------
' FindEmails - Find emails in MS Outlook or Exchange using a combination of search values like subject contains,
' date is greater than or less than, sender is equal to... Emails are sorted newest messages first.
' Params: FolderType As OutlookFolders - olFolderInbox = search Inbox, olFolderSentMail = Search the Sent
' SubFolders As String - Semicolon delimited list of folders to search for emails in. Note, an
' empty string ("" or ";SearchFolders) will search the root folder. Folders are
' search in the order that they are listed.
' EmailDict As Variant - a Scripting.Dictionary list of found emails. Can be "Nothing" if not making
' subsequent calls to FindEmails.
' LastConvOnly As Boolean - If true, then the last email received in the first folder found with a
' specific conversation id will be returned. Rules for mail servers generating
' a new Conversation ID: a new email even with identical subjects, or the
' subject changes.
' ParamArray SearchParams As Variant - a list of search conditions built using one or more
' AWE_Email.CreateSearchParam(SearchType, SearchOperator, SearchVal)
' See Function CreateSearchParam for more information.
' Returns: Array of found Outlook Mailitems
' Example: Dim Emails As New AWE_Email, Email as Variant
' For Each Email In AWEEmail.FindEmails(olFolderInbox, ";SubFolder", Nothing, True, _
' AWEEmail.CreateSearchParam(Subject, CONTAINS, "Test"), _
' AWEEmail.CreateSearchParam(Subject, _
' AWEEmail.CreateSearchParam(LastModDt, GTE, Format(Now - 365, "General Date")), _
' AWEEmail.CreateSearchParam(LastModDt, LTE, Format(Now, "General Date")))
' Debug.Print Email.Body
' Next Email
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionFindEmails(FolderTypeAsOutlookFolders,SubFoldersAsString,ByRefEmailDictAsVariant,_LastConvOnlyAsBoolean,ParamArraySearchParams()AsVariant)AsVariantIfFolderType=DefaultThenFolderType=OutlookFolders.olFolderInboxIfSubFolders=""ThenSubFolders=" "DimolAppAsObject:SetolApp=CreateObject("Outlook.Application")DimolNsAsObject:SetolNs=olApp.GetNamespace("MAPI")DimsubFldrAsVariant,FldrAsObject:SetFldr=olNs.GetDefaultFolder(FolderType)DimOlItemsAsObject,OlMailAsObjectDimSearchParamAsVariant,sSrchBldrAsStringDimRcvdDtAsDate,SentDtAsDateIfTypeName(EmailDict)<>"Dictionary"ThenSetEmailDict=CreateObject("Scripting.Dictionary")EndIfForEachSearchParamInSearchParamsIfsSrchBldr=""ThensSrchBldr="@SQL="ElsesSrchBldr=sSrchBldr&" and "sSrchBldr=sSrchBldr&SearchParamNextSearchParamForEachsubFldrInSplit(SubFolders,";")subFldr=Trim(CStr(subFldr))IfsubFldr=""ThenSetFldr=olNs.GetDefaultFolder(FolderType)_Else:SetFldr=olNs.GetDefaultFolder(FolderType).Folders(CStr(subFldr))SetOlItems=Fldr.itemsIfFolderType=olFolderInboxThenOlItems.Sort"ReceivedTime",True_ElseOlItems.Sort"SentOn",TrueSetOlMail=OlItems.Find(sSrchBldr)WhileNotOlMailIsNothingIfTypeName(OlMail)="MailItem"ThenIfLastConvOnly=FalseThenSetEmailDict(EmailDict.Count)=OlMailElseIfEmailDict.Exists(OlMail.ConversationID)ThenIfEmailDate(EmailDict(OlMail.ConversationID))<EmailDate(OlMail)ThenSetEmailDict(OlMail.ConversationID)=OlMailEndIfElseSetEmailDict(OlMail.ConversationID)=OlMailEndIfEndIfSetOlMail=OlItems.FindNextEndIfWendNextsubFldrFindEmails=EmailDict.itemsEndFunction'-------------------------------------------------------------------------------------------------------------------
' CreateSearchParam - Create search paramaters (SearchParams) for FindEmails
' Params: SeearchType - Possible search type (intelliSense display) values are:
' * ============= From Emails ========================================
' * ActualFrom - Sender email address (ignore alias)
' * FromEmail - Sender email address (alias overrides actual sender)
' * FromName - Sender email name
' * ============= TO/CC Emails =======================================
' * DisplayTo - To email address
' * DisplayCC - CC email address
' * ============= Dates ==============================================
' * LastModDt - Date the email was last modified
' * DateReceived - Date that the email was received
' * DateSent - Date that the email was sent by you
' ' ============= Attachment, Subject & Body =========================
' * HasAttach - True if email has attachment otherwise false
' * Subject - Email subject
' * body - Email body
' OperatorType - Possible search oerator (intelliSense display) values are:
' * EQ: = SearchVal
' * LT: < SearchVal
' * LTE: <= SearchVal
' * GT: > SearchVal
' * GTE: >= SearchVal
' * BEGINSWITH: Like SearchVal%
' * CONTAINS: Like %SearchVal%
' * USERDEFINED: User defined search and operator values
' SrchForStr - The string to search for
' * '|' combine multiple search parameters by "or"
' Returns: String of fully formatted search parameter for FindEmails
' Example: Debug.Print AWEEmail.CreateSearchParam(Subject, CONTAINS, "Test")
' Debug.Print AWEEmail.CreateSearchParam(LastModDt, GTE, Format(Now - 365, "General Date"))
' Debug.Print AWEEmail.CreateSearchParam(LastModDt, LTE, Format(Now, "General Date"))
' Debug.Print AWEEmail.CreateSearchParam(FromName, CONTAINS, "Mike|Michael")
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCreateSearchParam(SearchTypeAsSchemaTyp,SearchOperatorAsOperatorTyp,SrchForStrAsVariant)AsStringDimsBldrAsString,varAsVariantForEachvarInSplit(SrchForStr,"|")IfsBldr<>""ThenIfLeft(sBldr,1)<>"("ThensBldr="("&sBldrsBldr=sBldr&" or "EndIfSelectCaseSearchType'========= From Emails ==========================
CaseSchemaTyp.ActualFrom:sBldr=sBldr&"urn:schemas:httpmail:sender"CaseSchemaTyp.FromEmail:sBldr=sBldr&"urn:schemas:httpmail:fromemail"CaseSchemaTyp.FromName:sBldr=sBldr&"urn:schemas:httpmail:fromname"'========= To/CC Emails =========================
CaseSchemaTyp.DisplayTo:sBldr=sBldr&"urn:schemas:httpmail:displayto"CaseSchemaTyp.DisplayCC:sBldr=sBldr&"urn:schemas:httpmail:displaycc"'========= Dates =================================
CaseSchemaTyp.LastModDt:sBldr=sBldr&"DAV:getlastmodified"CaseSchemaTyp.DateReceived:sBldr=sBldr&"urn:schemas:httpmail:datereceived"CaseSchemaTyp.DateSent:sBldr=sBldr&"urn:schemas:httpmail:date"'========= Attachment, Subject & Body ============
CaseSchemaTyp.HasAttach:sBldr=sBldr&"urn:schemas:httpmail:hasattachment"CaseSchemaTyp.Subject:sBldr=sBldr&"urn:schemas:httpmail:subject"CaseSchemaTyp.body:sBldr=sBldr&"urn:schemas:httpmail:textdescription"EndSelectSelectCaseSearchOperatorCaseOperatorTyp.EQ:sBldr=sBldr&" = '"&var&"'"CaseOperatorTyp.LT:sBldr=sBldr&" < '"&var&"'"CaseOperatorTyp.LTE:sBldr=sBldr&" <= '"&var&"'"CaseOperatorTyp.GT:sBldr=sBldr&" > '"&var&"'"CaseOperatorTyp.GTE:sBldr=sBldr&" >= '"&var&"'"CaseOperatorTyp.BEGINSWITH:sBldr=sBldr&" Like '"&var&"%'"CaseOperatorTyp.CONTAINS:sBldr=sBldr&" Like '%"&var&"%'"EndSelectNextvarIfLeft(sBldr,1)="("ThensBldr=sBldr&")"CreateSearchParam=sBldrEndFunction'-------------------------------------------------------------------------------------------------------------------
' IsEmailSent - Returns true if the email was sent otherwise false
' Params: Email as Variant and an Outlook.MailItem
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionIsEmailSent(EmailAsVariant)AsBooleanOnErrorResumeNextIsEmailSent=False:IfEmail.SentOn>0ThenIsEmailSent=TrueIfEmail.ReceivedTime>Email.SentOnThenIsEmailSent=FalseEndFunction'-------------------------------------------------------------------------------------------------------------------
' EmailDate - Returns the last date the email was either sent or received
' Params: Email as Variant and an Outlook.MailItem
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionEmailDate(EmailAsVariant)AsDateIfIsEmailSent(Email)ThenEmailDate=Email.SentOnElseEmailDate=Email.ReceivedTimeEndFunction'-------------------------------------------------------------------------------------------------------------------
' Recips - Returns an array of email recipients.
' Params: Outlook Email Object (retuned from FindEmails)
' RecipType as OlMailRecipientType - Type of recipients to return. Default = All.
' Returns: Array of two dimensional outlook items (ListNb)(0=Name, 1=EmailAddr, 3=RecipientObject)
' Example: Dim Emails As New AWE_Email, Email as Variant, Recip as Variant
' For Each Email inEmails.FindEmails("String to Find in Subject")
' For Each Recip In AWEEmail.ToRecips(oEmail)
' Debug.Print "Recipient: " & Recip(0) & ", EmailAddr: "; Recip(1)
' Next Recip
' Next Email
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionRecips(oEmailAsVariant,_OptionalRecipTypeAsOlMailRecipientType=OlMailRecipientType.All)AsVariantConstPR_SMTP_ADDRESSAsString="http://schemas.microsoft.com/mapi/proptag/0x39FE001E"DimoRecipAsVariant,dictAsObject:Setdict=CreateObject("Scripting.Dictionary")ForEachoRecipInoEmail.RecipientsIfoRecip.Type=RecipTypeOrRecipType=OlMailRecipientType.AllThen_dict(oRecip.name)=Array(oRecip.name,oRecip.PropertyAccessor.GetProperty(PR_SMTP_ADDRESS),oRecip)NextoRecipRecips=dict.itemsEndFunction'===================================================================================================================
'== CREATE EMAILS ==================================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' CreateEmail - Create an outlook HTML Email
' Params: ToStr As String - To Email Addresses
' CcStr As String - CCs Email Addresses
' Subject As String - Email Subject
' HTML As String - HTML formatted body of the email
' Optional HiddenFileAttachments As string - Semicolon list of hidden attachment files.
' Optional FileAttachments As String - Semicolon list of attachment files.
' Optional KillAttachements as Boolean - True=delete attachements; otherwise, False (default).
' Optional SendImmediately as Boolean - True=send without display; otherwise false (default).
' Example: AWEEmail.CreateEmail("to@domain.com", "CCs@...", "Subject", "FullFileAttach", "HTML Body")
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCreateEmail(ToStrAsString,CcStrAsString,SubjectAsString,HTMLAsString,_OptionalHiddenFileAttachmentsAsString="",OptionalFileAttachmentsAsString,_OptionalKillAttachementsAsBoolean=False,OptionalSendImmediatelyAsBoolean=False)DimolAppAsObject:SetolApp=CreateObject("Outlook.Application")DimolEmailAsObject:SetolEmail=olApp.CreateItem(OutlookItemType.olMailItem)DimFileNmAsVariantWitholEmail.to=ToStr.CCs=CcStr.Subject=SubjectIfHiddenFileAttachments<>""ThenForEachFileNmInSplit(HiddenFileAttachments,";").attachments.AddFileNm,1,0NextFileNmEndIfIfFileAttachments<>""ThenForEachFileNmInSplit(FileAttachments,";").attachments.AddFileNmNextFileNmEndIf.BodyFormat=OutlookBodyFormat.olFormatHTML.Display' display here so that the signature can be shown if it exists
.htmlBody=HTML&.htmlBodyIfSendImmediatelyThen.SendElse.DisplayEndWithIfKillAttachements=TrueThenForEachFileNmInSplit(HiddenFileAttachments,";")KillFileNmNextFileNmForEachFileNmInSplit(FileAttachments,";")KillFileNmNextFileNmEndIfEndFunction'===================================================================================================================
'== CREATE GRAPHICS ================================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' CopyRangeToJPG - Create a JPG image from a range return the JPG's temp folder FullFileName.
' Params: NameWorksheet As String - Name of the Worksheet
' RangeAddress As String - Range of the worksheet to copy to a picture
' Returns: FullFileName to the picture stored in the temp folder
' Example: Dim FileNm as String: FileNm = AWEEmail.CopyRangeToJPG ("SheetNm" "RangeAddr")
'-------------------------------------------------------------------------------------------------------------------
FunctionCopyRangeToJPG(NameWorksheetAsString,RangeAddressAsString)AsStringDimPictureRangeAsRangeWithActiveWorkbookOnErrorResumeNext.Worksheets(NameWorksheet).ActivateSetPictureRange=.Worksheets(NameWorksheet).Range(RangeAddress)IfPictureRangeIsNothingThenMsgBox"Sorry this is not a correct range"ExitFunctionEndIfPictureRange.CopyPictureWith.Worksheets(NameWorksheet).ChartObjects.Add(PictureRange.Left,PictureRange.Top,_PictureRange.Width,PictureRange.Height).Activate.Chart.Paste.Chart.ExportEnviron$("temp")&Application.PathSeparator&"Picture.jpg","JPG"EndWith.Worksheets(NameWorksheet).ChartObjects(.Worksheets(NameWorksheet).ChartObjects.Count).DeleteEndWithCopyRangeToJPG=Environ$("temp")&Application.PathSeparator&"Picture.jpg"SetPictureRange=NothingEndFunction'-------------------------------------------------------------------------------------------------------------------
' CopyChartToJPG - Create a JPG image from a chart and return the JPG's temp folder FullFileName.
' Params: ws As Worksheet
' ChartNm As String
' Returns: FullFileName to the picture stored in the temp folder
' Example: Dim FileNm As String: FileNm = AWEEmail.CopyChartToJPG ("SheetNm", "ChartNm")
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCopyChartToJPG(wsAsWorksheet,ChartNmAsString)AsStringDimchrtObjAsChartObject:SetchrtObj=ws.ChartObjects(ChartNm)DimChrtNmAsString:ChrtNm=Environ$("temp")&Application.PathSeparator&ChartNm&".jpg"chrtObj.ActivateActiveChart.ExportChrtNm,"JPG"CopyChartToJPG=ChrtNmEndFunction'-------------------------------------------------------------------------------------------------------------------
' ChartToHtml - Create HTML to display attached image
' Params: ws As Worksheet - Chart worksheet
' ChartNm as String - Chart name
' optonal Height as Long - Height of chart in pixels. Default = Original Height
' Returns: String - HTML to display attached image
' Example: Dim HTML as String: HTML = AWEEmail.ChartToHtml(ws, "ChartNm", 50)
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionChartToHtml(wsAsWorksheet,ChrtNmAsString,OptionalHeightAsLong=0)AsStringDimchrtObjAsChartObject:SetchrtObj=ws.ChartObjects(ChrtNm)DimWidthAsLong,ChrtPctAsDoubleIfHeight<>0ThenChrtPct=(Height-chrtObj.Height)/HeightWidth=chrtObj.Width:IfChrtPct<>0ThenWidth=Width*ChrtPctEndIfChartToHtml="<img src=""cid:"&ChrtNm&".jpg"&""" width="&Width&" height="&Height&">"EndFunction'===================================================================================================================
'== RANGE TO HTML ==================================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' RangetoHTML - Convert a worksheet range to HTML
' Params: Rng as Range - Range to convert
' Returns: Range formatted as HTML
' Example: Dim HTML as string: HTML = AWEEmail.RangeToHTML(rng, False)
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionRangetoHTML(RngAsRange)AsStringDimfsoAsObject,tsAsObject,TempFileAsString,TempWBAsWorkbook,TempWSAsWorksheetDimiFmStartColAsLong,iFmEndColAsLong,iFmStartRowAsLong,iFmEndRowAsLongDimiToStartColAsLong,CopyFormatRngAsRange,CopyDataRngAsRange,PasteRngAsRange,SrcRngAsRangeDimwsAsWorksheet:Setws=Rng.ParentDimColNmsAsVariant,ColNmAsVariant,irowAsLong,iColAsLongDimLnkRngAsRangeTempFile=Environ$("temp")&"\"&Format(Now,"dd-mm-yy h-mm-ss")&".htm"'--- Copy range ---
Rng.CopySetTempWB=Workbooks.Add(1)SetTempWS=TempWB.Sheets(1)WithTempWS.Cells(1).PasteSpecialxlPasteColumnWidths,,False,False.Cells(1).PasteSpecialxlPasteAll,,False,False.Cells(1).PasteSpecialxlPasteValues,,False,False.Cells(1).PasteSpecialxlPasteFormats,,False,False.Cells(1).SelectApplication.CutCopyMode=FalseOnErrorResumeNext.DrawingObjects.Visible=True.DrawingObjects.DeleteOnErrorGoTo0EndWith'--- copy the range to html ---
Application.ReferenceStyle=xlA1'--- get the final range ---
WithTempWSSetSrcRng=TempWS.UsedRangeEndWithWithTempWB.PublishObjects.Add(_SourceType:=xlSourceRange,_Filename:=TempFile,_Sheet:=TempWB.Sheets(1).name,_Source:=SrcRng.Address,_HtmlType:=xlHtmlStatic).Publish(True)EndWithSetfso=CreateObject("Scripting.FileSystemObject")Setts=fso.GetFile(TempFile).OpenAsTextStream(1,-2)RangetoHTML=ts.ReadAllts.CloseRangetoHTML=Replace(RangetoHTML,"align=center x:publishsource=",_"align=left x:publishsource=")'--- clean up ---
TempWB.Closesavechanges:=FalseKillTempFileSetts=NothingSetfso=NothingSetTempWB=NothingEndFunction'===================================================================================================================
'== CONVERT RANGE TO ATTACHMENT ====================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' RangetoNewWorkbook - Convert a worksheet range to an email attachment
' Params: Rng as Range - Range to convert
' AttachFullFileNm as String - FileNm. Default="WB_" Format(Now, "yymmdd-hhmmss") & ".xlsx"
' Note: AttachFullFileNm can be deleted after the email is sent.
' Example: Dim FileNm as String: FileNm = AWEEmail.RangeToHTML(rng, False)
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionRangetoNewWorkbook(RngAsRange,OptionalAttachFullFileNmAsString="")AsStringDimfsoAsObject,tsAsObject,TempFileAsString,TempWBAsWorkbook,TempWSAsWorksheetDimiFmStartColAsLong,iFmEndColAsLong,iFmStartRowAsLong,iFmEndRowAsLongDimiToStartColAsLong,CopyFormatRngAsRange,CopyDataRngAsRange,PasteRngAsRange,SrcRngAsRangeDimwsAsWorksheet:Setws=Rng.ParentDimColNmsAsVariant,ColNmAsVariant,irowAsLong,iColAsLongDimLnkRngAsRangeIfAttachFullFileNm=""ThenAttachFullFileNm=Environ$("temp")&"\"&"WB_"&Format(Now,"yymmdd-hhmmss")&".xlsx"EndIfRangetoNewWorkbook=AttachFullFileNm'--- Copy range ---
Rng.CopySetTempWB=Workbooks.Add(1)SetTempWS=TempWB.Sheets(1)WithTempWS.Cells(1).PasteSpecialxlPasteColumnWidths,,False,False.Cells(1).PasteSpecialxlPasteAll,,False,False.Cells(1).PasteSpecialxlPasteValues,,False,False.Cells(1).PasteSpecialxlPasteFormats,,False,False.Cells(1).SelectApplication.CutCopyMode=FalseOnErrorResumeNext.DrawingObjects.Visible=True.DrawingObjects.DeleteEndWithTempWB.SaveAsAttachFullFileNmTempWB.CloseSetTempWB=NothingEndFunction'-------------------------------------------------------------------------------------------------------------------
' KillTempFile - Removes temporary files that were created for attachements.
' Params: Full path to the tempoary file
' Example: AWEEmail.KillTempFile("FullFileName")
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionKillTempFile(FullFileNmAsString)KillFullFileNmEndFunction'===================================================================================================================
'== Contact Info ===================================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' GetRecipient - Get the Recipient Object from Outlook
' Params: Name as String - Outlook name to lookup
' Returns: Recipient object
' Example: Dim recip as Object: set recip = AWEEmail.GetRecipient("Full Name")
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionGetRecipient(nameAsString)AsVariantDimoutlAppAsObject:SetoutlApp=CreateObject("Outlook.Application")DimoutlNameSpaceAsObject:SetoutlNameSpace=outlApp.GetNamespace("MAPI")DimoutlGALAsObject:SetoutlGAL=outlNameSpace.GetGlobalAddressList()DimoutlEntryAsObject:SetoutlEntry=outlGAL.AddressEntriesDimoutlRecipientAsObject,outlMemberAsObject,varAsVariantIfname=""ThenExitFunctionOnErrorResumeNextSetoutlRecipient=outlNameSpace.CreateRecipient(name)outlRecipient.ResolveIfoutlRecipient.ResolvedThenSetGetRecipient=outlRecipientEndFunction'-------------------------------------------------------------------------------------------------------------------
' GetOutlookContact - Get the Contact Object for a name from Outlook.
' Params: Name as String - Outlook name to lookup
' Returns: oRecipient.AddressEntry.GetContact object
' Example: Dim recip as Object: set recip = AWEEmail.GetRecipient("Full Name")
' Note1: See https://learn.microsoft.com/en-us/office/vba/api/outlook.contactitem
' Note2: If the outlook profile isn't already open, the user will be prompted to select one.
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionGetOutlookContact(nameAsString)AsVariantDimoRecipientAsObjectSetoRecipient=GetRecipient(name)SetGetOutlookContact=NothingIfNotoRecipientIsNothingThenIfNotoRecipient.AddressEntryIsNothingThenSetGetOutlookContact=oRecipient.AddressEntry.GetContactEndIfEndIfEndFunction'-------------------------------------------------------------------------------------------------------------------
' GetExchangeUser - Get an ExchangeUser Object for a name from Exchange's GAL (Global Access Libary).
' Params: Name as String - Outlook name to lookup
' Returns: outlRecipient.AddressEntry.GetExchangeUser
' Example: Dim oExchgUser as Object: set oExchgUser = AWEEmail.GetRecipient("Full Name")
' Note: See https://learn.microsoft.com/en-us/office/vba/api/outlook.exchangeuser#properties
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionGetExchangeUser(nameAsString)AsVariantDimoutlAppAsObject:SetoutlApp=CreateObject("Outlook.Application")DimoutlNameSpaceAsObject:SetoutlNameSpace=outlApp.GetNamespace("MAPI")DimoutlRecipientAsObjectSetGetExchangeUser=NothingIfname=""ThenExitFunctionOnErrorResumeNextSetoutlRecipient=outlNameSpace.CreateRecipient(name)outlRecipient.ResolveIfoutlRecipient.ResolvedThenSetGetExchangeUser=outlRecipient.AddressEntry.GetExchangeUserEndFunction'===================================================================================================================
'== Save Email/Attachments =========================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' SaveEmail - Save the email.
' Params: Email as Object - Outlook email object.
' Optional FilePath as String - Path to the filename (default=Environ$("temp")).
' Optional FileNm as String - Name of the file (default=RecvdTm_Sender_Subject).
' Optional PromptUser as Boolean - True if prompt user to save; otherwise, false (default).
' Returns: List of saved email filenames.
' Example: Dim Arr as Variant: set Arr = AWEEmail.SaveEmail(oEmail)
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionSaveEmail(EmailAsObject,OptionalFilePathAsString="",_OptionalFileNmAsString="",OptionalPromptUserAsBoolean=False)AsStringDimsFullFileNmAsStringIfEmailIsNothingThenExitFunctionIfFilePath=""ThenFilePath=Environ$("temp")&Application.PathSeparatorIfFileNm=""ThenFileNm=Format(CDate(Email.ReceivedTime),"yyyymmdd_hhmmAM/PM")&"_"&_CleanString(Email.Sender,"")&"_"&CleanSubject(Email.Subject)&".msg"sFullFileNm=FilePath&FileNmIfPromptUserThenIfMsgBox("Save email..."&vbCrLf&FileNm,vbYesNo+vbQuestion)=vbNoThenExitFunctionEndIfEmail.SaveAssFullFileNmSaveEmail=sFullFileNmEndFunction'-------------------------------------------------------------------------------------------------------------------
' SaveAttachments - Save the email attachments.
' Params: Email as Object - Outlook email object.
' Optional FilePath as String - Path to the filename (default=Environ$("temp")).
' Optional FileNm as String - Name of the file (default=RecvdTm_Sender_Subject).
' Returns: List of saved attachments as an array of strings
' Example: Dim Arr as Variant: set ARR = AWEEmail.SaveAttachments(oEmail)
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionSaveAttachments(EmailAsObject,OptionalFilePathAsString="",_OptionalFileNamesAsString="")AsVariantDimvarAsVariant,FileNmAsVariant,oAttachAsObjectDimdictAsObject:Setdict=CreateObject("Scripting.Dictionary")IfEmailIsNothingThenExitFunctionIfEmail.attachments.Count=0ThenExitFunctionIfFilePath=""ThenFilePath=Environ$("temp")&Application.PathSeparatorIfFileNames=""ThenForEachvarInEmail.attachmentsIfFileNames<>""ThenFileNames=FileNames&";"FileNames=FileNames&var.FilenameNextvarEndIfForEachFileNmInSplit(FileNames,";")SetoAttach=Email.attachments(CStr(FileNm))IfNotoAttachIsNothingThenoAttach.SaveAsFileFilePath&FileNmdict(FileNm)=FilePath&FileNmEndIfNextFileNmSaveAttachments=dict.itemsEndFunction'===================================================================================================================
'== Hyperlinks =====================================================================================================
'===================================================================================================================
PublicFunctionGetHyperlink(EmailAsVariant,OptionalRegExSrchPtrnAsString,_OptionalisGlobalAsBoolean=False)AsVariantDimdictAsObject:Setdict=CreateObject("Scripting.Dictionary")DimoHyperlinkAsObject,oMailDocAsObjectOnErrorResumeNextSetoMailDoc=Email.GetInspector.WordEditorForEachoHyperlinkInoMailDoc.HyperlinksIfRegExSrchPtrn=""OrFindPattern(oHyperlink.Address,RegExSrchPtrn)<>""ThenIfisGlobalThendict(oHyperlink.Address)=oHyperlink.AddressElseGetHyperlink=oHyperlink.Address:ExitFunctionEndIfEndIfNextoHyperlinkIfisGlobal=TrueThenGetHyperlink=dict.itemsEndFunction'===================================================================================================================
'== RegEx/Strings ==================================================================================================
'===================================================================================================================
'-------------------------------------------------------------------------------------------------------------------
' FindPattern - Search for a RegEx pattern.
' Params: FindInStr as String - String being searched.
' SrchPtrn as String - RegEx Pattern to search for.
' IsGobal as Boolean - If False (default) returns a string; otherwise, an array of strings.
' Srch PhoneNumber="\(?\b[2-9][0-9]{2}\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}\b"
' Ptrns: Zip Codes="\b[0-9]{5}(?:-[0-9]{4})?\b"
' HTTPS, FTP, or File="\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|$!:,.;]*[A-Z0-9+&@#/%=~_|$]"
' Web Site="\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$]"
' Email Address="\(?\b[2-9][0-9]{2}\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}\b"
' Specific Pattern="E-\d{5}\.\d{2}" = Starts with "E-", 5 digits, a "." and 2 digits.
' From and to string="Find From String(.*?)Find To String"
' Multiple matches="(From1|From2|From3)(.*?)(To1|To2|To3)"
'
' Example: Print AWEEmail.FindPattern ("Find in String E-12345.12", "E-\d(5)\.\d(2)")
' Note: "^"=Beginning of a string or line. "$"=End of a string. "([^\r]+)"=VBCRLF. "\."=period
' "\n"=New Line
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionFindPattern(FindInStrAsString,RegExSrchPtrnAsString,_OptionalisGlobalAsBoolean=False,OptionalReturnStringAsBoolean=True)AsVariantDimregExMatchAsObject,vPtrnAsVariant,sPtrnBldrAsStringDimidxAsLong,dictAsObject:Setdict=CreateObject("Scripting.Dictionary")WithCreateObject("VBScript.RegExp").ignorecase=True.Global=isGlobal.pattern=RegExSrchPtrnIf.test(FindInStr)ThenIfisGlobal=FalseThenSetregExMatch=.Execute(FindInStr)IfReturnString=TrueThenFindPattern=regExMatch(0).ValueElseFindPattern=regExMatch(0)ElseForEachregExMatchIn.Execute(FindInStr)IfReturnString=TrueThendict("Idx"&idx)=regExMatch.Value_Elsedict("Idx"&idx)=regExMatchidx=idx+1NextregExMatchFindPattern=dict.itemsEndIfEndIfEndWithIfisGlobal=TrueAndIsArray(FindPattern)=FalseThenFindPattern=dict.itemsEndFunction'-------------------------------------------------------------------------------------------------------------------
' CleanPhoneNbr - Returns phone number digits only (special characters are removed)
' Params: PhNum as String - Phone number
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCleanPhoneNbr(PhNumAsString)AsStringDimXAsLongForX=1ToLen(PhNum)IfMid(PhNum,X,1)Like"[!0-9]"ThenMid(PhNum,X)=" "NextCleanPhoneNbr=Replace(PhNum," ","")EndFunction'-------------------------------------------------------------------------------------------------------------------
' CleanSubject - Removes [EXTERNAL|INTERNAL] trailing spaces from the subject
' Params: Subject as string
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCleanSubject(strAsString)AsStringDimvarAsString,locAsLong:loc=InStr(str,":")Ifloc>0Thenvar=Trim(Right(str,Len(str)-loc))Elsevar=strvar=Trim(Replace(var,"[EXTERNAL]",""))var=Trim(Replace(var,"[INTERNAL]",""))WithCreateObject("vbscript.regexp").Global=True:.MultiLine=True:.ignorecase=False:.pattern="[^a-zA-Z0-9\- ]"CleanSubject=Trim(.Replace(var," "))CleanSubject=Replace(Replace(CleanSubject,vbCr,""),vbLf,"")EndWithEndFunction'-------------------------------------------------------------------------------------------------------------------
' CleanString - Removes specified characters from the string.
' Params: StringToClean as String - string to search through.
' ParamArray RemoveStrings - list of strings to remove from the StringToClean
' Example: Dim str as String: str = CleanString(StringToClean, "RemoveString", vbCR, vbLF,
' This example removes the string "RemoveString" and special characters carriage returns and line feeds.
'-------------------------------------------------------------------------------------------------------------------
PublicFunctionCleanString(StringToCleanAsString,ParamArrayRemoveStrings()AsVariant)AsStringDimvarAsVariantForEachvarInRemoveStringsStringToClean=Replace(StringToClean,var,"")NextvarCleanString=Trim(StringToClean)EndFunction
AWE_Email Examples
The below examples show how to use the above AWE_Email class to create and send emails, find and read emails, and get Outlook and Exchange Server contacts. Use AWE_Class as it is or extend its capabilities even further to meet your specific needs.
Create and Send Emails
Send a Simple HTML Email - Create a simple "Hello World" email.
PublicFunctionHelloWorld()DimAWEEmailAsNewAWE_EmailCallAWEEmail.CreateEmail("World@domain.com","","Hello World","Hi World,<BR><BR>First email with AWE_Email!")EndFunction
Send a Pivot Chart - Create an email that contains an Excel Chart embedded in the HTML.
PublicFunctionPivotChartEmail()DimAWEEmailAsNewAWE_EmailDimwsAsWorksheet:Setws=ThisWorkbook.Sheets("Dashboard")DimEmpNmAsString:EmpNm=GetSelectedSlicerItems("Slicer_Employee_Name"):IfEmpNm=""ThenEmpNm="All"DimsChrtPathAsString:sChrtPath=AWEEmail.CopyChartToJPG(ws,"ChartEmpRev")DimsAttachmentsAsString:sAttachments=sChrtPathDimHTMLAsStringHTML="Hi "&EmpNm&",<BR><BR>Below is a graph showing revenue by month for the year...<BR><BR>"&_AWEEmail.ChartToHtml(ws,"ChartEmpRev",125)CallAWEEmail.CreateEmail("Emp@Domain.com","","PivotChartEmail - "&EmpNm,HTML,sAttachments)EndFunction'--- The below code retrieves Excel Slicer Selections which is used above. It does not apply to AWE_Email ---
PublicFunctionGetSelectedSlicerItems(SlicerNameAsString)AsStringDimsIAsSlicerItem,NamesAsStringForEachsIInActiveWorkbook.SlicerCaches(SlicerName).SlicerItemsIfsI.Selected=TrueThenIfNames<>""ThenNames=Names&", "Names=Names&(sI.Value)EndIfNextIfUBound(Split(Names))>1ThenNames=StrReverse(Replace(StrReverse(Names),StrReverse(","),StrReverse(", and"),,1))EndIfGetSelectedSlicerItems=NamesEndFunction
Send a PivotTable - Create an email that contains an Excel PivotTable embedded in the HTML.
PublicFunctionPivotTableEmail()DimAWEEmailAsNewAWE_EmailDimwsAsWorksheet:Setws=ThisWorkbook.Sheets("Dashboard")DimEmpNmAsString:EmpNm=GetSelectedSlicerItems("Slicer_Employee_Name"):IfEmpNm=""ThenEmpNm="All"DimHTMLAsString:HTML="Hi "&EmpNm&",<BR><BR>Below is a PivotTable showing revenue for the year...<BR>"HTML=HTML&AWEEmail.RangetoHTML(ws.PivotTables(1).TableRange1)HTML=HTML&"<BR>Your hard work is appreciated."CallAWEEmail.CreateEmail("Emp@Domain.com","","PivotTableEmail - "&EmpNm,HTML)EndFunction
Attach a Range as a Worksheet - Send an email with an Excel Range as an attachment
PublicFunctionAttachRangeToEmail()DimAWEEmailAsNewAWE_EmailDimwsAsWorksheet:Setws=ThisWorkbook.Sheets("Timecard")DimAttachFileNmAsString,HTMLAsStringAttachFileNm=AWEEmail.RangetoNewWorkbook(ws.Range("A1",ws.Cells(ws.UsedRange.Rows.Count,9)))HTML="Hi<BR><BR>Attached are timesheets for the year"AWEEmail.CreateEmailToStr:="Emp@Domain.com",CcStr:="",Subject:="Timesheets for the year",HTML:=HTML,_FileAttachments:=AttachFileNmAWEEmail.KillTempFile(AttachFileNm)EndFunction
Putting it altogether - Create an an email with a Pivot Chart, Pivot Table and an attachment.
PublicFunctionPuttingItTogether()DimAWEEmailAsNewAWE_EmailDimwsAsWorksheet:Setws=ThisWorkbook.Sheets("Dashboard")DimEmpNmAsString:EmpNm=GetSelectedSlicerItems("Slicer_Employee_Name"):IfEmpNm=""ThenEmpNm="All"DimsChrtPathAsString,sHiddenAttachAsString,sShowAttachAsString,HTMLAsStringHTML="Hi "&EmpNm&",<BR><BR>Below is a graph showing your revenue by month for the year...<BR><BR>"sChrtPath=AWEEmail.CopyChartToJPG(ws,"ChartEmpRev")sHiddenAttach=sChrtPathHTML=HTML&AWEEmail.ChartToHtml(ws,"ChartEmpRev",125)HTML=HTML&"<BR><BR>Below is a PivotTable showing your revenue by month for the year...<BR>"HTML=HTML&AWEEmail.RangetoHTML(ws.PivotTables(1).TableRange1)HTML=HTML&"<p>Your hard work is appreciated.</p>"sShowAttach=AWEEmail.RangetoNewWorkbook(ws.Range("A1",ws.Cells(ws.UsedRange.Rows.Count,9)))HTML=HTML&"<p>Though your revenue would never be emailed to you, I've attached everyone's revenue.</p>"HTML=HTML&"<p>By the way all data is ficticiouPs😀</p>"CallAWEEmail.CreateEmail("Emp@Domain.com","","AllTogether - "&EmpNm,HTML,sHiddenAttach,sShowAttach)EndFunction
Find and Read Emails
Find emails - use complex search criteria to find emails
PublicFunctionFindEmails()DimAWEEmailAsNewAWE_Email,EmailAsVariant'=========================================================================================================
' Find all emails located in the InBox and in Inbox\TestFolder, where the
' Subject contains "Test" and where the date is within the last year.
'=========================================================================================================
ForEachEmailInAWEEmail.FindEmails(olFolderInbox,";TestFolder",Nothing,True,_AWEEmail.CreateSearchParam(Subject,CONTAINS,"Test"),_AWEEmail.CreateSearchParam(LastModDt,GTE,Format(Now-365,"General Date")),_AWEEmail.CreateSearchParam(LastModDt,LTE,Format(Now,"General Date")))Debug.PrintEmail.Subject&"; IsEmailSent:"&AWEEmail.IsEmailSent(Email)&"; EmailDate:"&AWEEmail.EmailDate(Email)'--- Business Logic Here ---
NextEmailEndFunction
Use fuction AWE_Email::CreateSearchParam (SearchType, OperatorType, SrchForStr As String) to create the parameters for FindEmails SearchParams.
SearchType - Possible search type (intelliSense display) values are:
DisplayTo - Display sent to
CCs - CCs on the email
BCCs - Blind CCs's (sent emails only)
LastModDt - Date the email was last modified
ActualFrom - Actual message sender
DisplayFrom - Email sender (could by alias)
HasAttach - True if attachment else false
AttachFlNm - the name of attachment
Priority - Urgent=-1; Normal=0; Non-Urgent=1
SenderEmail - Sender email address, "rl@ex.com"
SenderName - Sender email name, "Ralph Lie"
Subject - Email subject
Body - Email body
OperatorType - Possible search oerator (intelliSense display) values are:
EQ: = SearchVal
LT: < SearchVal
LTE: <= SearchVal
GT: > SearchVal
GTE: >= SearchVal
BEGINSWITH: Like SearchVal%
CONTAINS: Like %SearchVal%
SrchForStr - The string to search for
Search your inbox and sent folders for the last conversation that has not been responded to. Note, you will need to create a EmailDict object that is passed between FindEmails call (see below)...
PublicFunctionRcvdEmailsNeedingReply()DimAWEEmailAsNewAWE_Email,EmailAsVariant,EmailDictAsObjectDimLastConvOnlyAsBoolean:LastConvOnly=True'=========================================================================================================
' Find the last email conversation from emails located in the InBox, Inbox\TestFolder, or SentMail,
' where the Body contains Mike or Michael that were sent or received in the last month.
'=========================================================================================================
CallAWEEmail.FindEmails(olFolderInbox,";TestFolder",EmailDict,LastConvOnly,_AWEEmail.CreateSearchParam(body,CONTAINS,"Mike|Michael"),_AWEEmail.CreateSearchParam(DateReceived,GTE,Format(Now-30,"General Date")))ForEachEmailInAWEEmail.FindEmails(olFolderSentMail,"",EmailDict,LastConvOnly,_AWEEmail.CreateSearchParam(body,CONTAINS,"Mike|Michael"),_AWEEmail.CreateSearchParam(DateSent,GTE,Format(Now-30,"General Date")))'--- open emails I've received but have not responded to ---
IfAWEEmail.IsEmailSent(Email)=FalseThenEmail.DisplayEndIfNextEmailEndFunctionPublicFunctionSentEmailsWaitingForReply()DimAWEEmailAsNewAWE_Email,EmailAsVariant,EmailDictAsObjectDimLastConvOnlyAsBoolean:LastConvOnly=True'=========================================================================================================
' Find the last email conversation from emails located in the InBox, Inbox\TestFolder, or SentMail,
' that were sent or received in the last month.
'=========================================================================================================
CallAWEEmail.FindEmails(olFolderInbox,";TestFolder",EmailDict,LastConvOnly,_AWEEmail.CreateSearchParam(DateReceived,GTE,Format(Now-30,"General Date")))ForEachEmailInAWEEmail.FindEmails(olFolderSentMail,"",EmailDict,LastConvOnly,_AWEEmail.CreateSearchParam(DateSent,GTE,Format(Now-30,"General Date")))'--- Open emails that I've sent but have not received a response ---
IfAWEEmail.IsEmailSent(Email)=TrueThen'--- Do not open emails containing the words "Thank you for completing" ---
IfAWEEmail.FindPattern(Email.body,"Thank you for completing")=""ThenEmail.DisplayEndIfEndIfNextEmailEndFunction
Read and Find Strings in Emails - use search patterns to locate content within emails
PublicFunctionReadEmails()DimAWEEmailAsNewAWE_Email,vEmailAsVariant,vRecipAsVariant,varAsVariantDimsFoundStrAsString,vPropAsVariant'--- Find all emails with "Find String" anywhere in the Subject and sent in the last year ---
ForEachvEmailInAWEEmail.FindEmails(olFolderInbox," ;TestFolder",Nothing,True,_AWEEmail.CreateSearchParam(Subject,CONTAINS,"Test"),_AWEEmail.CreateSearchParam(LastModDt,GTE,Format(Now-365,"General Date")))'--- Subject ---
Debug.Print"Subject: "&vEmail.Subject'--- Sender ---
Debug.Print"Sender: "&vEmail.Sender'--- Received Time ---
Debug.Print"Received Time: "&vEmail.ReceivedTime'--- Sent to ---
ForEachvRecipInAWEEmail.Recips(vEmail,olTo)Debug.Print"Sent To: "&vRecip(0)&", EmailAddr: ";vRecip(1)Next'--- CC'd ---
ForEachvRecipInAWEEmail.Recips(vEmail,olCC)Debug.Print"CC'd: "&vRecip(0)&", EmailAddr: ";vRecip(1)Next'--- Attachments ---
Debug.Print"Attach Count: "&vEmail.attachments.CountForEachvarInvEmail.attachmentsDebug.Print"Attach Name: "&var.FilenameNextvar'--- Saluation ---
Debug.Print"Salutation: "&AWEEmail.FindPattern(vEmail.body,"(Hi|Hello|Dear)(.*?),")'--- Phone Number ---
Debug.Print"Phone: "&AWEEmail.FindPattern(vEmail.body,_"\(?\b[2-9][0-9]{2}\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}\b")'--- Zip Code ---
Debug.Print"Zip: "&AWEEmail.FindPattern(vEmail.body,"\b[0-9]{5}(?:-[0-9]{4})?\b")'--- Web https|ftp|file ---
Debug.Print"Web https|ftp|file: "&AWEEmail.FindPattern(vEmail.body,_"\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|$!:,.;]*[A-Z0-9+&@#/%=~_|$]")'--- Web Site ---
Debug.Print"Web Site: "&AWEEmail.FindPattern(vEmail.body,_"\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$]")'--- Email ---
Debug.Print"Email: "&AWEEmail.FindPattern(vEmail.body,_"\(?\b[2-9][0-9]{2}\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}\b")'--- Specific Pattern ---
Debug.Print"Pattern ""E-#####.##"":"&AWEEmail.FindPattern(vEmail.body,"E-\d{5}\.\d{2}")Debug.Print"=== END OF EMAIL ==="NextvEmailEndFunction
Get Contacts
Find Outlook Contacts - Use MS Outlook to find and retrieve Outlook Contacts
PublicFunctionGetOutlookContact()DimAWEEmailAsNewAWE_EmailDimoContactAsObject'----------------------------------------------------------------
'--- Pass a unique identifier (not name) to GetOutlookContact ---
'--- i.e. Phone number, email address, employee id... ---
'----------------------------------------------------------------
SetoContact=AWEEmail.GetOutlookContact("UniqueContactName")IfNotoContactIsNothingThenDebug.PrintoContact.FullName&" - "&oContact.Email1AddressEndIfEndFunction
Find Exchange Contacts - Use MS Exchange to find and retrieve contacts from the GAL (Global Address List)
PublicFunctionGetExchangeContact()DimAWEEmailAsNewAWE_EmailDimoContactAsObject'---------------------------------------------------------------
'--- Pass a unique identifier (not name) to GetChangeUser ------
'--- i.e. Phone number, email address, employee id... ------
'---------------------------------------------------------------
SetoContact=AWEEmail.GetExchangeUser("EmpId")IfNotoContactIsNothingThenDebug.PrintoContact.name&" - "&oContact.PrimarySmtpAddressEndIfEndFunction
Download Example Workbook
See the following modules in the download for examples:
CreateEmails - Creating a simple email, pivot chart and table, and attach a Worksheet/Workbook.
GetContacts - Get contacts from MS Outlook or Exchange
ReadEmails - Search for and iterate through emails. Search for strings within found emails.
SaveEmailAttach - Save an email or an email attachment to the local drive.
Add comment
Comments