刚失恋的黄瓜 · android ...· 2 天前 · |
多情的长颈鹿 · PermissionError: ...· 1 年前 · |
闯红灯的蛋挞 · java - Error Code: ...· 1 年前 · |
刀枪不入的柿子 · Python习题(二) - 知乎· 1 年前 · |
我知道如何在当前用户的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团队中的所有用户读取日历事件(假设共享权限已被正确设置)。理想情况下,我需要能够迭代每个用户,但如果我只是获得所有事件的集合,然后可以通过用户进行查询,那也就足够了。
我能从哪里开始呢?
注意:这是使用Outlook的日历窗格来表示团队的方式。敏感的细节被修改了。
发布于 2018-08-20 17:22:11
感谢@Dmitry for his answer ,它帮助我解决了我的问题。然而,为了最大限度地提高这个问题对未来读者的效用,我想我会对其进行扩展。
假设:
using Microsoft.Office.Interop.Outlook;
并引用COM程序集
Microsoft Outlook 16.0 Object Library
。
第一步是创建一个
Outlook.Application
对象,该对象充当Outlook函数的接口(您可以将它看作是整个Outlook程序的内部实例):
Application app = new Application();
然后,我从与团队关联的Global列表中的通讯组列表中提取所有用户。这是通过从
Recipient
实例的
Session
属性创建
Application
对象来完成的。
Recipient distList = app.Session.CreateRecipient(yourDistList);
从这里,我们可以提取所有的实名和用户名竞争我们的收件人的
AdressEntry.Members
属性。要将这两种查询都放入
(string,string)
的匿名元组中,我们可以使用这个LINQ查询,如果您不喜欢这个查询,可以像普通一样迭代:
List<(string,string)> usersData = distList.AddressEntry.Members.Cast<AddressEntry>().Select(entry => (entry.Name,entry.Address)).ToList();
现在,给定一个特定的用户名,只要日历与curernt用户共享,就可以使用
Session
的
Session
方法访问它
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格式构建一个
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
,具体取决于编译器是否可以推断这一点。
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>();
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;
多情的长颈鹿 · PermissionError: [WinError 5] 拒绝访问。: ‘d:\\anaconda3\\lib\\site-packages\\numpy\\core\\multiarray.cp3_翟羽嚄的博客-CSDN博客 1 年前 |
闯红灯的蛋挞 · java - Error Code: 1046. No database selected Select the default DB to be used by double-clicking its name in the SCHEMAS list in 1 年前 |
刀枪不入的柿子 · Python习题(二) - 知乎 1 年前 |