Good Afternoon All,
About twice a year at my company I have to generate user reports for certain managers. I have no problem generating these reports and sending them to the proper user but this always requires operator action on my teams end. I wanted to see if there was an easier way to do this. My idea was to generate and email these mass reports using a single button. Could I do this through VBA or Macros? Or should I not have to go that route because there is a simpler way?
Thanks guys for any help.
yes, you can. Since you are asking only for direction, and this is not a freelancer group so that you can expect people write the whole code for you, I only give you a part that I already had on one of my files and explain how you should do the rest.
I am not sure the report you have will be presented in Excel, word or any other file, but the main idea would be to write a vba code that runs your queries and collects data and formats it in a way you want. That would be your challenge to figure out the details and you will not get the answer to all of your questions in one single posting.
For the part that you want to email, here is the code that I can help you with:
Sub Email_Recepients(sEMailSubj As String, sPath As String, sBody As String)
Dim olApp As Object
Dim olMail As Object
If bolHandleErrors Then On Error GoTo Handler
Set olApp = CreateObject("Outlook.Application")
' olApp.Visible=True
Set olMail = olApp.CreateItem(0)
With olMail
.To = Mat_EmailAddress
.Subject = sEMailSubj
' .Attachments.Add sPath
' .DeleteAfterSubmit = True
' .HTMLBody = sBody
' .Send
End With
Set olMail = Nothing
Set olApp = Nothing
Application.Wait Now + TimeValue("00:00:04")
Exit Sub
Handler:
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox "Oops! Something went worng. I could not get Outlook to send your message. Please try again later.",vbInformation, "Email HHI Governance Function"
End Sub
some of the lines have been commented out, but you can uncomment them and use them if you wanted to. Make sure you define variables that they use at the beginning of the code.
Related
I want to loop through a list of email addresses and check if they have OOF's turned on (these will be other people's email addresses). Then if possible retrieve the OOF text.
I tried the options of getting the OOF through VBA but with my own trial and error and googling I can see that most people (and myself) realize it's only possible to get your own OOF information.
Sub Check_OOF()
Dim oNS As Outlook.NameSpace
Dim oStores As Outlook.Stores
Dim oStr As Outlook.Store
Dim oPrp As Outlook.PropertyAccessor
Set oNS = Outlook.GetNamespace("MAPI")
Set oStores = oNS.Stores
For Each oStr In oStores
If oStr.ExchangeStoreType = olPrimaryExchangeMailbox Then
Set oPrp = oStr.PropertyAccessor
MsgBox oPrp.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x661D000B")
End If
Next
End Sub
Is this possible with Outlook-Redemption? I can only see the syntax to interact with your own automatic reply.
You will need to use EWS - GetMailTips operation.
Also you can use Redemption, see RDOMailTips object for more information.
Thanks for pointing me in the right direction Eugene, also Dmitry thanks again for redemption.
I installed redemption by downloading here and installing it via the command line (thanks for the clear instructions). I'm using the RDOMailTips object which allowed me to loop through mailbox's and retrieve OOF messages and other helpful information.
Below is an example I quickly wrote to show the basic premise of looping through emails and getting OOF's text and start/end date.
Sub Get_OOF()
Dim session As Redemption.RDOSession
Dim arr As Variant
Set session = CreateObject("Redemption.RDOSession")
session.Logon
session.SkipAutodiscoverLookupInAD = True
arr = Array("user1#email.com", "user2#email.com", "user3#email.com")
For i = LBound(arr) To UBound(arr)
Set AdrEntry = session.AddressBook.ResolveName(arr(i))
Set mailtips = AdrEntry.GetMailTips
Debug.Print mailtips.OutOfOfficeMessage
Debug.Print mailtips.OutOfOfficeEndTime
Debug.Print mailtips.OutOfOfficeStartTime
Next i
Set session = Nothing
Set AdrEntry = Nothing
Set mailtips = Nothing
End Sub
Four things to note
If the person doesn't have an out of office it will return an empty string
If the person hasn't set out of office dates it will return 01/01/4501 which I assume is an error code formatted as a date
You will need to split the string from mailtips.OutOfOfficeMessage as it has a lot of formatting fluff around the out of office text
I didn't need to put my credentials in the parameters of AdrEntry.GetMailTips for this to work. But as the documentation says this is optional for EWS.
I'm trying to use Outlook VBA to check all my emails on startup, and whenever I receive a new email, to see if the email subject is "Sample Daily Data Pull". If the email subject matches, I want outlook to save the attachment to a specified network drive folder. Here is the code I have:
In "ThisOutlookSession"
Option Explicit
Private WithEvents inboxItems As Outlook.Items
Private Sub Application_Startup()
Dim outlookApp As Outlook.Application
Dim objectNS As Outlook.NameSpace
Set outlookApp = Outlook.Application
Set objectNS = outlookApp.GetNamespace("MAPI")
Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
Dim Msg As Outlook.MailItem
If TypeName(Item) = "MailItem" Then
If Item.Subject = "Sample Daily Data Pull" Then
Call SaveAttachmentsToDisk
Else
End If
End If
End Sub
I also have the following code in a module:
Public Sub SaveAttachmentsToDisk(MItem As Outlook.MailItem)
Dim oAttachment As Outlook.Attachment
Dim sSaveFolder As String
sSaveFolder = "N:\SampleFilePath\"
For Each oAttachment In MItem.Attachments
oAttachment.SaveAsFile sSaveFolder & oAttachment.DisplayName
Next
End Sub
This is my first time working in Outlook VBA, so my apologies if it's something very basic and obvious. Not really sure what is going wrong as I'm not getting any error messages. All I know is that the the macro is not saving attachments on my network drive as it should be.
Thanks in advance for any help.
Your code does not work for me because of:
Set inboxItems = objectNS.GetDefaultFolder(olFolderInbox).Items
Outlook saves mail items, calendar items, tasks and other such information in files it calls Stores. You can have several stores each of which will have an Inbox. I am a home user with two email accounts. I did a default installation of Outlook then used a wizard to add an account for each of my email addresses. The result is I had three stores:
Outlook Data File
MyName#myisp.com
MyName#gmail.com
“Outlook Data File” is the default store and contains the default Inbox but new emails are placed in the Inboxes in the other two stores. To test if you have the same problem, open Outlook, open the VBA Editor, type the following into your Immediate Window and press [Return].
? Session.GetDefaultFolder(olFolderInbox).Parent.Name
On my system, this statement outputs “Outlook Data File” because that store contains the default Inbox. If I want to have an event handler for new emails I need to have:
Private Sub Application_Startup()
Set InboxItems = Session.Folders("MyName#myisp.com").Folders("Inbox").Items
End Sub
This is someone shorter than your macro, which I will explain later, but the key difference is I am naming the Inbox I wish to monitor. If the Inbox that receives your new emails is not Outlook’s default Inbox, you will have to name the folder containing the Inbox you wish to monitor.
Why is my macro so much shorter than yours?
Dim outlookApp As Outlook.Application
Set outlookApp = Outlook.Application
You are already within Outlook so these statements are redundant.
You could replace:
Set objectNS = outlookApp.GetNamespace("MAPI")
by
Set objectNS = Application.GetNamespace("MAPI")
But you do not have to. The only GetNamespace is under Application so the qualification is optional. The only qualification that I know to be non-optional is Outlook.Folder and Scripting.Folder. If you write Folder within Outlook it assumes you want one of its folders. If you want to refer to a disk folder you must say so.
You have:
Dim objectNS As Outlook.NameSpace
Set objectNS = outlookApp.GetNamespace("MAPI")
I have used Session. The documentation states that Namespace and Session are identical. I prefer Session but most people seem to prefer Namespace. Your choice.
If you are references the correct Inbox, we need to look further for the cause of your problem.
The next possible issue is If Item.Subject = "Sample Daily Data Pull". This requires Item.Subject be exactly equal to "Sample Daily Data Pull". An extra space or a lower case letter and they are not equal.
Next, I suggest adding a statement at the top of each of procedure to give:
Private Sub Application_Startup()
Debug.Assert False
: : :
Private Sub inboxItems_ItemAdd(ByVal Item As Object)
Debug.Assert False
: : :
Public Sub SaveAttachmentsToDisk(MItem As Outlook.MailItem)
Debug.Assert False
: : :
Many programming languages have an Assertion statement; this is VBA’s version. It allows the programmer to assert that something will be true. Execution will stop if the assertion is false. I find Debug.Assert False invaluable during testing. Debug.Assert False will always be false so execution will always stop. This is an easy way to test that Application_Startup, inboxItems_ItemAdd and SaveAttachmentsToDisk are being executed.
Try the above suggestions. If they fail to find a problem, we will have to try something else.
Error Handling
In your original posting, you had:
On Error GoTo ErrorHandler
: : :
: : :
ExitNewItem:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
You will often see code like this but I have never seen a justification for it.
If an error occurs during development, this code will result in the error number and description being displayed and the routine exited. How is this helpful? It leaves you to guess from the error description which statement failed. If you omit all the error code, execution stops on the faulty statement. There is no guessing as to which statement was in error. If you can fix the error, you can click F5 and restart with the previously faulty statement. Even if you cannot fix and restart, you have a better understanding of the situation.
For a live system, I have difficulty in imagining anything less user friendly than an error resulting in display of a cryptic error message and the macro terminating.
For a live system, you want something like:
Dim ErrNum As Long
Dim ErrDesc As String
On Error Resume Next
Statement that might fail
ErrNum = Err.Num
ErrDesc = Err.Description
On Error GoTo 0
If ErrNum > 0 Then
' For each possible value for ErrNum, code to provide user friendly
' description of what has gone wrong and how to fix it.
End If
VBA is not the ideal language for writing code that fails gracefully but with care you can create some very acceptable error handling code.
I have the following script to run, which sends out an email acknowledgement from a template to external users that contact a shared mailbox. About once or twice a week I encounter the error listed in the Title field.
Would you be able to assist in providing code that would ignore an email address it cannot resolve and, if possible, a message to notify me when this occurs?
Sorry, I set this up a couple of years ago and learned just enough to get this to work :/
Sub AutoReplywithTemplate(Item As Outlook.MailItem)
Dim oRespond As Outlook.MailItem
' Use this for a real reply
' Set oRespond = Item.Reply
' This sends a response back using a template
Set oRespond = Application.CreateItemFromTemplate("C:\Users\dannygonzales\AppData\Roaming\Microsoft\Templates\GMS Technical Support Email Acknowledgment (Default).oft")
With oRespond
.Recipients.Add Item.SenderEmailAddress
.Subject = "GMS Technical Support Acknowledgement"
.HTMLBody = vbCrLf & oRespond.HTMLBody
' includes the original message as an attachment
' .Attachments.Add Item
' use this for testing, change to .send once you have it working as desired
.Send
End With
Set oRespond = Nothing
End Sub
Use the Recipients.ResolveAll method; it will return False if there is a problem with any of the recipient's addresses. You can evaluate Recipient.Resolved for each member of the collection to determine which one is invalid.
I am looking for a VB Script that will "phone home" if the document is open. I have created an empty macro named AutoOpen which executes properly when the document is open.
I would like to collect the time, current user logged in, and computer name and then automatically send an email address with that information. Basically to see who is opening that document.
Is there a way to do that with VB in word?
I haven't seen any php like function calls that send an email out for example mail("blahblah#mail.com", "mysubject", "my text"); That is kind of what I am looking for but in VB
Here is my email code that I use ALL the time.
Sub EmailCopy()
Dim oApp, oMail As Object
On Error Resume Next
Set oApp = CreateObject("Outlook.Application")
Set oMail = oApp.CreateItem(0)
With oMail
.To = "Someone#Somewhere.com.au"
.Subject = "My Subject Title"
.Body = "Here is the information you asked for"
.Send
End With
Set oMail = Nothing
Set oApp = Nothing
End Sub
Try to implement it into your code and post back if you get stuck. You will need a reference to outlook (I am assuming you are sending via outlook? if not you need to use the CDO method posted by Mat's Mug)
Also maybe remove the vbscript tag from your question, this is VBA :)
I am currently in the process of anonymizing emails with vba for a project.
Currently when an email is received I have created a rule which moves the email into a folder, thereafter I run a script using the getlast function, in that specific folder, where I display the newly received email and copy the content of the email and then i paste this into a new email and send to a particular email address. This effectively removes the identifying features of the email.
The final movement to the Rubik's Cube is to find the email signature and replace with blank, in other words delete the signature. I will have the email signatures to do this, however it would be great if someone someone could help with this...
I found this solution.
'I also had to add Word in tools/references of VBA and then Call DeleteSig(msg) after displaying the item.
'http://www.access-programmers.co.uk/forums/showthread.php?t=259417
Sub DeleteSig(msg As Outlook.MailItem)
Dim objDoc As Word.Document
Dim objBkm As Word.Bookmark
On Error Resume Next
Set objDoc = msg.GetInspector.WordEditor
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
If Not objBkm Is Nothing Then
objBkm.Select
objDoc.Windows(1).Selection.Delete
End If
Set objDoc = Nothing
Set objBkm = Nothing
End Sub
It's not very hard, but depend on some properties of the mail:
Is the mail plain text? or html
if HTML, do you have the signature in html format ? (with tags)
I presume you read your mail with a variable of type Outlook.MailItem
' Definition of your mail
Dim OutMail As Outlook.MailItem
dim signature as string
...
with OutMail
.HTMLBody = Replace(.HTMLBody, signature, "")
End with
If the signature you have is not the exact match, it'll be a little more tricky.
I suggest to create a function that detect the signature and return the HTMLBody without it