*使用mutable来读取Excel ThisWorkbook.Names?
问题描述:
我想获取一个基于F#的加载项的Excel命名范围中的数据。我希望能够在工作簿中的任何位置使用命名范围,而不仅仅是特定的工作表。*使用mutable来读取Excel ThisWorkbook.Names?
let xlRange (xl:Microsoft.Office.Interop.Excel.Application, name:string) =
let name_list = xl.ThisWorkbook.Names:Microsoft.Office.Interop.Excel.Names
let mutable result=null
for n in name_list do
let nn = n :?> Microsoft.Office.Interop.Excel.Name
if nn.Name = name then
let range=nn.RefersToRange
result <- range.Value2 :?> obj[,]
result
上面的代码工作,但我不喜欢它,因为我不得不使用一个可变的和命令式的风格。问题是Excel.Names集合表现不佳。例如
let name_seq = Seq.toList name_list
给
类型“名”是不是与类型兼容“序列<‘一>’
是否有这样做的更多的F#习惯的方法?
答
您应该使用Seq.cast
将name_list
转换为类型序列。
优点很明显;您可以更好地与F#进行互操作,并且可以使用Seq module中的高阶函数,而不是必需的for
循环。
let xlRange (xl: Microsoft.Office.Interop.Excel.Application, name: string) =
xl.ThisWorkbook.Names
|> Seq.cast<Microsoft.Office.Interop.Excel.Name>
|> Seq.tryPick (fun n -> if n.Name = name
then Some (n.RefersToRange.Value2 :?> obj[,])
else None)
的返回类型现在是obj[,] option
这给你免费的类型安全。
+0
感谢这是我第一次尝试,但我得到'类型'名称'不兼容'IEnumerable'类型 – 2012-07-09 10:27:01
答
我无法使用Seq。直接因为不兼容的类型。 我做了这个函数,目的是将集合转换为一个F#列表,然后我可以像上面那样处理。它编译罚款,但我没有,因为考...
let xlNamesToList names =
let rec xlNameList_r (names:Microsoft.Office.Interop.Excel.Names) idx =
if idx>names.Count then // should this be >= ?
[]
else
names.Item(idx)::xlNameList_r names (idx+1)
xlNameList_r names 0
...然后我发现了一个更简单的办法直接做到这一点:
let xlRange (xl:Microsoft.Office.Interop.Excel.Application, name:string) =
try
let r=xl.ThisWorkbook.Names.Item(name :> obj).RefersToRange
Some(r.Value2 :?> obj[,])
with
| _ -> None
感谢您的帮助家伙!
尝试'Seq.toList(Seq.cast name_list)',甚至可能指定一个类型(即'let name_seq:... = ...')。 – 2012-07-07 19:23:14