Deleting appointment from someone else's calendar - vba

I have Access VBA code that creates appointments in three tech colleagues' calendars.
If vbYes = MsgBox("Send Calendar Appointments?", vbYesNo) Then
Dim outMail As Outlook.AppointmentItem
Set outMail = Outlook.CreateItem(olAppointmentItem)
outMail.Subject = "Lab Booking - " & FullName & " - for date " & Forms!frmLabSession_edit!BookingDate
outMail.Mileage = Me.LabBooking_ID
outMail.Location = Forms!frmLabSession_edit!frm_qryLabsBookedPerBooking_subform!RoomNo
outMail.MeetingStatus = olMeeting
outMail.Start = BookingDate & " " & TimeFrom
outMail.End = BookingDate & " " & TimeTo
outMail.ReminderMinutesBeforeStart = 21600
outMail.RequiredAttendees = "Person1#tees.ac.uk; Person2#tees.ac.uk; Person3#tees.ac.uk" & Me.txtCCList
outMail.Body = "You have received this notification with a 15 days countdown to cover periods of leave when you may not have received initial notification." & Chr$(13) & _
Chr$(13) & Me.Notes
outMail.Attachments.Add FileName
outMail.Send
Set outMail = Nothing
End If
I have code for deleting appointments based on the subject line, but I can't figure out how to add recipients - the other calendar users - it only removes it from my calendar.
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.NameSpace
Dim objFolder As Outlook.MAPIFolder
Dim objAppointment As Outlook.AppointmentItem
Dim lngDeletedAppointements As Long
Dim strSubject As String
Dim strLocation As String
Dim dteStartDate As Date
'******************************** Set Criteria for DELETION here ********************************
strSubject = "Lab Booking - " & FullName & " - for date " & Forms!frmLabSession_edit!BookingDate
strLocation = Forms!frmLabSession_edit!frm_qryLabsBookedPerBooking_subform!RoomNo
dteStartDate = BookingDate
'************************************************************************************************
Set objOutlook = Outlook.Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderCalendar)
For Each objAppointment In objFolder.Items
If objAppointment.Subject = strSubject And objAppointment.Location = strLocation And _
objAppointment.Start > dteStartDate Then
objAppointment.Delete
lngDeletedAppointements = lngDeletedAppointements + 1
End If
Next
MsgBox lngDeletedAppointements & " appointment(s) DELETED.", vbInformation, "DETETE Appointments"
How do I declare or state in the code the attendees' calendars to remove the item from, as the top code does to send them?
I have delete rights to their calendars. I can go into their calendars and delete the appointment, so shouldn't be a permissions issue.

You may use the following sequence of action to cancel the meeting and notify attendees:
AppointmentItem.MeetingStatus = olMeetingCanceled
AppointmentItem.Save
AppointmentItem.Send
AppointmentItem.Delete
Just set the meeting canceled status which stands for - the scheduled meeting has been cancelled.

Related

Making automatic email reminder using VBA

