Office 문서에서 동적 컨트롤 유지
런타임에 추가된 컨트롤은 문서나 통합 문서가 저장되고 닫힐 때 유지되지 않습니다. 정확한 동작은 컨트롤이 호스트 컨트롤인지 Windows Forms 컨트롤인지에 따라 다릅니다. 두 경우 모두 사용자가 문서를 다시 열 때 컨트롤을 다시 만들 수 있도록 솔루션에 코드를 추가할 수 있습니다.
런타임에 문서에 추가하는 컨트롤을 동적 컨트롤이라고 합니다. 동적 컨트롤에 대한 자세한 내용은 런타임에 Office 문서에 컨트롤 추가를 참조하십시오.
적용 대상: 이 항목의 정보는 Excel 2007 및 Excel 2010, Word 2007 및 Word 2010의 문서 수준 프로젝트 및 응용 프로그램 수준 프로젝트에 적용됩니다. 자세한 내용은 Office 응용 프로그램 및 프로젝트 형식에 따라 사용 가능한 기능을 참조하십시오.
문서에 호스트 컨트롤 유지
문서가 저장된 후 닫히면 모든 동적 호스트 컨트롤이 문서에서 제거되고 내부 네이티브 Office 개체만 유지됩니다. 예를 들어 Microsoft.Office.Tools.Excel.ListObject 호스트 컨트롤은 Microsoft.Office.Interop.Excel.ListObject가 됩니다. 네이티브 Office 개체는 호스트 컨트롤 이벤트에 연결되어 있지 않으며 호스트 컨트롤의 데이터 바인딩 기능이 없습니다.
다음 표에서는 각 호스트 컨트롤 형식에 대해 문서에 유지되는 네이티브 Office 개체를 보여 줍니다.
문서가 열릴 때 동적 호스트 컨트롤 다시 만들기
사용자가 문서를 열 때마다 기존 네이티브 컨트롤 대신 동적 호스트 컨트롤을 다시 만들 수 있습니다. 문서가 열릴 때 이 방법으로 호스트 컨트롤을 만들면 사용자가 원하는 환경이 시뮬레이션됩니다.
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 클래스에 기존 Microsoft.Office.Interop.Excel.ListObject를 기반으로 하는 동적 Microsoft.Office.Tools.Excel.ListObject인 MyListObject를 다시 만듭니다.
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를 다시 만듭니다. 기존 Microsoft.Office.Interop.Excel.Chart를 기반으로 새 Microsoft.Office.Tools.Excel.Chart를 만들 수 있는 Add<control class> 메서드는 없습니다.
네이티브 Microsoft.Office.Interop.Excel.Chart를 먼저 삭제하지 않은 경우 Microsoft.Office.Tools.Excel.Chart를 다시 만들면 두 번째 중복 차트가 만들어집니다.
문서에 Windows Forms 컨트롤 유지
문서가 저장된 후 닫히면 Microsoft Visual Studio Tools for Office Runtime에서는 동적으로 만들어진 모든 Windows Forms 컨트롤을 문서에서 자동으로 제거합니다. 그러나 제거 동작은 프로젝트가 문서 수준 프로젝트인지 응용 프로그램 수준 프로젝트인지에 따라 다릅니다.
문서 수준 사용자 지정에서는 다음에 문서가 열릴 때 컨트롤과 문서에서 해당 컨트롤을 호스팅하는 데 사용되는 내부 ActiveX 래퍼가 제거됩니다. 따라서 컨트롤이 문서에 있었다는 표시가 남지 않습니다.
응용 프로그램 수준 추가 기능에서는 컨트롤이 제거되지만 ActiveX 래퍼는 문서에 남아 있습니다. 따라서 다음에 사용자가 해당 문서를 열면 ActiveX 래퍼가 표시됩니다. Excel에서 ActiveX 래퍼는 컨트롤의 이미지를 마지막으로 문서가 저장되었을 때의 모양으로 표시합니다. Word에서는 사용자가 클릭하지 않는 한 ActiveX 래퍼가 표시되지 않으며 사용자가 ActiveX 래퍼를 클릭할 경우에는 컨트롤의 테두리를 나타내는 점선이 표시됩니다. ActiveX 래퍼를 제거하는 방법에는 몇 가지가 있습니다. 자세한 내용은 추가 기능의 ActiveX 래퍼 제거를 참조하십시오.
문서가 열릴 때 Windows Forms 컨트롤 다시 만들기
사용자가 문서를 다시 열 때 삭제된 Windows Forms 컨트롤을 다시 만들 수 있습니다. 이렇게 하려면 솔루션에서 다음과 같은 작업을 수행해야 합니다.
문서가 저장되거나 닫힐 때 컨트롤의 크기, 위치 및 상태에 대한 정보를 저장합니다. 문서 수준 사용자 지정에서는 문서의 데이터 캐시에 이 데이터를 저장할 수 있으며, 응용 프로그램 수준 추가 기능에서는 문서의 사용자 지정 XML 부분에 이 데이터를 저장할 수 있습니다.
문서가 열릴 때 발생하는 이벤트에 컨트롤을 다시 만듭니다. 이 작업은 문서 수준 프로젝트의 경우 Sheetn_Startup 또는 ThisDocument_Startup 이벤트 처리기에서 수행할 수 있으며, 응용 프로그램 수준 프로젝트의 경우 WorkbookOpen 또는 DocumentOpen 이벤트의 이벤트 처리기에서 수행할 수 있습니다.
추가 기능의 ActiveX 래퍼 제거
추가 기능을 사용하여 문서에 Windows Forms 컨트롤을 추가할 경우, 다음과 같은 방법으로 이후에 문서가 열릴 때 해당 컨트롤의 ActiveX 래퍼가 나타나지 않도록 할 수 있습니다.
문서가 열릴 때 ActiveX 래퍼 제거
모든 ActiveX 래퍼를 제거하려면 GetVstoObject 메서드를 호출하여 새로 열린 문서를 나타내는 Microsoft.Office.Interop.Word.Document 또는 Microsoft.Office.Interop.Excel.Workbook에 대한 호스트 항목을 생성합니다. 예를 들어 Word 문서에서 모든 ActiveX 래퍼를 제거하려면 GetVstoObject 메서드를 호출하여 DocumentOpen 이벤트의 이벤트 처리기에 전달된 Document 개체에 대한 호스트 항목을 생성할 수 있습니다.
이 절차는 문서가 추가 기능이 설치된 컴퓨터에서만 열릴 경우에 유용합니다. 문서가 추가 기능을 설치하지 않은 다른 사용자에게 전달될 수 있는 경우에는 문서를 닫기 전에 컨트롤을 제거하는 것이 좋습니다.
다음 코드 예제에서는 문서가 열릴 때 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 메서드가 호출됩니다. 따라서 이 경우에는 ActiveX 래퍼를 제거하기 위해 GetVstoObject 메서드에 대한 별도의 호출을 추가할 필요가 없습니다.
문서가 닫히기 전에 동적 컨트롤 제거
문서가 닫히기 전에 추가 기능을 통해 문서에서 각 동적 컨트롤을 명시적으로 제거할 수 있습니다. 이 절차는 문서가 추가 기능을 설치하지 않은 다른 사용자에게 전달될 수 있는 경우에 유용합니다.
다음 코드 예제에서는 Word 문서가 닫힐 때 해당 문서에서 모든 Windows Forms 컨트롤을 제거하는 방법을 보여 줍니다.
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);
}
}
}