可以使用 VSTO 外接程序通过以下方式自定义 Word 文档和 Excel 工作簿:
- 将托管控件添加到任何打开的文档或工作表。 
- 将 Excel 工作表上的现有列表对象转换为公开事件的扩展ListObject对象,并能通过 Windows 窗体数据绑定模型绑定到数据。 
- 访问 Word 和 Excel 为特定文档、工作簿和工作表公开的应用程序级事件。 - 若要使用此功能,请在运行时生成扩展文档或工作簿的对象。 - 适用于: 本文中的信息适用于以下应用程序的 VSTO 外接程序项目:Excel 和 Word。 有关详细信息,请参阅 Office 应用程序和项目类型提供的功能。 
在 VSTO 外接程序中生成扩展对象
              扩展对象 是 Visual Studio Tools for Office 运行时提供的类型的实例,可将功能添加到 Word 或 Excel 对象模型中本机存在的对象(称为 本机 Office 对象)。 若要为 Word 或 Excel 对象生成扩展对象,请使用 GetVstoObject 该方法。 首次调用 GetVstoObject 指定 Word 或 Excel 对象的方法时,它将返回一个新对象,该对象扩展指定对象。 每次调用该方法并指定相同的 Word 或 Excel 对象时,它都会返回相同的扩展对象。
扩展对象的类型与本机 Office 对象的类型同名,但该类型是在Microsoft.Office.Tools.Excel或Microsoft.Office.Tools.Word命名空间中定义的。 例如,如果调用 GetVstoObject 方法来扩展 Document 对象,该方法将返回一个 Document 对象。
这些 GetVstoObject 方法主要用于 VSTO 外接程序项目中。 还可以在文档级项目中使用这些方法,但它们的行为方式不同,并且使用次数更少。
若要确定是否已为特定本机 Office 对象生成扩展对象,请使用该方法 HasVstoObject 。 有关详细信息,请参阅 确定是否已扩展 Office 对象。
生成主机项
使用GetVstoObject扩展文档级对象(即 a、WorkbookWorksheet或Document)时,返回的对象称为宿主项。 宿主项是可以包含其他对象(包括其他扩展对象和控件)的类型。 它类似于 Word 或 Excel 主互操作程序集中的相应类型,但它具有其他功能。 有关主机项的详细信息,请参阅 主机项和主机控件概述。
生成宿主项后,可以使用它向文档、工作簿或工作表添加托管控件。 有关详细信息,请参阅 向文档和工作表添加托管控件。
为 Word 文档生成宿主项
- 下面的代码示例演示如何为活动文档生成主机项。 
为 Excel 工作簿生成宿主项
- 下面的代码示例演示如何为活动工作簿生成主机项。 
为 Excel 工作表生成宿主项
- 下面的代码示例演示如何为项目中的活动工作表生成宿主项。 
生成 ListObject 主机控件
使用方法 GetVstoObject 扩展 a ListObject时,该方法返回 a ListObject. 
              ListObject具有原始ListObject的所有功能。 它还具有其他功能,可以使用 Windows 窗体数据绑定模型绑定到数据。 有关详细信息,请参阅 ListObject 控件。
