hug*_*own 9 excel excel-udf com-server
我在COM服务器中编写了几个Excel UDF.我想获得按fx时获得的标准帮助(" 插入函数"对话框).是的,我可以看到我的COM服务器列在类别下拉列表中,但是
这是我得到的跛足:
插入函数对话框http://www.iwebthereforeiam.com/files/Insert%20function%20dialog.gif
Excel函数参数对话框http://www.iwebthereforeiam.com/files/Function%20Arguments%20dialog.gif
是否有.NET属性我可以把方法传递给Excel?
(我发现在ExcelDNA中看起来很容易,但我不会那样做.模仿govert的代码[自定义属性,某种类型的加载器等]看起来很难.)
如果您以前没有使用Excel + COM服务器,这里有一些有用的资源可以加快速度:
以前的StackOverflow问题:
如何在VB.NET中安装并在Automation Servers列表中注册的用于Excel的COM Server for Excel?
如何将COM暴露的.NET项目添加到VB6(或VBA)引用对话框?
其他资源:
在.NET中为Excel编写用户定义的函数
构建和部署.NET COM程序集
在C#中编写自定义Excel工作表函数
编辑2009-10-20 14:10
我试着打电话Application.MacroOptions给Sub New().
Cannot register assembly "...\Foo.dll". Exception has been thrown by the target of an invocation.
我怀疑这对于MacroOptions和Charles推荐的更复杂的路线都是一个问题.
编辑2009-10-20 14:55
从好的方面来说,Mike建议创建一个实现的接口确实可以消除暴露的烦人的额外方法.
编辑2009-10-20 15:00
这篇 2007年初的微软文章(通过Mike的链接)似乎是关于这个主题的一个相当完整的答案:
自动化加载项和功能向导
每个自动化加载项在Excel函数向导中都有自己的类别.类别名称是加载项的ProgID; 您无法为自动化加载项功能指定其他类别名称.此外,无法在"函数向导"中指定自动化加载项功能的函数说明,参数说明或帮助.
1呵呵,一个StackOverFlow错误.看起来你不能在显式的HTML ul-list中使用斜体字符串?
Mik*_*lum 11
其中一些很容易纠正,其他部分相当困难.但是,如果你愿意花时间,那么所有这些都是可行的.
你写了:
我还看到了Equals,GetHashCode,GetType和ToString(这些对于向Excel用户公开是不合适的)
是的,同意,这绝对是不受欢迎的,但可以预防.之所以发生这种情况是因为您的类继承自'System.Object',就像所有.NET类一样,并且暴露给COM的默认接口包括这些成员.例如,如果使用'ClassInterfaceAttribute',则使用"ClassInterfaceType.AutoDual"设置会发生这种情况.
例如在C#中:
[ClassInterface(ClassInterfaceType.AutoDual)]
Run Code Online (Sandbox Code Playgroud)
在VB.NET中:
<ClassInterface(ClassInterfaceType.AutoDual)>
Run Code Online (Sandbox Code Playgroud)
但是,应避免使用'ClassInterfaceType.AutoDual',以防止从'System.Object'继承的成员被暴露(以及防止将来出现潜在的版本问题).相反,定义您自己的接口,在类中实现接口,然后使用值为"ClassInterfaceType.None"的"ClassInterface"属性标记您的类.
例如,使用C#:
[ComVisible(true)]
[Guid("5B88B8D0-8AF1-4741-A645-3D362A31BD37")]
public interface IClassName
{
double AddTwo(double x, double y);
}
[ComVisible(true)]
[Guid("010B0245-55BB-4485-ABAF-46DF4356DB7B")]
[ProgId("ProjectName.ClassName")]
[ComDefaultInterface(typeof(IClassName))]
[ClassInterface(ClassInterfaceType.None)]
public class ClassName : IClassName
{
public double AddTwo(double x, double y)
{
return x + y;
}
}
Run Code Online (Sandbox Code Playgroud)
使用VB.NET:
<ComVisible(True)> _
<Guid("5B88B8D0-8AF1-4741-A645-3D362A31BD37")> _
Public Interface IClassName
Function AddTwo(ByVal x As Double, ByVal y As Double) As Double
End Interface
<ComVisible(True)> _
<Guid("010B0245-55BB-4485-ABAF-46DF4356DB7B")> _
<ProgId("ProjectName.ClassName")> _
<ComDefaultInterface(GetType(IClassName))> _
<ClassInterface(ClassInterfaceType.None)> _
Public Class ClassName
Implements IClassName
Public Function AddTwo(ByVal x As Double, ByVal y As Double) As Double _
Implements IClassName.AddTwo
Return x + y
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
通过使用值为'ClassInterfaceType.None'的'ClassInterfaceAtribute',将排除继承的'System.Object'成员,因为类的接口不是COM可见的.相反,只有已实现的接口(在此示例中为"IClassName")才会导出到COM.
以上也使用'ComDefaultInterfaceAttribute'.这不是很重要,如果只实现一个接口,则不执行任何操作 - 如本示例所示 - 但如果稍后添加接口(例如IDTExtensibility2),这是一个好主意.
有关详细信息,请参阅:
(1)Andrew Whitechapel的托管自动化加载项.
(2)用Gabhan Berry 编写C#中的自定义Excel工作表函数.
好的,现在到了困难的部分.你写了:
选择我的COM服务器将打开 Function Arguments [1]对话框,其中没有参数信息,也没有该函数的描述.
我可以提供功能说明吗?
我可以提供参数说明吗?
我可以为我的功能提供类别名称,这样我得到的东西比ProgID更好吗?
这里最简单的方法是使用Application.MacroOptions方法.使用此方法可以提供函数的说明,并指定要在其下显示的类别.不幸的是,这种方法不允许您为函数参数指定任何信息,但允许您这样做的技术非常复杂,我将在稍后介绍.[更正:'Application.MacroOptions'方法仅适用于通过VBA创建的UDF,不能用于自动化加载项.继续阅读更复杂的方法来处理自动化插件中UDF的注册 - Mike Rosenblum 2009.10.20]
需要注意的是帮助文件为Excel 2003和帮助Excel 2007中的文件,一个字符串可以以提供您所选择的自定义类别名称提供的类别参数状态.但请注意,Excel 2002的帮助文件没有.我不知道这是否是Excel 2002帮助文件中的遗漏,或者这是Excel 2003中的新功能.我猜测后者,但您必须进行测试才能确定.
将参数信息输入函数向导的唯一方法是使用涉及'Excel.Application.ExecuteExcel4Macro'方法的相当复杂的技术.但请注意:许多Excel MVP都在努力应对这种方法,并且未能产生可靠的结果.然而,最近,Jan Karel Pieterse(JKP)似乎已经解决了问题,并在此处发布了详细信息:使用Excel注册用户定义函数.
略读那篇文章,你会发现它不适合胆小的人.问题的一部分是他为VBA/VB 6.0编写了它,因此所有代码都必须转换为VB.NET或C#.但是,关键命令是'Excel.Application.ExecuteExcel4Macro'方法,它暴露给.NET,所以一切都应该正常工作.
然而,实际上,我非常喜欢使用'Excel.Application.MacroOptions'方法,因为它简单可靠.它没有提供参数信息,但我还没有强烈要求激励我采用'ExecuteExcel4Macro'方法.
所以,祝你好运,但我的建议是利用'MacroOptions',除非你按小时付款.;-)
- 迈克
Hugh的回复的后续行动
我尝试在Sub New()中调用Application.MacroOptions.
No Sub New()半可接受:功能列在ProgID类别下.
Shared Sub New()不可接受:构建时错误.无法注册程序集"...\Foo.dll".调用的目标抛出了异常.
Sub New()不可接受:"插入函数"对话框中未列出类别.我怀疑这对于MacroOptions和Charles推荐的更复杂的路线都是一个问题.
在将类暴露给COM时,不能使用共享(也称为"静态")类或构造函数,因为COM不知道这个概念,因此无法编译 - 正如您所发现的那样!您可能能够将值为'False'的'COMVisibleAttribute'应用于共享构造函数,以至少允许它进行编译.但无论如何这对你来说无济于事......
尝试通过自动化加载项本身注册自动化加载项可能会很棘手.我意识到这是可取的,以便将其保持为单个独立组件,但它可能是不可能的.或者至少这并不容易.
问题是自动化加载项是需求加载的.也就是说,在Excel尝试从您的自动化加载项访问第一个工作表函数之前,它们并不存在.有两个与此相关的问题:
(1)如果将注册码放在类的构造函数中,那么根据定义,在第一次调用函数之前,函数向导信息不能存在.
(2)当Excel未准备好接受自动化命令时,您的构造函数可能正在执行.例如,当用户开始键入自动化加载项中定义的某个用户定义函数(UDF)的名称时,通常会自动加载自动化加载项.结果是,当您的自动化加载项首次加载时,单元格处于编辑模式.如果在编辑模式下构造函数中包含自动化代码,则许多命令将失败.我不知道'Excel.Application.MacroOptions'或'Excel.Application.Excel4Macro'方法是否存在问题,但是当单元格处于编辑模式时,许多命令会在尝试执行时阻塞.如果自动加载项是第一次加载,因为它是在函数向导打开时调用的,我不知道这些方法是否可以正常工作.
如果您希望自动化插件完全独立而没有其他支持,则没有简单的解决方案.但是,您可以创建一个托管的COM加载项,它将在Excel启动时通过"Excel.Application.MacroOptions"或"Excel.Application.Excel4Macro"方法为您注册自动化加载项.托管COM加载项类可以与自动化加载项位于同一程序集中,因此您仍然只需要一个程序集.
顺便说一句,你甚至可以使用VBA工作簿或.XLA加载项来做同样的事情 - 使用VBA中的Workbook.Open事件来调用注册码.在Excel启动时,您只需要一些东西来调用您的注册码.在这种情况下使用VBA的优点是,您可以使用Jan Karel Pieterse的注册用户自定义函数和Excel文章的代码,而无需将其转换为.NET.
从好的方面来说,Mike建议创建一个实现的接口确实可以消除暴露的烦人的额外方法.
大声笑,我很高兴有所作为!
这篇2007年初的微软文章(通过Mike的链接)似乎是关于这个主题的一个相当完整的答案:
自动化加载项和功能向导
每个自动化加载项在Excel函数向导中都有自己的类别.类别名称是加载项的ProgID; 您无法为自动化加载项功能指定其他类别名称.此外,无法在"函数向导"中指定自动化加载项功能的函数说明,参数说明或帮助.
这仅限于"Excel.Application.MacroOptions"方法.(我很抱歉,当我在上面写下原始答案时,我已经忘记了关于自动化插件的'Excel.Application.MacroOptions'方法的限制.)更复杂的'Excel.Application.但是,ExecuteExcel4Macro'方法绝对适用于自动化加载项.它也适用于.NET("托管")自动化加载项,因为Excel不知道它是否正在加载通过VB 6.0/C++创建的COM自动化加载项而不是使用创建的托管COM自动化加载项VB.NET/C#.机制是从围栏的COM端完全相同的,因为Excel不知道.NET是什么,或者.NET甚至存在.
也就是说,'Excel.Application.Excel4Macro'方法肯定会有很多工作......
| 归档时间: |
|
| 查看次数: |
15755 次 |
| 最近记录: |