Office ドキュメントでのダイナミック コントロールの永続化

実行時に追加されるコントロールは、文書またはブックを保存するときおよび閉じるときに永続化されません。ホスト コントロールと Windows フォーム コントロールとでは、動作が異なります。どちらの場合も、ユーザーによってドキュメントが再び開かれたときにコントロールが再作成されるようにコードをソリューションに追加できます。

実行時にドキュメントに追加するコントロールをダイナミック コントロールといいます。ダイナミック コントロールの詳細については、「実行時の Office ドキュメントへのコントロールの追加」を参照してください。

対象: このトピックの情報は、Excel 2013 と Excel 2010、および Word 2013 と 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

Cc442765.collapse_all(ja-jp,VS.110).gifドキュメントが開かれたときにダイナミック ホスト コントロールを再作成する

ユーザーによってドキュメントが開かれるたびに、既存のネイティブ コントロールの代わりにダイナミック ホスト コントロールを再作成できます。ドキュメントが開かれるときにこの方法でホスト コントロールを作成することで、ユーザーが期待する操作をシミュレートできます。

Word 用のホスト コントロール、または Excel 用の Microsoft.Office.Tools.Excel.NamedRange ホスト コントロールまたは Microsoft.Office.Tools.Excel.ListObject ホスト コントロールを再作成するには、Microsoft.Office.Tools.Excel.ControlCollection オブジェクトまたは Microsoft.Office.Tools.Word.ControlCollection オブジェクトの Add<control class> メソッドを使用します。ネイティブの Office オブジェクトのパラメーターを持つメソッドを使用します。

たとえば、ドキュメントが開かれたときに既存のネイティブ Microsoft.Office.Interop.Excel.ListObject から Microsoft.Office.Tools.Excel.ListObject ホスト コントロールを作成するには、AddListObject(ListObject) メソッドを使用し、既存の Microsoft.Office.Interop.Excel.ListObject を渡します。Excel のドキュメント レベルのプロジェクトでこの操作を実行するコード例を次に示します。このコードでは、Sheet1 クラスの MyListObject という名前の既存の Microsoft.Office.Interop.Excel.ListObject に基づくダイナミック Microsoft.Office.Tools.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);
    }
}

Cc442765.collapse_all(ja-jp,VS.110).gifグラフを再作成する

Microsoft.Office.Tools.Excel.Chart ホスト コントロールを再作成するには、ネイティブ Microsoft.Office.Interop.Excel.Chart をまず削除してから、AddChart(Range, String) メソッドまたは AddChart(Double, Double, Double, Double, String) メソッドを使って、Microsoft.Office.Tools.Excel.Chart を再作成する必要があります。既存の Microsoft.Office.Interop.Excel.Chart に基づいて新しい Microsoft.Office.Tools.Excel.Chart を作成できる Add<control class> メソッドはありません。

ネイティブの Microsoft.Office.Interop.Excel.Chart を先に削除せずに Microsoft.Office.Tools.Excel.Chart を再作成すると、2 つ目の重複したグラフが作成されます。

ドキュメントでの Windows フォーム コントロールの永続化

ドキュメントを保存して閉じるとき、動的に作成された Windows フォーム コントロールはすべて Visual Studio Tools for Office Runtime によって自動的にドキュメントから削除されます。ただし、ドキュメント レベルのプロジェクトとアプリケーション レベルのプロジェクトでは動作が異なります。

ドキュメント レベルのカスタマイズの場合、コントロールとその基になる ActiveX ラッパー (ドキュメント上でコントロールをホストするために使用されます) は、ドキュメントが次回開かれるときに削除されます。コントロールが配置されていたことを示すものは残りません。

アプリケーション レベルのアドインの場合、コントロールは削除されますが、ActiveX ラッパーはドキュメント上に残されます。ユーザーによってドキュメントが次回開かれたときに、ActiveX ラッパーは表示されます。Excel の場合、ActiveX ラッパーは、ドキュメントが前回保存されたときと同じように、コントロールのイメージを表示します。Word の場合、ActiveX ラッパーは、ユーザーによってクリックされない限り表示されません。クリックされた場合、コントロールの境界線を表す点線が表示されます。ActiveX ラッパーを削除する方法はいくつかあります。詳細については、「アドインからの ActiveX ラッパーの削除」を参照してください。

