技术开发 频道

详解VSTS与OFFICE的协同开发:Outlook篇

  【IT168 专稿】书接上回,在前面一篇文章中,我们结合Office Word 2007,以实例的形式介绍了如何在Visual Sutton  2010中进行文档级自定义项的开发,相信大家在其基础上都可以开发出自己的丰富多彩的Office应用。前面介绍的文档级自定义项是跟某个具体的文档相关联的,如果我们需要Office程序具有某些扩展功能,那该怎么办呢?能不能开发跟文档无关,而针对Office程序适用的插件,帮助我们完成一些繁琐的辅助工作?答案当然是肯定的。在这篇文章中,我们继续在Visual Studio 2010中进行Office开发的话题,介绍如何开发跟文档无关的应用程序级插件。

  在上一篇文章中我们已经介绍过,在Visual Studio 2010中,Office开发主要有三种类型,其中应用程序级插件就是本文将要介绍的主要内容。应用程序级插件包含一个与某个 Microsoft Office 应用程序相关联的程序集。通常,该插件随着所关联的应用程序的启动而运行。当然,用户也可以在关联应用程序已经在运行的时候动态地加载插件。我们所创建的应用程序级插件中的功能可用于应用程序本身,而与所打开的文档无关。

  第一篇:详解VSTS与OFFICE的协同开发:WORD篇

  在本文中,我们以最常用的Outlook收发邮件为例,介绍应用程序级插件的开发流程。我们可以设想这样这个Office应用场景:我们是工作在一个比较规范的组织中,我们在利于Outlook发送新邮件时,通常会有一些固定的格式,例如给主题加上标头,邮件正文末尾添加固定的联系方式等等。另外,对于某些管理者,常常会收到一些固定格式的报表,例如每周销售报表等等。这些报表需要专门整理保持到特定的目录以备查看。

  为了系统安全,甚至可以自动运行杀毒软件进行扫描。这些都是我们在使用Outlook时的常见任务,虽然这些任务都可以通过Outlook的设置来实现,但是这里我们还是利于开发的方式,来看看如果利于应用程序级插件,更加灵活高效地完成这些功能。

  Outlook对象模型概述

  在利用Visual Studio 2010开发应用程序级插件之前,我们还是先来了解一下即将用到的Outlook对象模型。Outlook对象模型提供许多我们可以与之进行交互的类。若要有效地使用Outlook对象模型,我们应该熟悉以下这些最常用类:

  •Application 类
  Application 类表示 Outlook 应用程序,它是 Outlook 对象模型中最顶层的类。此类的一些最重要的成员包括:
  CreateItem 方法,该方法可用来创建新项,例如电子邮件、任务或约会等。
  Explorers 属性,该属性可用来访问在 Outlook 用户界面 (UI) 中显示文件夹内容的窗口。
  Inspectors 属性,该属性可用来访问显示单个项(如电子邮件或会议要求)内容的窗口。
  在我们所创建的应用程序级插件项目中,若要获得 Application 类的实例,可以使用 自动生成的ThisAddin 类的 Application 属性,这个属性就代表了Application类的一个实例。

  •ThisAddIn 类
  我们在创建新的 Outlook 插件项目时,Visual Studio 2010会自动在新项目中创建 ThisAddIn.vb 或 ThisAddIn.cs 代码文件。此代码文件中定义了一个继承自 OutlookAddIn 的 ThisAddin 类。
 


