共用方式為


在 Office 文件中保存動態控制項

儲存和關閉文件或活頁簿時,並不會保存在執行階段加入的控制項。 實際的行為會隨著主控制項和 Windows Form 控制項而不同。 對於這兩種情況,當使用者重新開啟文件時,您都可以在方案中加入程式碼重新建立控制項。

在執行階段加入至文件的控制項稱為「動態控制項」(Dynamic Control)。 如需動態控制項的詳細資訊,請參閱在執行階段將控制項加入至 Office 文件

**適用於:**本主題中的資訊適用於下列應用程式的文件層級專案和應用程式層級專案:Excel 2007 和 Excel 2010、Word 2007 和 Word 2010。如需詳細資訊,請參閱依 Office 應用程式和專案類型提供的功能

在文件中保存主控制項

當儲存並關閉文件時,所有動態的主控制項都會從文件移除。 只會留下基礎原生的 Office 物件。 例如,Microsoft.Office.Tools.Excel.ListObject 主控制項會變成 Microsoft.Office.Interop.Excel.ListObject。 原生的 Office 物件不會連接到主控制項事件,而且也沒有主控制項的資料繫結功能。

下表列出針對每種主控制項型別而留在文件中的原生 Office 物件。

主控制項型別

原生 Office 物件型別

Microsoft.Office.Tools.Excel.Chart

Microsoft.Office.Interop.Excel.Chart

Microsoft.Office.Tools.Excel.ListObject

Microsoft.Office.Interop.Excel.ListObject

Microsoft.Office.Tools.Excel.NamedRange

Microsoft.Office.Interop.Excel.Range

Microsoft.Office.Tools.Word.Bookmark

Microsoft.Office.Interop.Word.Bookmark

Microsoft.Office.Tools.Word.BuildingBlockGalleryContentControl

Microsoft.Office.Tools.Word.ComboBoxContentControl

Microsoft.Office.Tools.Word.ContentControl

Microsoft.Office.Tools.Word.DatePickerContentControl

Microsoft.Office.Tools.Word.DropDownListContentControl

Microsoft.Office.Tools.Word.GroupContentControl

Microsoft.Office.Tools.Word.PictureContentControl

Microsoft.Office.Tools.Word.PlainTextContentControl

Microsoft.Office.Tools.Word.RichTextContentControl

Microsoft.Office.Interop.Word.ContentControl

在開啟文件時重新建立動態主控制項

您可以在每次使用者開啟文件時,重新建立動態主控制項來取代現有的原生 (Native) 控制項。 以這種方式在開啟文件時建立主控制項,即可模擬使用者預期的情況。

若要重新建立 Word 的主控制項,或 Excel 的 Microsoft.Office.Tools.Excel.NamedRangeMicrosoft.Office.Tools.Excel.ListObject 主控制項,請使用 Microsoft.Office.Tools.Excel.ControlCollectionMicrosoft.Office.Tools.Word.ControlCollection 物件的 Add<控制項類別> 方法。 請使用具有原生 Office 物件之參數的方法。

例如,如果您要在開啟文件時,從現有的原生 Microsoft.Office.Interop.Excel.ListObject 建立 Microsoft.Office.Tools.Excel.ListObject 主控制項,請使用 AddListObject(ListObject) 方法並傳入現有的 Microsoft.Office.Interop.Excel.ListObject。 下列程式碼範例示範 Excel 文件層級專案中的這項作業。 程式碼會重新建立動態 Microsoft.Office.Tools.Excel.ListObject,它是以 Sheet1 類別中名為 MyListObject 的現有 Microsoft.Office.Interop.Excel.ListObject 為基礎。

Private vstoListObject As Microsoft.Office.Tools.Excel.ListObject
Private Const DISP_E_BADINDEX As Integer = CInt(&H8002000B)

Private Sub Sheet1_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
    Dim nativeListObject As Excel.ListObject = Nothing

    Try
        nativeListObject = Me.ListObjects("MyListObject")
    Catch ex As System.Runtime.InteropServices.COMException
        ' "MyListObject" does not exist.
        If ex.ErrorCode <> DISP_E_BADINDEX Then
            Throw
        End If
    End Try

    If nativeListObject IsNot Nothing Then
        vstoListObject = Me.Controls.AddListObject(nativeListObject)
    End If
End Sub
private Microsoft.Office.Tools.Excel.ListObject vstoListObject;
private const int DISP_E_BADINDEX = unchecked((int)0x8002000B);

