通过Python读取Outlook事件

20

Outlook有一些需要改进的地方 - 比如显示多个月份的视图。

我决定尝试通过Python提取事件数据(然后找到一种漂亮的展示方式)。但是,谷歌的搜索结果很差。

我的目标是:

  • 读取共享日历
  • 读取事件信息,如开始时间、结束时间、主题、创建者等。

这是我整理出来的代码(灵感来自这个网站

import win32com.client, datetime
from dateutil.relativedelta import relativedelta

Outlook = win32com.client.Dispatch("Outlook.Application")
ns = Outlook.GetNamespace("MAPI")

appointments = namespace.GetDefaultFolder(9).Items 
# TODO: Need to figure out howto get the shared calendar instead Default [9] 
# (I have placed the shared folder into a separate folder - don't know if it matters)
# I would just like the user to select which calendar to execute on
appointments.Sort("[Start]")
appointments.IncludeRecurrences = "True"
begin = date.today().strftime("%m%d%Y")
end = (date.today() + relativedelta( months = 3 )).strftime("%m%d%Y")
appointments = appointments.Restrict("[Start] >= '" +begin+ "' AND [END] >= '" +end+ "'")

我该如何循环遍历事件并读取它们?


3
你是不是想用 ns.GetDefaultFolder(9) 而不是 namespace.?如果我使用你的代码,会出现 NameError 错误。 - alexwlchan
1个回答

26

我需要帮助来循环遍历这些事件并读取它们。

基本上,您只需遵循 Microsoft 的 COM API 文档即可。例如,Restrict() 方法返回的是在 Outlook 2010 的 AppointmentItem Object 中有详细说明的 AppointmentItem 对象。因此,从一个文件夹开始,您可以按以下方式获取和列出约会:

# Get the AppointmentItem objects
# http://msdn.microsoft.com/en-us/library/office/aa210899(v=office.11).aspx
appointments = someFolder.Items

# Restrict to items in the next 30 days (using Python 3.3 - might be slightly different for 2.7)
begin = datetime.date.today()
end = begin + datetime.timedelta(days = 30);
restriction = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" +end.strftime("%m/%d/%Y") + "'"
restrictedItems = appointments.Restrict(restriction)

# Iterate through restricted AppointmentItems and print them
for appointmentItem in restrictedItems:
    print("{0} Start: {1}, End: {2}, Organizer: {3}".format(
          appointmentItem.Subject, appointmentItem.Start, 
          appointmentItem.End, appointmentItem.Organizer))
请注意,我不得不使用略微不同的时间格式来限制表达式("%m/%d/%Y"而不是"%m%d%Y")。正确的解决方法是使用Outlook的Format函数,如http://msdn.microsoft.com/en-us/library/office/ff869597(v=office.14).aspx文档中所述,Date部分。还请注意,我使用的是Python 3.3,因此您可能需要使用不同的函数来创建日期。无论如何,为了测试目的,您可以使用硬编码表达式,例如"[Start] >= '02/03/2014' AND [End] <= '03/05/2014'"
要获取共享日历,以下代码应该有效-这是API文档中常见的顺序,但我无法使其实际工作,但这可能是由于使用不同的后端服务器(未使用Exchange服务器):
recipient = namespace.createRecipient("User Name")
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)

要将所有可用的文件夹显示为树形结构,您可以使用类似以下的内容:

def folderTree(folders, indent = 0):
    prefix = ' ' * (indent*2)
    i = 0
    for folder in folders:
        print("{0}{1}. {2} ({3})".format(prefix, i, folder.Name, folder.DefaultItemType))
        folderTree(folder.Folders, indent + 1)
        i = i + 1

...
folderTree(namespace.Folders)

要按路径查找文件夹(例如,在“Internet Calendars”文件夹下找到名为“Norfeld@so.com”的日历文件夹),您可以使用类似以下的内容:

def findFolder(folders, searchPath, level = 0):
    for folder in folders:
        if folder.Name == searchPath[level]:
            if level < len(searchPath)-1:
                # Search sub folder
                folder = findFolder(folder.folders, searchPath, level+1)
            return folder
    return None

...
sharedCalendar = findFolder(namespace.Folders, ["Internet Calendars", "Norfeld@so.com"])

另请参阅:


1
谢谢你的回答 - 所以我的限制字符串命令是错误的。我很难理解MS API。如果我想选择另一个日历,该怎么办?考虑通过所有日历名称的循环来实现可能会不错。 - Norfeldt
2
我同意COM API不容易阅读,但基本上,模型很简单:有对象具有方法和属性(以及事件)。方法可以被调用并可能返回结果,例如对另一个对象的引用。属性可以被读取(如果不是只读的话也可以被写入),读取可能再次导致对另一个对象的引用。一些方法/属性返回COM集合,可以进行迭代,这无缝地集成到Python中,因此您可以使用for ... in ... - Andreas Fester
并不是说我没有尝试过,只是无法使你的文件夹树工作 - 而我需要它来获取感兴趣的日历。我在Python中没有使用类。 - Norfeldt
对于 ns.Folders 中的每个文件夹:打印文件夹名称。输出为 "Internet Calendars"、"SharePoint Lists" 和 "my@mail.com"。 - Norfeldt
假设我想在“Internet Calendars”中获取一个日历 - 我该如何定义一个收件人名称作为一个字符串,以获取“Internet Calendars”文件夹中的日历? - Norfeldt
请查看我的更新答案 - 我已更改代码,使其不使用类,并提供了一个独立的脚本链接,该脚本列出文件夹树,通过路径查找特定文件夹(例如“Internet Calendars”=>“Name@mail.com”),并列出此日历中的项目。我建议您使用此脚本作为起点,并查看是否可以在您的环境中运行它。如果无法运行,请发表后续问题,说明您卡住的具体错误代码/问题,以保留此问题的上下文。 - Andreas Fester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接