演练:在 VSTO 外接程序项目中的运行时向工作表添加控件

可通过使用 Excel VSTO 外接程序向任何打开的工作表添加控件。 本演练演示如何利用功能区使用户能够向工作表添加 ButtonNamedRangeListObject。 有关信息,请参阅在运行时向办公室文档添加控件。

适用于: 本主题中的信息适用于 Excel 的 VSTO 外接程序项目。 有关详细信息,请参阅按 Office 应用程序和项目类型提供的功能

本演练阐释了以下任务:

  • 提供用于将控件添加到工作表的用户界面 (UI)。

  • 将控件添加到工作表。

  • 从工作表中移除控件。

    注意

    以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 这些元素取决于你所使用的 Visual Studio 版本和你所使用的设置。 有关详细信息,请参阅个性化设置 IDE

先决条件

你需要满足以下条件才能完成本演练:

创建新的 Excel VSTO 外接程序项目

首先创建 Excel VSTO 外接程序项目。

若要新建 Excel VSTO 外接程序项目

  1. 在 Visual Studio 中,创建名为 ExcelDynamicControls 的 Excel VSTO 外接程序项目。 有关详细信息,请参阅 How to: Create Office Projects in Visual Studio

  2. 添加对 Microsoft.办公室 的引用。Tools.Excel.v4.0.Utilities.dll 程序集。 在本演练稍后内容中,需要此引用以编程方式将 Windows 窗体控件添加到工作表。

提供用于向工作表添加控件的 UI

添加自定义选项卡到 Excel 功能区。 用户可以选中选项卡上的复选框,以向工作表添加控件。

若要提供用于将控件添加到工作表的 UI

  1. “项目” 菜单上,单击 “添加新项”

  2. “添加新项 ”对话框中,选择 功能区(可视化设计器),然后单击“ 添加”。

    在功能区设计器中打开名为 Ribbon1.csRibbon1.vb 的文件,并显示默认选项卡和组。

  3. 从工具箱“办公室功能区控件”选项卡中,将 CheckBox 控件拖到 group1 上。

  4. 单击 CheckBox1 以将其选中。

  5. “属性” 窗口中,更改下列属性。

    属性
    Name Button
    标签 按钮
  6. 将第二个复选框添加到 group1,然后更改下列属性。

    属性
    Name NamedRange
    标签 NamedRange
  7. 将第三个检查框添加到 group1,然后更改以下属性。

    属性
    Name ListObject
    标签 ListObject

向工作表添加控件

托管的控件只能添加到主机项,充当容器。 因为 VSTO 外接程序项目使用任何打开的工作簿,所以 VSTO 外接程序会将工作表转换为主机项,或获取现有的主机项,然后才添加控件。 将代码添加到每个控件的单击事件处理程序中以生成基于打开的工作表的 Worksheet 主机项。 然后,在工作表当前所选内容中添加 ButtonNamedRangeListObject

若要向工作表添加控件

  1. 在功能区设计器中,双击“ 按钮”。

    按钮Click检查框的事件处理程序将在代码编辑器中打开。

  2. Button_Click 事件处理程序替换为以下代码。

    此代码使用 GetVstoObject 方法获取表示工作薄中第一个工作表的主机项,然后将 Button 控件添加到当前选定的单元格。

    private void Button_Click(object sender, RibbonControlEventArgs e)
    {
        Worksheet worksheet = Globals.Factory.GetVstoObject(
            Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]);
    
        
        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);
        }
    }
    
  3. 解决方案资源管理器中,选择 Ribbon1.csRibbon1.vb

  4. “视图 ”菜单上,单击“ 设计器”。

  5. 在功能区设计器中,双击 NamedRange

  6. NamedRange_Click 事件处理程序替换为以下代码。

    此代码使用 GetVstoObject 方法获取表示工作簿中第一个工作表的主机项,然后为当前选定的单元格定义 NamedRange 控件。

    private void NamedRange_Click(object sender, RibbonControlEventArgs e)
    {
        Worksheet worksheet = Globals.Factory.GetVstoObject(
            Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]);
    
    
        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);
        }
    }
    
  7. 在功能区设计器中,双击 ListObject

  8. ListObject_Click 事件处理程序替换为以下代码。

    此代码使用 GetVstoObject 方法获取表示工作薄中第一个工作表的主机项,然后为当前选定的单元格定义 ListObject

    private void ListObject_Click(object sender, RibbonControlEventArgs e)
    {
        Worksheet worksheet = Globals.Factory.GetVstoObject(
            Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets[1]);
    
    
        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);
        }
    }
    
  9. 将下面的语句添加到功能区代码文件的顶部。

    using Excel = Microsoft.Office.Interop.Excel;
    using Microsoft.Office.Tools.Excel;
    using Microsoft.Office.Tools.Excel.Extensions;
    

