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

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

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

  • 创建在特定文档或工作簿中识别的智能标记。

    提示

    在 Excel 2010 和 Word 2010 中已弃用智能标记。 有关更多信息,请参见智能标记概述

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

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

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

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

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

“扩展对象”是 Visual Studio Tools for Office 运行时提供的类型实例,用于将功能添加到 Word 或 Excel 对象模型中固有的对象(称为“本机 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 方法的方式取决于项目所面向的 .NET Framework 版本:

GetVstoObject 方法主要用在应用程序级项目中。 也可以在文档级项目中使用这些方法,但此时它们的行为将不同于在应用程序级项目中时的行为,且用处较少。 有关更多信息,请参见从文档级自定义项中的本机 Office 对象获取扩展对象

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

提示

若要在面向 .NET Framework 3.5 的项目中使用除 ThisAddIn.cs 或 ThisAddIn.vb 以外的代码文件中的 GetVstoObjectHasVstoObject 方法,则必须修改该项目。 有关更多信息,请参见配置项目以使用 GetVstoObject 和 HasVstoObject 方法。

生成宿主项

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

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

为 Word 文档生成宿主项

  • 下面的代码示例演示如何在面向 .NET Framework 4 的项目中为活动文档生成宿主项。

    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);
    }
    
  • 下面的代码示例演示面向 .NET Framework 3.5 的项目中的相同任务。

    If Globals.ThisAddIn.Application.Documents.Count > 0 Then
        Dim NativeDocument As Microsoft.Office.Interop.Word.Document =
            Globals.ThisAddIn.Application.ActiveDocument
        If NativeDocument IsNot Nothing Then
            Dim vstoDocument As Microsoft.Office.Tools.Word.Document =
                NativeDocument.GetVstoObject()
        End If
    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 =
            nativeDocument.GetVstoObject();
    }
    

为 Excel 工作簿生成宿主项

  • 下面的代码示例演示如何在面向 .NET Framework 4 的项目中为活动工作簿生成宿主项。

    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);
    }
    
  • 下面的代码示例演示面向 .NET Framework 3.5 的项目中的相同任务。

    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 = _
            NativeWorkbook.GetVstoObject()
    End If
    
    Microsoft.Office.Interop.Excel.Workbook nativeWorkbook =
        Globals.ThisAddIn.Application.ActiveWorkbook;
    
    if (nativeWorkbook != null)
    {
        Microsoft.Office.Tools.Excel.Workbook vstoWorkbook =
            nativeWorkbook.GetVstoObject();
    }
    

为 Excel 工作表生成宿主项

  • 下面的代码示例演示如何在面向 .NET Framework 4 的项目中为活动工作表生成宿主项。

    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);
    }
    
  • 下面的代码示例演示面向 .NET Framework 3.5 的项目中的相同任务。

    Dim NativeSheet As Microsoft.Office.Interop.Excel.Worksheet = _
        TryCast(Globals.ThisAddIn.Application.ActiveSheet,  _
        Microsoft.Office.Interop.Excel.Worksheet)
    
    If NativeSheet IsNot Nothing Then
        Dim VstoSheet As Microsoft.Office.Tools.Excel.Worksheet = _
            NativeSheet.GetVstoObject()
    End If
    
    Microsoft.Office.Interop.Excel.Worksheet nativeSheet =
        Globals.ThisAddIn.Application.ActiveSheet as
        Microsoft.Office.Interop.Excel.Worksheet;
    
    if (nativeSheet != null)
    {
        Microsoft.Office.Tools.Excel.Worksheet vstoSheet =
            nativeSheet.GetVstoObject();
    }
    

生成 ListObject 宿主控件

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

为 ListObject 生成宿主控件

  • 下面的代码示例演示如何在面向 .NET Framework 4 的项目中为活动工作表中的第一个 Microsoft.Office.Interop.Excel.ListObject 生成 Microsoft.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);
    }
    
  • 下面的代码示例演示面向 .NET Framework 3.5 的项目中的相同任务。

    Dim sheet As 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 = _
            listObject.GetVstoObject()
    End If
    
    Microsoft.Office.Interop.Excel.Worksheet sheet =
        Globals.ThisAddIn.Application.ActiveSheet as
        Microsoft.Office.Interop.Excel.Worksheet;
    
    if (sheet.ListObjects.Count > 0)
    {
        Excel.ListObject listObject = sheet.ListObjects[1];
        Microsoft.Office.Tools.Excel.ListObject vstoListObject =
            listObject.GetVstoObject();
    }
    

向文档和工作簿中添加智能标记

生成 Microsoft.Office.Tools.Word.DocumentMicrosoft.Office.Tools.Excel.Workbook 后,可以创建在这些对象所表示的文档或工作簿的上下文中识别的智能标记。 实现方式是:使用 Microsoft.Office.Tools.Word.DocumentMicrosoft.Office.Tools.Excel.WorkbookVstoSmartTags 属性。 有关更多信息,请参见下列主题:

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

生成 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 控件。 这些宿主控件不能以编程方式添加。 有关更多信息,请参见宿主项和宿主控件的编程限制

保留和删除控件

向文档或工作表中添加托管控件后,保存然后关闭文档时并不保留这些控件。 所有宿主控件都被删除,这样只有基础本机 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 对象,则必须处理这些应用程序级事件,然后编写额外的代码,以确定引发了这些事件的文档是否是您自定义过的文档。 宿主项在文档级别提供这些事件,这样更便于处理特定文档的事件。 可以生成一个宿主项,然后处理该宿主项提供的事件。

使用本机 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;
    }
}

使用宿主项的示例

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

下面的代码示例演示面向 .NET Framework 4 的项目中的此任务。

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;
}

下面的代码示例演示面向 .NET Framework 3.5 的项目中的此任务。

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

Private Sub CreateDocument2()
    document2 = Me.Application.Documents.Add()
    vstoDocument = document2.GetVstoObject()
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 = document2.GetVstoObject();
    vstoDocument.BeforeSave += new SaveEventHandler(vstoDocument_BeforeSave);
}

private void vstoDocument_BeforeSave(object sender, SaveEventArgs e)
{
    e.Cancel = true;
}

确定 Office 对象是否已扩展

若要确定是否已为某个特定本机 Office 对象生成扩展对象,请使用 HasVstoObject 方法。 如果已生成扩展对象,则该方法返回 true,否则返回 false。

在面向 .NET Framework 3.5 的项目中,可在 Excel 和 Word 主互操作程序集中以下任一类型实例上获取 HasVstoObject 方法:

在面向 .NET Framework 4 的项目中,请使用 Globals.Factory.HasVstoMethod 方法。 传入要针对扩展对象进行测试的本机 Word 或 Excel 对象(如 Microsoft.Office.Interop.Word.DocumentMicrosoft.Office.Interop.Excel.Worksheet)。

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

配置 .NET Framework 3.5 项目以使用 GetVstoObject 和 HasVstoObject 方法

创建以 .NET Framework 3.5 为目标的应用程序级项目时,该项目自动进行配置,以便您在 ThisAddIn.cs 或 ThisAddIn.vb 代码文件中使用 GetVstoObjectHasVstoObject 方法。 若要在除 ThisAddIn.cs 和 ThisAddIn.vb 以外的代码文件中使用这些方法,则必须对该代码文件做如下更改。

修改 Excel 项目中的代码文件以创建扩展对象

  • 将下面的 using(对于 C#)或 Imports(对于 Visual Basic)语句添加到代码文件的开头处,以便可以在其中使用 GetVstoObjectHasVstoObject 方法。

    Imports Microsoft.Office.Tools.Excel.Extensions
    
    using Microsoft.Office.Tools.Excel.Extensions;
    

修改 Word 项目中的代码文件以创建扩展对象

  • 将下面的 using(对于 C#)或 Imports(对于 Visual Basic)语句添加到代码文件的开头处,以便可以在其中使用 GetVstoObjectHasVstoObject 方法。

    Imports Microsoft.Office.Tools.Word.Extensions
    
    using Microsoft.Office.Tools.Word.Extensions;
    

需要进行这些更改的原因在于 GetVstoObjectHasVstoObject 方法是作为扩展方法实现的。 尽管您使用 GetVstoObjectHasVstoObject 方法时就好像它们是在 Excel 或 Word 主互操作程序集中的类型中定义的,但实际上它们是在 Visual Studio Tools for Office Runtime 的 Microsoft.Office.Tools.Excel.ExtensionsMicrosoft.Office.Tools.Word.Extensions 命名空间中的类型中定义的。 有关扩展方法的更多信息,请参见扩展方法(C# 编程指南)扩展方法 (Visual Basic)

请参见

概念

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

宿主项和宿主控件概述

从文档级自定义项中的本机 Office 对象获取扩展对象

其他资源

应用程序级外接程序编程

智能标记概述

Office 开发示例和演练