[英]Fetch Shared Outlook Calendar Events C#
我知道如何在当前用户的Outlook日历中检索事件,例如,以下代码可删除与特定模式匹配的项目:
private void RemoveAppointments()
{
Outlook.Application outlook = new Outlook.Application();
Outlook.MAPIFolder calendarFolder = outlook.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.Items outlookCalendarItems = calendarFolder.Items;
for (int i = outlookCalendarItems.Count; i > 0; i--)
{
if (outlookCalendarItems[i].Subject.Contains("On Call: Regions:") && outlookCalendarItems[i].Start.Year == _year)
{
outlookCalendarItems[i].Delete();
}
}
}
但是,我现在需要能够从Outlook Team中的所有用户读取日历事件(假定共享权限已正确设置)。 理想情况下,我需要能够对每个用户进行迭代,但是如果我只是获得所有事件的集合,然后可以按用户查询就足够了。
有什么想法可以开始吗?
注意:这是在Outlook的“日历”窗格中代表团队的方式。 敏感细节已删除。
代替使用Namespace.GetDefaultFolder
,使用Namespace.GetSharedDefaultFolder
,传递从Namespace.CreateRecipient
返回的Recipient
对象。
还请记住,循环浏览文件夹中的所有项目是一个可怕的主意,尤其是当您打开未缓存在本地OST文件中的在线文件夹时。 请改用Items.Find/FindNext
或Items.Restrict
。
感谢@Dmitry 的回答 ,它帮助我解决了我的问题。 但是,为了使该问题对将来的读者最大程度地发挥作用,我认为我会对此进行扩展。
假使,假设:
using Microsoft.Office.Interop.Outlook;
并引用了COM程序集Microsoft Outlook 16.0 Object Library
。
第一步是创建一个Outlook.Application
对象,该对象充当Outlook功能的接口(您可以将其视为完整Outlook程序的内部实例):
Application app = new Application();
然后,我从全局列表中与团队相关联的通讯组列表中拉出所有用户。 这是通过从Application
实例的Session
属性创建一个Recipient
对象来完成的。
Recipient distList = app.Session.CreateRecipient(yourDistList);
从这里,我们可以提取所有真实姓名和用户名,以AdressEntry.Members
收件人的AdressEntry.Members
属性。 要将它们都拉到(string,string)
的匿名元组中(string,string)
我们可以使用此LINQ查询,如果您不喜欢,则可以像平常一样进行迭代:
List<(string,string)> usersData = distList.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
现在,给定特定的用户名,只要日历已与当前用户共享,就可以使用Session
的GetSharedDefaultFolder()
方法访问它:
MAPIFolder sharedCalendar = _app.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
在这一点上,我发现进行一些筛选以尝试避免最常见的COMException
很有用,但是,我似乎无法确定很多原因,因此我只catch (COMException)
并将其分类。 我知道这不是一个好习惯,但似乎并没有干扰我访问我有权使用的日历。 一些(非常)基本过滤:
if (sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0)
{
return null; //Calendar not shared.
}
现在,我们必须使用Microsoft Outlook格式构建一个Filter
字符串,可以使用以下语句( from
和to
均为DateTime
对象)完成此操作:
string sFilter = $"[End] > '{from:g}' AND [Start] < '{to:g}' AND [Recurring] = 'No'";
我们会过滤掉重复发生的事件,否则开始日期和结束日期可能会超出范围而没有内部发生。 就我的目的而言,无论如何我都不需要重复发生的事件,但是,如果您这样做,则必须将其单独处理。
最后,我们现在可以收集我们需要利用的事件Items.Restrict()
的方法MAPIFolder
:
Items results = sharedCalendar.Items.Restrict(sFilter);
这将向所有属于我们过滤器的项目返回一个Items
接口。
最后,我们可以遍历每个项目(我以相反的顺序进行遍历,因为我从我的旧应用程序中复制了删除事件的代码,但是在这种情况下这无关紧要)。 您可能必须将object
AppointmentItem
为AppointmentItem
具体取决于编译器是否可以推断出该对象。
List<AppData> appointments = new List<AppData>();
for (int i = results.Count; i > 0; i--)
{
appointments.Add(new AppData(results[i], username));
}
我将每个事件存储为AppData
结构,仅保留我需要的数据:
public struct AppData
{
public string Subject { get; }
public DateTime From { get; }
public DateTime To { get; }
public string Location { get; }
public string Categories { get; }
public string Username { get; }
public AppData(AppointmentItem appItem, string username)
{
Subject = appItem.Subject;
From = appItem.Start;
To = appItem.End;
Location = appItem.Location;
Categories = appItem.Categories;
Username = username;
}
}
所有这些都会导致一个看起来像这样的类:
public class OutlookCommunicator : IDisposable
{
private readonly Application _app;
public OutlookCommunicator()
{
_app = new Application();
}
/// <summary>
/// Username of the distribution list according to the GAL.
/// </summary>
private const string DistList = "redacted";
/// <summary>
/// Fetches a list of all usernames and names within the DistList.
/// </summary>
/// <returns>List<string> containing all usernames.</returns>
public List<(string,string)> GetUsers()
{
Recipient warEngineering = _app.Session.CreateRecipient(DistList);
List<(string,string)> usernames = warEngineering.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
return usernames;
}
/// <summary>
/// Fetches all calendar events for a user falling within the provided range.
/// </summary>
/// <param name="from">Start search date.</param>
/// <param name="to">End search dat.</param>
/// <param name="username">User's calendar to search.</param>
/// <returns></returns>
public List<AppData> GetEventsInRange(DateTime from, DateTime to, string username)
{
List<AppData> appointments = new List<AppData>();
try
{
Recipient teamMember = _app.Session.CreateRecipient(username);
MAPIFolder sharedCalendar = _app.Session.GetSharedDefaultFolder(teamMember, OlDefaultFolders.olFolderCalendar);
if (sharedCalendar.DefaultMessageClass != "IPM.Appointment" || teamMember.DisplayType != 0)
{
return null; //Calendar not shared.
}
string sFilter = $"[End] > '{from:g}' AND [Start] < '{to:g}' AND [Recurring] = 'No'";
Items results = sharedCalendar.Items.Restrict(sFilter);
for (int i = results.Count; i > 0; i--)
{
appointments.Add(new AppData(results[i], username));
}
return appointments;
}
catch (COMException)
{
return null;
}
}
public void Dispose()
{
_app?.Quit();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.