Outlook VBA, display title in MsgBox - vba

I have written the following module to display the Subject of an email that is currently open in Outlook, in a MsgBox.
Outlook 2010. Version 14.0.7140.5002.
I am getting a run-time error '424' Object Required.
With the debugger highlighting:
Set objItem = objApp.ActiveInspector.CurrentItem
Code is below:
Sub ShowTitle()
Dim objMail As Object
Set objItem = objApp.ActiveInspector.CurrentItem
Dim Title As String
Set objMail = objItem.Subject
Title = objItem
MsgBox (Title)
End Sub

Sub ShowTitle()
Dim objMail As Object
Set objItem = objApp.ActiveInspector.CurrentItem
Dim Title As String
Title = objItem.Subject
MsgBox (Title)
End Sub

Try this untested code.
Option Explicit
Sub ShowTitle()
'Dim objApp as Outlook.Application
Dim objItem As Object
Dim Title As String
' If exclusively in Outlook there is no need for objApp
'Set objApp = Outlook.Application
'Set objItem = objApp.ActiveInspector.CurrentItem
' or simpler
'Set objItem = Application.ActiveInspector.CurrentItem
' or simplest
Set objItem = ActiveInspector.CurrentItem
If objItem is mailitem then
Title = objItem.Subject
MsgBox (Title)
End if
'Set objApp = Nothing
Set objItem = Nothing
End Sub

Diane Poremsky over at Slipstick answered this one well in this article. Per her answer, make one module that contains this function:
Function GetCurrentItem() As Object
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
End Select
Set objApp = Nothing
End Function
Then, also per her answer, call that function with this line in your macro:
Set objItem = GetCurrentItem()
So, modifying your code, I made a second macro like this, which works for me:
Sub subjectLine()
Dim Title As String
Set objItem = GetCurrentItem()
Title = objItem.subject
MsgBox (Title)
End Sub
This way, you can run subjectLine() on either a selected email or an open email.

Related

How to send mail based on a draft then keep the draft?

