10 c# vba vsto add-in office-interop
这是一个假设的情况.
我想知道是否可以在文档级外接程序中将C#类公开给VBA.
这是一个SSCCE:
在VS PRO 2012中,我启动了一个新项目,选择Office - > Excel 2010 Workbook.(确保选择.Net framework ver 4)
我已经DateTimePicker
向Sheet1 添加了一个控件.
我可以在C#解决方案中设置/获取.Value
属性DateTimePicker
而不会出现问题.
在调试时:在VBA中,.Value
属性不会公开.(试过.OLEFormat.Object.Value
)
并非所有属性都可以暴露给VBA,因为ActiveX控件DateTimePicker
被包装,MSForms
因此Excel可以识别它(兼容性).
我需要能够从VBA获取包装控件的实际值,但我不确定如何去做(无论是否可能)......
我知道控件本身支持事件,但这不是我想要的路径.我希望能够从控件中获取静态/当前值.
这是我希望能够做到的:
在我的C#解决方案中添加一个类
暴露它,所以它可以从VBA中恢复过来 Dim obj as new MyExposedClass
然后在C#中显示MyExposedClass
商店参考DateTimePicker
(所有可用的属性)
然后我可以定义一个GetValue(string controlName)
从C#POV返回值的函数
所以我发现这个解决方案 +(这个)似乎与应用程序级外接程序一起使用,但它不适用于文档级外接程序.
当我调试我的解决方案并打开VBA的对象浏览器时,我可以看到引用被自动添加到Microsoft Visual Studio 2008 Tools for Office Execution Engine 9.0 Type Library
但我不认为我可以添加额外的类...
当我在VBE中打开引用时,没有额外的引用添加到项目中但是在我的解决方案的/ debug文件夹中有一个ExcelWorkbook1.dll
甚至附加到解决方案的方式?
所以我的问题是:
如何使用C#在Excel的文档级外接程序中公开类,以扩展.Net控件上默认可访问的属性范围?
更新:
这是我到目前为止最接近但它只允许你公开主题项,如工作表,工作簿,图表等.它允许你调用方法,所以我将进一步调查这一点并返回一些反馈
小智 6
您需要创建一个公共接口以将该类公开给VBA,这对我来说是一个文档级别的插件.
打开一个新的Excel工作簿并将以下内容复制到MODULE中
Sub CallVSTOMethod()
Dim dt As Date
Dim VSTOSheet1 As DocLevelAddin.Sheet1
Set VSTOSheet1 = GetManagedClass(Sheet1)
dt = VSTOSheet1.GetDatePickerVal
End Sub
Run Code Online (Sandbox Code Playgroud)将Excel保存为"TestProj.xlsm"并关闭.
在Excel Sheet1上将DateTimePicker控件添加到来自VS的工作表中,双击以创建ValueChanged事件并更新Sheet1.cs中的代码以进行读取
private DateTime dtVal;
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
dtVal = dateTimePicker1.Value;
}
Run Code Online (Sandbox Code Playgroud)仍然在Sheet1.cs中,添加一个公共方法来返回dtVal
public DateTime GetDatePickerVal()
{
return dtVal;
}
Run Code Online (Sandbox Code Playgroud)还要将以下内容添加到Sheet1.cs中
protected override object GetAutomationObject()
{
return this;
}
Run Code Online (Sandbox Code Playgroud)在Sheet1.cs中的公共部分类Sheet1上面添加以下内容
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ClassInterface(
System.Runtime.InteropServices.ClassInterfaceType.None)]
Run Code Online (Sandbox Code Playgroud)现在,您需要为该方法创建一个公共接口.在Sheet1.cs中右键单击选择Refactor,Extract Interface并检查公共方法GetDatePickerVal
使界面公开,COM可见
[System.Runtime.InteropServices.ComVisible(true)]
public interface ISheet1
{
DateTime GetDatePickerVal();
}
Run Code Online (Sandbox Code Playgroud)双击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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
ISheet1.cs:
using System;
namespace DocLevelAddin
{
[System.Runtime.InteropServices.ComVisible(true)]
public interface ISheet1
{
DateTime GetDatePickerVal();
}
}
Run Code Online (Sandbox Code Playgroud)