我正在研究创建Excel的自动化加载项,以替代Excel DNA。参考Adam Tibi(http://www.adamtibi.net/07-2012/using-c-sharp-net-user-defined-functions-udf-in-excel)的文章,我能够获得一个用于处理某些问题的类库。最大的问题是该公式可以工作,但不能显示在Excel公式列表中。另外,我想对UDF参数有个智能的了解,并且还想知道是否有任何方法可以捕获公式发送来源的单元格引用。
在设置方面,我选择了“使程序集显示COM”和“注册COM互操作”。
按代码分类,我有以下课程。
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace AutoExcel
{
public abstract class UdfBase
{
[ComRegisterFunction]
public static void ComRegisterFunction(Type type)
{
Registry.ClassesRoot.CreateSubKey(
GetClsIdSubKeyName(type, "Programmable"));
// Solves an intermittent issue where Excel
// reports that it cannot find mscoree.dll
// Register the full path to mscoree.dll.
var key = Registry.ClassesRoot.OpenSubKey(GetClsIdSubKeyName(type, "InprocServer32"), true);
if (key == null)
{
return;
}
key.SetValue("", $"{Environment.SystemDirectory}\\mscoree.dll", RegistryValueKind.String);
}
[ComUnregisterFunction]
public static void ComUnregisterFunction(Type type)
{
// Adds the "Programmable" registry key under CLSID
Registry.ClassesRoot.DeleteSubKey(GetClsIdSubKeyName(type, "Programmable"));
}
private static string GetClsIdSubKeyName(Type type, String subKeyName)
{
return $"CLSID\\{{{type.GUID.ToString().ToUpper()}}}\\{subKeyName}";
}
// Hiding these methods from Excel
[ComVisible(false)]
public override string ToString()
{
return base.ToString();
}
[ComVisible(false)]
public override bool Equals(object obj)
{
return base.Equals(obj);
}
[ComVisible(false)]
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}
和
using System.Runtime.InteropServices;
namespace AVstoAddIn
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("3CA06A95-F1A6-4C36-9E56-501BDC7AFDCF")]
public class UdfTest : UdfBase
{
public double AddNumbers(double a, double b)
{
return a + b;
}
public double SubtractNumbers(double a, double b)
{
return a - b;
}
}
}
当我尝试使用Excel VSTO加载项并应用相同的技术时,除了选择“注册COM互操作”以外,其他所有操作都可以使它构建。
我的开发环境是Windows 10,用于Office 365 64位的Excel,Visual Studio Professional 2017版本15.9.7。我的Excel插件需要支持2010、2013、2016 2019和Office 365。
我想让该函数出现在函数列表中,并且还希望为其创建一个类别,但不知道该怎么做。
任何帮助将不胜感激。
编辑1
我弄清楚了如何确定调用UDF的范围。有趣的是,即使我尝试将其保留在静态类/变量/属性中,也不会保留该应用程序。我在ThisAddIn_Startup方法中的ThisAddIn.cs中设置应用程序,但是当我尝试在COM Automation方法中访问它时,该应用程序为空。
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace AVstoAddIn
{
public static class ExcelApplication
{
static Excel.Application application;
public static Excel.Application XlApplication
{
get => application ?? (Excel.Application) Marshal.GetActiveObject("Excel.Application");
set { application = Globals.ThisAddIn.Application ?? (Excel.Application) Marshal.GetActiveObject("Excel.Application"); }
}
}
}
在上面提到的COM Automation类中,可以在下面找到这些引用。
public class UdfTest : UdfBase
{
public double AddNumbers(double a, double b)
{
Excel.Application excelApp = ExcelApplication.XlApplication;
Excel.Range target = (Excel.Range)excelApp.get_Caller(Type.Missing);
string cellAddress = target.get_Address(Missing.Value, Missing.Value, Excel.XlReferenceStyle.xlA1, Missing.Value, Missing.Value);
return a + b;
}
}
我现在的问题如下: 1.如何使UDF在用户开始键入时显示。 2.如何使智能感知在UDF参数上起作用。 3.如何保留应用程序。