创建C#.NET用户定义函数的问题

时间:2019-02-19 19:19:49

标签: c# excel excel-addins com-automation

我正在研究创建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.如何保留应用程序。

0 个答案:

没有答案