gpt4 book ai didi

c# - 如何在文档级加载项中将 C# 类公开给 VBA 模块?

转载 作者:可可西里 更新时间:2023-11-01 09:11:50 24 4
gpt4 key购买 nike

这是一个假设情况。

我想知道是否可以在文档级加载项中向 VBA 公开 C# 类。

这是一个 SSCCE:

在 VS PRO 2012 中,我开始了一个新项目,Selected Office -> Excel 2010 Workbook . ( make sure you select .Net framework ver 4 )

我已将 DateTimePicker 控件添加到 Sheet1。

我可以在 C# 解决方案中设置/获取 .Value 属性关闭 DateTimePicker 控件而不会出现问题。

调试时:在 VBA 中,.Value 属性公开。 (尝试过 .OLEFormat.Object.Value)

enter image description here

并非所有属性都可以向 VBA 公开,因为 ActiveX 控件 DateTimePickerMSForms 包装,因此 Excel 可以识别它(兼容性)。

我需要能够从 VBA 获取包装控件的实际值,但我不确定该怎么做(是否可能) ...

我知道控件本身支持事件,但这不是我想走的路。我希望能够从控件中获取静态/当前值。


这是我希望能够做的:

  • 向我的 C# 解决方案添加一个类

  • 公开它,以便它可以从 VBA 重新创建,例如 Dim obj as new MyExposedClass

  • 然后让 MyExposedClass 存储对 DateTimePicker 的引用,因为它出现在 C# 中(所有属性都可用)

  • 然后我可以定义一个函数 GetValue(string controlName),它从 C# POV 返回值


所以我找到了this solution + ( this one ) 似乎适用于应用程序级 加载项,但不适用于文档级 加载项。

当我调试我的解决方案并打开 VBA 的对象浏览器时,我可以看到引用自动添加到 Microsoft Visual Studio 2008 Tools for Office Execution Engine 9.0 Type Library 但我不认为我可以向它添加一个额外的类...

当我在 VBE 中打开引用时,项目中没有添加额外的引用,但在我的解决方案的/debug 文件夹中有一个 ExcelWorkbook1.dll 所以它是如何附加到解决方案的?

所以我的问题是:

如何使用 C# 在 Excel 的文档级加载项中公开一个类,以扩展 .Net 控件默认可访问的属性范围?

更新:

这是目前为止我得到的最接近的,但它只允许你公开宿主项,如工作表、工作簿、图表等。它允许你调用方法,所以我将进一步调查这个并返回一些意见反馈

Calling Code in Document-Level Customizations from VBA

How to: Expose Code to VBA in a Visual C# Project

Walkthrough: Calling Code from VBA in a Visual C# Project

最佳答案

您需要创建一个公共(public)接口(interface)来将类公开给 VBA,这对我来说是一个文档级插件。

  1. 打开一个新的 Excel 工作簿并将以下内容复制到一个模块中

    Sub CallVSTOMethod()
    Dim dt As Date
    Dim VSTOSheet1 As DocLevelAddin.Sheet1
    Set VSTOSheet1 = GetManagedClass(Sheet1)
    dt = VSTOSheet1.GetDatePickerVal
    End Sub
  2. 将 Excel 另存为“TestProj.xlsm”并关闭。

  3. 打开 VS,新建项目,Excel 20xx 工作簿并将项目命名为“DocLevelAddin”
  4. 在向导中,选择复制现有文档并选择新创建的工作簿“TestProj.xlsm”
  5. 在 Excel Sheet1 上,通过 VS 将 DateTimePicker 控件添加到工作表,双击以创建 ValueChanged 事件并更新 Sheet1.cs 中的代码以读取

    private DateTime dtVal;
    private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
    {
    dtVal = dateTimePicker1.Value;
    }
  6. 还是在Sheet1.cs中,添加一个public方法返回dtVal

    public DateTime GetDatePickerVal()
    {
    return dtVal;
    }
  7. 同时将以下内容添加到 Sheet1.cs

    protected override object GetAutomationObject()
    {
    return this;
    }
  8. 在 Sheet1.cs 中的 public partial class Sheet1 上面添加以下内容

    [System.Runtime.InteropServices.ComVisible(true)]
    [System.Runtime.InteropServices.ClassInterface(
    System.Runtime.InteropServices.ClassInterfaceType.None)]
  9. 现在您需要为该方法创建一个公共(public)接口(interface)。在 Sheet1.cs 中右键单击选择 Refactor,Extract Interface 并检查公共(public)方法 GetDatePickerVal

  10. 使接口(interface)公开并且COM可见

    [System.Runtime.InteropServices.ComVisible(true)]
    public interface ISheet1
    {
    DateTime GetDatePickerVal();
    }
  11. 双击 Sheet1.cs 使 Excel 工作表可见。选择任何单元格以打开属性窗口并更改属性 ReferenceAssemblyFromVbaProject = true

  12. 在 Excel 中,您可能需要转到“信任中心设置”并将 VS 解决方案文件夹和子文件夹添加为受信任位置

  13. 运行项目,Excel MODULE 中的代码将通过公开的 GetDatePickerVal 方法返回 dateTimepicker。

enter image description here

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();
}
}

关于c# - 如何在文档级加载项中将 C# 类公开给 VBA 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22787956/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com