What does CreateItem do in VBA for outlook emails? - vba

Why do we use CreateItem to create a MailItem in VBA as opposed to the New keyword? More generally, what’s the difference between the two methods? I noticed that to create an instance of the app we do:
Set OutlookApp = New Outlook.Application
However for the MailItem we do:
Set OutlookEmail = OutlookApp.CreateItem(olMailItem)
Tried the above method and it worked but am wondering why it works like that.

They are entirely different lines of code. In the first case a new Outlook Application instance is created:
Set OutlookApp = New Outlook.Application
That is actually all what you could do with the New operator and Outlook object model. Everything else is retrieved from using methods and properties available in the Outlook object model. For example, there are several ways of creating a new MailItem instance:
Set OutlookEmail = OutlookApp.CreateItem(olMailItem)
And
Set OutlookEmail = folder.Items.Add(olMailItem)
The difference is where the item will be saved when calling Save().
You can read more about possible ways of creating Outlook items in the article which I wrote for the technical blog, see How to create and show a new Outlook mail item programmatically: C#, VB.NET.

Related

Is it possible to find related emails and loop the results in the background?

I'd like to find related emails to the email I have currently selected. Then I want to loop the results.
Using the ActiveExplorer.Search takes a moment, and at the same time the code keeps running. So it doesn't return any results, because of loading still happening in the background, I guess.
So my questions are:
How do I find related emails?
How do I loop the search results (in the background)?
To find related emails, maybe something like this:
Sub FindRelatedEmails()
Dim ns As Outlook.NameSpace
Set ns = myOlApp.GetNamespace("MAPI")
Dim oMail As Outlook.MailItem
Set oMail = ActiveExplorer.Selection.Item(1)
Dim strFrom As String
strFrom = oMail.SenderName
Dim strSubject As String
strSubject = oMail.ConversationTopic
Dim myOlApp As New Outlook.Application
Set myOlApp.ActiveExplorer.CurrentFolder = ns.GetDefaultFolder(olFolderInbox)
Dim txtSearch As String
txtSearch = "[Konversation]:=""" & strSubject & """"
myOlApp.ActiveExplorer.Search txtSearch, olSearchScopeAllFolders
' Problem occurs below, since the code keeps running but the search results haven't loaded yet.
myOlApp.ActiveExplorer.SelectAllItems
Dim i As Long
For i = ActiveExplorer.Selection.Count To 1 Step -1
Dim Item As MailItem
Set Item = ActiveExplorer.Selection.Item(i)
Debug.Print Item.Subject, Item.Sender, Item.Parent.FolderPath
Next
Set ns = Nothing
Set oMail = Nothing
Set myOlApp = Nothing
Set Item = Nothing
End Sub
Try to use Application.AdvancedSearch instead - it exposes Application.AdvancedSearchComplete event.
The Explorer.Search method is used to perform a Microsoft Instant Search on the current folder displayed in the Explorer using the given Query. Basically, it will use Outlook UI for searching items and the result is visible in Outlook. The functionality of Explorer.Search is analogous to the Search button in Instant Search. It behaves as if the user has typed the query string in the Instant Search user interface and then clicked Search. When calling Search, the query is run in the user interface, and there is no programmatic mechanism to obtain the search results. The Search method does not provide a callback to enable the developer to determine when the search is complete.
Instead, you may find the Find/FindNext or Restrict methods of the Items class helpful. Read more about them 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
Also you may consider using the AdvancedSearch method of the Application class helpful. The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
The Outlook Object Model provides the AdvanvedSearchComplete event of the Application class. An instance of the Search class containing the search results is passed to the event handler (see the Results property).
See Advanced search in Outlook programmatically: C#, VB.NET for more information.

VB: Generate E-Mail via outlook

Microsoft outlines how to leverage the Microsoft.Office.Interop.Outlook namespace quite well. example
I currently have a window form app created in VB, with a series of text fields requiring input. Upon submission of form, I have a text file that is created locally, but I also want to chain that event with the creation of an email, in a template fashion, having the user values embedded in the body of said email.
In my initial testing, to simply just generate the email, I have imported the appropriate function based on MS's documentation.
Imports Outlook = Microsoft.Office.Interop.Outlook
However when I enter the code provided after my text file creation code, there are many errors highlighted. I was prompted to create a friendclass for "Office."
Build does not like the CType(Application.CreateItem(Outlook.OlItemType - I observe the error CreateItem is not a member of Application.
Is this due to the windows form I selected when building this project?
Dim mail As Outlook.MailItem = CType(Application.CreateItem(Outlook.OlItemType.olMailItem), Outlook.MailItem)
Any help would be appreciated..
this appears to work - different approach but appears to work..
Dim oApp As Outlook.Application
oApp = New Outlook.Application
Dim oMsg As Outlook.MailItem
oMsg = oApp.CreateItem(Outlook.OlItemType.olMailItem)
oMsg.Recipients.Add("test#test.com")
oMsg.Subject = "test"
oMsg.HTMLBody = "<HTML><BODY>test - test</BODY></HTML>"
oMsg.Display()
now it is to figure out how to define a variable within the htmlbody section...

Get autocomplete address list of Outlook in VBA

I am trying to add all my "autocompleted addresses" to a new contact folder but I can't get those addresses. What I call "autocompleted addresses" are the addresses saved when you send an email to somebody and you type it again in the "To" field of a new email.
I know I can get all the Global Address List by using
Set objOutlook = CreateObject("Outlook.Application")
Set myNameSpace = objOutlook.GetNamespace("MAPI")
Set GAL = myNameSpace.AddressLists("Offline Global Address List")
But how can I get my autocompleted addresses ?
I am using Outlook 2010 and my account is an Exchange Account.
Thank you for your help and your time.
EDIT
My complete code :
Set objOutlook = CreateObject("Outlook.Application")
Set myNameSpace = objOutlook.GetNamespace("MAPI")
Set folder = myNameSpace.GetDefaultFolder(OlDefaultFolders.olFolderInbox)
Set storage = folder.GetStorage("IPM.Configuration.Autocomplete", OlStorageIdentifierType.olIdentifyByMessageClass)
Set propacc = storage.PropertyAccessor
Set got = propacc.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7C090102")
Problem : got is empty...
instead of
Set got = propertyAcc.GetProperty(yadayada)
Don't use Set... just
got = propertyAcc.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7C090102")
This will give a zero-based array of the bytes used in the text stream.
got(0) = 13
got(1) = 240
etc etc...
From there, you can analyze each byte to get the text... but it would be very very ugly to parse it all out, when Redemption does that for you. In fact, if you've gotten this far in the post, then you've probably sorted out that it would be a better use of time to figure out how to use Redemption than to build your own parser for this purpose.
Autocomplete (nickname) stream is stored in a hidden (associated) message with the message class of "IPM.Configuration.Autocomplete" in the Inbox folder. Its format is documented at https://msdn.microsoft.com/en-us/library/office/ff625288.aspx. You can access that message using MAPIFolder.GetStorage.
If using Redemption is an option (I am its author), it exposes nicknames through the RDOStore / RDOSession.Nicknames collection.
Also note that in case of Outlook VBA you do need to create an instance of the Outlook.Application object, you already have an intrinsic Application variable pointing to that object.

Extract email metadata with VBA script

I have a folder full of emails that are a custom message class (iXOS-Archive, related to OpenText Enterprise Archive). Each email has a custom metadata property, visible within Outlook, called "Document Identifier". I'm trying to extract this from the emails using a VBA script. I found a script that extracts common metadata (To, From, Subject etc.) from the emails and writes it to Excel. This works well.
http://spreadsheetpage.com/index.php/tip/getting_a_list_of_file_names_using_vba/
I've tried debugging the script and looking within the email properties, but I cannot find any collection that contains custom metadata.
Does anyone know how I can access the custom metadata through the VBA script?
You will probably not be able to do this using a FileSystemObject or DIR function (as given in the code you linked to, above).
I am unable to test without a suitable example, but this might work:
Bind Outlook to Excel
Open the MSG file in Outlook
Use the Outlook object model to review the MSG file's .ItemProperties
Practically speaking you will set this up in a loop, similar to your example code, but for the sake of testing, try it out on a single file and see if this will help you.
'Requires reference to Outlook object model
Sub foo()
Dim olApp As Outlook.Application
Dim msg As Outlook.MailItem
Dim properties As Outlook.ItemProperties
Dim p As Long
Set olApp = GetObject(, "Outlook.Application")
Set msg = olApp.CreateItemFromTemplate("C:\your filename.msg")
Set properties = msg.ItemProperties
For p = 0 To properties.Count - 1
Debug.Print properties(p).Name
Next
Set msg = Nothing
Set olApp = Nothing
End Sub
This should print the list of ItemProperties in the Immediate window, scroll through that list and check to see if the one you're looking for -- "Document Identifier" -- is included. If so, then this should work and you can modify as needed to do whatever it is you want to do with that information.
I cannot be of further assistance unless you can provide a test/sample version of this email format.
Cheers.

Accessing OlExchangeStoreType from outside Outlook

I'm currently working on a small application that allows me to make some changes to a user's profile, namely add or remove specific PST files and transferring Contacts/Calendars from attached PST files into their primary mailbox. This is for Outlook 2007. After some searching, I found an enumeration in Outlook that I would like to use if possible: OlExchangeStoreType.
I want to use it to help determine which store I'm operating on (eg, public, primary, or PST file). I'm just not sure how I can reach it. I'm using late binding in my code to work around possible problems moving between different versions. Current Binding:
Dim olApp,olNS
On Error Resume Next
olApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
olApp = CreateObject("Outlook.Application")
olNS = olApp.GetNamespace("MAPI")
Else
olNS = olApp.GetNamespace("MAPI")
End If
This works fine. If I try GetObject(, "Outlook") instead, I get "Cannot create ActiveX component."
Is there an interface I can use for Outlook that will give me access to the public enumerations?
And as for why I'm doing it this way, I don't want to have to deal with macro security nor pushing out the macro to multiple users. I'm also new to using VBA so there may be an easier method than what I'm trying to do.
Let me know what you think. Thanks,
Figured it out. I was originally under the impression that the enumeration values were objects of a class, but they're just integers.
I found that
StoreObj.ExchangeStoreType
will return an integer that matches what OlExchangeStoreType uses. I'll just recreate the enum in my class.
Thanks,