图1 插件项目中所包含的类

  从上面的类视图中我们可以发现,ThisAddIn类提供的属性和事件可用于访问宿主应用程序的对象模型以及在加载和关闭插件时运行代码。通过在 ThisAddIn 类中使用关键字 Me(Visual Basic 中)或 this(C# 中),我们可以访问 OutlookAddIn类的成员,例如上文提到的Application属性。ThisAddIn 类以外的代码可以使用静态 Globals.ThisAddIn 属性访问 ThisAddIn 对对象。

  •Explorer 类
  Explorer 类表示显示包含项(如电子邮件、任务或约会)的文件夹内容的窗口。Explorer 类包括可用来修改窗口的方法和属性,以及窗口更改时所引发的事件。我们可以通过如下的方式获得Explorer类的实例: 
  使用 Application 类的 Explorers 属性来访问 Outlook 中的所有 Explorer 对象。
  使用 Application 类的 ActiveExplorer 方法来获取当前具有焦点的 Explorer。
  使用 MAPIFolder 类的 GetExplorer 方法来获取当前文件夹的 Explorer。

  •Inspector 类
  Inspector 类表示一个显示单个项(如电子邮件、任务或约会)的窗口。Inspector 类包括可用来修改窗口的方法和属性,以及窗口更改时所引发的事件。我们可以通过如下的方式获得Inspector类的对象:
  使用 Application 类的 Inspectors 属性来访问 Outlook 中的所有 Inspector 对象。
  使用 Application 类的 ActiveInspector 方法来获取当前具有焦点的 Inspector对象。
  使用特定项(如 MailItem 或 AppointmentItem)的 GetInspector 方法检索与其关联的 Inspector对象。

  •MAPIFolder 类
  MAPIFolder 类表示包含电子邮件、联系人、任务及其他项的文件夹。Outlook 提供 16 个默认 MAPIFolder 对象。默认 MAPIFolder 对象由 OlDefaultFolders 枚举值定义。例如, Outlook.OlDefaultFolders.olFolderInbox 与 Outlook 中的“收件箱”文件夹相对应。

  •MailItem 类
  MailItem 类表示电子邮件。MailItem 对象通常在“收件箱”、“已发送邮件”和“发件箱”等文件夹中。MailItem 类包含了可用于创建和发送电子邮件的属性和方法,我们可以利于这些成员对邮件进行具体的操作。例如,我们可以通过下面的代码创建一封新邮件:

private void CreateMailItem()
{
    
// 创建新邮件
    Outlook.MailItem mailItem = (Outlook.MailItem)
        
this.CreateItem(Outlook.OlItemType.olMailItem);
    
// 设置邮件的主题,收件人,邮件正文,优先级等
    mailItem.Subject = "测试邮件";
    mailItem.To
= "chenlq@live.com";
    mailItem.Body
= "这是一封测试邮件。";
    mailItem.Importance
= Outlook.OlImportance.olImportanceLow;
    mailItem.Display(
false);
}

  •AppointmentItem 类
  AppointmentItem 类表示“日历”文件夹中的会议、一次性约会,或定期约会或会议。AppointmentItem 类包括执行操作(如响应或转发会议要求)的方法,以及指定会议详细信息(如位置和时间)的属性。

  •TaskItem 类
  TaskItem 类表示要在指定时间范围内执行的任务。TaskItem 对象位于“任务”文件夹。

  •ContactItem 类
  ContactItem类表示“联系人”文件夹中的联系人。ContactItem 对象包含它们所表示的人的各种联系信息,如街道地址、电子邮件地址和电话号码等。通过这个对象,我们可以搜索联系人,编辑联系人的信息等。例如,下面的代码演示了如何搜索特定的联系人:

// 在程序启动的时候,搜索联系人“陈良乔”
private void ThisApplication_Startup(object sender, System.EventArgs e)
{
    FindContactEmailByName(
"", "良乔");
}

private void FindContactEmailByName(string firstName, string lastName)
{
    Outlook.NameSpace outlookNameSpace
= this.GetNamespace("MAPI");
    
// 获得联系人文件夹
    Outlook.MAPIFolder contactsFolder =
        outlookNameSpace.GetDefaultFolder(
        Microsoft.Office.Interop.Outlook.
        OlDefaultFolders.olFolderContacts);
    
// 获取“联系人”文件夹中的所有联系人
    Outlook.Items contactItems = contactsFolder.Items;

    
try
    {
        
// 查找联系人
        Outlook.ContactItem contact =
            (Outlook.ContactItem)contactItems.
            Find(String.Format(
"[FirstName]='{0}' and "
            
+ "[LastName]='{1}'", firstName, lastName));
        
if (contact != null)
        {
            contact.Display(
true);
        }
        
else
        {
            MessageBox.Show(
"无法找到联系人。");
        }
    }
    
catch (Exception ex)
    {
        
throw ex;
    }
}

  创建应用程序级插件

  在了解了Outlook对象模型之后,我们就可以开发基于Outlook的应用程序级插件了。首先,我们启动Visual Studio 2010,创建一个新的Visual C#类型的项目。在“新建项目”对话框中,我们选择“Outlook 2007 Add-In”作为项目模板,然后输入项目名称为“FirstOutlookAddIn”,点击“确定”关闭新建项目对话框,Visual Studio将为我们创建一个基于Outlook的应用程序级插件项目。
 


图2 新建应用程序级插件
 
  默认情况下,Visual Studio会为我们创建一个名为ThisAddIn的类,这个类就代表了整个插件,我们可以在其中访问Outlook对象模型中的各个对象,从而完成插件的各项具体的功能。在这个类中包含了ThisAddIn_Startup 和ThisAddIn_Shutdown两个函数,两个函数会在插件被加载和卸载时自动调用,我们可以在这两个函数中分别完成一些初始化工作和资源清理的工作。

  创建自定义主题的新邮件

  在Outlook中新建邮件时,Outlook会新建一个新邮件的窗口,我们就在新建窗口的时候,添加邮件的标题和邮件体的相关内容。在ThisAddIn类中新定义一个表示所有窗口的变量Outlook.Inspectors inspectors,并在ThisAddIn_Startup函数中对其初始化:

        // 表示所有窗口的对象
        Outlook.Inspectors inspectors;

        
private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            
// 使用这个对象表示Outlook中的所有窗口
            inspectors = this.Application.Inspectors;

            
// 为新建窗口事件添加一个事件处理函数
            inspectors.NewInspector +=
            
new Microsoft.Office.Interop.Outlook.
                InspectorsEvents_NewInspectorEventHandler(
                Inspectors_NewInspector);
        }

  这样,当我们在Outlook中新建邮件的时候,事件处理函数Inspectors_NewInspector会被自动调用,我们可以在这个函数中访问Outlook对象模型,填写合适的邮件主题,并对邮件的内容进行编辑:

