Create Outlook calendar event with Visual Basic VB for selected chosen calendar, when having multiple accounts - vba

I want to create Visual Basic scrip to create calendar event/invitation.
Script is working perfectly, when only one account is registered in outlook, and event is created OK for this single calendar (account).
PROBLEM:
I have two accounts registered in my outlook. One of the accounts is company-managed (let's call it FIRST). I have also manually created account (let's call it SECOND).
The problem is when I want to create event "on behalf" of SECOND calendar registered manually. I've already set SECOND account as primary account in outlook with:
Outlook->File->Account Settings->Account Setting...->Email Tab->Set as default.
When I'm using (almost) identical code as below to create Outlook email object, script is working perfectly fine, and field "Sender" in the message is populated with correct SECOND account name.
Picture: Email outlook object created, with SENDER populated with correct SECOND account
I've tried to set property: objAppointmentItem.SendUsingAccount = myAccount , with the SECOND account, but then Sender field is left empty, and you can't select account from combo. When I'm sending it it ANYWAY, then it is send to correct recipients, but is NOT send to my SECOND calendar (desired), and invitation/event is visible in my FIRST calendar, which I DON'T want to use anymore.
Picture: Outlook event object with FROM field empty, no selection possible
When I'm NOT setting property: objAppointmentItem.SendUsingAccount = myAccount , event object is created, but is assigned with FIRST account, despite SECOND is set as default.
Picture: Event created with wrong sender, and NO SELECTION possible for SECOND account
When I create invitation with double-click on calendar itself (SECOND account calendar), then invitation is created with correct SECOND account populated in SENDER field, (still no option to select other account - but no need, as is correct :) )
Sub OutOfOfficeEvent()
Dim oAccount As Outlook.Account
Dim myAccount As Outlook.Account
'try to find PERSONAL account. If failed, then send with last avail on the list Application.Session.Accounts
For Each oAccount In Application.Session.Accounts
Set myAccount = oAccount
If InStr(UCase(oAccount.DisplayName), "PERSONAL.COM") Then
Exit For
End If
Next
Dim objOutlookApplication As Outlook.Application
Dim objAppointmentItem As Outlook.AppointmentItem
Dim objRecipient As Recipient
Dim objRecipients As Recipients
Set objOutlookApplication = CreateObject("Outlook.Application")
Set objAppointmentItem = objOutlookApplication.CreateItem(olAppointmentItem)
'###############################################
'####### NOT working for event/invitation
'####### Working OK for email object creation
'###############################################
objAppointmentItem.SendUsingAccount = myAccount
'###############################################
objAppointmentItem.Display
Set objRecipients = objAppointmentItem.Recipients
Set objRecipient = objAppointmentItem.Recipients.Add("somebody1#PERSONAL.COM")
Set objRecipient = objAppointmentItem.Recipients.Add("somebody2#PERSONAL.COM")
objRecipient.Type = olRequired
For Each objRecipient In objAppointmentItem.Recipients
objRecipient.Resolve
Next
Dim DateStart As Date
Dim DateEnd As Date
DateStart = DateTime.DateAdd("d", 0, DateTime.DateAdd("h", 1, DateTime.DateAdd("s", -Second(Now()), DateTime.DateAdd("n", -Minute(Now()), Now()))))
DateEnd = DateTime.DateAdd("h", 1, DateStart)
With objAppointmentItem
.MeetingStatus = olMeeting
.Subject = "[OOO] " & strUser
.Start = DateStart
.End = DateEnd
.AllDayEvent = False
.ReminderSet = False
.BusyStatus = olFree
.ResponseRequested = False
.Location = ""
.Body = "Some body content"
End With
objAppointmentItem.Display
Set objOutlookApplication = Nothing
End Sub

There are several ways of creating new items in Outlook. See How To: Create a new Outlook Appointment item for more information.
If you have two accounts configured in Outlook you need to get the right calendar folder and then add a new calendar entry there. To get this done you can use the GetDefaultFolder method of the Store class which returns a Folder object that represents the default folder in the store and that is of the type specified by the FolderType argument. 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. So, you may get the right store and add the new calendar entry.
The NameSpace.Stores property returns a Stores collection object that represents all the Store objects in the current profile.
Sub EnumerateFoldersInStores()
Dim colStores As Outlook.Stores
Dim oStore As Outlook.Store
Dim oCalendar As Outlook.Folder
On Error Resume Next
Set colStores = Application.Session.Stores
For Each oStore In colStores
Set oCalendar = oStore.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
Debug.Print (oCalendar.FolderPath)
Next
End Sub

