ExcelDNA 在运行时动态注册 UDF
ExcelDNA Dynamically Registering UDF at Runtime
我的目标是在运行时在 ExcelDNA 加载项中动态构建和注册 Excel 用户定义函数。
Here is an example 由 ExcelDNA 作者提供,重点介绍了如何从简单的 C# 代码字符串编译 UDF。
如您所见,这段代码是通过从 AddIn 的 AutoOpen
方法中调用 RegisterMyClass
来执行的;一切都很完美。
但是,如果将 RegisterMyClass
方法移动到(例如)功能区按钮的操作方法中,动态 UDF 的注册将不起作用并导致以下错误:
Registration [Error] xlfRegister call failed for function or command: 'MyDynamicAdd'
事实上,在上述错误消息中似乎对 ExcelIntegration.RegisterMethods
的任何调用都失败了 - 除非它们是从 AutoOpen
方法中调用的。
我的问题是:
How can I dynamically register a new UDF at runtime and triggered by a click on a Ribbon button?
为了完整起见参考的 Gist 代码:
<DnaLibrary Name="ExcelDna Test Dynamic Method" Language="C#">
<Reference Name="System.Windows.Forms" />
<![CDATA[
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.CSharp;
using ExcelDna.Integration;
public class Test : IExcelAddIn
{
// Just to test that we are loaded.
public static double MyAdd(double d1, double d2)
{
return d1 + d2;
}
public void AutoOpen()
{
RegisterMyClass();
}
public void AutoClose()
{
}
private void RegisterMyClass()
{
string code =
@"
public class Script
{
public static double MyDynamicAdd(double d1, double d2)
{
return d1 + d2;
}
}";
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
cp.TreatWarningsAsErrors = false;
cp.ReferencedAssemblies.Add("System.dll"); //, "System.Windows.Forms.dll", "ExcelDna.Integration.dll" );
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults cr = provider.CompileAssemblyFromSource(cp, new string[] { code });
if (!cr.Errors.HasErrors)
{
Assembly asm = cr.CompiledAssembly;
Type[] types = asm.GetTypes();
List<MethodInfo> methods = new List<MethodInfo>();
// Get list of MethodInfo's from assembly for each method with ExcelFunction attribute
foreach (Type type in types)
{
foreach (MethodInfo info in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
methods.Add(info);
}
}
Integration.RegisterMethods(methods);
}
else
{
MessageBox.Show("Errors during compile!");
}
}
}
]]>
</DnaLibrary>
注册该函数的代码需要位于 C API 可用的上下文中。它不适用于功能区回调或任何其他 COM 事件处理程序。
切换到 C API 可用的宏上下文的一个选项是调用 ExcelAsyncUtil.QueueAsMacro
帮助程序,并 运行 您传入的委托中的注册代码。
我的目标是在运行时在 ExcelDNA 加载项中动态构建和注册 Excel 用户定义函数。
Here is an example 由 ExcelDNA 作者提供,重点介绍了如何从简单的 C# 代码字符串编译 UDF。
如您所见,这段代码是通过从 AddIn 的 AutoOpen
方法中调用 RegisterMyClass
来执行的;一切都很完美。
但是,如果将 RegisterMyClass
方法移动到(例如)功能区按钮的操作方法中,动态 UDF 的注册将不起作用并导致以下错误:
Registration [Error] xlfRegister call failed for function or command: 'MyDynamicAdd'
事实上,在上述错误消息中似乎对 ExcelIntegration.RegisterMethods
的任何调用都失败了 - 除非它们是从 AutoOpen
方法中调用的。
我的问题是:
How can I dynamically register a new UDF at runtime and triggered by a click on a Ribbon button?
为了完整起见参考的 Gist 代码:
<DnaLibrary Name="ExcelDna Test Dynamic Method" Language="C#">
<Reference Name="System.Windows.Forms" />
<![CDATA[
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Microsoft.CSharp;
using ExcelDna.Integration;
public class Test : IExcelAddIn
{
// Just to test that we are loaded.
public static double MyAdd(double d1, double d2)
{
return d1 + d2;
}
public void AutoOpen()
{
RegisterMyClass();
}
public void AutoClose()
{
}
private void RegisterMyClass()
{
string code =
@"
public class Script
{
public static double MyDynamicAdd(double d1, double d2)
{
return d1 + d2;
}
}";
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
cp.TreatWarningsAsErrors = false;
cp.ReferencedAssemblies.Add("System.dll"); //, "System.Windows.Forms.dll", "ExcelDna.Integration.dll" );
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults cr = provider.CompileAssemblyFromSource(cp, new string[] { code });
if (!cr.Errors.HasErrors)
{
Assembly asm = cr.CompiledAssembly;
Type[] types = asm.GetTypes();
List<MethodInfo> methods = new List<MethodInfo>();
// Get list of MethodInfo's from assembly for each method with ExcelFunction attribute
foreach (Type type in types)
{
foreach (MethodInfo info in type.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
methods.Add(info);
}
}
Integration.RegisterMethods(methods);
}
else
{
MessageBox.Show("Errors during compile!");
}
}
}
]]>
</DnaLibrary>
注册该函数的代码需要位于 C API 可用的上下文中。它不适用于功能区回调或任何其他 COM 事件处理程序。
切换到 C API 可用的宏上下文的一个选项是调用 ExcelAsyncUtil.QueueAsMacro
帮助程序,并 运行 您传入的委托中的注册代码。