在运行时在应用程序级外接程序中扩展 Word 文档和 Excel 工作簿

您可以使用应用程序级外接程序以下列方式自定义 Word 文档和 Excel 工作簿:

  • 将托管控件添加到任何打开的文档或工作表。

  • 将 Excel 工作表中的现有列表对象转换为扩展的 ListObject,后者公开事件,且可通过使用 Windows 窗体数据绑定模型将后者绑定到数据。

  • 访问由 Word 和 Excel 公开的有关特定文档、工作簿和工作表的应用程序级事件。

若要使用此功能,应在运行时生成一个扩展文档或工作簿的对象。

本主题中的信息适用于以下应用程序的应用程序级项目中适用于: :Excel 2010;Word 2010。有关更多信息,请参见按 Office 应用程序和项目类型提供的功能

在外接程序中生成扩展对象

"扩展对象 "是将函数添加到对象本身存在于Word或Excel对象模型for Office runtime的Visual Studio工具提供类型的实例(称为"本机 Office对象")。若要为 Word 或 Excel 对象生成扩展对象,请使用 GetVstoObject 方法。首次为指定的Word或Excel对象的 GetVstoObject 方法,该方法会返回一个扩展指定对象的新对象。每次调用该方法并指定相同的Word或Excel对象,则返回同一扩展对象。

该扩展对象的类型名称与此本机 Office 对象的类型名称相同,但扩展对象的类型是在 Microsoft.Office.Tools.ExcelMicrosoft.Office.Tools.Word 命名空间中定义的。例如,如果调用 GetVstoObject 方法来扩展 Microsoft.Office.Interop.Word.Document 对象,则该方法会返回 Microsoft.Office.Tools.Word.Document 对象。

GetVstoObject 方法主要用在应用程序级项目中。也可以在文档级项目中使用这些方法,但此时它们的行为将不同于在应用程序级项目中时的行为,且用处较少。

若要确定是否已为某个特定本机 Office 对象生成扩展对象,请使用 HasVstoObject 方法。有关更多信息,请参见确定 Office 对象是否已扩展。

Cc442981.collapse_all(zh-cn,VS.110).gif生成宿主项

使用 GetVstoObject 扩展文档级对象(即 Microsoft.Office.Interop.Excel.WorkbookMicrosoft.Office.Interop.Excel.WorksheetMicrosoft.Office.Interop.Word.Document)时,返回的对象称为“宿主项”。宿主项是一种可以包含其他对象的类型,这些对象包括其他扩展对象和控件。宿主项类似于 Word 或 Excel 主互操作程序集中的相应类型,但还具有其他功能。有关宿主项的更多信息,请参见宿主项和宿主控件概述

在生成一个宿主项后,可用它将托管控件添加到文档、工作簿或工作表中。有关更多信息,请参见 文档和工作表中添加托管控件。

为 Word 文档生成宿主项

  • 下面的代码示例演示如何生成活动的项目文档的。

    If Globals.ThisAddIn.Application.Documents.Count > 0 Then
        Dim NativeDocument As Microsoft.Office.Interop.Word.Document = _
            Globals.ThisAddIn.Application.ActiveDocument
        Dim VstoDocument As Microsoft.Office.Tools.Word.Document = _
            Globals.Factory.GetVstoObject(NativeDocument)
    End If
    
    if (Globals.ThisAddIn.Application.Documents.Count > 0)
    {
        Microsoft.Office.Interop.Word.Document nativeDocument =
            Globals.ThisAddIn.Application.ActiveDocument;
        Microsoft.Office.Tools.Word.Document vstoDocument =
            Globals.Factory.GetVstoObject(nativeDocument);
    }
    

为 Excel 工作簿生成宿主项

  • 下面的代码示例演示如何生成活动工作簿的一个宿主项。

    Dim NativeWorkbook As Microsoft.Office.Interop.Excel.Workbook =
        Globals.ThisAddIn.Application.ActiveWorkbook
    If NativeWorkbook IsNot Nothing Then
        Dim vstoWorkbook As Microsoft.Office.Tools.Excel.Workbook =
            Globals.Factory.GetVstoObject(NativeWorkbook)
    End If
    
    Microsoft.Office.Interop.Excel.Workbook nativeWorkbook = 
        Globals.ThisAddIn.Application.ActiveWorkbook;
    if (nativeWorkbook != null)
    {
        Microsoft.Office.Tools.Excel.Workbook vstoWorkbook = 
            Globals.Factory.GetVstoObject(nativeWorkbook);
    }
    