I am trying to make email using Outlook to remind someone to update their CV information per 6 months (180 days).
I have 1 query and 1 table.
Duedate_7 query consists of employee information, which passed 180 days or more since the last update. Access would send email to those employees.
Highlights table consists of the ID of the employees (Number), date of the project (date) and content of the project (long text).
Option Compare Database
Option Explicit
Function Otomail()
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim emailTo As String
Dim emailSubject As String
Dim emailText As String
Dim outApp As Outlook.Application
Dim outMail As Outlook.MailItem
Dim outlookStarted As Boolean
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
Set outApp = CreateObject("Outlook.Application")
outlookStarted = True
End If
Set db = CurrentDb
Set rs1 = db.OpenRecordset("SELECT ID, NIK, Nama, email, datemailsend FROM DueDate_7")
Do Until rs1.EOF
emailTo = rs1.Fields("email")
emailSubject = "Update CV"
emailText = "Please send the newest project highlights informations of Mr/Mrs' " & rs1.Fields("Nama").Value & " to the inside sales department for updating your CV which is scheduled once per 6 months." & vbCr & _
"Your latest project highlights update was " & vbCr & _
"This email is auto generated from Task Database. Please Do Not Reply!"
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = emailTo
outMail.Subject = emailSubject
outMail.Body = emailText
outMail.Display
rs1.Edit
rs1!datemailsend = Date
rs1.Update
rs1.MoveNext
Loop
rs1.Close
Set rs1 = Nothing
Set db = Nothing
Set outMail = Nothing
Set outApp = Nothing
End Function
I want to include each of the employee's 3 latest project highlights, stored in Highlights table, in each of the email I send.
What you need to do is to use a second recordset inside the loop that you have already got that selects the information required. Something like:
If Not (rs1.BOF And rs1.EOF) Then
Do
strProject = ""
strSQL = "SELECT TOP 3 ProjectName, ProjectDate " _
& " FROM Highlights " _
& " WHERE NameID=" & rs1!NameID _
& " ORDER BY ProjectDate DESC;"
Set rsProject = db.OpenRecordset(strSQL)
If Not (rsProject.BOF And rsProject.EOF) Then
Do
strProject = strProject & rsProject!ProjectDate & vbTab & rsProject!ProjectName & vbCrLf
rsProject.MoveNext
Loop Until rsProject.EOF
End If
Set outMail = outApp.CreateItem(olMailItem)
outMail.To = rs1!email
outMail.Subject = "Update CV"
outMail.Body = emailText & strProject
outMail.Display
rs1.MoveNext
Loop Until rs1.EOF
End If
This is assuming that you have a field called NameID that identifies the person to be selected.
Regards,

Get only today's appointments through Outlook VBA