从工作表中删除控件

保存并关闭工作表时,不会保留控件。 保存工作表之前应以编程方式移除所有生成的 Windows 窗体控件,否则再次打开工作薄时,将仅出现控件的边框。 将代码添加到用于从生成的主机项的控件集合中移除 Windows 窗体控件的 WorkbookBeforeSave 事件中。 有关详细信息,请参阅在办公室文档中保留动态控件。

若要从工作表中移除控件

  1. 解决方案资源管理器中,选择“ThisAddIn.cs“ThisAddIn.vb”。

  2. “视图” 菜单上,单击 “代码”

  3. 将以下方法添加到 ThisAddIn 类。 此代码会获取工作簿中的第一个工作表,然后使用 HasVstoObject 方法检查该工作表是否含有生成的工作表项目。 如果生成的工作表对象中含有控件,则该代码会获取工作表项目并循环访问控件集合,从而移除控件。

           void Application_WorkbookBeforeSave(Microsoft.Office.Interop.Excel.Workbook workbook, 
               bool SaveAsUI, ref bool Cancel)
           {
               Excel.Worksheet worksheet =
                   workbook.Worksheets[1] as Excel.Worksheet;
               
               if (Globals.Factory.HasVstoObject(worksheet) && 
                   Globals.Factory.GetVstoObject(worksheet).Controls.Count > 0)
               {
                   Worksheet vstoWorksheet = Globals.Factory.GetVstoObject(worksheet);
               
              
                   
                   while (vstoWorksheet.Controls.Count > 0)
                   {
                       object vstoControl = vstoWorksheet.Controls[0];
                       vstoWorksheet.Controls.Remove(vstoControl);
                   }
    
               }
           }
    
  4. 在 C# 中,必须为 WorkbookBeforeSave 事件创建一个事件处理程序。 你可以将此代码放置在 ThisAddIn_Startup 方法中。 有关创建事件处理程序的详细信息,请参阅如何:在办公室项目中创建事件处理程序。 将 ThisAddIn_Startup 方法替换为以下代码。

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        this.Application.WorkbookBeforeSave += 
            new Microsoft.Office.Interop.Excel.AppEvents_WorkbookBeforeSaveEventHandler
                (Application_WorkbookBeforeSave);
    }
    

测试解决方案

通过从功能区上的自定义选项卡中选择控件,将控件添加到工作表。 保存该工作表时,这些控件也随之移除。

若要测试解决方案。

  1. F5 运行项目。

  2. 在 Sheet1 中选择任意单元格。

  3. 单击 “外接程序” 选项卡。

  4. group1 组中,单击“ 按钮”。

    选定的单元格中会出现一个按钮。

  5. 在 Sheet1 中选择不同的单元格。

  6. group1 组中,单击 NamedRange

    则会为选定的单元格定义命名范围。

  7. 在 Sheet1 中选择一系列单元格。

  8. group1 组中,单击 ListObject

    则会为选定的单元格添加列表对象。

  9. 保存该工作表。

    添加到 Sheet1 的控件将不再出现。

后续步骤

你可以从此主题中了解关于 Excel VSTO 外接程序项目中控件的详细信息:

  • 若要了解如何将控件保存到工作表,请参阅办公室开发示例和演练中的 Excel VSTO 外接程序动态控件示例。