为 Excel 工作表生成宿主项

  • 下面的代码示例演示如何生成活动工作表的宿主项在项目。

    Dim NativeWorksheet As Microsoft.Office.Interop.Excel.Worksheet =
        Globals.ThisAddIn.Application.ActiveSheet
    If NativeWorksheet IsNot Nothing Then
        Dim vstoSheet As Microsoft.Office.Tools.Excel.Worksheet =
            Globals.Factory.GetVstoObject(NativeWorksheet)
    End If
    
    Microsoft.Office.Interop.Excel.Worksheet nativeWorksheet =
        Globals.ThisAddIn.Application.ActiveSheet;
    if (nativeWorksheet != null)
    {
        Microsoft.Office.Tools.Excel.Worksheet vstoSheet = 
            Globals.Factory.GetVstoObject(nativeWorksheet);
    }
    

Cc442981.collapse_all(zh-cn,VS.110).gif生成 ListObject 宿主控件

使用 GetVstoObject 方法扩展 Microsoft.Office.Interop.Excel.ListObject 时,该方法返回一个 Microsoft.Office.Tools.Excel.ListObjectMicrosoft.Office.Tools.Excel.ListObject 不但具有原始 Microsoft.Office.Interop.Excel.ListObject 的所有功能,而且还具有其他功能,例如能够通过使用 Windows 窗体数据绑定模型绑定到数据。有关更多信息,请参见 ListObject 控件

为 ListObject 生成宿主控件

  • 下面的代码示例演示如何生成第一 Microsoft.Office.Interop.Excel.ListObjectMicrosoft.Office.Tools.Excel.ListObject 在项目中为活动工作表。

    Dim sheet As Microsoft.Office.Interop.Excel.Worksheet =
        Globals.ThisAddIn.Application.ActiveSheet
    If sheet.ListObjects.Count > 0 Then
        Dim listObject As Excel.ListObject = sheet.ListObjects(1)
        Dim vstoListObject As Microsoft.Office.Tools.Excel.ListObject =
            Globals.Factory.GetVstoObject(listObject)
    End If
    
    Microsoft.Office.Interop.Excel.Worksheet sheet =
        Globals.ThisAddIn.Application.ActiveSheet;
    if (sheet.ListObjects.Count > 0)
    {
        Excel.ListObject listObject = 
            sheet.ListObjects[1];
        Microsoft.Office.Tools.Excel.ListObject vstoListObject =
            Globals.Factory.GetVstoObject(listObject);
    }
    

向文档和工作表中添加托管控件

生成 Microsoft.Office.Tools.Word.DocumentMicrosoft.Office.Tools.Excel.Worksheet 后,可以向这些扩展对象表示的文档或工作表中添加控件。实现方式是:使用 Microsoft.Office.Tools.Word.DocumentMicrosoft.Office.Tools.Excel.WorksheetControls 属性。有关更多信息,请参见在运行时向 Office 文档添加控件

可以添加 Windows 窗体控件或宿主控件。宿主控件是 Visual Studio Tools for Office Runtime 提供的控件,用于封装 Word 或 Excel 主互操作程序集中的相应控件。宿主控件公开基础本机 Office 对象的所有行为,除此之外还引发事件,并可通过使用 Windows 窗体数据绑定模型绑定到数据。有关更多信息,请参见宿主项和宿主控件概述

说明说明

使用外接程序,则无法添加 XmlMappedRange 控件添加到工作表或 XMLNodeXMLNodes 控件添加到文档中,。这些宿主控件不能以编程方式添加。有关更多信息,请参见宿主项和宿主控件的编程限制

Cc442981.collapse_all(zh-cn,VS.110).gif保留和删除控件

