3

我在文档存储库中有一个用户可编辑的 Excel 文件,它为 F# 程序定义了一些输入。我想用 F#-y 来阅读它,所以我想我会尝试 FSharpX 和他们的 ExcelFile 类型提供程序。

什么有效

提供程序是通过 NuGet 安装并启用的,这有效:

open FSharpX
type Example = ExcelFile<"example.xlsx", "Worksheet1", true>
let file = new Example()
for row in File.Data do ......

什么不

但是,当我尝试使用不同的文件(我在运行时从数据库中提取并存储在临时位置的文件)初始化构造函数时,我得到了一个非常奇怪的类型错误。

let file = new Example(@"c:\temp\path\to.xlsx")

结果是

类型提供程序 'FSharpx.TypeProviders.ExcelProvider+ExcelProvider' 在提供的类型 'FSharpx.ExcelFile,filename="example.xlsx",sheetname="Worksheet1",forcestring="True"', member '的上下文中报告错误。医生'。错误:将表达式拼接成引号文字时类型不匹配。插入的表达式树的类型与拼接操作所期望的类型不匹配。应为“System.String”,但收到类型“System.Tuple`2[System.String,System.String]”。考虑使用预期的表达式类型进行类型注释,例如 (%% x : string) 或 (%x : string)。参数名称:receiveType

嗯?

我不知道它所谈论的元组可能来自哪里,而且我对如何初始化它没有任何其他想法。

额外的问题:如果我想在运行时改变工作表名称怎么办?现有的 FSharpx 提供商似乎不允许这样做。

4

2 回答 2

4

这是提供程序中的错误,而不是您的代码。提供的构造函数使用您传入的文件名,但底层代码需要一个文件名和一个工作簿名称(这是元组应该来自的地方)。

于 2013-04-25T21:38:23.687 回答
4

似乎是一个错误。提供的接受单个文件名参数的构造函数不会在引号中正确调用内部构造函数:

ty.AddMember(ProvidedConstructor([ProvidedParameter("filename", typeof<string>)], InvokeCode = fun [filename] -> <@@  ExcelFileInternal(%%filename) @@>))
....
type  ExcelFileInternal(filename, sheetorrangename)

如果文件>= office 2007(我注意到您的工作簿是),我前一段时间分叉了 FSharpx.Excel 类型提供程序,以修改它以便使用 ClosedXML(而不是 office interop)。我还对 API 进行了一些更改,将工作表(和/或范围)公开为提供的类型、“行”提供的类型和“行{n}”类型。

type exc = ExcelFile<"C:\\temp\\Template.xlsx",false>
let file = new exc(@"C:\\temp\\Book.xlsx")
for row in file.Sheet1.Rows do
    printfn "%s" row.BID
let sht1Row1Col20 = file.Sheet1.Row1.BID

不过,恐怕没有提供“表格”类型,因此您不能在运行时更改工作表名称。有一个 string[] 'SheetAndRangeNames' 类型,但这对你没有多大用处。但是,实施起来应该不是特别棘手。你可以在这里找到它:

https://github.com/bennylynch/ExcelTypeProvider/

于 2013-04-26T10:12:00.470 回答