为 ListObject 生成主机控件
- 下面的代码示例演示了如何在项目中活动工作表的第一个ListObject生成ListObject。 
向文档和工作表添加托管控件
生成Document或Worksheet对象后,可以向这些扩展对象所表示的文档或工作表添加控件。 若要添加控件,请使用 Controls 的Document或Worksheet属性。 有关详细信息,请参阅 运行时向 Office 文档添加控件。
可以添加 Windows 窗体控件或 主机控件。 主机控件是由 Visual Studio Tools for Office 运行时提供的控件,用于封装 Word 或 Excel 主互操作程序集中的相应控件。 主机控件公开基础本机 Office 对象的所有行为。 它还会触发事件,并且可以使用 Windows Forms 的数据绑定模型进行数据绑定。 有关详细信息,请参阅 主机项和主机控件概述。
注释
不能使用 VSTO 外接程序将XmlMappedRange控件添加到工作表,也不能将XMLNode控件或XMLNodes控件添加到文档中。 无法以编程方式添加这些主机控件。 有关详细信息,请参阅 主机项和主机控件的编程限制。
保留和删除控件
向文档或工作表添加托管控件时,保存文档后关闭控件时不会保留这些控件。 删除所有主机控件,以便仅留下基础本机 Office 对象。 例如,一个 ListObject 变为一个 ListObject。 所有 Windows 窗体控件将被删除,但文档中将保留控件的 ActiveX 包装器。 必须在 VSTO 外接程序中包含代码以清理控件,或在下次打开文档时重新创建控件。 有关详细信息,请参阅 在 Office 文档中持久保存动态控件。
访问文档和工作簿上的应用程序级事件
本地 Word 和 Excel 对象模型中的某些文档、工作簿和工作表事件仅在应用程序级别触发。 例如,DocumentBeforeSave 在 Word 中打开文档时引发该事件,但此事件在 Application 类中定义,而不是在 Document 类中。
在 VSTO 外接程序中仅使用本机 Office 对象时,必须处理这些应用程序级事件,然后编写其他代码来确定引发该事件的文档是否是你自定义的文档。 宿主项在文档级别提供这些事件,以便更轻松地处理特定文档的事件。 可以生成主机项,然后处理该主机项的事件。
使用本机 Word 对象的示例
下面的代码示例演示如何处理 Word 文档的应用程序级事件。 该方法 CreateDocument 创建一个新文档,然后定义一个 DocumentBeforeSave 事件处理程序,以防止保存此文档。 该事件是为Application对象引发的应用程序级事件,事件处理程序必须将参数与Doc对象进行比较document1,以确定是否document1表示已保存的文档。
private Word.Document document1 = null;
private void CreateDocument1()
{
    document1 = this.Application.Documents.Add(ref missing,
        ref missing, ref missing, ref missing);
    this.Application.DocumentBeforeSave += 
        new Word.ApplicationEvents4_DocumentBeforeSaveEventHandler(
        Application_DocumentBeforeSave);
}
private void Application_DocumentBeforeSave(Word.Document Doc, 
    ref bool SaveAsUI, ref bool Cancel)
{
    if (Type.ReferenceEquals(Doc, document1)) 
    {
        Cancel = true;
    }
}
使用主机项的示例
以下代码示例通过处理 BeforeSave 主机项的事件 Document 来简化此过程。 
              CreateDocument2方法在这些示例中生成一个Document,扩展document2对象,然后定义BeforeSave事件处理程序,以防止文档被保存。 事件处理程序仅在 document2 保存时调用,可以取消保存操作,而无需执行任何额外的工作来验证哪个文档已保存。
下面的代码示例演示了此任务。
private Word.Document document2 = null;
private Microsoft.Office.Tools.Word.Document vstoDocument = null;
private void CreateDocument2()
{
    document2 = this.Application.Documents.Add(ref missing,
        ref missing, ref missing, ref missing);
    vstoDocument = Globals.Factory.GetVstoObject(document2);
    vstoDocument.BeforeSave += new SaveEventHandler(vstoDocument_BeforeSave);
}
private void vstoDocument_BeforeSave(object sender, SaveEventArgs e)
{
    e.Cancel = true;
}
确定是否已扩展 Office 对象
若要确定是否已为特定本机 Office 对象生成扩展对象,请使用该方法 HasVstoObject 。 如果已生成扩展对象,此方法将返回 true 。
使用 Globals.Factory.HasVstoObject 方法。 传入本机 Word 或 Excel 对象,例如 Document 或 Worksheet,以测试扩展对象。
仅当指定的 Office 对象具有扩展对象时,HasVstoObject 方法才非常有用,因为这时你只想运行代码。 例如,如果有一个 Word VSTO 外接程序用于处理 DocumentBeforeSave 事件,以便在文档保存之前从文档中删除托管控件,那么请使用 HasVstoObject 方法来确定文档是否已经扩展。 如果文档尚未扩展,则它不能具有托管控件,并且事件处理程序可以在不尝试清理文档上的控件的情况下返回。