I am working on a program to look for a specific email in a folder and perform some actions on that email based on a UserForm.
I create and show the UserForm but it is not connected to the email, so I am unable to pass the data from the Userform to the email before the UserForm is unloaded for the next email in the list.
UserForm with redacted information
None of the code is implemented, so I will not include the code here.
If I try to run a script if "Format and Send" is pressed, I am unable to find what email my loop is on as it is in another sub.
Is there a way to access the values of the UserForm in my sub function that creates the UserForm?
Sub nameofSubRedacted()
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = FindInFolders(myNameSpace.Folders, "specific folder")
Dim mail As MailItem
For Each mail In myFolder.Items
If InStr(mail.Subject, "specific text") Then
mail.Display
UserForm_Main.Show
'this is where the form is filled in, and a selection is made.
End If
Next mail
End Sub
You need to change the MessageClass property of the message to match that of the custom form.
You can pass the mailitem as a parameter.
Option Explicit
Sub nameofSubRedacted()
Dim myFolder As Folder
Dim mail As MailItem
Dim replyMail As MailItem
Set myFolder = Session.GetDefaultFolder(olFolderInbox)
For Each mail In myFolder.Items
If InStr(mail.subject, "specific text") Then
mail.Display
UserForm_Main.Show
'this is where the form is filled in, and a selection is made.
Set replyMail = mail.reply
With replyMail
.HTMLBody = "Hello " & UserForm_Main.TextBox1.Value & .HTMLBody
.Display
End With
MsgBox "Preferred name updated." & vbCr & vbCr & _
"Pass replyMail for more processing."
moreProcessing replyMail
End If
Next mail
End Sub
Sub moreProcessing(mailAsParameter As MailItem)
MsgBox "Reply mail with subject:" & vbCr & vbCr & _
mailAsParameter.subject & vbCr & vbCr & _
" has been passed to moreProcessing."
End Sub
Related
I have a client that is using Access 2002 because it allows Replication. He is using this on Windows 10 with Outlook from Office 365.
The goal is to create a new email with all of the info filled in and attach a scanned proposal so that my client can review the email, make any changes that he wants and then send it.
In Access, the SendObject command creates and opens a plain text email and while this email is open my Outlook macro to scan a document and attach it to the email will not run.
So I would like to create a new Outlook email from Access that allows me to run my Outlook macro.
Or if I could get Access 2002 to create an email and attach the scanned document to it, I think I could get by with using msgboxes to verify specific items.
Below is the Access macro with the SendObject command followed by the Outlook macro.
Private Sub EmailProposal_Click()
'Access macro.
Dim stDocName As String
Dim stEmailAddress As String
Dim stSubject As String
Dim stMessage As String
stDocName = "rptProposal"
stEmailAddress = Forms!RequestForm!EmailAddress.Value
stSubject = "PROPOSAL"
stMessage = "Your proposal is attached." & vbCrLf & vbCrLf & "If you have any questions, please call us."
'Email the proposal.
DoCmd.SendObject acReport, stDocName, acFormatRTF, stEmailAddress, , , stSubject, stMessage
End Sub
Sub Scan()
'Outlook macro.
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
On Error Resume Next
Dim objCommonDialog As WIA.CommonDialog
Dim objImage As WIA.ImageFile
Dim strPath As String
Set objCommonDialog = New WIA.CommonDialog
'This shows the dialog box. I'd rather tell it what to do instead of having to manually choose each time.
Set objImage = objCommonDialog.ShowAcquireImage
strPath = Environ("TEMP") & "\TempScan.jpg" 'Save the scan.
If Not objImage Is Nothing Then
objImage.SaveFile strPath ' save into temp file
On Error GoTo ErrHandler
If TypeName(ActiveWindow) = "Inspector" Then
If ActiveInspector.IsWordMail And ActiveInspector.EditorType = olEditorWord Then
ActiveInspector.WordEditor.Application.Selection.Inlineshapes.AddPicture strPath 'Insert into email. I want to attach it instead.
End If
End If
Kill strPath
Else
MsgBox "The Scan macro in Outlook did not find a document." & vbCrLf & vbCrLf & _
"Please place the proposal in the printer so it can be scanned.", vbOKOnly
End If
lbl_Exit:
Set objImage = Nothing
Set objCommonDialog = Nothing
Exit Sub
ErrHandler:
Beep
Resume lbl_Exit
End Sub
It seems you just need to automate Outlook for sending out emails with the required content set up. Take a look at the following articles that give you the basics of Outlook automation:
Automating Outlook from a Visual Basic Application
Automating Outlook from Other Office Applications
Sub Send_Mail_Outlook()
Dim OutApp As Object
Dim OutMail As Object
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "eugene#astafiev.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'You can add a file like this
'.Attachments.Add ("C:\test.txt")
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I was actually going through the below code for counting the attachments from selected emails.
Sub CountAttachmentsinSelectedEmails()
Dim olSel As Selection
Dim oMail As Object
Dim AttCount As Long
Dim strMsg As String
Set olSel = Outlook.Application.ActiveExplorer.Selection
For Each oMail In olSel
'To confirm if the selected items are all emails
If oMail.Class <> olMail Then
strMsg = "Please select mail items only!"
nRes = MsgBox(strMsg, vbOKOnly + vbExclamation)
Exit Sub
End If
'Get the total number of the attachments in selected emails
AttCount = oMail.Attachments.Count + AttCount
Next
strMsg = "There are " & AttCount & " attachments in the " & olSel.Count & " selected emails."
nRes = MsgBox(strMsg, vbOKOnly + vbInformation, "Count Attachments")
End Sub
But this is actually considering the logo in signature and any embedded or inserted pictures in email body and showing the wrong result.
So, here I need help on below two questions:
Is there any way to skip them ?
Is there any code for counting the total documents in a zip or rar file attachment in the email ?
If there is any code, can we include that here ?
Untested but one method would be to loop on all attachments and check if their filename ends with .zip or .rar
Option Explicit
Sub CountAttachmentsinSelectedEmails()
Dim olSel As Selection
Dim oMail As Outlook.MailItem
Dim AttCount As Long
Dim strMsg As String
Dim nRes As Long
Dim objAttach As Outlook.Attachment
Set olSel = Outlook.Application.ActiveExplorer.Selection
For Each oMail In olSel
'To confirm if the selected items are all emails
If oMail.Class <> olMail Then
strMsg = "Please select mail items only!"
nRes = MsgBox(strMsg, vbOKOnly + vbExclamation)
Exit Sub
End If
'Loop on attachements
For Each objAttach In Item.Attachments
'increment counter if the attachement extention is .zip or .rar
If LCase(Right(objAttach.FileName, 4)) = ".rar" Or LCase(Right(objAttach.FileName, 4)) = ".zip" Then
AttCount = AttCount + 1
End If
Next objAttach
Next
strMsg = "There are " & AttCount & " attachments in the " & olSel.Count & " selected emails."
nRes = MsgBox(strMsg, vbOKOnly + vbInformation, "Count Attachments")
End Sub
Both of the things you want to do are a bit tricky.
I don't know if there's a predictable way to determine if a given attachment is a logo or embedded image. There might be, but some quick testing shows that Outlook reports the AttachmentType of the attachment as olByValue (1) regardless if it's a signature, logo, PDF or whatever. You might have luck by "black-listing" specific file-names or attachments, if you identify that all the logo attachments have similar names (e.g., in your count, skip files that are named image001.jpg. Alternatively, you could white-list specific attachments and only show attachments that are Excel, Word, or PDF files, for example.
Regarding ZIP/RAR archives: It seems that VBA doesn't have native support for opening ZIP archives. However, it appears that you can make calls to the shell for processing them. You might want to start searching for something like this.
I'm trying to look through a specific inbox for unread e-mails with .pdf files attached to them, and then save them into a specific folder.
I need to look through the inbox of certain account profile. My code only works if there is just one Inbox folder and one account profile.
Let's say I have two profiles;
One is xxxx#hotmail.com
The second zzzz#hotmail.com
How do I run the code on the Inbox of the second account?
(zzzz#hotmail.com)
The following is the code that I have so far;
Sub GetAttachments()
On Error GoTo GetAttachments_err
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim varResponse As VbMsgBoxResult
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
i = 0
' Checks inbox for messages.
If Inbox.Items.Count = 0 Then
MsgBox "There are no messages in your Inbox.", vbInformation, _
"Nothing found"
Exit Sub
End If
' Checks inbox for unread messages.
If Inbox.UnReadItemCount = 0 Then
"Nothing found"
Exit Sub
End If
' Checks for unread messages with .pdf files attached to them, if yes then saves it to specific folder. _
Puts date and time from when the mail was created infront of the filename.
For Each Item In Inbox.Items
For Each Atmt In Item.Attachments
If Item.UnRead = True Then
If Right(Atmt.FileName, 3) = "pdf" Then
FileName = "C:\Users\XXX\Documents\Office Macro\" & _
Format(Item.CreationTime, "yyyymmdd_hhnnss_") & Atmt.FileName
Atmt.SaveAsFile FileName
i = i + 1
End If
End If
Next Atmt
Next Item
' Shows how many attached files there are if any are found.
If i > 0 Then
& vbCrLf & "Jag har sparat dem till C:\Users\XXX\Documents\Office Macro folder." _
& vbCrLf & vbCrLf & "Would you like to see your files?" _
vbQuestion + vbYesNo, "Finished!")
If varResponse = vbYes Then
Shell "Explorer.exe /e,C:\Users\XXX\Documents\Office Macro\", vbNormalFocus
End If
Else
MsgBox "No attached files could be found.", vbInformation, _
"Finished!"
End If
GetAttachments_exit:
Set Atmt = Nothing
Set Item = Nothing
Set ns = Nothing
Exit Sub
GetAttachments_err:
MsgBox "An unkown ghost spooked the program." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: GetAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume GetAttachments_exit
Exit Sub
End Sub
After further inspection of the mailboxes I see that there are some differences:
xxxx#hotmail.com is of the type "IMAP/SMTP"
zzzz#hotmail.com is of the type "Exchange ActiveSync"
I've also noticed that that the account ID I would need to use is 4, as seen in this code when sending a new message with a test-macro specifying what profile you want to send the mail from by assigning profile ID in the script:
Sub Mail_small_Text_Change_Account()
'Only working in Office 2007-2013
'Don't forget to set a reference to Outlook in the VBA editor
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "blabla#blabla.nl"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'SendUsingAccount is new in Office 2007
'Change Item(1)to the account number that you want to use
.SendUsingAccount = OutApp.Session.Accounts.Item(4) <<<< ACCOUNT ID
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
You get only the delivery store's inbox folder to find the items.
The Stores property of the Namespace class returns a Stores collection object that represents all the Store objects in the current profile. You can find the required store and then use the GetDefaultFolder method of the Store class instead. This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
There is no need to create a new Outlook Application instance in Outlook VBA.
The Outlook object model provides the Find/FindNext or Restrict methods of the Items class. Also you may find the AdvancedSearch method of the Application class helpful.
I am working on a project using excel-vba and outlook.
I am working in an excel workbook. I need to be able to run a macro in order to:
Check if there are unread emails,
Dim oOutlook As Object
Dim oOlns As Object
Dim oOlInb As Object
Const olFolderInbox = 6
'~~> Get Outlook instance
Set oOutlook = GetObject(, "Outlook.application")
Set oOlns = oOutlook.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'~~> Check if there are any actual unread emails
If oOlInb.Items.Restrict("[UnRead] = True").Count = 0 Then
MsgBox "NO Unread Email In Inbox"
Else
MsgBox "Unread Email available In Inbox"
Exit Sub
If there are unread emails ,
I need to check if there are attachments in these unread emails.
If there are attachments,
i need to check if these attachments have an attachment name which contains "Production Plan" as part of the name.
This is because this attachment is sent to me regularly.
The attachment name will be in this manner
Production Plan (day - month - year).xls
If there is such an attachment then a MsgBox should be displayed in excel saying
Msg Box "Such attachments are available"
At this point in time i know how to do part 1 and 4.
I want to know: how to do part 2 and 3?
Please guide me on how this can be done.
update: I have made a small addition, which does not work. This is in order to display a msg, if there are attachments detected, but they are not of the form "Production Plan".
Else
If Not att.Filename Like "Production Plan*.xls" Then
MsgBox "no production plan attachment"
Exit Sub
End If
I don't have Outlook, so untested:
EDIT - to list all attachments
Dim oOutlook As Object
Dim oOlns As Object
Dim oOlInb As Object
Dim unRead, m As Object, att As Object
Dim some As String, other As String
Const olFolderInbox = 6
'~~> Get Outlook instance
Set oOutlook = GetObject(, "Outlook.application")
Set oOlns = oOutlook.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox)
'~~> Check if there are any actual unread emails
Set unRead = oOlInb.Items.Restrict("[UnRead] = True")
If unRead.Count = 0 Then
MsgBox "NO Unread Email In Inbox"
Else
some = ""
other = ""
For Each m In unRead
If m.Attachments.Count > 0 Then
For Each att In m.Attachments
If att.Filename Like "Production Plan*.xls" Then
some = some & vbLf & " - " & att.Filename
Else
other = other & vbLf & " - " & att.Filename
End If
Next att
End If
Next m
If some <> "" Or other <> "" Then
MsgBox "Production Plans:" & vbLf & _
IIf(some <> "", some, "{none}") & _
vbLf & vbLf & "Other files:" & vbLf & _
IIf(other <> "", other, "{none}"), _
vbExclamation, "Unread mails with attachments!"
End If
End If
You may find this mammoth answer from Siddharth Rout useful: Download attachment from Outlook and Open in Excel
We get hundreds of invoices emailed in per day - all are PDF format, and for most members of my dept, they're doing nothing more than marking them as read and moving them to a folder. My folder is called "invoices" and is a subfolder to my Inbox. I have written the following code, it throws an error 424 on the lines:
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
All I'm trying to do is check if an email is unread and has a pdf attachment, then move it to my "invoices" folder. Code follows:
Sub Lazy()
On Error GoTo Lazy_err
' Declare the variables
Dim ns As NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim Item As Object
Dim Atmt As Attachment
Dim i As Integer
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = myInbox.Folders("invoices")
i = 0
' If statement to check if there's any unread emails in the box
If Inbox.UnReadItemCount = 0 Then
MsgBox "There are no unread messages in your Inbox.", vbInformation, _
"Nothing Found"
Exit Sub
End If
For Each Item In Inbox.Items
If Item.UnRead = True Then
For Each Atmt In Item.Attachments
If Right(Atmt.FileName, 3) = "pdf" Then
myItem.Move myDestFolder
Item.UnRead = False
i = i + 1
End If
Next Atmt
' close off If statements, then move to next item and start again
End If
Next Item
' Display a summary message!
If i > 0 Then
MsgBox "I found " & i & " emails." _
& vbCrLf & "I have moved them into the correct folder." _
& vbCrLf & vbCrLf & "Maybe double check to make sure nothing else has been moved?", vbInformation, "Finished!"
Else
MsgBox "There's nothing to find", vbInformation, _
"Finished!"
End If
' Housekeeping - reset everything for next time macro is run
Lazy_exit:
Set Atmt = Nothing
Set Item = Nothing
Set ns = Nothing
' Exit the macro :)
Exit Sub
' Error Handler - goes at very end of script, even after "exit sub"
Lazy_err:
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: SaveAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume Lazy_exit
End Sub
First of all, you need to correct the namespace variable name as Paul suggested:
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = ns.GetDefaultFolder(olFolderInbox)
Then I have noticed the following lines of code:
For Each Item In Inbox.Items
If Item.UnRead = True Then
Don't iterate over all items in the folder. It will take a lot of time and may cause issues related to not releasing objects in time. Use the Find/FindNext or Restrict methods of the Items class instead. You can read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
You have created/initialized a Namespace Object variable ns, but not myNameSpace. Make sure you modify your code to reference appropriate objects.
Sub Lazy()
On Error GoTo Lazy_err
' Declare the variables
Dim ns As NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim Item As Object
Dim Atmt As Attachment
Dim i As Integer
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = ns.GetDefaultFolder(olFolderInbox)
'Code continues...