ActiveExplorer/Inspector selecting more than one item - vba

I'm trying to tell Outlook to select only one mail item, but it appears to be selecting multiple (The internal program I'm sending it to is referencing "These documents" rather than "this document"). Because of that, it's not letting me choose a file type and I believe it's because the program is interpreting the file as a container instead of a file. tl;dr: Can anyone see anything in my code that would be allowing Outlook to select more than one mail item?
Dim objApp As Outlook.Application
Set objApp = Application
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
If objApp.ActiveExplorer.Selection.Count > 0 Then
Set currentItem = objApp.ActiveExplorer.Selection.Item(1)
Else
MsgBox ("No Message Selected.")
Exit Sub
End If
Case "Inspector"
Set currentItem = objApp.ActiveInspector.currentItem
Case Else
MsgBox ("Please select a mail item.")
Exit Sub
End Select

Looks like you need to iterate over all items selected in the Explorer window:
Set currentItem = objApp.ActiveExplorer.Selection.Item(i)
For example:
For i = 1 To oSel.Count ' Loop through all the currently .selected items
Set oItem = oSel.Item(i) ' Get a selected item.
Next i
Take a look at the How To Get the Currently Selected Item in an Outlook Folder from Visual Basic article for the sample code.
Also I'd suggest breaking the chain of calls and declaring each property or method call on a separate line of code.

Related

How to run an Outlook VBA only when creating a New e-mail?

I have written an Outlook VBA action to count the words in an e-mail body and place this count in the subject. This runs fine, however I would like this to only run for new e-mails, and not fire when writing a response as a reply, reply all, or forward.
Code runs fine but runs for all types of e-mails: replies, new, forwarding and I need it to only run for new e-mail.
Thank you
The EntryID property is blank for newly created items in Outlook.
Also you may consider handling the Reply, Forward, ReplyAll events of the MailItem class to detect cases when you shouldn't count words.
Maybe like:
Sub GetReplyType()
Dim objItem As Object
Set objItem = Application.ActiveInspector.CurrentItem
If objItem.Class = olMail Then
Select Case objItem.Verb
Case olReply
MsgBox "The current item is a Reply."
Case olReplyAll
MsgBox "The current item is a ReplyAll."
Case olForward
MsgBox "The current item is a Forward."
Case Else
MsgBox "The current item is not a Reply, ReplyAll or Forward."
End Select
End If
End Sub

Outlook VBA fails to save changes to MailItem on older items only

I have a macro in Outlook VBA that is designed to set the category of the selected email and send a reply email to the sender when a user clicks a button on the "Ribbon".
The below code will properly set the category on any newer emails, but throws "Run-time error '440': Cannot save this item." when run on emails that have been sitting around for a while. I don't know what causes this, as it runs fine for a while and then no longer works.
I tried restarting Outlook, logging in and logging out, and restarting the computer, and none of these seem to trigger the change in behavior, so I believe it is somehow related to the duration that the email has been sitting. This is rather confusing, as I don't see why length of time sitting in the folder should affect the ability to save, but not the ability to access the properties of the MailItem.
A simplified version of the code (without the email-sending part, which works fine) is as follows:
Public Sub UpdateCategory
Dim objItem as Object
Set objItem = GetCurrentItem()
'Verify that selected item is an email and an engineering request
If TypeName(objItem) = "MailItem" And InStr(LCase(objItem.Subject), "engineering request") > 0 Then
objItem.Categories = "Test"
objItem.Save
End If
Set objItem = Nothing
End Sub
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
Any thoughts or suggestions would be greatly appreciated!!
Is this is an Exchange mailbox, it is possible that Exchange modified the item on the server side, that change was downloaded to the OST file, but since Outlook Object Model is not aware of the change, when you try to save the (stale) item, you get a conflict error.

Add attachment to all selected items in Outlook 2016 with VBA

