技术开发 频道

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

  【IT168 专稿】在前面的系列文章中,我们曾经介绍过Visual Studio 2010中C# 4.0新的语言特性对Office开发的帮助。实际上,除了新的语言特性对Office开发的增强外,Visual Studio 2010在IDE本身,在开发体验方面,都对Office开发做了很多改进和增强。在接下来的几篇文章中,我们将以实例的形式,介绍如何利用Visual Studio 2010进行Office开发。

  在Visual Studio 2010中,微软提供了专门的Office开发套件VSTO来支持Office的开发。利用VSTO,我们可以开发下面几种类型的Office应用:

  •文档级自定义项
  文档级自定义项由与单一文档关联的程序集、工作簿或 Microsoft Office Word 或 Microsoft Office Excel 中的模板组成。在打开关联的文档时,程序集将自动加载。你所创建的自定义项中的功能仅在关联的文档被打开时可用。自定义项不能进行应用程序范围的更改,例如打开任何文档时都显示一个新菜单项或功能区选项卡。

  •应用程序级插件
  应用程序级插件包含一个与某个 Microsoft Office 应用程序相关联的程序集。通常,该插件随着所关联的应用程序的启动而运行。当然,用户也可以在关联应用程序已在运行时加载插件。你所创建的插件程序中的功能可用于应用程序本身,而与所打开的文档无关。

  在Visual Studio 2010中,我们可以使用相应的模板创建Office应用程序的插件。通常,应用程序插件项目包含一个表示插件的自动生成的类。此类提供的属性和事件可用于访问宿主应用程序的对象模型以及在加载和关闭插件程序时运行代码。许多 Visual Studio的通用功能在应用程序级插件项目中都是可用的,如 Windows 窗体和集成调试器等。

  •Office Ribbon界面插件
  跟应用程序级插件相类似,Office Ribbon界面插件不仅可以执行普通插件的功能,同时它还可以在Office应用程序的Ribbon面板上添加相应的控件,从而与用户进行交互,实现用户的输入或者应用程序的输出。在Ribbon界面插件中,你可以自定义Office程序的Ribbon界面,通过功能区以控件的形式组织相关的命令。界面插件通过在Office程序的“Add-ons”Ribbon页面中添加相应的控件,使它们易于查找,从而与用户进行界面交互,实现相应的功能。在早期版本的Microsoft Office中使用菜单和工具栏访问的大部分功能,现在都可以使用Ribbon功能区访问。

 
图1 Office开发的三种基本类型

  下面我们分别以实例的形式,来分别演示Visual Studio 2010中这三种Office应用的开发方式。

  在这一篇文章中,我们以Word 文档为例,介绍文档级自定义项的开发。我们知道,Office开发都是以Office文档对象模型为基础的,在开始进行具体的开发之前,我们有必要简单地介绍一下Word对象模型,让大家对我们要操作的对象有个清晰的概念。

  Word对象模型概述

  在我们即将开发的文档级自定义项中,我们需要操作Word文档的段落,文字,格式等等,VSTO对这些文档对象进行了封装,提供了数百个我们可以与之交互的对象,形成了Word对象模型。这些对象排列在一个与用户界面密切相关的层次结构中。层次结构顶部的对象是 Application 对象。此对象表示 Word 宿主程序的当前实例。Application 对象包含 Document、Selection、Bookmark 和 Range 对象。这些对象各自都有很多方法和属性,我们可以访问这些方法和属性来操作对象或与对象交互。
 


图2 Word对象模型