Cc442765.collapse_all(ja-jp,VS.110).gifドキュメントが開かれたときに Windows フォーム コントロールを再作成する

削除された Windows フォーム コントロールをユーザーによってドキュメントが開かれたときに再作成できます。これを行うには、ソリューションで次の手順を実行する必要があります。

  1. ドキュメントを保存または閉じたときのコントロールのサイズ、位置、および状態に関する情報を格納します。ドキュメント レベルのカスタマイズの場合、このデータをドキュメントのデータ キャッシュに保存できます。アプリケーション レベルのアドインの場合、このデータをドキュメントのカスタム XML 部分に保存できます。

  2. ドキュメントが開かれたときに発生するイベントでコントロールを再作成します。ドキュメント レベルのプロジェクトの場合、Sheetn_Startup イベント ハンドラーまたは ThisDocument_Startup イベント ハンドラーを使用します。アプリケーション レベルのプロジェクトの場合、WorkbookOpen イベントまたは DocumentOpen イベントのイベント ハンドラーを使用します。

Cc442765.collapse_all(ja-jp,VS.110).gifアドインからの ActiveX ラッパーの削除

アドインを使用してダイナミック Windows フォーム コントロールをドキュメントに追加するとき、次の方法で、ドキュメントが次回開かれたときにコントロールの ActiveX ラッパーが表示されないようにできます。

Cc442765.collapse_all(ja-jp,VS.110).gifドキュメントが開かれたときに ActiveX ラッパーを削除する

すべての ActiveX ラッパーを削除するには、新しく開かれたドキュメントを表す Microsoft.Office.Interop.Word.Document または Microsoft.Office.Interop.Excel.Workbook のホスト項目を生成する GetVstoObject メソッドを呼び出します。たとえば、Word 文書からすべての ActiveX ラッパーを削除するには、DocumentOpen イベントのイベント ハンドラーに渡される Document オブジェクトのホスト項目を生成する GetVstoObject メソッドを呼び出します。

この手順は、アドインがインストールされているコンピューター上でのみドキュメントが開かれることがわかっている場合に便利です。アドインがインストールされていない他のユーザーにドキュメントが渡される可能性がある場合は、ドキュメントを閉じる前にコントロールを削除することを検討してください。

次のコード例は、ドキュメントが開かれたときに GetVstoObject メソッドを呼び出す方法を示しています。

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

    Dim vstoDocument As Document = Globals.Factory.GetVstoObject(Doc)

End Sub
private void Application_DocumentOpen_ClearActiveXWrappers(Word.Document Doc)
{
    Microsoft.Office.Tools.Word.Document vstoDocument = Globals.Factory.GetVstoObject(Doc);

}

GetVstoObject メソッドは、主に実行時に新しいホスト項目を生成するために使用されますが、特定のドキュメントに対して初めて呼び出されたときにドキュメントからすべての ActiveX ラッパーを消去するためにも使用されます。GetVstoObject メソッドの使用方法の詳細については、「アプリケーション レベルのアドインにおける実行時の Word 文書や Excel ブックの拡張」を参照してください。

ドキュメントが開かれたときにアドインがダイナミック コントロールを作成する場合、コントロールの作成プロセスの一部として GetVstoObject メソッドが呼び出されます。このシナリオでは、ActiveX ラッパーを削除するために別個に GetVstoObject メソッドを呼び出す必要はありません。

Cc442765.collapse_all(ja-jp,VS.110).gifドキュメントを閉じる前にダイナミック コントロールを削除する

アドインを使用して、ドキュメントを閉じる前にドキュメントから各ダイナミック コントロールを明示的に削除できます。この操作は、アドインがインストールされていない他のユーザーにドキュメントを渡す可能性がある場合に有用です。

次のコード例は、Word 文書を閉じるときに文書からすべての Windows フォーム コントロールを削除する方法を示しています。

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

    Dim isExtended As Boolean = Globals.Factory.HasVstoObject(Doc)

    If isExtended Then

        Dim vstoDocument As Document = Globals.Factory.GetVstoObject(Doc)

        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)
{

    bool isExtended = Globals.Factory.HasVstoObject(Doc);

    if (isExtended)
    {
        Microsoft.Office.Tools.Word.Document vstoDocument = Globals.Factory.GetVstoObject(Doc);


        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 ドキュメントへのコントロールの追加