演练:在 Visual C# 项目中调用 VBA 中的代码
此演练演示如何从工作簿的 Visual Basic for Applications (VBA) 代码调用 Microsoft Office Excel 文档级自定义项中的方法。 该过程包括三个基本步骤:向 Sheet1 宿主项类添加方法,向工作簿中的 VBA 代码公开方法,然后从工作簿的 VBA 代码中调用该方法。
**适用于:**本主题中的信息适用于以下应用程序的文档级项目:Excel 2007 和 Excel 2010;Word 2007 和 Word 2010。有关更多信息,请参见按 Office 应用程序和项目类型提供的功能。
虽然此演练具体使用的是 Excel,但其中所阐释的概念同样适用于 Word 的文档级项目。
本演练阐释了以下任务:
创建一个包含 VBA 代码的工作簿。
使用 Excel 的“信任中心”信任工作簿的位置。
向 Sheet1 宿主项类添加方法。
提取 Sheet1 宿主项类的接口。
向 VBA 代码公开此方法。
从 VBA 代码中调用方法。
提示
以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 您安装的 Visual Studio 版本以及使用的设置决定了这些元素。 有关更多信息,请参见 使用设置。
系统必备
您需要以下组件来完成本演练:
-
Visual Studio 2010 的一个版本,其中包含 Microsoft Office 开发工具。有关更多信息,请参见[将计算机配置为开发 Office 解决方案](bb398242\(v=vs.100\).md)。
- Excel 2007 或 Excel 2010。
创建包含 VBA 代码的工作簿
第一步是创建一个启用宏的工作簿,该工作簿包含简单的 VBA 宏。 工作簿必须已经包含 VBA 代码,然后您才能向 VBA 公开自定义项中的代码。 否则,Visual Studio 无法修改 VBA 项目以使 VBA 代码能够调入自定义项程序集。
如果您已经拥有一个包含要使用的 VBA 代码的工作簿,则可以跳过此步骤。
创建包含 VBA 代码的工作簿
启动 Excel。
将活动文档另存为名为 WorkbookWithVBA 的**“启用宏的 Excel 工作簿(*.xlsm)”**。 将它保存到一个方便的位置,比如桌面。
在功能区上,单击**“开发人员”**选项卡。
提示
如果看不到“开发人员”选项卡,您必须首先显示该选项卡。 有关更多信息,请参见如何:在功能区上显示“开发人员”选项卡。
在**“代码”组中,单击“Visual Basic”**。
将打开 Visual Basic 编辑器。
在**“项目”窗口中,双击“ThisWorkbook”**。
将打开 ThisWorkbook 对象的代码文件。
向代码文件中添加以下 VBA 代码。 此代码定义一个不执行任何操作的简单函数。 此函数的唯一用途是确保 VBA 项目存在于工作簿中。 这对此演练中的后续步骤是必需的。
Sub EmptySub() End Sub
保存文档并退出 Excel。
创建项目
现在,您可以创建一个 Excel 文档级项目,这个项目使用您以前创建的、启用宏的工作簿。
创建新项目
启动 Visual Studio。
在**“文件”菜单上指向“新建”,再单击“项目”**。
在模板窗格中,展开**“Visual C#”,然后展开“Office”**。
选择**“2010”或“2007”**节点。
在项目模板列表中,选择**“Excel 工作簿”**项目。
在**“名称”**框中,键入 CallingCodeFromVBA。
单击**“确定”**。
会打开**“Visual Studio Tools for Office 项目向导”**。
选择**“复制现有文档”,并在“现有文档的完整路径”**框中,指定之前创建的 WorkbookWithVBA 工作簿的位置。 如果您正在使用自己的启用宏的工作簿,则改为指定此工作簿的位置。
单击**“完成”**。
Visual Studio 将在设计器中打开 WorkbookWithVBA 工作簿,并将**“CallingCodeFromVBA”项目添加到“解决方案资源管理器”**中。
信任工作簿的位置
在可以向工作簿中的 VBA 代码公开解决方案中的代码之前,必须信任要运行的工作簿中的 VBA。 有若干方法可用来执行此操作。 在此演练中,您将通过在 Excel 的**“信任中心”**中信任工作簿的位置来完成此任务。
信任工作簿的位置
启动 Excel。
单击**“文件”选项卡(对于 Excel 2010)或“Microsoft Office 按钮”**(对于 Excel 2007)。
单击**“Excel 选项”**按钮。
在类别窗格中单击**“信任中心”**。
在详细信息窗格中单击**“信任中心设置”**。
在类别窗格中单击**“受信任位置”**。
在细节窗格中单击**“添加新位置”**。
在**“Microsoft Office 受信任位置”**对话框中,浏览到包含 CallingCodeFromVBA 项目的文件夹。
选择**“同时信任此位置的子文件夹”**。
在**“Microsoft Office 受信任位置”对话框中,单击“确定”**。
在**“信任中心”对话框中,单击“确定”**。
在**“Excel 选项”对话框中单击“确定”**。
退出 Excel。
向 Sheet1 类中添加方法
既然设置了 VBA 项目,请向可从 VBA 代码中调用的 Sheet1 宿主项类中添加一个公共方法。
向 Sheet1 类中添加方法
在**“解决方案资源管理器”中右击“Sheet1.cs”,然后单击“查看代码”**。
Sheet1.cs 文件将在代码编辑器中打开。
向 Sheet1 类中添加下面的代码。 CreateVstoNamedRange 方法在指定的范围创建一个新的 NamedRange 对象。 此方法还会为 NamedRange 的 Selected 事件创建事件处理程序。 稍后在此演练中,您将从文档的 VBA 代码中调用 CreateVstoNamedRange 方法。
private Microsoft.Office.Tools.Excel.NamedRange namedRange1; public void CreateVstoNamedRange(Excel.Range range, string name) { if (!this.Controls.Contains(name)) { namedRange1 = this.Controls.AddNamedRange(range, name); namedRange1.Selected += new Excel.DocEvents_SelectionChangeEventHandler( namedRange1_Selected); } else { MessageBox.Show("A named range with this specific name " + "already exists on the worksheet."); } } private void namedRange1_Selected(Microsoft.Office.Interop.Excel.Range Target) { MessageBox.Show("This named range was created by Visual Studio " + "Tools for Office."); }
将下面的方法添加到 Sheet1 类中。 此方法将重写 GetAutomationObject() 方法,以返回 Sheet1 类的当前实例。
protected override object GetAutomationObject() { return this; }
在 Sheet1 类声明的第一行前面应用下列特性。 这些特性使类对于 COM 可见,但不生成类接口。
[System.Runtime.InteropServices.ComVisible(true)] [System.Runtime.InteropServices.ClassInterface( System.Runtime.InteropServices.ClassInterfaceType.None)]
提取 Sheet1 类的接口
在能够向 VBA 代码公开 CreateVstoNamedRange 方法之前,您必须创建一个定义此方法的公共接口,并且必须向 COM 公开此接口。
提取 Sheet1 类的接口
在 Sheet1.cs 代码文件中,单击 Sheet1 类中的任意位置。
在**“重构”菜单上,单击“提取接口”**。
在**“提取接口”对话框的“选择构成接口的公共成员”**框中,单击 CreateVstoNamedRange 方法项。
单击**“确定”**。
Visual Studio 将生成一个名为 ISheet1 的新接口,并修改 Sheet1 类的定义,以使其实现 ISheet1 接口。 Visual Studio 还将在代码编辑器中打开 ISheet1.cs 文件。
在 ISheet1.cs 文件中,将 ISheet1 接口声明替换为以下代码。 此代码使 ISheet1 接口成为公共接口,并且应用 ComVisibleAttribute 特性以使该接口对于 COM 可见。
[System.Runtime.InteropServices.ComVisible(true)] public interface ISheet1 { void CreateVstoNamedRange(Microsoft.Office.Interop.Excel.Range range, string name); }
生成项目。
向 VBA 代码公开方法
若要向工作簿中的 VBA 代码公开 CreateVstoNamedRange 方法,请将 Sheet1 宿主项的**“ReferenceAssemblyFromVbaProject”属性设置为“True”**。
向 VBA 代码公开方法
在**“解决方案资源管理器”**中双击 Sheet1.cs。
WorkbookWithVBA 文件将在设计器中打开,并显示 Sheet1。
在**“属性”窗口中,选择“ReferenceAssemblyFromVbaProject”属性,并将值更改为“True”**。
在显示的消息中单击**“确定”**。
生成项目。
从 VBA 代码中调用方法
现在可以从工作簿的 VBA 代码中调用 CreateVstoNamedRange 方法。
提示
在此演练中,将在调试项目时向工作簿中添加 VBA 代码。 在下次生成项目时,添加到此文档中的 VBA 代码将被覆盖,因为 Visual Studio 会将生成输出文件夹中的文档替换为主项目文件夹中文档的副本。 如果要保存 VBA 代码,可以将它复制到项目文件夹内的文档中。 有关更多信息,请参见从 VBA 中调用文档级自定义项中的代码。
从 VBA 代码中调用方法
按 F5 运行项目。
在**“开发人员”选项卡上的“代码”组中,单击“Visual Basic”**。
将打开 Visual Basic 编辑器。
在**“插入”菜单上,单击“模块”**。
向新模块添加以下代码。
此代码调用自定义项程序集中的 CreateTable 方法。 宏通过使用全局 GetManagedClass 方法来访问您向 VBA 代码公开的 Sheet1 宿主项类,从而访问此方法。 GetManagedClass 方法是您之前在此演练中设置**“ReferenceAssemblyFromVbaProject”**属性时自动生成的。
Sub CallVSTOMethod() Dim VSTOSheet1 As CallingCodeFromVBA.Sheet1 Set VSTOSheet1 = GetManagedClass(Sheet1) Call VSTOSheet1.CreateVstoNamedRange(Sheet1.Range("A1"), "VstoNamedRange") End Sub
按 F5。
在打开的工作簿中,单击**“Sheet1”上的单元格“A1”**。 验证是否出现消息框。
退出 Excel 而不保存更改。
后续步骤
在以下主题中,您可以了解有关从 VBA 调用 Office 解决方案中的代码的更多信息:
从 VBA 中调用 Visual Basic 自定义项中宿主项的代码。 此过程不同于 Visual C# 过程。 有关更多信息,请参见演练:在 Visual Basic 项目中调用 VBA 中的代码。
从 VBA 中调用应用程序级外接程序中的代码。 有关更多信息,请参见演练:从 VBA 中调用应用程序级外接程序中的代码。
请参见
任务
如何:向 VBA 公开 Visual Basic 项目中的代码
演练:在 Visual Basic 项目中调用 VBA 中的代码