向文档或工作表中添加托管控件后,保存然后关闭文档时并不保留这些控件。移除所有宿主控件,以便只有基础本机Office对象保留下来。例如, Microsoft.Office.Tools.Excel.ListObject 成为 Microsoft.Office.Interop.Excel.ListObject。此外还移除所有 Windows 窗体控件,但将这些控件的 ActiveX 包装留在文档中。必须在外接程序中包括代码,以清理这些控件,或者下次打开文档时重新创建它们。有关更多信息,请参见在 Office 文档中保存动态控件

访问关于文档和工作簿的应用程序级事件

本机 Word 和 Excel 对象模型中的某些文档、工作簿和工作表事件仅在应用程序级别引发。例如,在 Word 中打开某个文档时引发 DocumentBeforeSave 事件,但该事件是在 Microsoft.Office.Interop.Word.Application 类中定义的,而不是 Microsoft.Office.Interop.Word.Document 类中定义的。

如果在外接程序中仅使用本机 Office 对象,则必须处理这些应用程序级事件,然后编写额外的代码,以确定引发了这些事件的文档是否是您自定义过的文档。宿主项在文档级别提供这些事件,这样更便于处理特定文档的事件。可以生成一个宿主项,然后处理该宿主项提供的事件。

Cc442981.collapse_all(zh-cn,VS.110).gif使用本机 Word 对象的示例

下面的代码示例演示如何处理 Word 文档的应用程序级事件。CreateDocument 方法新建一个文档,然后定义一个使该文档无法保存的 DocumentBeforeSave 事件处理程序。由于这是一个针对 Microsoft.Office.Interop.Word.Application 对象引发的应用程序级事件,因此该事件处理程序必须将 Doc 参数与 document1 对象相比较,以确定 document1 对象是否表示已保存的文档。

Private document1 As Word.Document = Nothing

Private Sub CreateDocument1()
    document1 = Me.Application.Documents.Add()
End Sub

Private Sub Application_DocumentBeforeSave(ByVal Doc As Word.Document, _
    ByRef SaveAsUI As Boolean, ByRef Cancel As Boolean) _
    Handles Application.DocumentBeforeSave
    If Type.ReferenceEquals(Doc, document1) Then
        Cancel = True
    End If
End Sub
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;
    }
}

Cc442981.collapse_all(zh-cn,VS.110).gif使用宿主项的示例

以下代码示例通过处理 Microsoft.Office.Tools.Word.Document 宿主项的 BeforeSave 事件来简化该过程。这些示例中的 CreateDocument2 方法生成一个扩展 document2 对象的 Microsoft.Office.Tools.Word.Document,然后定义一个使文档无法保存的 BeforeSave 事件处理程序。由于仅在保存 document2 时调用该事件处理程序,因此该事件处理程序无需进行任何额外的工作来验证保存了哪个文件,即可取消保存操作。

下面的代码示例演示此任务。

Private document2 As Word.Document = Nothing
Private WithEvents vstoDocument As Microsoft.Office.Tools.Word.Document = Nothing

Private Sub CreateDocument2()
    document2 = Me.Application.Documents.Add()
    vstoDocument = Globals.Factory.GetVstoObject(document2)
End Sub

Private Sub vstoDocument_BeforeSave(ByVal sender As Object, _
    ByVal e As SaveEventArgs) Handles vstoDocument.BeforeSave
    e.Cancel = True
End Sub
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,否则返回 false。

请使用 Globals.Factory.HasVstoMethod 方法。通过在本机Word或Excel对象,如 Microsoft.Office.Interop.Word.DocumentMicrosoft.Office.Interop.Excel.Worksheet,要用于扩展对象测试。

如果希望仅在指定 Office 对象具有扩展对象时运行代码,则 HasVstoObject 方法会很有用。例如,如果您有一个 Word 外接程序,用于处理 DocumentBeforeSave 事件,以在文档保存之前从中移除托管控件,则可以使用 HasVstoObject 方法来确定该文档是否已扩展。如果该文档还未扩展,则它不能包含托管控件,因此事件处理程序只能返回,而不尝试清理该文档中的控件。

请参见

概念

在运行时向 Office 文档添加控件

宿主项和宿主控件概述

其他资源

应用程序级外接程序编程

Office 开发示例和演练