*使用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#习惯的方法?

+0

尝试'Seq.toList(Seq.cast name_list)',甚至可能指定一个类型(即'let name_seq:... = ...')。 – 2012-07-07 19:23:14

您应该使用Seq.castname_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 

感谢您的帮助家伙!