I aim to add an attachment to every item that is currently selected in Outlook 2016. My idea is to call Attachments.Add in a loop on each item in the current selection.
In my Drafts folder, I have three drafts with the subjects:
Draft Test 3
Draft Test 2
Draft Test 1
Because of the environment that I am in, I cannot use C#. I am using VBA instead. I ran all the test code by clicking Developer > Macros > [sub name] in the Outlook 2016 ribbon.
I started with this:
Sub AddTestTxtToSelection1()
Dim i As Long
With Application.ActiveExplorer.Selection
For i = .Count To 1 Step -1
.Item(i).Attachments.Add "C:\Full\Path\To\Test.txt", olByValue, 1
Next
End With
End Sub
Unfortunately, Test.txt was only attached to Draft Test 3 although all three drafts were selected. I thought that I might be iterating through the selection incorrectly, so I tried this:
Sub AddTestTxtToSelection2()
For Each objMessage In Application.ActiveExplorer.Selection
objMessage.Attachments.Add "C:\Full\Path\To\Test.txt", olByValue, 1
Next
End Sub
Again, although all three drafts were selected, Test.txt was only attached to Draft Test 3. In the example code in this article, Application.ActiveExplorer and its Selection property are stored in separate variables. I thought that that might have been what was missing, so I wrote this:
Sub AddTestTxtToSelection3()
Dim myOlExp As Explorer
Dim myOlSel As Selection
Set myOlExp = Application.ActiveExplorer
Set myOlSel = myOlExp.Selection
Dim i As Long
For i = 1 To myOlSel.Count
myOlSel.Item(i).Attachments.Add "C:\Full\Path\To\Test.txt", olByValue, 1
Next
End Sub
The behavior was identical to that of the first two tests. Finally, it occurred to me that the problem might be with modifying the drafts as I was looping over them. I then wrote this code, which stores the EntryID properties of the selected items in a separate string array before looping over them:
Sub AddTestTxtToSelection4()
Dim i As Long
Dim strEntryID As Variant
Dim namespaceMAPI As NameSpace
Dim objMessage As Object
Dim selected() As String
' Copy the current selection into an array of EntryID strings.
ReDim selected(1 To Application.ActiveExplorer.Selection.Count) As String
For i = 1 To Application.ActiveExplorer.Selection.Count
selected(i) = Application.ActiveExplorer.Selection.Item(i).EntryID
Next
' Retrieve each item from its EntryID string.
Set namespaceMAPI = Application.GetNamespace("MAPI")
namespaceMAPI.Logon
For Each strEntryID In selected
Set objMessage = namespaceMAPI.GetItemFromID(strEntryID)
objMessage.Attachments.Add "C:\Full\Path\To\Test.txt", olByValue, 1
Next
End Sub
Again, only Draft Test 3 had Test.txt attached after running this code. I thought that Outlook might be having trouble attaching the same file to multiple drafts, so I modified the last test to attach a different file to each draft. Only Draft Test 3 had an attachment after it was executed. Even if I swap out Application.ActiveExplorer.Selection for Application.ActiveExplorer.CurrentFolder.Items, still only the first draft gets an attachment.
Why can't Outlook attach a file to more than one mail item at a time? Is there a workaround?
Certain actions require a .Save.
There is likely a correlation with actions that require a save when done manually. In this case if you were to manually attach a file then close the draft you would be asked if the draft should be saved.
I have accepted #niton's answer, but here is my code after adding .Save:
' Based on AddTestTxtToSelection2
Sub AddTestTxtToSelection5()
For Each objMessage In Application.ActiveExplorer.Selection
objMessage.Attachments.Add "C:\Full\Path\To\Test.txt", olByValue, 1
objMessage.Save ' This line was added.
Next
End Sub
The attachments get added to every selected message now.

Writeable active inline response in outlook

I have the following code from some blog that inserts HTML from the clipboard into an outlook email.
Sub PrependClipboardHTML()
Dim email As Outlook.MailItem
Dim cBoard As DataObject
Set email = Application.ActiveInspector.CurrentItem
Set cBoard = New DataObject
cBoard.GetFromClipboard
email.HTMLBody = cBoard.GetText + email.HTMLBody
Set cBoard = Nothing
Set email = Nothing
End Sub
It works great except that the email has be in its own window (i.e. popped-out) otherwise it will fail.
I was looking around on the documentation and found Application.ActiveExplorer.ActiveInlineResponse here.
However the documentations says that it is read-only, and indeed it does not work. Is there way to get a writable version of the inline response?
It works great except that the email has be in its own window (i.e. popped-out) otherwise it will fail.
That is because you have the following statement in the code:
Set email = Application.ActiveInspector.CurrentItem
However the documentations says that it is read-only, and indeed it does not work.
Try to use the following code instead:
Set email = Application.ActiveExplorer.ActiveInlineResponse
The ActiveInlineResponse property is read-only, but not the object's properties you are going to use. That means you can't set another mail item to the inline response, but will be able to set up properties of the retrieved item.
Maybe you're trying to work with ActiveExplorer + Selection.Item Method (Outlook)
Example
Option Explicit
Public Sub Example()
Dim email As Outlook.MailItem
Set email = Application.ActiveExplorer.Selection.Item(1)
Debug.Print email.Subject ' print on immediate window
End Sub
Or Work with both opened and selected items
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
You cannot concatenate two HTML strings and expect a valid HTML back. The two must be merged.
That being said, use Word Object Model to paste from the clipboard:
Application.ActiveEXplorer.ActiveInlineResponseWordEditor.Application.Selection.Paste()

Whenever a mail is sent from Outlook 2010 that mail should move to dedicated folder in Outlook, using VBA/Macros

I have already wrote a code where the when ever a email comes from a definite email ID to outlook my ID it gets sent to anothee email address automatically by using one rule.
Now I have to add one feature. This mail which is sent is also saved in a dedicated folder other than sent items. All this in one script.
This my current script where only the mail goes automatically. Now I need help to add the dedicated folder feature.
Sub Project_1()
Dim objMail As Outlook.MailItem
Set objItem = GetCurrentItem()
Set objMail = objItem.Forward
objMail.To = "inbox#email.com"
objMail.Display
objMail.Send
Set objItem = Nothing
Set objMail = Nothing
End Sub
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
Case Else
End Select
End Function
I am very new to VBA.
As #destination-data stated above, the whole task will be much easier through outlooks rules.
This article is a step-by-step guide on how to set rules for moving certain mails based on conditions. Additionally you can easily add a "forward" rule, since all your desired functionality is already implemented into outlook and one should avoid rewriting existing tools.
According to your description, this should accomplish the exact same thing as intended by your code.