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

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

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

本演练阐释了以下任务:

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

  • 向工作表添加控件。

  • 从工作表中删除控件。

    注释

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

先决条件

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

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

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

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

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

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

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

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

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

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

  2. 添加新项 对话框中,选择功能区(Visual Designer),然后单击添加

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

  3. 工具箱Office 功能区控件选项卡中,将 CheckBox 控件拖动到 group1 上。

  4. 单击 CheckBox1 将其选中。

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

    资产 价值
    名称 按钮
    标签 按钮
  6. 将第二个复选框添加到 group1,然后更改以下属性。

    资产 价值
    名称 NamedRange
    标签 NamedRange
  7. 将第三个复选框添加到 group1,然后更改以下属性。

    资产 价值
    名称 ListObject
    标签 ListObject

向工作表添加控件

只能将托管控件添加到充当容器的宿主项。 由于 VSTO 外接程序项目适用于任何打开的工作簿,因此 VSTO 外接程序在添加控件之前将工作表转换为宿主项,或获取现有宿主项。 将代码添加到每个控件的单击事件处理程序,以在打开的工作表基础上生成 Worksheet 主机项。 然后,在工作表中的当前选定内容中添加 a Button、a NamedRange和 a ListObject

向工作表添加控件

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

    ClickButton复选框的事件处理程序在代码编辑器中打开。”

  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. 将以下语句添加到 Ribbon 代码文件的顶部。

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

从工作表中删除控件

保存和关闭工作表时不会保留控件。 在保存工作表之前,应以编程方式删除所有生成的 Windows 窗体控件,或者在再次打开工作簿时仅显示控件的大纲。 将代码添加到WorkbookBeforeSave事件以移除生成的宿主项的控件集合中的Windows窗体控件。 有关详细信息,请参阅 在 Office 文档中持久保存动态控件

从工作表中删除控件

  1. 解决方案资源管理器中,选择 ThisAddIn.csThisAddIn.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 。 有关创建事件处理程序的详细信息,请参阅 如何:在 Office 项目中创建事件处理程序。 将 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 外接程序项目中的控件: