演练:在 Visual C# 项目中从 VBA 调用代码
此演练演示如何从工作簿的 Visual Basic for Applications (VBA) 代码调用 Microsoft Office Excel 文档级自定义项中的方法。 该过程包括三个基本步骤:向 Sheet1
主机项类添加方法、向工作簿中的 VBA 代码公开方法,然后从工作簿的 VBA 代码中调用该方法。
适用于: 本主题中的信息适用于 Excel 和 Word 的文档级项目。 有关详细信息,请参阅办公室应用程序和项目类型提供的功能。
虽然本演练具体使用的是 Excel,但其中所阐释的概念同样适用于 Word 的文档级项目。
本演练阐释了以下任务:
创建包含 VBA 代码的工作簿。
使用 Excel 中的“信任中心”信任工作薄的位置。
向
Sheet1
主机项类添加方法。提取
Sheet1
主机项类的接口。向 VBA 代码公开方法。
从 VBA 代码中调用方法。
注意
以下说明中的某些 Visual Studio 用户界面元素在计算机上出现的名称或位置可能会不同。 这些元素取决于你所使用的 Visual Studio 版本和你所使用的设置。 有关详细信息,请参阅个性化设置 Visual Studio IDE。
先决条件
你需要满足以下条件才能完成本演练:
Visual Studio 的一个版本,其中包含 Microsoft Office 开发人员工具。 有关详细信息,请参阅配置计算机以开发办公室解决方案。
Microsoft Excel
创建包含 VBA 代码的工作簿
第一步是创建一个启用宏的工作簿,该工作簿包含简单的 VBA 宏。 工作簿必须已经包含 VBA 代码,然后你才能向 VBA 公开自定义项中的代码。 否则,Visual Studio 将无法修改 VBA 项目以允许 VBA 代码调入自定义项程序集。
如果已经拥有包含要使用的 VBA 代码的工作薄,则可以跳过此步骤。
创建包含 VBA 代码的工作薄
启动 Excel。
将活动文档另存为 Excel 已启用宏的工作簿(*.xlsm), 其名称 为 WorkbookWithVBA。 将其保存在一个方便的位置,例如桌面。
在功能区上,单击 “开发人员” 选项卡。
注意
如果看不到 “开发人员” 选项卡,则必须首先显示它。 有关详细信息,请参阅 “如何:在功能区上显示开发人员”选项卡。
在 “代码” 组中,单击 “Visual Basic”。
将打开 Visual Basic 编辑器。
在 “项目” 窗口中,双击 “ThisWorkbook”。
将打开
ThisWorkbook
对象的代码文件。向代码文件中添加以下 VBA 代码。 此代码定义一个不执行任何操作的简单函数。 此函数的唯一用途是确保 VBA 项目存在于工作簿中。 这是本演练中的后续步骤所必需的。
Sub EmptySub() End Sub
保存文档并退出 Excel。
创建项目
现在,你可以创建一个 Excel 文档级项目,这个项目使用先前创建的启用宏的工作簿。
创建新项目
启动 Visual Studio。
在 “文件” 菜单上,指向 “新建” ,然后单击 “项目” 。
在模板窗格中,展开 “Visual C#”,然后展开 “Office/SharePoint”。
选择“Office 外接程序” 节点。
在项目模板列表中,选择 “Excel 2010 工作簿” 或 “Excel 2013 工作簿” 项目。
在“名称” 框中,键入 CallingCodeFromVBA。
单击“确定”。
将打开“Visual Studio Tools for Office 项目向导” 。
选择 “复制现有文档”,然后在 “现有文档的完整路径” 框中,指定先前创建的 WorkbookWithVBA 工作薄的位置。 如果正在使用自己的启用宏的工作簿,则改为指定此工作簿的位置。
单击“完成” 。
Visual Studio 在设计器中打开 WorkbookWithVBA 工作簿,并将 CallingCodeFromVBA 项目添加到解决方案资源管理器。
信任工作簿的位置
必须先信任要运行的工作簿中的 VBA,然后才可向工作簿中的 VBA 代码公开解决方案中的代码。 有多种方法可实现此目的。 在本演练中,将通过在 Excel 的 “信任中心” 信任工作薄的位置来完成此任务。
信任工作薄的位置
启动 Excel。
单击 “文件” 选项卡。
单击 “Excel 选项” 按钮。
在类别窗格中,单击 “信任中心”。
在细节窗格中,单击 “信任中心设置”。
在类别窗格中,单击 “受信任位置”。
在细节窗格中,单击 “添加新位置”。
在“Microsoft Office 受信任位置” 对话框中,浏览到包含 CallingCodeFromVBA 项目的文件夹。
选择 “同时信任此位置的子文件夹”。
在 “Microsoft Office 受信任位置” 对话框中,单击 “确定”。
在 “信任中心” 对话框中,单击 “确定”。
在 “Excel 选项” 对话框中,单击 “确定”。
退出 Excel。
向 Sheet1 类添加方法
既然已设置 VBA 项目,请向可以从 VBA 代码中调用的 Sheet1
主机项类添加一个公共方法。
向 Sheet1 类添加方法
在 “解决方案资源管理器”中,右键单击 “Sheet1.cs”,然后单击 “查看代码”。
Sheet1.cs 文件将在代码编辑器中打开。
将以下代码添加到
Sheet1
类。CreateVstoNamedRange
方法在指定的范围创建一个新的 NamedRange 对象。 此方法还会为 Selected 的 NamedRange事件创建一个事件处理程序。 在本演练中,稍后将从文档的 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 类的接口
必须先创建一个定义 CreateVstoNamedRange
方法的公共接口,并向 COM 公开此接口,然后才可向 VBA 代码公开此方法。
提取 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
方法,请将 主机项的 “ReferenceAssemblyFromVbaProject” Sheet1
属性设置为 “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 调用 VSTO 外接程序中的代码。 有关详细信息,请参阅 演练:从 VBA 调用 VSTO 外接程序中的代码。