private void Sheet1_Startup(object sender, System.EventArgs e)
{
    Excel.ListObject nativeListObject = null;

    try
    {
        nativeListObject = this.ListObjects.get_Item("MyListObject");
    }
    catch (System.Runtime.InteropServices.COMException ex)
    {
        // "MyListObject" does not exist.
        if (ex.ErrorCode != DISP_E_BADINDEX)
            throw;
    }

    if (nativeListObject != null)
    {
        vstoListObject = this.Controls.AddListObject(nativeListObject);
    }
}

重新建立圖表

若要重新建立 Microsoft.Office.Tools.Excel.Chart 主控制項,您必須先刪除原生 Microsoft.Office.Interop.Excel.Chart,然後使用 AddChart(Range, String)AddChart(Double, Double, Double, Double, String) 方法重新建立 Microsoft.Office.Tools.Excel.Chart。 其中沒有 Add<控制項類別> 方法可讓您根據現有的 Microsoft.Office.Interop.Excel.Chart 建立新的 Microsoft.Office.Tools.Excel.Chart

如果沒有先刪除原生 Microsoft.Office.Interop.Excel.Chart,則您將會在重新建立 Microsoft.Office.Tools.Excel.Chart 時,建立第二個重複的圖表。

在文件上保存 Windows Form 控制項

當儲存並關閉文件時,Visual Studio Tools for Office Runtime 會自動從文件中移除所有動態建立的 Windows Form 控制項。 然而,這項行為會隨著文件層級和應用程式層級專案而不同。

在文件層級自訂中,控制項和其基礎 ActiveX 包裝函式 (這是用來在文件上裝載控制項的) 是在下次開啟文件時移除的。 而且不會有指示說明曾經有這些控制項存在。

在應用程式層級的增益集中會移除控制項,但 ActiveX 包裝函式會保留在文件中。 當使用者下次開啟文件時,就會看到 ActiveX 包裝函式。 在 Excel 中,ActiveX 包裝函式會顯示控制項的影像,就如同上次儲存文件時的顯示方式。 在 Word 中,除非使用者按一下 ActiveX 包裝函式,否則並不會顯示包裝函式,而這種情況下會顯示虛線表示控制項的框線。 您可以使用許多方式移除 ActiveX 包裝函式。 如需詳細資訊,請參閱移除增益集中的 ActiveX 包裝函式。

在開啟文件時重新建立 Windows Form 控制項

您可以在使用者重新開啟文件時,重新建立刪除的 Windows Form 控制項。 若要進行這項工作,您的方案必須執行下列工作:

  1. 在儲存或關閉文件時,儲存控制項的大小、位置和狀態的資訊。 在文件層級自訂中,您可以將這項資料儲存在文件的資料快取中。 在應用程式層級的增益集中,您可以將這項資料儲存在文件的自訂 XML 組件中。

  2. 在會於文件開啟時引發的事件中重新建立控制項。 在文件層級專案中,您可以在 Sheetn_Startup 或 ThisDocument_Startup 事件處理常式中進行這項作業。 在應用程式層級專案中,您可以在 WorkbookOpenDocumentOpen 事件的事件處理常式中進行這項作業。

移除增益集中的 ActiveX 包裝函式

使用增益集將動態 Windows Form 控制項加入文件中時,您可以使用下列方式,防止在下次開啟文件時出現控制項的 ActiveX 包裝函式。

在文件開啟時移除 ActiveX 包裝函式

若要移除所有的 ActiveX 包裝函式,請呼叫 GetVstoObject 方法產生 Microsoft.Office.Interop.Word.DocumentMicrosoft.Office.Interop.Excel.Workbook 的主項目,該主項目表示新開啟的文件。 例如,若要從 Word 文件移除所有 ActiveX 包裝函式,您可以呼叫 GetVstoObject 方法產生 Document 物件的主項目,該物件會傳遞給 DocumentOpen 事件的事件處理常式。

當您確定只會在有安裝增益集的電腦上開啟文件時,這個程序就非常好用。 如果文件可能會傳遞給沒有安裝增益集的其他使用者,請改為考慮在關閉文件前先移除控制項。

下列程式碼範例示範如何在開啟文件時呼叫 GetVstoObject 方法。