We are updating mails from the drafts folder and sending them a few times a day.
I want to open a selected mail resend it save it so it goes back to drafts and then close it.
I tried below
Sub DRAFT()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olResendMsg As Outlook.MailItem
' get current item & open if needed
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = Application.ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = Application.ActiveInspector.CurrentItem
Case Else
End Select
On Error GoTo 0
If myItem Is Nothing Then
MsgBox "Could not use current item. Please select or open a single email.", _
vbInformation
GoTo exitproc
End If
' run the resend command
Set objInsp = myItem.GetInspector
objInsp.CommandBars.ExecuteMso ("ResendThisMessage")
' save orig email
myItem.Save
' close orig email
myItem.Close
exitproc:
Set myItem = Nothing
Set objInsp = Nothing
Set objActionsMenu = Nothing
Set olResendMsg = Nothing
End Sub
You need to pass a OlInspectorClose enumeration value to the MailItem.Close method. It indicates the close behavior, i.e. the save mode. If the item displayed within the inspector has not been changed, this argument has no effect.
Name Value Description
olDiscard 1 Changes to the document are discarded.
olPromptForSave 2 User is prompted to save documents.
olSave 0 Documents are saved.
So, your code should like that:
' close orig email
myItem.Close olSave
Instead of executing the ribbon control programmatically using the CommandBars.ExecuteMso method you may try to create a cope of the source item and then send it.
The ExecuteMso method is useful in cases where there is no object model for a particular command. Works on controls that are built-in buttons, toggleButtons and splitButtons. On failure it returns E_InvalidArg for an invalid idMso, and E_Fail for controls that are not enabled or not visible.
Instead, you may use the MailItem.Copy method which creates another instance of an object.
Sub CopyItem()
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myNewFolder As Outlook.Folder
Dim myItem As Outlook.MailItem
Dim myCopiedItem As Outlook.MailItem
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myNewFolder = myFolder.Folders.Add("Saved Mail", olFolderDrafts)
Set myItem = Application.CreateItem(olMailItem)
myItem.Subject = "Speeches"
Set myCopiedItem = myItem.Copy
myCopiedItem.To = "email#address.com"
myCopiedItem.Send()
End Sub
Although there is a mistake in myItem.Close, you cannot resend mail that has not been sent.
Option Explicit
Sub SendMailBasedOnPermanentDraft()
Dim myItem As MailItem
Dim objInsp As Inspector
Dim myCopyOfUnsentItemInDrafts As MailItem
' get current item & open if needed
On Error Resume Next
Select Case TypeName(ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
On Error GoTo 0
If myItem Is Nothing Then
MsgBox "Could not use current item. Please select or open a single email.", vbInformation
GoTo exitProc
End If
If myItem.Sent = False Then
Set myCopyOfUnsentItemInDrafts = myItem.copy
With myCopyOfUnsentItemInDrafts
.Subject = "Copied " & Now & ": " & myItem.Subject
.Save
.Display ' change to .Send
End With
Else
MsgBox "Select or open a single unsent email.", vbInformation
End If
exitProc:
Set myItem = Nothing
Set objInsp = Nothing
Set myCopyOfUnsentItemInDrafts = Nothing
End Sub

Move Email with ItemAdd

I'm attempting to move email with specific subject when received.
The mail is still in my Inbox. I've tested by sending mail from my account with specific subject.
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 Items_ItemAdd(ByVal item As Object)
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
Set myInbox = GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
If TypeName(item) = "MailItem" Then
Set Msg = item
If InStr(0, Msg.Subject, "Testing Subject", vbTextCompare) > 0 Then
Set fldr = Outlook.Session.GetDefaultFolder(olFolderInbox).Folders("Testing")
Msg.Move fldr
End If
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
I created this macro in ThisOutlookSession.
I think you may have an error with the naming of your Sub which means it doesn't fire
Items_ItemAdd => inboxItems_ItemAdd
As an addendum: I recently implemented a RegEx filter to incoming e-mails as I found I couldn't easily use rules to filter out some junk e-mail coming my way. This should be able to adapted to your needs (I've added the rule I think should work for you, but it's untested)
Within the 'ThisOutlookSession'
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
On Error Resume Next
Call RegExFilterRules(EntryIDCollection)
End Sub
Within a module
Sub RegExFilterRules(ItemID As String)
' Requires Reference: Microsoft Scripting Runtime
Dim ThisNamespace As Outlook.NameSpace: Set ThisNamespace = Application.GetNamespace("MAPI")
Dim Inbox As Outlook.MAPIFolder: Set Inbox = ThisNamespace.GetDefaultFolder(olFolderInbox)
Dim Junk As Outlook.MAPIFolder: Set Junk = ThisNamespace.GetDefaultFolder(olFolderJunk)
Dim oMsg As Outlook.MailItem: Set oMsg = ThisNamespace.GetItemFromID(ItemID, Inbox.StoreID)
If Not oMsg Is Nothing And oMsg.Class = olMail Then
'If FindPattern(oMsg.Subject, "^M\d+$") Then oMsg.Move Junk ' oMsg.Delete
If FindPattern(oMsg.Subject, "^Testing Subject") Then oMsg.Move Inbox.Folders("Testing")
End If
End Sub
Private Function FindPattern(Str As String, Pattern As String) As Boolean
Dim RegEx As Object: Set RegEx = CreateObject("vbscript.RegExp")
With RegEx
.Global = True
.IgnoreCase = True
.MultiLine = True
.Pattern = Pattern
FindPattern = .Test(Str)
End With
End Function

Delete automatic Signature from forwarded emails VBA macro

Newbie Outlook VBA. intermediate Excel VBA. Windows 7 Professional, Outlook 2010
I have a script running from a rule that autoforwards all incoming emails. I need it as a rule because otherwise it will not forward the mails in the queue when Outlook loads.
I would like to have the default signature deleted when the mails are forwarded. As the reply is "blank" it is unnecessary to have the sig appended. I have found some code that supposedly worked in Outlook 2007 from the MSDN site. It compiles no errors, executes no errors. I have referenced MS Word in VBA. But the forwarded emails all have the signature still attached.
I cannot just delete the signature because I need it to be there on replies. The switch for the signature is for both replies and forwarded mail.
Here is the code:
Option Explicit
Sub Incoming3(MyMail As MailItem)
Dim strID As String
Dim strSender As String
Dim StrSubject As String
Dim objItem As Outlook.MailItem
Dim myItem As Outlook.MailItem
strID = MyMail.entryID
Set objItem = Application.Session.GetItemFromID(strID)
strSender = objItem.SenderName
StrSubject = objItem.Subject
StrSubject = strSender + ": " + StrSubject
objItem.Subject = StrSubject
objItem.AutoForwarded = False
Set myItem = objItem.Forward
myItem.Recipients.Add "bcc.hwb#gmail.com"
myItem.DeleteAfterSubmit = True
Call DeleteSig(objItem)
myItem.Send
Set myItem = Nothing
Set objItem = Nothing
End Sub
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
Any help with Outlook or VBA code would be much appreciated.
Processing the wrong mail in DeleteSig.
myItem.DeleteAfterSubmit = True
Call DeleteSig(myItem)
myItem.Send
Edit 2015 02 26
Debugging VBA Code
Private Sub Incoming3_test()
' Open a mailitem then click F8 repeatedly from this code
Dim currItem As MailItem
Set currItem = ActiveInspector.currentItem
Incoming3 currItem
End Sub
Sub Incoming3(MyMail As MailItem)
Dim myItem As Outlook.MailItem
Set myItem = MyMail.Forward
myItem.Subject = MyMail.senderName & ": " & MyMail.Subject
myItem.Recipients.Add "bcc.hwb#gmail.com"
myItem.DeleteAfterSubmit = True
myItem.Display ' If you are using F8 you can
' view the action taken in DeleteSig.
' Delete the line later.
Call DeleteSig(myItem)
'myItem.Send
Set myItem = Nothing
End Sub
Sub DeleteSig(msg As Outlook.MailItem)
Dim objDoc As Word.Document
Dim objBkm As Word.Bookmark
On Error Resume Next '<--- Very bad without On Error GoTo 0
Set objDoc = msg.GetInspector.WordEditor
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
On Error GoTo 0
If Not objBkm Is Nothing Then
objBkm.Select ' <--- This is where the action starts.
objDoc.Windows(1).Selection.Delete
End If
Set objDoc = Nothing
Set objBkm = Nothing
End Sub
Edit 2015 02 26 - End
When you assign a VBA macro sub to run by the rule you get an instance of the MailItem object. For example:
Sub Incoming3(MyMail As MailItem)
The MyMail object represents an incoming email message which you should use in the code. But I see that you get a new instance:
strID = MyMail.entryID
Set objItem = Application.Session.GetItemFromID(strID)
There is no need to do so. Use the MyMail object in the code.
Also I see the following code:
Set objBkm = objDoc.Bookmarks("_MailAutoSig")
Try to run the code under the debugger and see whether the bookmark can be found. If there is no such bookmark you need to search the body for the first entry From: in the text and delete all the content before that keyword.
Finally, you may find the Getting Started with VBA in Outlook 2010 article in MSDN helpful.

VBA Outlook How to add hyperlink into email body

This macro adds hyperlink to email :
Sub test_add_hyperlink()
Dim NewMail As Outlook.MailItem
Set NewMail = Application.ActiveInspector.CurrentItem
NewMail.HTMLBody = "<HTML><BODY><A href=http://www.someaddress.com>URL_TEXT</A></BODY></HTML>" & NewMail.HTMLBody End Sub
but how to add hyperlink in place where active cursor is ? I ask beacause I would like to add hyperlink not at the front of message, but where my currently writing message.
The hyperlink I would like to add is the hyperlink to file which is currently copied to Windows' clipboard, this part I've written, but I can't figure out how to place it not at the front of email, but in place where active cursor is. I think that macro based emulation of Windows' keypressing is one of the directions to follow.
This describes how to paste at the selection.
http://www.slipstick.com/developer/code-samples/paste-formatted-text-vba/
Sub PasteFormattedClipboard()
Dim objItem As Object
Dim objInsp As Outlook.Inspector
Dim objWord As Word.Application
Dim objDoc As Word.Document
Dim objSel As Word.Selection
Set objItem = Application.ActiveInspector.CurrentItem
Set objInsp = objItem.GetInspector
Set objDoc = objInsp.WordEditor
Set objWord = objDoc.Application
Set objSel = objWord.Selection
objSel.PasteAndFormat (wdFormatOriginalFormatting)
Set objItem = Nothing
Set objInsp = Nothing
Set objDoc = Nothing
Set objWord = Nothing
Set objSel = Nothing
End Sub
Sub InsertHyperlinkAtCursorPositon()
On Error GoTo finish
strLink = "http://www.outlookcode.com"
strLinkText = "Get Outlook code samples here"
Set objInsp = Application.ActiveInspector
Set objMsg = objInsp.CurrentItem
Set objDoc = objInsp.WordEditor
Set objSel = objDoc.Windows(1).Selection
If objMsg.BodyFormat <> olFormatPlain Then
objDoc.Hyperlinks.Add objSel.Range, strLink, _
"", "", strLinkText, ""
Else
objSel.InsertAfter strLink
End If
finish:
End Sub

Inserting text into incoming email Outlook 2013 locked read only

I'm struggling to insert a string in an incoming email via VBA. The routine works fine when sending mail and it will work on incoming mail if the user clicks Actions Edit. The issue is that incoming mail is locked in read only mode. I've spent the past 13.5 hours searching everywhere. It is possible in earlier versions of Outlook, however Microsoft have removed the CommandBar functionality in Office 2013. Basically I need a way to allow the mail to be editable via a setting in VBA.
Here is the routine
Sub StampReference()
Dim objOL As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objDoc As Word.Document
Dim objSel As Word.Selection
strFullReference = "Reference: " & Reference
On Error Resume Next
Set objOL = Application
If objOL.ActiveInspector.EditorType = olEditorWord Then
Set objDoc = objOL.ActiveInspector.WordEditor
Set objNS = objOL.Session
Set objSel = objDoc.Windows(1).Selection
objSel.Move wdStory, -1
objDoc.Characters(1).InsertBefore _
strFullReference & vbCrLf & vbCrLf
objSel.Move wdParagraph, 1
End If
Set objOL = Nothing
Set objNS = Nothing
End Sub
EDIT
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
I've cracked it! Here is the way to change the mode for anyone interested. It is quick and dirty, however it shows how it can be done. I took some code that someone had written to do a Resend and played around with variants to stumble across the correct value to edit. I call this routine just before stamping the information in
Sub SetEditMode()
Dim myItem As Outlook.MailItem
Dim objInsp As Outlook.Inspector
Dim objActionsMenu As Office.CommandBarControl
Dim olNewMailItem As Outlook.MailItem
On Error Resume Next
Select Case TypeName(Application.ActiveWindow)
Case "Explorer"
Set myItem = ActiveExplorer.Selection.Item(1)
myItem.Display
Case "Inspector"
Set myItem = ActiveInspector.CurrentItem
Case Else
End Select
If myItem Is Nothing Then GoTo ExitProc
'edit mode
Set objInsp = ActiveInspector
objInsp.CommandBars.ExecuteMso ("EditMessage")
objActionsMenu.Execute
ExitProc:
End Sub
user2970334