Excel 的互操作程序集都是标准的 .NET 程序集,我们可以在 F# Interactive 中使用 #r 指令进行引用。引用程序集之后,就能使用类了,既可以把Excel 作为独立(可见或不可见)的应用程序运行,也可以写脚本。清单 13.18 演示了如何启动 Excel,创建有一个工作表的新工作簿,以及把数据写入工作表。
清单13.18 启动 Excel 创建工作表 (F#)
#r "office.dll"
#r "Microsoft.Office.Interop.Excel.dll"
open System
open Microsoft.Office.Interop.Excel
let app = new ApplicationClass(Visible = true) [1]
let workbook = app.Workbooks.Add(XlWBATemplate.xlWBATWorksheet) [2]
let worksheet = (workbook.Worksheets.[1] :?> _Worksheet) [3]
worksheet.Range("C2").Value2 <- "1990" | [4]
worksheet.Range("C2", "E2").Value2 <- [| "1990"; "2000"; "2005" |] |
在清单 13.18 中,我们创建了 ApplicationClass 类的新实例[1],这个类型来自 Excel 命名空间,表示 Excel 这个应用程序。运行这行代码之后,应该显示一个新的 Excel 窗口。下一行[2]创建工作簿,因此,运行以后,应该看到通常的 Excel 表格。再下一行,我们获取表示工作簿中的第一个工作表(工作表显示在应用程序左下角)的对象。可以看到,我们需要把这个对象强制转换为 Worksheet 类[3],因为 Excel 编程接口(API)在很多地方是弱类型的。我们得到了这个工作表之后,就可以开始将数据写入网格,这可以使用 Range 索引器和 Value2 属性[4]实现。这个属性的类型是object,所以,可以用各种方式来使用。第一个示例将一个字符串值写到一列,第二个示例用 .NET 数组值填充范围 (一行三列)。在图 13.1 中可以看到,运行代码后创建的 Excel 工作表。
图 13.1 从 F# Interactive 中启动Excel 应用程序,以编程方式输入数据。
到目前为止,我们已经创建了想要显示的表头,下一步是填充所有剩余的信息,且最重要的,表格包含了不同年份的森林面积。清单 13.19 将数据转换成二维数组,这也是Value2 属性的有效数据源。
清单13.19 把数据导出到 Excel 工作表 (F#)
let statsArray = stats |> Array.ofSeq
let names = Array2D.init statsArray.Length 1 (fun index _ –> [1]
let name, _ = statsArray.[index] | 得到二维数组中的地区名
name ) |
let dataArray = Array2D.init statsArray.Length 3 (fun index year –>
let _, values = statsArray.[index]
let yearValue = values.[year]
yearValue / 1000000.0 ) <-- 显示为百万平方公里
let endColumn = string(statsArray.Length + 2)
worksheet.Range("B3", "B" + endColumn).Value2 <- namesVert | 把数据写到工作表
worksheet.Range("C3", "E" + endColumn).Value2 <- tableArr |
把数据写入到 Excel 工作表,我们可以使用基本值,比如数组或二维数组。一维数组可用于写数据行,像在第一个示例中看到的,但如果我们想要用数据填充矩阵或列,必须使用二维数组。在清单 13.19 中,我们首先创建一个二维数组,纵向保存地区名。为此,创建一个简单的数组,包含名称,然后,使用 Array2D.init 函数,将其转换为二维数组[1]。init 函数的前两个参数为数组的宽和高,再加一个函数,用于为每个坐标生成值。生成的数组仅包含一列,所以,在初始化过程中,可以忽略第二个坐标。
下一步是用地区数据生成二维数组。我们把输入序列转换成数组,还使用 Array2D.init 函数生成二维数组,以便可以使用索引。lambda 函数,每个数组单元格都执行,在函数中,首先获得地区信息,然后,找到指定年份的值,除以 100 万,使输出更方便阅读。最后,我们计算 Excel 工作表中的右边范围(取决于地区的数量),并设置数据,方法同前面的示例。
运行代码,数据应该出现在 Excel 中。因为我们运行的是 F# 脚本,因此,可以同时处理工作表,调整刚生成的表设计,结果类似于图 13.2。
图 13.2 由 F# 脚本生成的 Excel 表格,显示在过去 20 年里,世界各地森林覆盖面积的变化。
现在,有了 Excel,更容易理解数据了;还可以再进一步,用数据创建图表。这既可以手工完成,但是,用 F# 生成完整的 Excel 文件,包括图表,更容易。