I am extracting all appointments across all Outlook accounts for today.
I am experiencing the same issue encountered in this post here, but I am trying to do this through VBA.
Originally I managed to get the appointments for today, but it would also return reoccurring meetings that are not taking place today (like in the linked question).
I do not understand how the Powershell code, in the answer, manages to filter out the reoccurring appointments, because in my VBA attempt I get the whole week of appointments.
This is my attempt. I've included the filter where I get the appointments for today as well the reoccurring appointments which do not take place today.
Sub GetAllCalendarAppointmentsForToday()
Dim olApplication As Outlook.Application
Dim olNamespace As NameSpace
Dim olAccounts As Accounts
Dim olStore As Outlook.Store
Dim olCalendarFolder As Outlook.Folder
Dim olCalendarItems As Outlook.Items
Dim olTodayCalendarItems As Outlook.Items
Dim strFilter As String
Dim strFilter2 As String
Set olApplication = CreateObject("Outlook.Application")
Set olNamespace = olApplication.Session
Set olAccounts = olNamespace.Accounts
Debug.Print olAccounts.Count
For Each oAccount In olAccounts
Debug.Print oAccount
Set olStore = oAccount.DeliveryStore
Set olCalendarFolder = olStore.GetDefaultFolder(olFolderCalendar)
Set olCalendarItems = olCalendarFolder.Items
olCalendarItems.Sort "[Start]", True
olCalendarItems.IncludeRecurrences = True
Debug.Print olCalendarItems.Count
'Find your today's appointments
strFilter = Format(Now, "ddddd")
strFilter2 = Format(DateAdd("d", 7, Now), "ddddd")
Debug.Print strFilter
Debug.Print strFilter2
'strFilter = "[Start] > " & Chr(34) & strFilter & " 00:00" & Chr(34) & " AND [Start] < " & Chr(34) & strFilter & " 00:00" & Chr(34)
strFilter = "[Start] > " & Chr(34) & strFilter & " 00:00" & Chr(34) & " AND [Start] < " & Chr(34) & strFilter2 & " 00:00" & Chr(34)
Debug.Print strFilter
Set olTodayCalendarItems = olCalendarItems.Restrict(strFilter)
Debug.Print olTodayCalendarItems.Count
Debug.Print "Begin Print of Appointments"
For Each objAppointment In olTodayCalendarItems
Counter = Counter + 1
Debug.Print Counter & ":" & objAppointment.Subject & " " & objAppointment.Location & " [" & objAppointment.Start & "|" & objAppointment.End & "]"
Next
Debug.Print vbNewLine
Next
End Sub
Edit #1:
As per Eugene's answer, I updated the strFilter to be this to no avail
strFilter = [Start] <= '07/15/2020 11:59 PM' AND [End] >= '07/15/2020 12:00 AM'
In addition, I put IncludeReccurence first as well and no change in the results
Edit #2
Replaced the for each loop to use GetFirst() and GetNext() to no avail
Set olTodayCalendarItems = olCalendarItems.Restrict(strFilter)
Set olItem = olTodayCalendarItems.GetFirst()
Do While Not olItem Is Nothing
Set olAppointment = olItem
counter = counter + 1
Debug.Print counter & ":" & olAppointment.Subject & " " & olAppointment.Location & " [" & olAppointment.Start & "|" & olAppointment.End & "]"
Set olItem = olTodayCalendarItems.GetNext()
Loop
Edit #3:
I created a VB.NET application where I used the function, provided in the link in the answer, verbatim and it worked as expected. So maybe there is a issue in VBA (unlikely) or I missed something small in my VBA script?
Edit #4:
The problem was in my logic all along. Items needed to be sorted in ascending. Thank you to both Eugene and niton
The OP left a comment to indicate Restrict is valid.
" ... the link to the docs on IncludeRecurrences ... mentioned that .Sort needs to be done in ascending order"
It is possible .Restrict is not appropriate for this task.
An example using .Find.
Items.IncludeRecurrences property(Outlook) https://learn.microsoft.com/en-us/office/vba/api/outlook.items.includerecurrences
Sub DemoFindNext()
' https://learn.microsoft.com/en-us/office/vba/api/outlook.items.includerecurrences
Dim myNameSpace As Outlook.NameSpace
Dim tdystart As Date
Dim tdyend As Date
Dim myAppointments As Outlook.Items
Dim currentAppointment As Outlook.AppointmentItem
Set myNameSpace = Application.GetNamespace("MAPI")
tdystart = VBA.Format(Now, "Short Date")
tdyend = VBA.Format(Now + 1, "Short Date")
Set myAppointments = myNameSpace.GetDefaultFolder(olFolderCalendar).Items
myAppointments.Sort "[Start]"
myAppointments.IncludeRecurrences = True
Set currentAppointment = myAppointments.Find("[Start] >= """ & tdystart & """ and [Start] <= """ & tdyend & """")
While TypeName(currentAppointment) <> "Nothing"
Debug.Print currentAppointment.Subject
' MsgBox currentAppointment.Subject
Set currentAppointment = myAppointments.FindNext
Wend
End Sub
Microsoft doesn’t recommend using the Count property in case you set the IncludeRecurrences property. The Count property may return unexpected results and cause an infinite loop. Read more about that in the How To: Use Restrict method in Outlook to get calendar items article.
Here is a sample VB.NET code where you can see how you can filter appointment items properly:
Imports System.Text
Imports System.Diagnostics
' ...
Private Sub RestrictCalendarItems(folder As Outlook.MAPIFolder)
Dim dtEnd As DateTime = New DateTime(DateTime.Now.Year, DateTime.Now.Month, _
DateTime.Now.Day, 23, 59, 0, 0)
Dim restrictCriteria As String = "[Start]<=""" + dtEnd.ToString("g") + """" + _
" AND [End]>=""" + DateTime.Now.ToString("g") + """"
Dim strBuilder As StringBuilder = Nothing
Dim folderItems As Outlook.Items = Nothing
Dim resultItems As Outlook.Items = Nothing
Dim appItem As Outlook._AppointmentItem = Nothing
Dim counter As Integer = 0
Dim item As Object = Nothing
Try
strBuilder = New StringBuilder()
folderItems = folder.Items
folderItems.IncludeRecurrences = True
folderItems.Sort("[Start]")
resultItems = folderItems.Restrict(restrictCriteria)
item = resultItems.GetFirst()
Do
If Not IsNothing(item) Then
If (TypeOf (item) Is Outlook._AppointmentItem) Then
counter = counter + 1
appItem = item
strBuilder.AppendLine("#" + counter.ToString() + _
" Start: " + appItem.Start.ToString() + _
" Subject: " + appItem.Subject + _
" Location: " + appItem.Location)
End If
Marshal.ReleaseComObject(item)
item = resultItems.GetNext()
End If
Loop Until IsNothing(item)
If (strBuilder.Length > 0) Then
Debug.WriteLine(strBuilder.ToString())
Else
Debug.WriteLine("There is no match in the " _
+ folder.Name + " folder.")
End If
catch ex As Exception
System.Windows.Forms.MessageBox.Show(ex.Message)
Finally
If Not IsNothing(folderItems) Then Marshal.ReleaseComObject(folderItems)
If Not IsNothing(resultItems) Then Marshal.ReleaseComObject(resultItems)
End Try
End Sub

Set reminders for recurring appointments

I am trying to set reminders for recurring appointments.
If objAppointment.ReminderSet = False Then
If objAppointment.IsRecurring Then
'Dim objRecurrencePattern As RecurrencePattern
'Set objRecurrencePattern = objAppointment.GetRecurrencePattern
'Set objAppointment = objRecurrencePattern.GetOccurrence(objAppointment.Start)
objAppointment.ReminderOverrideDefault = True
End If
objAppointment.ReminderSet = True
objAppointment.ReminderMinutesBeforeStart = 15 ' Enter your default time
objAppointment.Save
Debug.Print "Reminder set for '" & objAppointment.Subject & "'."
End If
I found this post in MS forum.
The reminder properties seems to be properly set in the VBA debugger but if I check the appointment in the calendar the reminder is still not set/effective.
If you are dealing with an instance of a recurring appointment or an exception (check the AppointmentItem.RecurrenceState property), set the reminder on the master appointment retrieved from the AppointmentItem.Parent property.
In case the meeting is recurring you have to edit All Occurences <->Parent meeting
See code here https://gist.github.com/tdalon/60a746cfda75ad191e426ee421324386
Sub CheckTodayReminders()
' https://www.datanumen.com/blogs/quickly-send-todays-appointments-someone-via-outlook-vba/
Dim objAppointments As Outlook.Items
Dim objTodayAppointments As Outlook.Items
Dim strFilter As String
Dim objAppointment As Outlook.AppointmentItem ' Object
Set objAppointments = Application.Session.GetDefaultFolder(olFolderCalendar).Items
objAppointments.IncludeRecurrences = True
objAppointments.Sort "[Start]", False ' Bug: use False/descending see https://social.msdn.microsoft.com/Forums/office/en-US/919e1aee-ae67-488f-9adc-2c8518854b2a/how-to-get-recurring-appointment-current-date?forum=outlookdev
'Find your today's appointments
strFilter = Format(Now, "ddddd")
'strFilter = "2019-03-07"
strFilter = "[Start] > '" & strFilter & " 00:00 AM' AND [Start] <= '" & strFilter & " 11:59 PM'"
Set objTodayAppointments = objAppointments.Restrict(strFilter)
For Each objAppointment In objTodayAppointments
Debug.Print "Check Reminder for '" & objAppointment.Subject & "'..."
If objAppointment.IsRecurring Then
Set objAppointment = objAppointment.Parent
End If
If objAppointment.ReminderSet = False Then
objAppointment.ReminderSet = True
objAppointment.ReminderMinutesBeforeStart = 15 ' Enter your default time
objAppointment.Save
Debug.Print "Reminder set for '" & objAppointment.Subject & "'."
End If
Next
' MsgBox "Meeting reminders were checked!"
End Sub

Create outlook task from shared inbox

I need to create outlook task from shared inbox. So far when below code runs, task is created with owner of shared inbox as I want, but when saved I get "You must be in a public folder to change the owner field of a task" error and owner is changed back to me.
I couldn't find solution or it might have been beyond my understanding. I appreciate the help. Thanks!
If task = "YES" Then
user_task = "GR"
Const olTaskItem = 3
Dim OlApp As Object
Dim OlTask As Object
Set OlApp = CreateObject("Outlook.Application")
Set OlTask = OlApp.CreateItem(olTaskItem)
With OlTask
'.Assign
'.Recipients.Add "shared#inbox.com" 'workaround to assign task for another owner, but does not show .BCC so not suitable solution.
.Owner = "shared#inbox.com" ' does not work. changes back to my user
.Subject = material_full_email & " spp "
.StartDate = Date
.DueDate = Date + 7
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.ReminderSet = False
'.ReminderTime = dtReminderDate
'.Categories = "Business" 'use any of the predefined Categorys or create your own
.Body = Date & " " & user_task & ":" & " RFQ sent: " & Supplier1 & " / " & Supplier2 & " / " & Supplier3 & " / " & Supplier4
'.Save 'use .Display if you wish the user to see the task form and make
.Display 'them perform the save
End With
End If
Instead of using Application.CreateItem, call Application.Session.CreateRecipient passing the name or address of the owner of the mailbox, call Application.Session.GetSharedDefaultFolder, then use MAPIFolder.Items.Add.
UPDATE:
Set OlApp = CreateObject("Outlook.Application")
set NS = olApp.getNamespace("MAPI")
NS.Logon
ste Recip = NS.CreateRecipient("someuser#company.demo")
set SharedFolder = NS.GetSharedDefaultFolder(Recip, olFoldersTasks)
Set OlTask = SharedFolder.Items.Add
...
I managed to get below code work. I believe biggest problem was MS Outlook library not ticked in references.
If task = "YES" Then
user_task = "GR"
Const olTaskItem = 3
Dim olApp As Object
Dim ns As Object
Dim OlTask As Object
Dim SharedFolder As Object
Set olApp = CreateObject("Outlook.Application")
Set ns = olApp.GetNamespace("MAPI")
ns.Logon
Set Recip = ns.CreateRecipient("inboxname")
Set SharedFolder = ns.GetSharedDefaultFolder(Recip, olFolderTasks)
Set OlTask = SharedFolder.Items.Add("IPM.Task")
'Set OLApp = CreateObject("Outlook.Application")
'Set OlTask = OLApp.CreateItem(olTaskItem)
With OlTask
'.Assign
'.Recipients.Add "shared#inbox.com"
'.Owner = "shared#inbox.com" ' not needed
.Subject = material_full_email & " spp "
.StartDate = Date
.DueDate = Date + 7
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.ReminderSet = False
'.ReminderTime = dtReminderDate
'.Categories = "Business" 'use any of the predefined Categorys or create your own
.Body = Date & " " & user_task & ":" & " RFQ sent to suppliers: " & Supplier1 & " / " & Supplier2 & " / " & Supplier3 & " / " & Supplier4
'.Save 'use .Display if you wish the user to see the task form and make
.Display 'them perform the save
End With
End If
I think that I have something more simple for this:
Dim objOLApp As Outlook.Application
Dim NewTask As Outlook.TaskItem
' Set the Application object
Set objOLApp = New Outlook.Application
Set NewTask = objOLApp.Session.Folders.Item(x).Items.Add(olTaskItem)
With NewTask...
Where 'x' stands for your shared inbox ID (for me this is 5). You can use MsgBox Prompt:=objOLApp.Session.Folders.Item(x) to check. It should return shared inbox adress on correct ID (adress#server.com).

Apply CommandBars functionality in Outlook 2013

I created macros to automate the creation of new calendar appointments and to edit existing calendar appointments in Outlook 2010.
Since upgrading to Outlook 2013 the macro no longer works. I don't get any error message.
Sub NewCustomAppt()
'objects
Dim objExpl As Outlook.Explorer
Dim objFolder As Outlook.MAPIFolder
Dim objCB As Office.CommandBarButton
'appointment
Dim objAppt As Outlook.AppointmentItem
Dim objApptCustom As Outlook.AppointmentItem
Dim objOutlookAttach As Outlook.Attachment
Dim objNS
Set objNS = Application.GetNamespace("MAPI")
On Error Resume Next
Set objExpl = Application.ActiveExplorer
If Not objExpl Is Nothing Then
Set objFolder = objExpl.CurrentFolder
If objFolder.DefaultItemType = olAppointmentItem Then
Set objCB = objExpl.CommandBars.FindControl(, 1106)
If Not objCB Is Nothing Then
objCB.Execute
Set objAppt = Application.ActiveInspector.CurrentItem
Set objApptCustom =
objFolder.Items.Add("IPM.Appointment.your_custom_class")
Set objSel = objDoc.Windows(1).Selection
With objApptCustom
.Start = objAppt.Start
.End = objAppt.End
objAppt.Location = "Careers Service, Level 6 Livingstone Tower"
objAppt.ReminderSet = True
objAppt.ReminderMinutesBeforeStart = 4320
objAppt.Body = "If you wish to cancel or re-schedule this
appointment please let us know as soon as possible, by telephone:
0141 548 4320 or email: yourcareer#strath.ac.uk." & vbNewLine & _
"" & vbNewLine & _
"Please make sure you are prompt for your appointment, if you are
more than 10 minutes late you will not be seen by the adviser."
& vbNewLine & _
& vbNewLine & _
& vbNewLine & _
"Your Careers Adviser for this appointment is:" & vbNewLine & _
"" & vbNewLine & _
"" & vbNewLine & _
In order to prepare for your appointment with your Careers Adviser
please read through the information attached below"
& vbNewLine & _
"" & vbNewLine & _
"" & vbNewLine & _
"" & vbNewLine & _
"" & vbNewLine & _
"" & vbNewLine & _
"This appointment was created on the " & Date & " at" & " " & Time
& vbNewLine & _
objAppt.Attachments.Add "I:\Admin\Careers\INTERVIEW.DOC
'Add the attachment to the e-mail message.
End With
End If
End If
End If
End Sub
From Microsoft:
Command bars are not used in Outlook 2013. CommandBar functions will fail silently.
Use the IRibbonExtensibility interface in an Outlook 2013 add-in instead of command bars. You can’t customize Inspector ribbons by using VBScript code behind forms.
http://technet.microsoft.com/en-us/library/cc178954%28v=office.15%29.aspx
.FindControl(, 1106) works in 2010 so if there is a silent fail in 2013 switch to ExecuteMso
http://msdn.microsoft.com/en-us/library/ff862419.aspx
Private Sub NewCustomAppt_ExecuteMso()
'objects
Dim objExpl As Outlook.Explorer
Dim objFolder As Outlook.Folder
'appointment
Dim objAppt As Outlook.AppointmentItem
Dim objOutlookAttach As Outlook.attachment
Dim objNS
Set objNS = Application.GetNamespace("MAPI")
Set objExpl = Application.ActiveExplorer
If Not objExpl Is Nothing Then
Set objFolder = objExpl.CurrentFolder
If objFolder.DefaultItemType = olAppointmentItem Then
objExpl.CommandBars.ExecuteMso ("NewAppointment") ' <----
Set objAppt = Application.ActiveInspector.CurrentItem
objAppt.location = "Careers Service, Level 6 Livingstone Tower"
objAppt.ReminderSet = True
objAppt.ReminderMinutesBeforeStart = 4320
objAppt.body = "If you wish to cancel or re-schedule this "
End If
End If
End Sub
The IdMso can be seen if you hover over the command when modifying ribbons or the QAT.