这是一种假设情况。
我想知道是否可以在文档级外接程序中将C#类公开给VBA。
这是一个SSCCE:
在VS PRO 2012中,我开始了一个新项目Selected Office -> Excel 2010 Workbook。 (make sure you select .Net framework ver 4)
我在Sheet1中添加了DateTimePicker
控件。
我可以在C#解决方案中设置/获取.Value
属性,而不会出现问题。
调试时:在VBA中,DateTimePicker
属性不公开。 (尝试.Value
)
并非所有属性都可以向VBA公开,因为ActiveX控件.OLEFormat.Object.Value
由DateTimePicker
包装,因此Excel可识别它(兼容性)。
我需要能够从VBA获取包装控件的实际值,但我不确定如何去做(是否可能< / EM>)...
我知道控件本身支持事件,但这不是我想要的路径。我希望能够从控件中获取静态/当前值。
这是我希望能够做到的:
在我的C#解决方案中添加一个类
公开它,因此可以从MSForms
然后Dim obj as new MyExposedClass
存储对MyExposedClass
的引用,因为它出现在C#中(所有可用属性)
然后我可以定义一个函数DateTimePicker
,它返回来自C#POV的值
所以我发现this solution +(this one)似乎与应用程序级加载项一起使用,但它不适用于文档 - 级别加载项。
当我调试我的解决方案并打开VBA的对象浏览器时,我可以看到引用会自动添加到 GetValue(string controlName)
但我不认为我可以为它添加一个额外的类......
当我在VBE中打开引用时,没有额外的引用添加到项目中但在我的解决方案的/ debug文件夹中有一个Microsoft Visual Studio 2008 Tools for Office Execution Engine 9.0 Type Library
所以它如何附加到解决方案?
所以我的问题是:
如何使用C#在Excel的文档级外接程序中公开类,以扩展.Net控件上默认可访问的属性范围?
更新
这是我到目前为止最接近但它只允许你公开主题项,如工作表,工作簿,图表等。它允许你调用方法,所以我将进一步调查这一点,然后回来一些反馈
Calling Code in Document-Level Customizations from VBA
答案 0 :(得分:6)
您需要创建一个公共接口以将该类公开给VBA,这对我来说是一个文档级别的插件。
打开一个新的Excel工作簿并将以下内容复制到MODULE
Sub CallVSTOMethod()
Dim dt As Date
Dim VSTOSheet1 As DocLevelAddin.Sheet1
Set VSTOSheet1 = GetManagedClass(Sheet1)
dt = VSTOSheet1.GetDatePickerVal
End Sub
将Excel保存为“TestProj.xlsm”并关闭。
在Excel Sheet1上将DateTimePicker控件添加到来自wihin VS的工作表中,双击以创建ValueChanged事件并更新Sheet1.cs中的代码以读取
private DateTime dtVal;
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dtVal = dateTimePicker1.Value;
}
仍然在Sheet1.cs中,添加一个公共方法来返回dtVal
public DateTime GetDatePickerVal()
{
return dtVal;
}
还将以下内容添加到Sheet1.cs
protected override object GetAutomationObject()
{
return this;
}
在Sheet1.cs上面的公共部分类Sheet1上面添加以下内容
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(
System.Runtime.InteropServices.ClassInterfaceType.None)]
现在您需要为该方法创建一个公共接口。在Sheet1.cs中右键单击选择Refactor,Extract Interface并检查公共方法GetDatePickerVal
使界面公开,COM可见
[System.Runtime.InteropServices.ComVisible(true)]
public interface ISheet1
{
DateTime GetDatePickerVal();
}
双击Sheet1.cs以显示Excel工作表。选择任何单元格以打开属性窗口并更改属性ReferenceAssemblyFromVbaProject = true
在Excel中,您可能需要转到信任中心设置并将VS解决方案文件夹和子文件夹添加为受信任位置
运行项目,Excel MODULE中的代码将通过公开的GetDatePickerVal方法返回dateTimepicker。
<强> Sheet1.cs:强>
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
namespace DocLevelAddin
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(
System.Runtime.InteropServices.ClassInterfaceType.None)]
public partial class Sheet1 : DocLevelAddin.ISheet1
{
private void Sheet1_Startup(object sender, System.EventArgs e)
{
}
private void Sheet1_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker1_ValueChanged);
this.Startup += new System.EventHandler(this.Sheet1_Startup);
this.Shutdown += new System.EventHandler(this.Sheet1_Shutdown);
}
#endregion
private DateTime dtVal;
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dtVal = dateTimePicker1.Value;
}
public DateTime GetDatePickerVal()
{
return dtVal;
}
protected override object GetAutomationObject()
{
return this;
}
}
}
<强> ISheet1.cs:强>
using System;
namespace DocLevelAddin
{
[System.Runtime.InteropServices.ComVisible(true)]
public interface ISheet1
{
DateTime GetDatePickerVal();
}
}