Private Sub Application_DocumentOpen_ClearActiveXWrappers( _
    ByVal Doc As Word.Document) Handles Application.DocumentOpen

    ' Use the following line of code in projects that target the .NET Framework 4.
    Dim vstoDocument As Document = Globals.Factory.GetVstoObject(Doc)

    ' In projects that target the .NET Framework 3.5, use the following line of code.
    ' Dim vstoDocument As Microsoft.Office.Tools.Word.Document = Doc.GetVstoObject()
End Sub
private void Application_DocumentOpen_ClearActiveXWrappers(Word.Document Doc)
{
    // Use the following line of code in projects that target the .NET Framework 4.
    Microsoft.Office.Tools.Word.Document vstoDocument = Globals.Factory.GetVstoObject(Doc);

    // In projects that target the .NET Framework 3.5, use the following line of code.
    // Microsoft.Office.Tools.Word.Document vstoDocument = Doc.GetVstoObject();
}

雖然 GetVstoObject 方法主要是用來在執行階段產生新的主項目,但針對特定文件首次呼叫這個方法時,方法也會清除文件中的所有 ActiveX 包裝函式。 如需如何使用 GetVstoObject 方法的詳細資訊,請參閱在應用程式層級增益集的執行階段中擴充 Word 文件和 Excel 活頁簿

請注意,如果增益集會在文件開啟時建立動態控制項,那麼增益集即已經將呼叫 GetVstoObject 方法做為建立控制項的程序的一部分。 在這種情況下,不需要加入個別的 GetVstoObject 方法呼叫來移除 ActiveX 包裝函式。

在關閉文件前移除動態控制項

增益集可以在關閉文件前,明確移除文件中的每個動態控制項。 當文件可能會傳遞給沒有安裝增益集的其他使用者時,這個程序就非常好用。

下列程式碼範例將示範如何在關閉文件時,移除 Word 文件中的所有 Windows Form 控制項。

Private Sub Application_DocumentBeforeClose(ByVal Doc As Word.Document, _
    ByRef Cancel As Boolean) Handles Application.DocumentBeforeClose

    ' Use the following line of code in projects that target the .NET Framework 4.
    Dim isExtended As Boolean = Globals.Factory.HasVstoObject(Doc)

    ' In projects that target the .NET Framework 3.5, use the following line of code.
    ' Dim isExtended As Boolean = Doc.HasVstoObject()

    If isExtended Then
        ' Use the following line of code in projects that target the .NET Framework 4.
        Dim vstoDocument As Document = Globals.Factory.GetVstoObject(Doc)

        ' In projects that target the .NET Framework 3.5, use the following line of code.
        ' Dim vstoDocument As Document = Doc.GetVstoObject()

        Dim controlsToRemove As System.Collections.ArrayList = _
            New System.Collections.ArrayList()

        ' Get all of the Windows Forms controls.
        For Each control As Object In vstoDocument.Controls
            If TypeOf control Is System.Windows.Forms.Control Then
                controlsToRemove.Add(control)
            End If
        Next

        ' Remove all of the Windows Forms controls from the document.
        For Each control As Object In controlsToRemove
            vstoDocument.Controls.Remove(control)
        Next
    End If
End Sub
void Application_DocumentBeforeClose(Word.Document Doc, ref bool Cancel)
{
    // Use the following line of code in projects that target the .NET Framework 4.
    bool isExtended = Globals.Factory.HasVstoObject(Doc);

    // In projects that target the .NET Framework 3.5, use the following line of code.
    // bool isExtended = Doc.HasVstoObject();

    if (isExtended)
    {
        // Use the following line of code in projects that target the .NET Framework 4.
        Microsoft.Office.Tools.Word.Document vstoDocument = Globals.Factory.GetVstoObject(Doc);

        // In projects that target the .NET Framework 3.5, use the following line of code.
        // Microsoft.Office.Tools.Word.Document vstoDocument = Doc.GetVstoObject();

        System.Collections.ArrayList controlsToRemove = 
            new System.Collections.ArrayList();

        // Get all of the Windows Forms controls.
        foreach (object control in vstoDocument.Controls)
        {
            if (control is System.Windows.Forms.Control)
            {
                controlsToRemove.Add(control);
            }
        }

        // Remove all of the Windows Forms controls from the document.
        foreach (object control in controlsToRemove)
        {
            vstoDocument.Controls.Remove(control);
        }
    }
}

請參閱

概念

在執行階段將控制項加入至 Office 文件

主控制項的 Helper 方法

Windows Form 控制項的 Helper 方法