I had the same problem and with above suggestion and some more Google, I found the total solution:
Dim myAI As Outlook.AppointmentItem
myAI = Nothing
Dim oStore As Outlook.Store
For Each oStore In colStores
Dim oCalendar As Outlook.Folder
Set oCalendar = oStore.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
If LCase(oCalendar.Description) = "<accountname>" Then
Set myAI = oCalendar.Items.Add(Outlook.OlItemType.olAppointmentItem)
Exit For
End If
Next

Related

Access VBA code to import emails into table [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 months ago.
Improve this question
I have inherited a database which has VBA code, unfortunately the colleague has left the organisation and we need to make 4 amendments. 1 - The code works on your personal inbox however we have moved to a team mailbox, so can anyone assist with how to change the code to address this? 2 - We need to pull the senders email address currently it pulls the persons name on occasion it will identify an email but that is very limited (is it to do with the SMTP address?) 3 - we would like to put a date range for the pulling of emails. 4- Once it has imported the emails can it move them to a folder called imported.
Thanks
Sub ImportMailPropFromOutlook()
' Code for specifing top level folder and initializing routine.
' Set up Outlook objects.
Dim ol As New Outlook.Application
Dim olns As Outlook.Namespace
Dim ofO As Outlook.MAPIFolder
Dim ofSubO As Outlook.MAPIFolder
Dim objItems As Outlook.Items
Set olns = ol.GetNamespace("MAPI")
Set ofO = olns.GetDefaultFolder(olFolderInbox) '--- Specifies top level folder for importing Oultook mail.
'Set of = olns.PickFolder '--- Allows user to select top level folder for importing Outlook mail.
'Set info and call GetMailProp code.
Set objItems = ofO.Items
GetMailProp objItems, ofO
'Set info and call ProcessSubFolders.
'For Each ofSubO In of.Folders
' Set objItems = ofSubO.Items
' ProcessSubFolders objItems, ofSubO
'Next
End Sub
Sub GetMailProp(objProp As Outlook.Items, ofProp As Outlook.MAPIFolder)
' Code for writeing Outlook mail properties to Access.
' Set up DAO objects (uses existing Access "Email" table).
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordset("Email")
'Set Up Outlook objects.
Dim cMail As Outlook.MailItem
Dim cAtch As Outlook.Attachments
'Write Outlook mail properties to Access "Email" table.
iNumMessages = objProp.Count
If iNumMessages <> 0 Then
For i = 1 To iNumMessages
If TypeName(objProp(i)) = "MailItem" Then
Set cMail = objProp(i)
'If ([rst]![EmailLocation] <> ofProp.Name) And ([rst]![EntryID] <> cMail.EntryID) Then
rst.AddNew
rst!EntryID = cMail.EntryID
rst!ConversationID = cMail.ConversationID
rst!Sender = cMail.Sender
rst!SenderName = cMail.SenderName
rst!SentOn = cMail.SentOn
rst!To = cMail.To
rst!CC = cMail.CC
rst!BCC = cMail.BCC
rst!Subject = cMail.Subject
Set cAtch = cMail.Attachments
cntAtch = cAtch.Count
If cntAtch > 0 Then
For j = cntAtch To 1 Step -1
strAtch = cAtch.Item(j).FileName
rst!Attachments = strAtch
Next
Else
rst!Attachments = "No Attachments"
End If
'rst!Count = cMail.Attachments.Count
rst!Body = cMail.Body
rst!HTMLBody = cMail.HTMLBody
rst!Importance = cMail.Importance
rst!Size = cMail.Size
rst!CreationTime = cMail.CreationTime
rst!ReceivedTime = cMail.ReceivedTime
rst!ExpiryTime = cMail.ExpiryTime
'rst!EmailLocation = ofProp.Name
rst.Update
'End If
End If
Next i
End If
End Sub
Sub ProcessSubFolders(objItemsR As Outlook.Items, OfR As Outlook.MAPIFolder)
'Code for processing subfolders
' Set up Outlook objects.
Dim ofSubR As Outlook.MAPIFolder
'Set info and call GetMailProp code.
GetMailProp objItemsR, OfR
'Set info and call ProcessSubFolders. Recursive.
For Each ofSubR In OfR.Folders
Set objItemsR = ofSubR.Items
ProcessSubFolders objItemsR, ofSubR
Next
End Sub
We need to pull the senders email address currently it pulls the persons name on occasion it will identify an email but that is very limited (is it to do with the SMTP address?)
In the code you are getting the Sender property, but it is not a scalar property. it returns an instance of the an AddressEntry object that corresponds to the user of the account from which the MailItem is sent. Instead, you need to use the Address property of the AddressEntry class to get a string representing the email address.
In case of Exchange accounts you may use the AddressEntry.GetExchangeUser method which returns an ExchangeUser object that represents the AddressEntry if the AddressEntry belongs to an Exchange AddressList object such as the Global Address List (GAL) and corresponds to an Exchange user. Then you may get the ExchangeUser.PrimarySmtpAddress property value which is a string representing the primary Simple Mail Transfer Protocol (SMTP) address for the ExchangeUser. Returns an empty string if this property has not been implemented or does not exist for the ExchangeUser object.
In cases when you need to convert Ex-like addresses to SMTP ones you may find the HowTo: Convert Exchange-based email address into SMTP email address article helpful.
Once it has imported the emails can it move them to a folder called imported.
Use the Move method available for all Outlook items.

How to forward a calendar item without notifying organizer

I want to forward all calendar items within a certain date range to a specific email address without notifying the organizer.
Is there a way to do this using VBA code? I have the below code to not notify the meeting organizer but need to modify to forward all calendar items to a specific email address?
Also note I cannot forward as icalendar. I have a script which forwards emails when moved to a specific folder, however i cannot seem to convert or move meeting invites into the normal inbox folder.
Sub ForwardMeetingInvitation()
Dim olSel As Selection
Dim olMeeting As MeetingItem
Dim olFWMeeting As MeetingItem
Dim Recip As String
Set olSel = Outlook.Application.ActiveExplorer.Selection
Set olMeeting = olSel.Item(1)
'Replace with your own desired recipient's email address
Recip = "pirate#fakemail.com"
Set olFWMeeting = olMeeting.Forward
With olFWMeeting
.Recipients.Add (Recip)
.Attachments.Add olMeeting
.Display
End With
Set olSel = Nothing
Set olMeeting = Nothing
Set olFWMeeting = Nothing
End Sub

objItems_ItemAdd not triggered when items added to olItems: How to apply the ItemAdd event?

I want to set an auto-category for the incoming email in Outlook 2010 but my code does not work.
I restarted Outlook many times.
Public WithEvents olItems As Outlook.Items
Private Sub Application_Startup()
Set objItems = Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub objItems_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim strSenderEmailAddress As String
Dim objContacts As Outlook.Items
Dim objContact As Object
Dim objFoundContact As Outlook.ContactItem
Dim strFilter As String
Dim strContactCategory As String
Dim i As Long
If TypeOf Item Is MailItem Then
Set objMail = Item
strSenderEmailAddress = objMail.SenderEmailAddress
Set objContacts =
Outlook.Application.Session.GetDefaultFolder(olFolderContacts).Items
For Each objContact In objContacts
If TypeOf objContact Is ContactItem Then
For i = 1 To 3
strFilter = "[Email" & i & "Address] = " &
strSenderEmailAddress
Set objFoundContact = objContacts.Find(strFilter)
'Check if the sender exists in your contacts folder
If Not (objFoundContact Is Nothing) Then
strContactCategory = objFoundContact.Categories
'If the corresponding contact has no category
'Assign the "Known" category to the email
If strContactCategory = "" Then
objMail.Categories = "Known"
'If the contact has, directly use its category
Else
objMail.Categories = strContactCategory
End If
Exit For
End If
Next i
'If the sender doesn't exist in the Contacts folder
'Assign the "Unknown" category to the email
If objFoundContact Is Nothing Then
objMail.Categories = "Unknown"
End If
End If
Next objContact
End If
End Sub
I am not good in VBA. When new email arrives my mailbox, it is not auto-categorized, no color filling in Category field in Outlook, nothing happens.
I want to set auto-category for the incoming email in outlook 2010 but my code does not work.
First of all, you need to handle the NewMailEx event of the Application class which is fired when a new item is received in the Inbox.
The NewMailEx event fires when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item. Use this method with caution to minimize the impact on Outlook performance. However, depending on the setup on the client computer, after a new message arrives in the Inbox, processes like spam filtering and client rules that move the new message from the Inbox to another folder can occur asynchronously.
After getting the item received you may set a category.
P.S. The ItemAdd event may not be fired at all if you receive more than sixteen items simultaneously. This is a known issue in the Outlook object model.

Sending Email from Access

I am trying to develop a database where teachers log an application for when they need a lesson to be covered (I'd do this in SQL but I can't currently).
I would like the database to notify a certain member of staff when an application is made. Selecting the member of staff would be done from a combobox, driven by a query. The reason for the query is that I only want specific members of staff to receive this notification - essentially those who manage other staff.
Once that member of staff has been selected, I want the person making the application to click a button, which will then fire an email to the person selected in the combobox.
I get a flicker of Outlook doing something and then nothing.
This is what I have so far, with the DLookup using the staff member selected in the combobox to then find the email address in the Staff table:
Private Sub Command788_Click()
Dim Email_Note As Variant
Email_Note = DLookup("Email", "Staff", Forms![Cover Application Form]!Combo767)
Dim olLook As Outlook.Application
Dim olNewEmail As Outlook.CreateItem
Dim StrContactEmail As String
Set olLook = New Outlook.Application
Set olNewEmail = olLook.CreateItem(olMailItem)
strEmailSubject = "Application for Cover: Line Manager Notification"
strEmailText = "Something in here..."
StrContactEmail = "Email_Note"
olNewEmail.Display
End Sub
You should ensure that the Outlook library is referenced in the tools tab of VBA Editor. It also looks like you created strings for the body and subject but didn't declare them. Instead of declaring them as string variables just set the outlook. body etc. to the appropriate string as I have shown below.
You don't need to encapsulate email_note with quotes once you have declared it as a variable. I assumed that was an email address?
The strContactEmail is no longer needed, I don't see where it is used.
Private Sub Command788_Click()
Dim Email_Note As Variant
Email_Note = DLookup("Email", "Staff", Forms![Cover Application Form]!Combo767)
Dim olLook As Outlook.Application
Dim olNewEmail As Outlook.mailItem
'Dim StrContactEmail As String
Set olLook = New Outlook.Application
Set olNewEmail = olLook.CreateItem(olMailItem)
olNewEmail.Subject="Application for Cover: Line Manager Notification"
olNewEmail.Body = "Something in here..."
olNewEmail.To = email_note
olNewEmail.Send
Set olNewEmail = Nothing
Set olLook = Nothing
End Sub

Outlook VBA AppointmentItem.Move creating a copy

When using the Move method on an AppointmentItem in an Outlook macro, I lose the ability to receive updates because it is creating a copy of the item instead of truly moving it. This behavior causes the item to no longer be linked with the original and will not retain item updates as a result.
I want to replicate through VBA the cut/paste behavior you get which is able to maintain the original object and does not cause updates to be lost.
I believe this has something to do with the GlobalAppointmentID based on searching around, however I have not been able to find a way to actually move the appointment.
The code I'm using is below. GetFolderFromPath is a helper function to just return a folder object from the path, which works perfectly well.
Sub MoveItem()
Dim targetPath As String: targetPath = "\\tnolan#microsoft.com\Calendar\OOFS"
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("No item selected")
Exit Sub
Else
Dim targetFolder As Outlook.Folder
Set targetFolder = GetFolderFromPath(targetPath)
For x = 1 To Application.ActiveExplorer.Selection.Count
Dim oSelected As Variant
Set oSelected = Application.ActiveExplorer.Selection.Item(x)
If oSelected.Class = olAppointment Then
Dim NS As NameSpace: Set NS = Application.GetNamespace("MAPI")
Dim oAppt As AppointmentItem: Set oAppt = NS.GetItemFromID(oSelected.EntryID)
oAppt.Move targetFolder
Set oAppt = Nothing
Set NS = Nothing
End If
Set oSelected = Nothing
Next x
Set targetFolder = Nothing
End If
End Sub
Outlook processes incoming meeting updates/deletions only against the default Calendar folder. If you move an appointment to a different folder, meeting update in your Inbox will create a new appointment in the default Calendar folder.
After playing around with my code for a little bit, I've found that this code works for me in a similar situation:
oAppt.CopyTo(targetFolder, olCopyAsAccept)
oAppt.Delete
I have a feeling that for some reason the AppointmentItem.Move command passes as olCreateAppointment which would always create a new GlobalAppointmentID.
However, this still has a side-effect of responding accept to the Appointment.