// 新建邮件窗口事件处理函数
void Inspectors_NewInspector(
            Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {
            
// 获得当前邮件体
            Outlook.MailItem mailItem =
                (Outlook.MailItem)Inspector.CurrentItem;

            
if (mailItem != null)
            {
                
if (mailItem.EntryID == null)
                {
                    
// 设置邮件的标题
                    mailItem.Subject = "[试金石软件创意工作室]";
                    
// 构造邮件体
                    string strMailBody;
                  
// 添加称谓,写信人,联系方式和日期
                    strMailBody = "尊敬的: \n\n陈良乔\n\E-Mail: chenlq@live.com" +
                        DateTime.Now.ToShortDateString();
                    
// 设置邮件体
                    mailItem.Body = strMailBody;
                }
            }
        }

  这时,我们就可以编译运行整个项目进行测试。当我们在Outlook中新建邮件时,Outlook会自动为我们添加邮件主题和邮件的联系信息,这样就省去了我们填写邮件主题和联系信息的时期,可以直接开始书写邮件正文了。
 


图3 新建自定义主题的邮件

  对邮件附件进行整理

  如果你是一个管理者,常常收到各种附件形式的报表,你希望把这些附件都保存到某个目录下。这时我们可以使用Outlook的“新到邮件”事件,自动将符合条件的邮件附件保存到某个特定目录下。
首先,我们在插件加载的时候,添加一个“新到邮件”事件的事件处理函数:

private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
            
// 添加一个“新到邮件”的事件处理函数
            this.Application.NewMail += new Microsoft.Office.Interop.
                Outlook.ApplicationEvents_11_NewMailEventHandler(
                ThisApplication_NewMail_Filter);
}

  添加“新到邮件”事件处理函数后,每次有新到的邮件,这个函数就会被自动调用。我们可以在这个函数中查找收件箱中所有的未读邮件,将符合条件的邮件附件保存到特定目录下。我们将这个事件处理函数实现如下,它可以查找收件箱中所有未读邮件主题包含“[Weekly Report]”字样的邮件,并将其附件保持到一个特定的目录下:

void ThisApplication_NewMail_Filter()
{
            
// 设置主题过滤器
            string filter = "[Weekly Report]";

            
// 获取收件箱中的所有邮件
            Outlook.MAPIFolder inBox = this.Application.ActiveExplorer()
        . Session.GetDefaultFolder(Outlook
           .OlDefaultFolders.olFolderInbox);
            Outlook.Items inBoxItems
= inBox.Items;
            Outlook.MailItem newEmail
= null;
            
// 只处理未读邮件
            inBoxItems = inBoxItems.Restrict("[Unread] = true");
            
// 处理所有未读邮件
            try
            {
                
foreach (object collectionItem in inBoxItems)
                {
                    
// 获取未读的新邮件项
                    newEmail = collectionItem as Outlook.MailItem;
                    
if (newEmail != null)
                    {
                        
// 判断邮件主题是否含有过滤器字符串
                        if (newEmail.MessageClass == "IPM.Note" &&
                            newEmail.Subject.ToUpper().Contains(filter.ToUpper()))
                        {
                            
// 判断邮件是否含有附件
                            if (newEmail.Attachments.Count > 0)
                            {
                                
// 保存所有附件到特定目录
                                for (int i = 1; i <= newEmail
                                   .Attachments.Count; i
++)
                                {
                                    newEmail.Attachments[i].SaveAsFile
                                        (
@"C:\TestFileSave\" +
                                        newEmail.Attachments[i].FileName);
                                }
                            }
                        }
                    }
                }
            }
            
catch (Exception ex)
            {
                
string errorInfo = (string)ex.Message
                    .Substring(
0, 11);
                
if (errorInfo == "Cannot save")
                {
                    MessageBox.Show(
@"Create Folder C:\TestFileSave");
                }
            }
        }

  这样,你收到的所有符合条件的工作报告邮件的附件就会集中保存到一个特定目录,你可以集中一次查看所有报告,而无需每封邮件都打开查看了,无形中节省了你宝贵的时间,提高了你的效率。当然,在这个实例中的附件处理还非常粗糙,如果想在实际工作中应用,还可以进一步细化,比如可以根据邮件发送的日期和部门分门别类地整理附件等等,使得Outlook大大地提升我们的办事效率。

  要想成为Office达人,离不开Visual Studio 2010的帮助!

0
相关文章