演练:在运行时在应用程序级项目中向工作表中添加控件
更新:2011 年 4 月
可以使用 Excel 外接程序向任何打开的工作表中添加控件。 本演练演示如何使用功能区让用户可以向工作表中添加 Button、NamedRange 和 ListObject。 有关信息,请参见在运行时向 Office 文档添加控件。
**适用于:**本主题中的信息适用于 Excel 2007 和 Excel 2010 的应用程序级项目。有关更多信息,请参见按 Office 应用程序和项目类型提供的功能。
本演练阐释了以下任务:
提供用于向工作表中添加控件的用户界面 (UI)。
向工作表中添加控件。
从工作表中移除控件。
提示
对于在以下说明中使用的某些 Visual Studio 用户界面元素,您的计算机可能会显示不同的名称或位置。这些元素取决于您所使用的 Visual Studio 版本和您所使用的设置。有关更多信息,请参见 Visual Studio 设置。
系统必备
您需要以下组件来完成本演练:
-
Visual Studio 2010 的一个版本,其中包含 Microsoft Office 开发工具。有关更多信息,请参见[将计算机配置为开发 Office 解决方案](bb398242\(v=vs.100\).md)。
- Microsoft Office Excel 2007 或 Excel 2010。
创建新的 Excel 外接程序项目
从创建 Excel 外接程序项目开始。
创建新的 Excel 外接程序项目
在 Visual Studio 中,创建一个名为 ExcelDynamicControls 的 Excel 外接程序项目。 有关更多信息,请参见如何:在 Visual Studio 中创建 Office 项目。
如果项目面向 .NET Framework 4,请添加对 Microsoft.Office.Tools.Excel.v4.0.Utilities.dll 程序集的引用。 在本演练后面的部分中,需要此引用才能以编程方式向工作表中添加 Windows 窗体控件。
提供用于向工作表中添加控件的用户界面
向 Excel 功能区中添加自定义选项卡。 用户可以选中该选项卡上的复选框,以向工作表中添加控件。
提供用于向工作表中添加控件的用户界面
在**“项目”菜单上,单击“添加新项”**。
在**“添加新项”对话框中,选择“功能区(可视化设计器)”,再单击“添加”**。
名为 Ribbon1.cs 或 Ribbon1.vb 的文件将在功能区设计器中打开,并显示一个默认选项卡和组。
从**“工具箱”的“Office 功能区控件”选项卡中将 CheckBox 控件拖到“group1”**上。
单击**“CheckBox1”**将其选定。
在**“属性”**窗口中,更改下列属性。
Property
值
名称
Button
标签
Button
向**“group1”**再添加一个复选框,然后更改下列属性。
Property
值
名称
NamedRange
标签
NamedRange
向**“group1”**中添加第三个复选框,然后更改以下属性。
Property
值
名称
ListObject
标签
ListObject
将控件添加到工作表
托管控件只能添加到充当容器的宿主项。 由于外接程序项目可以处理任何打开的工作簿,因此外接程序在添加控件之前会将工作表转换为宿主项,或获取现有的宿主项。 将代码添加到每个控件的 Click 事件处理程序,以生成基于打开的工作表的 Worksheet 宿主项。 然后,在工作表中的当前选定内容处添加 Button、NamedRange 和 ListObject。
向工作表中添加控件
在功能区设计器中双击**“Button”**。
**“Button”**复选框的 Click 事件处理程序在代码编辑器中打开。
用下面的代码替换 Button_Click 事件处理程序。
此代码使用 GetVstoObject 方法获取表示工作簿中的第一个工作表的宿主项,然后将 Button 控件添加到当前选定的单元格。
Private Sub Button_Click(ByVal sender As System.Object, _ ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _ Handles Button.Click Dim NativeWorksheet As Microsoft.Office.Interop.Excel.Worksheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1) ' Use the following line of code in projects that target the .NET Framework 4. Dim worksheet As Microsoft.Office.Tools.Excel.Worksheet = Globals.Factory.GetVstoObject(NativeWorksheet) ' In projects that target the .NET Framework 3.5, use the following line of code. ' Dim worksheet = CType(Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1), _ ' Excel.Worksheet).GetVstoObject() Dim buttonName As String = "MyButton" If CType(sender, RibbonCheckBox).Checked Then Dim selection As Excel.Range = Globals.ThisAddIn.Application.Selection If Not (selection Is Nothing) Then Dim button As New Microsoft.Office.Tools.Excel.Controls.Button() worksheet.Controls.AddControl(button, selection, buttonName) End If Else worksheet.Controls.Remove(buttonName) End If End Sub
private void Button_Click(object sender, RibbonControlEventArgs e) { // Use the following line of code in projects that target the .NET Framework 4. Worksheet worksheet = Globals.Factory.GetVstoObject( Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]); // In projects that target the .NET Framework 3.5, use the following line of code. // Worksheet worksheet = // ((Excel.Worksheet)Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]).GetVstoObject(); string buttonName = "MyButton"; if (((RibbonCheckBox)sender).Checked) { Excel.Range selection = Globals.ThisAddIn.Application.Selection as Excel.Range; if (selection != null) { Microsoft.Office.Tools.Excel.Controls.Button button = new Microsoft.Office.Tools.Excel.Controls.Button(); worksheet.Controls.AddControl(button, selection, buttonName); } } else { worksheet.Controls.Remove(buttonName); } }
在**“解决方案资源管理器”**中,选择 Ribbon1.cs 或 Ribbon1.vb。
在**“视图”菜单上,单击“设计器”**。
在功能区设计器中双击**“NamedRange”**。
用下面的代码替换 NamedRange_Click 事件处理程序。
此代码使用 GetVstoObject 方法获取表示工作簿中的第一个工作表的宿主项,然后为当前选定的一个或多个单元格定义 NamedRange 控件。
Private Sub NamedRange_Click(ByVal sender As System.Object, _ ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _ Handles NamedRange.Click Dim NativeWorksheet As Microsoft.Office.Interop.Excel.Worksheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1) ' Use the following line of code in projects that target the .NET Framework 4. Dim worksheet As Microsoft.Office.Tools.Excel.Worksheet = Globals.Factory.GetVstoObject(NativeWorksheet) ' In projects that target the .NET Framework 3.5, use the following line of code. ' Dim worksheet = CType(Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1), _ ' Excel.Worksheet).GetVstoObject() Dim rangeName As String = "MyNamedRange" If CType(sender, RibbonCheckBox).Checked Then Dim selection As Excel.Range = Globals.ThisAddIn.Application.Selection If Not (selection Is Nothing) Then Dim namedRange As NamedRange = _ worksheet.Controls.AddNamedRange(selection, rangeName) End If Else worksheet.Controls.Remove(rangeName) End If End Sub
private void NamedRange_Click(object sender, RibbonControlEventArgs e) { // Use the following line of code in projects that target the .NET Framework 4. Worksheet worksheet = Globals.Factory.GetVstoObject( Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]); // In projects that target the .NET Framework 3.5, use the following line of code. // Worksheet worksheet = // ((Excel.Worksheet)Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]).GetVstoObject(); string Name = "MyNamedRange"; if (((RibbonCheckBox)sender).Checked) { Excel.Range selection = Globals.ThisAddIn.Application.Selection as Excel.Range; if (selection != null) { worksheet.Controls.AddNamedRange(selection, Name); } } else { worksheet.Controls.Remove(Name); } }
在功能区设计器中双击**“ListObject”**。
用下面的代码替换 ListObject_Click 事件处理程序。
此代码使用 GetVstoObject 方法获取表示工作簿中的第一个工作表的宿主项,然后为当前选定的一个或多个单元格定义 ListObject。
Private Sub ListObject_Click(ByVal sender As System.Object, _ ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _ Handles ListObject.Click Dim NativeWorksheet As Microsoft.Office.Interop.Excel.Worksheet = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1) ' Use the following line of code in projects that target the .NET Framework 4. Dim worksheet As Microsoft.Office.Tools.Excel.Worksheet = Globals.Factory.GetVstoObject(NativeWorksheet) ' In projects that target the .NET Framework 3.5, use the following line of code. ' Dim worksheet = CType(Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets(1), _ ' Excel.Worksheet).GetVstoObject() Dim listObjectName As String = "MyListObject" If CType(sender, RibbonCheckBox).Checked Then Dim selection As Excel.Range = _ Globals.ThisAddIn.Application.Selection If Not (selection Is Nothing) Then worksheet.Controls.AddListObject(selection, listObjectName) End If Else worksheet.Controls.Remove(listObjectName) End If End Sub
private void ListObject_Click(object sender, RibbonControlEventArgs e) { // Use the following line of code in projects that target the .NET Framework 4. Worksheet worksheet = Globals.Factory.GetVstoObject( Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]); // In projects that target the .NET Framework 3.5, use the following line of code. // Worksheet worksheet = // ((Excel.Worksheet)Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]).GetVstoObject(); string listObjectName = "MyListObject"; if (((RibbonCheckBox)sender).Checked) { Excel.Range selection = Globals.ThisAddIn.Application.Selection as Excel.Range; if (selection != null) { worksheet.Controls.AddListObject(selection, listObjectName); } } else { worksheet.Controls.Remove(listObjectName); } }
将以下语句添加到功能区代码文件顶部。
Imports Excel = Microsoft.Office.Interop.Excel Imports Microsoft.Office.Tools.Excel Imports Microsoft.Office.Tools.Excel.Extensions
using Excel = Microsoft.Office.Interop.Excel; using Microsoft.Office.Tools.Excel; using Microsoft.Office.Tools.Excel.Extensions;
从工作表中移除控件
保存并关闭工作表后,控件不会保留。 您应该在保存工作表之前,以编程方式移除所有生成的 Windows 窗体控件,否则在再次打开工作簿时,将只显示控件的轮廓。 将代码添加到 WorkbookBeforeSave 事件,该事件将 Windows 窗体控件从生成的宿主项的控件集合中移除。 有关更多信息,请参见在 Office 文档中保存动态控件。
从工作表中移除控件
在**“解决方案资源管理器”**中,选择 ThisAddIn.cs 或 ThisAddIn.vb。
在**“视图”菜单上单击“代码”**。
将下面的方法添加到 ThisAddIn 类中。 此代码获取工作簿中的第一个工作表,然后使用 HasVstoObject 方法来检查该工作表是否具有生成的工作表对象。 如果生成的工作表对象具有控件,此代码将获取该工作表对象,并循环访问控件集合,同时移除控件。
Sub Application_WorkbookBeforeSave _ (ByVal workbook As Microsoft.Office.Interop.Excel.Workbook, _ ByVal SaveAsUI As Boolean, ByRef Cancel As Boolean) _ Handles Application.WorkbookBeforeSave Dim worksheet As Excel.Worksheet = workbook.Worksheets(1) ' Use the following code in projects that target the .NET Framework 4. If Globals.Factory.HasVstoObject(worksheet) And Globals.Factory.GetVstoObject(worksheet).Controls.Count > 0 Then Dim vstoWorksheet As Worksheet = Globals.Factory.GetVstoObject(worksheet) ' In projects that target the .NET Framework 3.5, use the following code. ' If worksheet.HasVstoObject() And worksheet.GetVstoObject().Controls.Count > 0 Then ' Dim vstoWorksheet As Worksheet = worksheet.GetVstoObject() While vstoWorksheet.Controls.Count > 0 Dim vstoControl As Object = vstoWorksheet.Controls(0) vstoWorksheet.Controls.Remove(vstoControl) End While End If End Sub
void Application_WorkbookBeforeSave(Microsoft.Office.Interop.Excel.Workbook workbook, bool SaveAsUI, ref bool Cancel) { Excel.Worksheet worksheet = workbook.Worksheets[1] as Excel.Worksheet; // Use the following lines of code in projects that target the .NET Framework 4. if (Globals.Factory.HasVstoObject(worksheet) && Globals.Factory.GetVstoObject(worksheet).Controls.Count > 0) { Worksheet vstoWorksheet = Globals.Factory.GetVstoObject(worksheet); // In projects that target the .NET Framework 3.5, use the following line of code. // if (worksheet.HasVstoObject() && worksheet.GetVstoObject().Controls.Count > 0) // { // Worksheet vstoWorksheet = worksheet.GetVstoObject(); while (vstoWorksheet.Controls.Count > 0) { object vstoControl = vstoWorksheet.Controls[0]; vstoWorksheet.Controls.Remove(vstoControl); } } }
在 C# 中,必须为 WorkbookBeforeSave 事件创建事件处理程序。 可以将此代码放在 ThisAddIn_Startup 方法中。 有关创建事件处理程序的更多信息,请参见如何:在 Office 项目中创建事件处理程序。 用下面的代码替换 ThisAddIn_Startup 方法。
private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.WorkbookBeforeSave += new Microsoft.Office.Interop.Excel.AppEvents_WorkbookBeforeSaveEventHandler (Application_WorkbookBeforeSave); }
测试解决方案
通过在功能区的自定义选项卡中选择控件来向工作表中添加控件。 保存工作表时,将移除这些控件。
测试解决方案。
按 F5 运行项目。
选择 Sheet1 中的任何单元格。
单击**“外接程序”**选项卡。
在**“group1”组中,单击“Button”**。
一个按钮显示在所选单元格中。
选择 Sheet1 中的另一个单元格。
在**“group1”组中,单击“NamedRange”**。
将为所选单元格定义一个命名区域。
选择 Sheet1 中的一系列单元格。
在**“group1”组中,单击“ListObject”**。
将为所选单元格添加一个列表对象。
保存工作表。
您添加到 Sheet1 的控件不再显示。
后续步骤
您可以从本主题中了解关于 Excel 外接程序项目中的控件的更多信息:
- 若要了解如何将控件保存到工作表的更多信息,请参见 Office 开发示例和演练中的“Excel 外接程序动态控件示例”。
请参见
概念
其他资源
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
2011 年 4 月 |
增加了描述项目面向 .NET Framework 4.0 时必须添加的程序集引用的文字。 |
内容 Bug 修复 |