虽然Word对象模型中的对象有数百个之多,但是其中我们需要用到的只有Application和Document和Range这三个对象:

  •Application 对象
  Application 对象表示 Word 应用程序本身,是其他所有Word对象的父级。它的所有成员通常作为一个整体应用于 Word。我们可以使用该对象的属性和方法来控制Word环境。

  •Document对象
  Document 对象是Office Word开发的核心。它表示文档及其所有内容。当我们打开文档或创建新文档时,就创建了新的 Document 对象,该对象被添加到 Application 对象的 Documents 集合中。具有焦点的文档称为当前活动文档。它由 Application 对象的 ActiveDocument 属性表示。

  •Range对象
  Range 对象表示文档中的一个连续的区域,由一个起始字符位置和一个结束字符位置定义。Range 对象的数量并不局限于一个。您可以在同一文档中定义多个 Range 对象。Range 对象具有以下这些特性:

  它的组成成分可以是单独的插入点,也可以是一个文本范围或整个文档。
  它包含非打印字符,例如空格、制表符和段落标记。
  它可以是当前选择所表示的区域,也可以表示当前选择之外的区域。
  与所选内容总是可见不同,它在文档中是不可见的。
  它不随文档保存,仅存在于代码运行期间。
  在向一个范围的末尾插入文本时,Word 会自动扩展该范围以包含插入的文本。

  当我们创建文档级项目时,Visual Studio 2010会生成一个名为 ThisDocument 的类,你可以在 ThisDocument 类中使用关键字“this”访问到Document对象的所有成员。例如,如果我们想要选择文档中的第一个段落,可以用如下的代码实现:

  this.Paragraphs[1].Range.Select();

 

  这里需要特别注意的是,为了便于理解,Office对象模型中,段落数组的起始序号是1,而不是我们通常在开发中所使用的0。
创建文档级自定义项

  在Office企业应用中,我们常常通过文档模板生成各种标准格式的报表,其中一个典型应用就是填写请假单:我们通过Word文档模板生成一个Word文档,然后在请假单Word文档中填写请假原因和请假期限,然后填写自己的名字和申请日期等。下面,我们通过开发一个文档级的自定义项来简化这一填写表单的过程。
我们知道,文档级自定义项是跟具体的某个文档关联的。当这个Word文档打开的时候,文档级自定义项被自动加载,然后弹出一个窗体,供用户输入请假的原因和选择请假期限,最后自动插入请假人和申请日期,生成请假单文档。在这个请假单的基础上,用户可以直接打印提交也可以继续编辑。

   首先,我们启动Visual Studio 2010 CTP,创建一个新的Visual C#类型的项目。在新建项目对话框中,我们选择“Word 2007 Document”作为项目模板类型,然后输入项目名称为“FirstDocumentCustomization”,点击“确定”关闭新建项目对话框,Visual Studio 2010将为我们创建一个文档级自定义项的Office开发项目。
 


图3 新建项目

  默认情况下,这个项目将包含一个Word文档和一个用于操作这个文档的类ThisDocument。
 
 


图4 向导生成的Word文档和ThisDocument类

  在设计器中编辑文档

  从上文的截图中我们可以看到,Visual Studio 2010为我们生成了一个Word文档,我们可以项在Office Word中编辑普通文档一样对这个文档进行编辑。为了实现请假条,我们可以在Visual Studio提供的文档设计器中直接编辑这个文档,添加页眉,标题等固定的内容。Visual Studio 2010的文档设计器跟Office Word完全一致,所以在文档设计器中修改编辑文档是一件非常容易的事情。
 


图5 在文档设计器中编辑文档

  创建并实现填写窗体

  按照前文我们的设计思路,为了实现请假单的简便填写,我们需要在文档打开的时候显示一个窗体接收用户的输入。所以,我们在项目中新添加一个窗体,并将其编辑如下:
 


图6 请假单填写窗体

  在这个窗体中,我们使用了一个支持多行的编辑框控件,供用户输入请假的原因。另外使用了两个日期选择控件,供用户输入请假的起止日期。完成窗体资源的编辑后,我们将整个窗体类实现如下:

public partial class FillForm : Form
{
        
public FillForm()
        {
            InitializeComponent();
        }

        
// 获得请假原因
        public string GetReason()
        {
    
// 从控件获得用户输入
            return this.textBoxReason.Text;
        }

        
// 获得开始时间
        public string GetTimeFrom()
        {
            
return this.dateTimeFrom.Value.ToShortDateString();
        }

        
// 获得结束时间
        public string GetTimeTo()
        {
            
return this.dateTimeTo.Value.ToShortDateString();
        }

        
//
        
// 用户点击确定按钮后关闭窗体
        private void OK_Click(object sender, EventArgs e)
        {
            
this.Close();
        }
}

 

  自定义Word启动过程

  完成请假单填写窗体的设计后,我们就可以在文档被打开的时候显示这个窗体,让用户在窗体中输入相应的信息后,文档级自定义项可以从窗体获得用户的输入,然后根据用户的输入生成相应的文档内容。在上文中我们已经提到了向导为我们自动生成的ThisDocument类,这个类负责对整个文档进行编程开发,同时提供了对Word文档模型中其他对象的访问接口。可以说,这个类实际上是整个文档的编程模型,通过ThisDocument类我们可以直接操作这个文档。

  在ThisDocument类中预先定义了两个事件处理函数:ThisDocument_Startup和ThisDocument_Shutdown。当文档被打开的时候,ThisDocument_Startup会被自动调用,我们可以在这个函数中进行一些初始化工作,例如显示我们的填写请假条窗体获取用户输入。当文档被关闭的时候,ThisDocument_Shutdown会被自动调用,在这里我们可以进行一些资源清理工作。

  为了在文档被打开的时候显示请假单填写窗体,在ThisDocument.cs代码文件中,我们将ThisDocument_Startup函数实现如下:

private void ThisDocument_Startup(object sender, System.EventArgs e)
        {
            
// 创建并显示填写请假条窗体
            FillForm formFill = new FillForm();
            formFill.ShowDialog();

            
// 获得用户输入的信息
            string strReaon = formFill.GetReason();
            
string strTimeFrom = formFill.GetTimeFrom();
            
string strTimeTo = formFill.GetTimeTo();

            
// 根据用户输入生成请假条内容
            string strContent;
            strContent
= "\t我因" + strReaon + ",需要请假(从 " + strTimeFrom +
                
"" + strTimeTo + " ),望批准。 ";

            
// 获取计算机登录用户名作为请假人
            string strApplyPerson;
            
string strName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            strApplyPerson
= "请假人:" + strName;

            
// 插入新的段落
            this.Paragraphs[2].Range.InsertParagraphAfter();
            
// 设置段落格式
            this.Paragraphs[3].Range.ParagraphFormat.Alignment =
                Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphLeft;
            
// 设置段落文本
            this.Paragraphs[3].Range.Text = strContent;
            
            
// 请假人段落
            this.Paragraphs[3].Range.InsertParagraphAfter();
            
this.Paragraphs[4].Range.ParagraphFormat.Alignment =
                Microsoft.Office.Interop.Word.WdParagraphAlignment.wdAlignParagraphRight;
            
this.Paragraphs[4].Range.Text = strApplyPerson;
            
            
// 请假日期
            this.Paragraphs[4].Range.InsertParagraphAfter();
            
this.Paragraphs[5].Range.InsertDateTime();
        }

  在这个函数中,我们首先创建并显示填写请假条窗体,用户在其中输入请假原因和请假期限后关闭窗体,然后程序从窗体中获得用户输入的信息,生成相应的文本内容。接着,插入新的段落,设置段落格式和文本内容,这样,我们就利用用户在窗体上的输入创建了一个完整的请假单文档。
测试项目

  现在,我们就可以编译测试整个项目。当文档被打开的时候,会出现我们设计好的“填写请假单窗体”,在其中我们输入请假原因和请假的起止时间,单击确定后,Word会自动更加我们的输入生成完整的请假单文档,这样是不是比以前逐个空格的填写方式快捷多了呢?请假单只是一个简单的例子,我们还可以在这个基础上,利于文档级自定义项开发出很多Office应用,提高办公效率。
 


图7 填写请假单和生成的请假单效果

  这里需要特别说明的是,为了系统的安全,完成Office项目的开发后,我们应该删除项目输出文件夹中的文件和项目生成过程中所创建的安全设置。我们可以通过“Build”->“Clean Solution”菜单项来清理项目。

0
相关文章