3

我正在研究 Boo,并认为尝试转换几个可自动执行 Excel 的古老 VB 脚本(在本例中为 2007 年)将是一个有用的练习。很多东西似乎很容易翻译,但是我在选择范围时遇到了很多麻烦——每当我尝试获取或设置它们时,我都会得到一个 TargetInvocationException Member not found。

这是我在 booish 中运行的(缩减)示例:

def CreateInstance(progid):
    type = System.Type.GetTypeFromProgID(progid)    
    return type()   

xl as duck = CreateInstance("Excel.Application")
xl.Visible = true
xl.Workbooks.Add

sht as duck = xl.ActiveSheet
#Next line throws exception
rng as duck = sht.Range("A1")

某些事情可以正常工作,例如设置工作表的 Name 属性等,但是如何使用范围?是否有一些我需要调用的 VB 隐藏的特殊方法,如果有,我将如何找出这些方法?

干杯,

莱尼。

4

1 回答 1

3

Range 实际上是一个属性,它是一个有点特殊的属性,因为它用作索引器,这意味着它具有类似数组或字典的语义。在大多数语言中,这意味着您可以访问sht.Range["A1"]. 那是语法糖,实际上它就像任何其他方法一样被访问,即:

sht.get_Range("A1",System.Reflection.Missing.Method)

我尝试使用 Boo、Ruby 和 IronRuby 来重复您的代码,同时使用语法糖样式和显式方法调用。在 IronRuby 中,我可以让它完美地工作,但只能在 32 位解释器中。在我配置的 32 位应用程序的常规 Ruby 中,它也运行良好。在 64 位解释器中,Range 属性从未正确解析。

所以这让我怀疑 Boo Interactive Shell 是在 64 位模式下运行的,因此互操作失败了。不幸的是,在使用 CORFLAGS.exe 将我的本地 Boo 二进制文件设置为在 32 位模式下运行后,同样的问题再次出现,所以我认为这不是真正的问题。

但是,起作用的是显式导入 Excel Dotnet 互操作库以及互操作服务命名空间,如下所示:

import Microsoft.Office.Interop.Excel
import System.Runtime.InteropServices

xl_type=typeof(Application).GetCustomAttributes(typeof(CoClassAttribute),true)[0].CoClass
xl=xl_type()
xl.Visible=true
xl.Workbooks.Add

然后:

xl.Range["A1","A2"].Value=12
xl.Range["A1",System.Type.Missing].Value="Alpha"
(xl.ActiveSheet as Worksheet).Range["A1","A2"].Value2='Whatever'

所有这些工作,但它们本质上要求你放弃你习惯于后期绑定的“脚本性”(这是你的鸭子打字所做的)。

对于大多数语言(C# 4.0 除外)而言,与 VB/VBScript 的一个不同之处在于,通常不会透明地处理可选参数,因此在处理支持可选参数的方法时需要更仔细地查看 API参数(用 System.Type.Missing 或等效的 System.Reflection 替换它们)。您可以通过 Excel 互操作文档找到这一点,但如果您发现这比查找它更容易,您可以使用反射来识别标记为可选的参数。

因为 Ruby 为后期绑定这些对象提供了合理的解决方案,所以我怀疑 Boo 的 COM 互操作场景中缺少一个特性(或错误)。

编辑添加:Sam Ng 在 C# 4.0 中写了关于索引属性支持的文章;他的帖子中描述的问题也可能适用于 Boo。

于 2009-12-03T04:53:11.283 回答